import discord from discord import app_commands from discord.ext import commands, tasks from utils.gitlab_client import gitlab_client import logging import json import os import asyncio kuby_logger = logging.getLogger("KubyBot") REPORTS_FILE = "data/gitlab_reports.json" def save_report(issue_iid, user_id): os.makedirs("data", exist_ok=True) try: if os.path.exists(REPORTS_FILE): with open(REPORTS_FILE, "r") as f: data = json.load(f) else: data = {} data[str(issue_iid)] = user_id with open(REPORTS_FILE, "w") as f: json.dump(data, f, indent=4) except Exception as e: kuby_logger.error(f"Error saving report to JSON: {e}") class BugReportModal(discord.ui.Modal, title="Signaler un Bug"): def __init__(self, priority_choice): super().__init__() self.priority_choice = priority_choice bug_title = discord.ui.TextInput( label="Titre du bug", placeholder="Décrivez brièvement le problème...", required=True, max_length=100 ) description = discord.ui.TextInput( label="Description détaillée", style=discord.TextStyle.paragraph, placeholder="Que s'est-il passé ? Comment reproduire le bug ?", required=True, max_length=1000 ) async def on_submit(self, interaction: discord.Interaction): await interaction.response.send_message("Envoi de votre rapport de bug à GitLab...", ephemeral=True) description_text = f"**Rapporté par:** {interaction.user} ({interaction.user.id})\n" description_text += f"**Priorité:** {self.priority_choice.name}\n\n" description_text += f"**Description:**\n{self.description.value}" # Mapping des priorités vers des labels GitLab stylisés (Scoped Labels) labels = ["bug", "manual-report", f"Priority::{self.priority_choice.value}"] result = await gitlab_client.create_issue( title=f"[MANUAL] {self.bug_title.value}", description=description_text, labels=labels ) if result: issue_iid = result.get("iid") save_report(issue_iid, interaction.user.id) await interaction.edit_original_response(content=f"✅ Votre bug a été signalé avec succès ! Gameur a bien été averti et le bug sera réglé dans la prochaine mise à jour. [Voir l'issue]({result.get('web_url')})") else: await interaction.edit_original_response(content="❌ Une erreur est survenue lors de l'envoi du rapport à GitLab. Veuillez contacter un administrateur.") class BugReport(commands.Cog): def __init__(self, bot): self.bot = bot self.check_gitlab_issues.start() def cog_unload(self): self.check_gitlab_issues.cancel() @tasks.loop(minutes=30) async def check_gitlab_issues(self): """Vérifie périodiquement si des issues suivies ont été fermées""" if not os.path.exists(REPORTS_FILE): return try: with open(REPORTS_FILE, "r") as f: reports = json.load(f) if not reports: return issues_to_remove = [] for issue_iid, user_id in reports.items(): issue = await gitlab_client.get_issue(int(issue_iid)) if issue and issue.get("state") == "closed": # L'issue est fermée ! On prévient l'utilisateur user = self.bot.get_user(user_id) if user: try: embed = discord.Embed( title="🛠️ Bug Résolu !", description=f"Bonne nouvelle ! Le bug que vous avez signalé (**{issue.get('title')}**) a été marqué comme terminé sur GitLab.", color=discord.Color.green() ) embed.add_field(name="Statut", value="Terminé / Résolu") embed.add_field(name="Prochaine étape", value="La mise à jour arrive prochainement !") embed.set_footer(text="Merci de votre aide pour améliorer le bot.") await user.send(embed=embed) issues_to_remove.append(issue_iid) except Exception as e: kuby_logger.error(f"Impossible d'envoyer un MP à {user_id}: {e}") else: # On ne peut pas trouver l'user, on retire quand même pour ne pas boucler issues_to_remove.append(issue_iid) if issues_to_remove: for iid in issues_to_remove: del reports[iid] with open(REPORTS_FILE, "w") as f: json.dump(reports, f, indent=4) except Exception as e: kuby_logger.error(f"Erreur lors du cycle de vérification GitLab: {e}") @app_commands.command(name="signaler_bug", description="Signaler un bug aux développeurs") @app_commands.choices(priority=[ app_commands.Choice(name="Basse", value="Low"), app_commands.Choice(name="Normale", value="Normal"), app_commands.Choice(name="Haute", value="High"), app_commands.Choice(name="Urgente", value="Urgent"), ]) async def signaler_bug(self, interaction: discord.Interaction, priority: app_commands.Choice[str]): await interaction.response.send_modal(BugReportModal(priority)) async def setup(bot): await bot.add_cog(BugReport(bot))