diff --git a/commandes/bug_report.py b/commandes/bug_report.py index e319851..05e1fcb 100644 --- a/commandes/bug_report.py +++ b/commandes/bug_report.py @@ -447,11 +447,14 @@ class BugReport(commands.Cog): async def signaler_bug( self, interaction: disnake.ApplicationCommandInteraction, + titre: str = commands.Param(description="Titre/Courte description du bug"), + description: str = commands.Param(description="Description détaillée (copy-paste accepté !)"), priority: str = commands.Param( description="Priorité du bug", choices={"Basse": "Low", "Normale": "Normal", "Haute": "High", "Urgente": "Urgent"}, ), ): + """Signale un bug directement avec arguments - copy-paste supporté.""" from collections import namedtuple Choice = namedtuple('Choice', ['name', 'value']) @@ -461,14 +464,80 @@ class BugReport(commands.Cog): p_name = reverse.get(priority, "Normal") choice = Choice(name=p_name, value=priority) - await interaction.response.send_modal(BugReportModal(choice)) + await interaction.response.send_message("Envoi de votre rapport de bug à GitLab...", ephemeral=True) + + bug_title = titre.strip() if titre else "Sans titre" + priority_name = choice.name + description_value = description + + description_text = f"**Rapporté par:** {interaction.user} ({interaction.user.id})\n" + description_text += f"**Priorité:** {priority_name}\n\n" + description_text += f"**Description:**\n{description_value}" + + labels = ["bug", "manual-report", f"Priority::{choice.value}"] + + result = await gitlab_client.create_issue( + title=f"[MANUAL] {bug_title}", + 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=( + "✅ Votre bug a été signalé avec succès ! " + "Nous avons bien été averti et le bug sera réglé dans la prochaine mise à jour. " + f"[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." + ) @commands.slash_command( name="suggerer_fonctionnalite", description="Proposer une nouvelle fonctionnalité pour le bot", ) - async def suggerer_fonctionnalite(self, interaction: disnake.ApplicationCommandInteraction): - await interaction.response.send_modal(FeatureSuggestionModal()) + async def suggerer_fonctionnalite( + self, + interaction: disnake.ApplicationCommandInteraction, + titre: str = commands.Param(description="Titre de la suggestion"), + description: str = commands.Param(description="Détails de la fonctionnalité (copy-paste accepté !)"), + ): + """Suggère une fonctionnalité directement avec arguments - copy-paste supporté.""" + await interaction.response.send_message("Envoi de votre suggestion à GitLab...", ephemeral=True) + + suggestion_title = titre.strip() if titre else "Sans titre" + description_value = description + + description_text = f"**Sugéré par:** {interaction.user} ({interaction.user.id})\n\n" + description_text += f"**Description:**\n{description_value}" + + labels = ["enhancement", "manual-suggestion"] + + result = await gitlab_client.create_issue( + title=f"[SUGGESTION] {suggestion_title}", + 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=( + "✅ Votre suggestion a été envoyée avec succès ! " + "Merci de contribuer à l'amélioration du bot. " + f"[Voir l'issue]({result.get('web_url')})" + ) + ) + else: + await interaction.edit_original_response( + content="❌ Une erreur est survenue lors de l'envoi de la suggestion à GitLab." + ) def setup(bot): diff --git a/commandes/modules_security/rules.py b/commandes/modules_security/rules.py index 2373eb8..05f0766 100644 --- a/commandes/modules_security/rules.py +++ b/commandes/modules_security/rules.py @@ -8,6 +8,14 @@ from typing import Optional SETTINGS_FILE = "data/security_settings.json" +def escape_mentions(text: str) -> str: + """Échappe les mentions @everyone et @here pour éviter les notifications involontaires""" + if not text: + return text + # Utilise un zero-width space pour briser la mention Discord + return text.replace("@everyone", "@\u200beveryone").replace("@here", "@\u200bhere") + + def load_settings(guild_id: int) -> dict: """Charge les paramètres de sécurité pour un serveur""" if not os.path.exists(SETTINGS_FILE): @@ -95,7 +103,7 @@ class RulesContentModal(disnake.ui.Modal): self.on_update_callback = on_update_callback async def callback(self, interaction: disnake.Interaction): - self.settings["rules_content"] = self.content_input.value + self.settings["rules_content"] = escape_mentions(self.content_input.value) save_settings(self.guild_id, self.settings) if self.on_update_callback: @@ -434,10 +442,11 @@ class RulesCog(commands.Cog): view = RulesAcceptButton(channel.guild.id, accept_role_id) if message_type == "simple": - # Message simple + # Message simple - échappe les mentions @everyone/@here pour éviter les notifications involontaires + safe_content = content.replace("@everyone", "@\u200beveryone").replace("@here", "@\u200bhere") text_message = ( f"📜 **{title}**\n\n" - f"{content}\n\n" + f"{safe_content}\n\n" "Bienvenue ! Pour accéder à l'ensemble des canaux du serveur, " "vous devez accepter le règlement en cliquant sur le bouton ci-dessous.\n\n" "En acceptant, vous confirmez avoir lu et compris les règles du serveur." @@ -455,19 +464,29 @@ class RulesCog(commands.Cog): return None else: # embed + # Échappe les mentions @everyone/@here pour éviter les notifications involontaires + safe_content = content.replace("@everyone", "@\u200beveryone").replace("@here", "@\u200bhere") + + # Utilise un Container avec TextDisplay pour un meilleur rendu du texte (markdown supporté) + components = [ + disnake.ui.Container( + disnake.ui.TextDisplay(safe_content) + ) + ] + # Créer l'embed embed = disnake.Embed( title=title, - description=content, color=0x2b2d31 ) embed.set_footer(text="Cliquez sur le bouton ci-dessous pour accepter le règlement") - # Envoyer seulement l'embed + # Envoyer l'embed avec le container et la view try: message = await channel.send( embed=embed, + components=components, view=view ) return message