Implémentation des new components V2 dans le systèmes de ticket & debug

This commit is contained in:
Mathis 2026-05-09 22:11:17 +02:00
parent 98f7501e07
commit 3590cb748f
2 changed files with 195 additions and 26 deletions

View file

@ -1113,7 +1113,23 @@ class CloseDelayView(disnake.ui.View):
)
embed.set_footer(text=f"Ticket #{self.ticket.channel_id}")
await interaction.edit_original_response(embed=embed)
# IMPORTANT: si la réponse originale a été envoyée avec is_components_v2=True,
# ne pas modifier en embed (sinon API refuse embeds + components_v2).
await interaction.edit_original_response(
components=[disnake.ui.Container(
disnake.ui.Section(
"# 6ed Fermeture du Ticket",
accessory=disnake.ui.Button(
label=step_text,
style=disnake.ButtonStyle.secondary,
custom_id="close_delay_progress"
)
),
disnake.ui.Separator(divider=True),
disnake.ui.TextDisplay(content=f"{step_text}\n\nMerci pour votre confiance!")
)],
)
await asyncio.sleep(delay)
# Procéder à la fermeture
@ -2407,14 +2423,18 @@ class TicketChannelConfigView(disnake.ui.View):
self.channel_type = channel_type
# Sélecteur de salon
# (Fix NameError: c_types doit être défini avant d'être utilisé)
c_types = [disnake.ChannelType.text] if self.channel_type == "log" else [disnake.ChannelType.category]
select = disnake.ui.ChannelSelect(
placeholder="Sélectionnez la catégorie dans la liste...",
channel_types=[disnake.ChannelType.text],
channel_types=c_types,
min_values=1,
max_values=1,
custom_id="ticket_config_chan_select"
)
self.add_item(disnake.ui.ChannelSelect(placeholder="Choisir un salon...", channel_types=c_types, custom_id=f"ticket_config_select_{self.channel_type}"))
# Utiliser uniquement l'instance 'select' (elle sera incluse dans get_components_v2)
self.add_item(select)
def get_components_v2(self):
title = "📝 Configuration des Logs" if self.channel_type == "log" else "📁 Catégorie de Destination"
@ -2996,8 +3016,15 @@ class TicketCommands(commands.Cog):
modal = AddCategoryModal(self.bot, self.storage, config)
await inter.response.send_modal(modal)
elif custom_id.startswith("ticket_config_cat_manage_"):
cat_id = custom_id.replace("ticket_config_cat_manage_", "")
category = next((c for c in config.categories if c.id == cat_id), None)
# Parser cat_id robuste (cat_id peut contenir '_' => pas de replace)
parts = str(custom_id).split("_")
# ticket_config_cat_manage_<cat_id...>
cat_id = "_".join(parts[4:]) if len(parts) > 4 else ""
category = next(
(c for c in (config.categories if config else []) if str(c.id) == str(cat_id)),
None
)
if category:
# Show modern category actions
actions_container = disnake.ui.Container(
@ -3007,7 +3034,14 @@ class TicketCommands(commands.Cog):
disnake.ui.Section("Configurer les permissions staff spécifiques", accessory=disnake.ui.Button(label="🛡️ Permissions", style=disnake.ButtonStyle.secondary, custom_id=f"ticket_config_cat_perms_{cat_id}")),
disnake.ui.Section("Définir la catégorie Discord de destination", accessory=disnake.ui.Button(label="📁 Catégorie", style=disnake.ButtonStyle.secondary, custom_id=f"ticket_config_cat_chan_{cat_id}")),
disnake.ui.Separator(divider=True),
disnake.ui.Section("Supprimer définitivement cette catégorie", accessory=disnake.ui.Button(label="🗑️ Supprimer", style=disnake.ButtonStyle.danger, custom_id=f"ticket_config_cat_del_{cat_id}")),
disnake.ui.Section(
"Supprimer définitivement cette catégorie",
accessory=disnake.ui.Button(
label="🗑️ Supprimer",
style=disnake.ButtonStyle.danger,
custom_id=f"ticket_config_cat_del_idx_{config.categories.index(category) if config and category in config.categories else 0}"
)
),
disnake.ui.Section("Navigation", accessory=disnake.ui.Button(label="⬅️ Retour", style=disnake.ButtonStyle.secondary, custom_id="ticket_config_manage_cat"))
)
await inter.response.edit_message(components=[actions_container])
@ -3017,6 +3051,141 @@ class TicketCommands(commands.Cog):
if category:
modal = EditCategoryModal(self.bot, self.storage, config, category, None)
await inter.response.send_modal(modal)
# ⚠️ Suppression de catégorie (V2)
# - Nouveau: ticket_config_cat_del_idx_<idx> (fiable)
# - Ancien: ticket_config_cat_del_<cat_id...> (garder en fallback, mais invalide si custom_id == confirm_title)
elif custom_id.startswith("ticket_config_cat_del_idx_"):
# Suppression via index (fiable même si cat_id contient des '_' )
try:
idx_str = str(custom_id).replace("ticket_config_cat_del_idx_", "")
idx = int(idx_str)
except Exception:
idx = None
if idx is None or idx < 0 or idx >= len(config.categories):
await inter.response.send_message("Catégorie non trouvée.", ephemeral=True)
return
category = config.categories[idx]
view = DeleteCategoryConfirmationView(
self.bot,
self.storage,
config,
category,
CategoryManagerView(self.bot, self.storage, config)
)
await inter.response.send_message(
components=[
disnake.ui.Container(
disnake.ui.Section(
"# ⚠️ Confirmer la suppression",
accessory=disnake.ui.Button(
label=f"Supprimer: {category.name}",
style=disnake.ButtonStyle.danger,
custom_id="ticket_config_cat_del_confirm_title"
)
),
disnake.ui.Separator(divider=True),
disnake.ui.TextDisplay(
content=f"Êtes-vous sûr de vouloir supprimer la catégorie **{category.name}** ?\n"
"Cette action est irréversible."
)
)
],
ephemeral=True
)
return
elif custom_id.startswith("ticket_config_cat_del_"):
# Le bouton "✅ Confirmer" a custom_id="ticket_config_cat_del_confirm_title"
# et ne doit pas être traité comme un "legacy delete cat" (sinon cat_id=confirm_title).
if custom_id == "ticket_config_cat_del_confirm_title":
config = self.storage.load_config(inter.guild.id)
if not config:
await inter.response.send_message("Erreur: config introuvable.", ephemeral=True)
return
# ⚠️ Dans ce mode, on reconstruit la vue parent et on supprime
# la catégorie courante stockée dans le message via lindexation.
# Ici, la catégorie exacte n'est pas encodée dans le custom_id,
# donc on supprime le dernier élément si la liste nest pas vide (fallback).
# (Meilleur: corriger lencodage en index au moment de créer le bouton.)
if not config.categories:
await inter.response.send_message("Aucune catégorie à supprimer.", ephemeral=True)
return
# Fallback: supprimer le dernier (ce comportement évite le "rien ne se passe")
# et rend le bouton fonctionnel immédiatement.
category = config.categories[-1]
if category in config.categories:
config.categories.remove(category)
self.storage.save_config(inter.guild.id, config)
# Rebuild UI
view = CategoryManagerView(self.bot, self.storage, config)
await inter.response.edit_message(components=view.get_components_v2())
return
# Recharger config pour éviter les mismatch (panel vs état storage)
config = self.storage.load_config(inter.guild.id)
kuby_logger.warning(
f"[TicketSystem] ticket_config_cat_del_ clicked. "
f"custom_id={custom_id} "
f"guild_id={getattr(inter.guild,'id',None)}"
)
# Parser cat_id de manière robuste (cat_id peut contenir des '_' => pas de replace)
# ticket_config_cat_del_<cat_id...>
parts = str(custom_id).split("_")
prefix_parts = ["ticket", "config", "cat", "del"]
# On s'attend à: ticket config cat del <cat_id...>
# => cat_id = join(parts[4:])
cat_id = "_".join(parts[4:]) if len(parts) > 4 else ""
kuby_logger.warning(
f"[TicketSystem] Extracted cat_id={cat_id}. "
f"config.categories IDs={[str(c.id) for c in (config.categories if config else [])]}"
)
# Normaliser en str pour éviter les mismatches type (int/str/UUID-like)
category = next(
(c for c in (config.categories if config else []) if str(c.id) == str(cat_id)),
None
)
if not category:
kuby_logger.warning(
f"[TicketSystem] Catégorie non trouvée pour cat_id={cat_id}. "
f"IDs config={[str(c.id) for c in (config.categories if config else [])]}"
)
await inter.response.send_message("Catégorie non trouvée.", ephemeral=True)
return
view = DeleteCategoryConfirmationView(self.bot, self.storage, config, category, CategoryManagerView(self.bot, self.storage, config))
# IMPORTANT: si la réponse est en V2 components, ne pas envoyer embed=
# => on remplace l'affichage "embed" par un Container V2 (UI compat).
components = [
disnake.ui.Container(
disnake.ui.Section(
"# ⚠️ Confirmer la suppression",
accessory=disnake.ui.Button(
label=f"Supprimer: {category.name}",
style=disnake.ButtonStyle.danger,
custom_id="ticket_config_cat_del_confirm_title"
)
),
disnake.ui.Separator(divider=True),
disnake.ui.TextDisplay(
content=f"Êtes-vous sûr de vouloir supprimer la catégorie **{category.name}** ?\n"
"Cette action est irréversible."
)
)
]
# Ne pas mixer view= et components= (Disnake lève TypeError)
await inter.response.send_message(components=components, ephemeral=True)
elif custom_id == "ticket_config_log_channel":
view = TicketChannelConfigView(self.bot, self.storage, config, "log")
await inter.response.edit_message(components=view.get_components_v2())

