Merge branch 'main' into 'dev'

# Conflicts:
#   commandes/ticket/__init__.py
This commit is contained in:
Gameur 2026-05-31 12:25:01 +02:00
commit 9f92d0d212
8 changed files with 761 additions and 149 deletions

View file

@ -35,16 +35,7 @@ def save_report(issue_iid, user_id):
class BugReportModal(disnake.ui.Modal):
def __init__(self, priority_choice):
if priority_choice is None:
self.priority_choice = type(
"PriorityChoice",
(),
{"name": "Normal", "value": "Normal"},
)()
else:
self.priority_choice = priority_choice
def __init__(self):
super().__init__(
title="Signaler un Bug",
components=[
@ -58,11 +49,11 @@ class BugReportModal(disnake.ui.Modal):
disnake.ui.TextInput(
label="Description détaillée",
style=disnake.TextInputStyle.paragraph,
placeholder="Que s'est-il passé ? Comment reproduire le bug ?",
placeholder="Que s'est-il passé ?",
custom_id="bug_description",
required=True,
max_length=1000,
)
),
]
)
@ -73,8 +64,8 @@ class BugReportModal(disnake.ui.Modal):
if not bug_title:
bug_title = "Sans titre"
priority_name = getattr(self.priority_choice, "name", None) or "Normal"
priority_value = getattr(self.priority_choice, "value", None) or "Normal"
priority_name = "Normale"
priority_value = "Normal"
description_value = interaction.text_values.get("bug_description") or ""
@ -106,6 +97,16 @@ class BugReportModal(disnake.ui.Modal):
)
class BugReportView(disnake.ui.View):
def __init__(self):
super().__init__(timeout=None)
@disnake.ui.button(label="🎫 Remplir le formulaire", style=disnake.ButtonStyle.primary, custom_id="open_bug_form")
async def open_bug_form(self, button: disnake.ui.Button, interaction: disnake.MessageInteraction):
modal = BugReportModal()
await interaction.response.send_modal(modal)
class FeatureSuggestionModal(disnake.ui.Modal):
def __init__(self):
super().__init__(
@ -135,7 +136,7 @@ class FeatureSuggestionModal(disnake.ui.Modal):
suggestion_title = (interaction.text_values.get("suggestion_title") or "").strip() or "Sans titre"
description_value = interaction.text_values.get("suggestion_description") or ""
description_text = f"**Suggéré par:** {interaction.user} ({interaction.user.id})\n\n"
description_text = f"**Sugéré par:** {interaction.user} ({interaction.user.id})\n\n"
description_text += f"**Description:**\n{description_value}"
labels = ["enhancement", "manual-suggestion"]
@ -162,6 +163,16 @@ class FeatureSuggestionModal(disnake.ui.Modal):
)
class FeatureSuggestionView(disnake.ui.View):
def __init__(self):
super().__init__(timeout=None)
@disnake.ui.button(label="🎫 Remplir le formulaire", style=disnake.ButtonStyle.green, custom_id="open_suggestion_form")
async def open_suggestion_form(self, button: disnake.ui.Button, interaction: disnake.MessageInteraction):
modal = FeatureSuggestionModal()
await interaction.response.send_modal(modal)
class BugReport(commands.Cog):
def __init__(self, bot):
self.bot = bot
@ -252,7 +263,7 @@ class BugReport(commands.Cog):
note_obj_attrs = payload.get("object_attributes") or {}
kuby_logger.info(
f"[GitLab note] system={note_obj_attrs.get('system', False)} "
f"note_len={len(str(note_obj_attrs.get('note') or note_obj_attrs.get('body') or payload.get('note') or ''))}"
f"note_len={len(str(note_obj_attrs.get('note') or note_obj_attrs.get('body') or payload.get('note') or ''))}"
)
app_info = await self.bot.application_info()
@ -300,11 +311,10 @@ class BugReport(commands.Cog):
f"**{current_labels_str}** pour l'issue #{issue_iid} ({issue_title})."
)
except (disnake.Forbidden, disnake.HTTPException) as e:
if isinstance(e, disnake.Forbidden) or (
isinstance(e, disnake.HTTPException) and e.code == 50007
):
error_code = getattr(e, 'code', None)
if isinstance(e, disnake.Forbidden) or error_code == 50007:
kuby_logger.warning(
f"Impossible d'envoyer un MP à {user} ({user.id}) - MPs désactivés (Code: {getattr(e, 'code', 'Unknown')})"
f"Impossible d'envoyer un MP à {user} ({user.id}) - MPs désactivés (Code: {error_code})"
)
if dev and dev.id != user.id:
await dev.send(
@ -312,8 +322,6 @@ class BugReport(commands.Cog):
)
else:
kuby_logger.error(f"Erreur HTTP lors de l'envoi du MP de statut à {user}: {e}")
except Exception as e:
kuby_logger.error(f"Erreur lors de l'envoi du MP de statut à {user}: {e}")
except Exception as e:
kuby_logger.error(f"Erreur inattendue dans la notification de label : {e}")
@ -343,18 +351,15 @@ class BugReport(commands.Cog):
f"✅ [SUIVI] L'utilisateur {user} ({user.id}) a bien reçu la notification de CLÔTURE pour l'issue #{issue_iid}."
)
except (disnake.Forbidden, disnake.HTTPException) as e:
if isinstance(e, disnake.Forbidden) or (
isinstance(e, disnake.HTTPException) and e.code == 50007
):
kuby_logger.warning(f"Impossible d'envoyer le MP de clôture à {user} ({user.id}).")
error_code = getattr(e, 'code', None)
if isinstance(e, disnake.Forbidden) or error_code == 50007:
kuby_logger.warning(f"Impossible d'envoyer le MP de clôture à {user} ({user.id}) - MPs désactivés.")
if dev and dev.id != user.id:
await dev.send(
f"⚠️ [DM BLOQUÉ] Impossible d'annoncer la clôture à {user} ({user.id}) pour l'issue #{issue_iid} (DMs désactivés)."
f"⚠️ [DM BLOQUÉ] Impossible d'annoncer la clôture à {user} ({user.id}) pour l'issue #{issue_iid}."
)
else:
kuby_logger.error(f"Erreur HTTP lors de l'envoi du MP de clôture à {user}: {e}")
except Exception as e:
kuby_logger.error(f"Erreur lors de l'envoi du MP de clôture à {user}: {e}")
except Exception as e:
kuby_logger.error(f"Erreur inattendue dans la notification de clôture : {e}")
@ -400,9 +405,12 @@ class BugReport(commands.Cog):
)
except (disnake.Forbidden, disnake.HTTPException):
if dev and dev.id != user.id:
await dev.send(
f"⚠️ [DM BLOQUÉ] Impossible d'envoyer votre commentaire à {user} ({user.id}) pour l'issue #{issue_iid} (DMs désactivés)."
)
try:
await dev.send(
f"⚠️ [DM BLOQUÉ] Impossible d'envoyer votre commentaire à {user} ({user.id}) pour l'issue #{issue_iid} (DMs désactivés)."
)
except (disnake.Forbidden, disnake.HTTPException):
pass # On ne peut pas envoyer au dev non plus, on abandonne
except Exception as e:
kuby_logger.error(
f"Erreur inattendue dans la notification de commentaire : {e}",
@ -419,31 +427,19 @@ class BugReport(commands.Cog):
name="signaler_bug",
description="Signaler un bug aux développeurs",
)
async def signaler_bug(
self,
interaction: disnake.ApplicationCommandInteraction,
priority: str = commands.Param(
description="Priorité du bug",
choices={"Basse": "Low", "Normale": "Normal", "Haute": "High", "Urgente": "Urgent"},
),
):
from collections import namedtuple
Choice = namedtuple('Choice', ['name', 'value'])
mapping = {"Basse": "Low", "Normale": "Normal", "Haute": "High", "Urgente": "Urgent"}
reverse = {v: k for k, v in mapping.items()}
p_name = reverse.get(priority, "Normal")
choice = Choice(name=p_name, value=priority)
await interaction.response.send_modal(BugReportModal(choice))
async def signifier_bug(self, interaction: disnake.ApplicationCommandInteraction):
"""Ouvre un formulaire pour signaler un bug."""
modal = BugReportModal()
await interaction.response.send_modal(modal)
@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())
"""Ouvre un formulaire pour suggérer une fonctionnalité."""
modal = FeatureSuggestionModal()
await interaction.response.send_modal(modal)
def setup(bot):