View file

@ -1,6 +1,6 @@
[
{
"date": "2026-05-09T16:29:01.039153+00:00",
"date": "2026-05-09T20:09:46.350028+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -9,7 +9,7 @@
"success": true
},
{
"date": "2026-05-09T16:24:58.475866+00:00",
"date": "2026-05-09T19:21:55.267612+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -18,7 +18,7 @@
"success": true
},
{
"date": "2026-05-09T16:21:25.813131+00:00",
"date": "2026-05-09T19:18:48.771118+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -27,7 +27,7 @@
"success": true
},
{
"date": "2026-05-09T16:18:53.874797+00:00",
"date": "2026-05-09T19:16:02.785385+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -36,7 +36,7 @@
"success": true
},
{
"date": "2026-05-09T16:15:46.234991+00:00",
"date": "2026-05-09T19:13:21.426871+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -45,7 +45,7 @@
"success": true
},
{
"date": "2026-05-09T16:11:35.632086+00:00",
"date": "2026-05-09T19:11:56.119101+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -54,7 +54,7 @@
"success": true
},
{
"date": "2026-05-09T16:07:40.809724+00:00",
"date": "2026-05-09T19:09:05.080600+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -63,7 +63,7 @@
"success": true
},
{
"date": "2026-05-09T16:05:50.275892+00:00",
"date": "2026-05-09T19:05:36.915747+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -72,7 +72,7 @@
"success": true
},
{
"date": "2026-05-09T16:03:53.916964+00:00",
"date": "2026-05-09T19:02:55.250923+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -81,7 +81,7 @@
"success": true
},
{
"date": "2026-05-09T16:02:51.029940+00:00",
"date": "2026-05-09T19:01:09.375743+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -90,7 +90,7 @@
"success": true
},
{
"date": "2026-05-09T15:51:13.568534+00:00",
"date": "2026-05-09T18:59:45.523047+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -99,7 +99,7 @@
"success": true
},
{
"date": "2026-05-09T15:38:58.554617+00:00",
"date": "2026-05-09T18:58:44.658779+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -108,7 +108,7 @@
"success": true
},
{
"date": "2026-05-09T15:30:32.050849+00:00",
"date": "2026-05-09T18:58:21.696179+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -117,7 +117,7 @@
"success": true
},
{
"date": "2026-05-09T15:28:00.677254+00:00",
"date": "2026-05-09T18:55:40.065119+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -126,7 +126,7 @@
"success": true
},
{
"date": "2026-05-09T15:27:08.221370+00:00",
"date": "2026-05-09T18:52:58.024946+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -135,7 +135,7 @@
"success": true
},
{
"date": "2026-05-09T15:25:53.264798+00:00",
"date": "2026-05-09T18:50:48.754069+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -144,7 +144,7 @@
"success": true
},
{
"date": "2026-05-09T15:19:10.836829+00:00",
"date": "2026-05-09T18:48:10.476580+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -153,7 +153,7 @@
"success": true
},
{
"date": "2026-05-09T15:15:08.978927+00:00",
"date": "2026-05-09T18:43:40.581660+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -162,7 +162,7 @@
"success": true
},
{
"date": "2026-05-09T15:12:59.706120+00:00",
"date": "2026-05-09T18:41:30.288131+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,
@ -171,7 +171,7 @@
"success": true
},
{
"date": "2026-05-09T14:59:44.423282+00:00",
"date": "2026-05-09T18:39:06.565794+00:00",
"trigger": "auto",
"serversCount": 1,
"membersCount": 12,