fix: stabilisation des boutons de gestion de ticket (Fermer, Réouvrir, Claim) avec defer()

This commit is contained in:
Mathis 2026-03-28 22:17:17 +01:00
parent c8d5bf2c4b
commit 9045b374fa

View file

@ -313,23 +313,23 @@ class TicketStep3(discord.ui.Modal, title="📋 Développement du Personnage"):
except discord.errors.NotFound:
await interaction.followup.send(f"✅ Ticket ouvert : {ticket_channel.mention}", ephemeral=True)
class TicketManagementView(discord.ui.View):
class TicketManagementView(discord.ui.view.View):
"""Vue pour gérer le ticket avec les boutons Fermer, Réouvrir, Claim et Supprimer"""
def __init__(self):
super().__init__(timeout=None)
self.claimed_by = None # Stocke le staff qui claim le ticket
async def get_ticket_owner(self, interaction: discord.Interaction):
"""Récupère le propriétaire du ticket via le topic du salon"""
if interaction.channel.topic and interaction.channel.topic.startswith("Ticket de "):
"""Récupère le propriétaire du ticket via le topic du salon (robuste)"""
if interaction.channel.topic and "Ticket de" in interaction.channel.topic:
try:
owner_id = int(interaction.channel.topic.split("Ticket de ")[1])
user_id_str = interaction.channel.topic.replace("Ticket de ", "").strip()
owner_id = int(user_id_str)
member = interaction.guild.get_member(owner_id)
if not member:
try:
member = await interaction.guild.fetch_member(owner_id)
except discord.NotFound:
except (discord.NotFound, discord.HTTPException):
return None
return member
except (ValueError, IndexError):
@ -339,58 +339,74 @@ class TicketManagementView(discord.ui.View):
@discord.ui.button(label="🔒 Fermer le Ticket", style=discord.ButtonStyle.red, custom_id="close_ticket")
async def close_ticket(self, interaction: discord.Interaction, button: discord.ui.Button):
"""Ferme le ticket en désactivant l'envoi de messages pour le membre"""
await interaction.response.defer(ephemeral=True)
settings = load_settings(interaction.guild.id)
staff_role_id = settings.get("staff_role_id")
if not discord.utils.get(interaction.user.roles, id=int(staff_role_id) if staff_role_id else 0) and not interaction.user.guild_permissions.administrator:
return await interaction.response.send_message("❌ Seuls les staffs peuvent fermer un ticket.", ephemeral=True)
is_staff = any(r.id == int(staff_role_id) for r in interaction.user.roles) if staff_role_id else False
if not is_staff and not interaction.user.guild_permissions.administrator:
return await interaction.followup.send("❌ Seuls les staffs peuvent fermer un ticket.", ephemeral=True)
owner = await self.get_ticket_owner(interaction)
if not owner:
return await interaction.response.send_message("❌ Impossible de trouver le propriétaire du ticket à fermer.", ephemeral=True)
return await interaction.followup.send("❌ Impossible de trouver le propriétaire du ticket à fermer.", ephemeral=True)
await interaction.channel.set_permissions(owner, read_messages=False, send_messages=False)
await interaction.channel.edit(name="ticket-fermé")
await interaction.response.send_message("🔒 Le ticket a été fermé. Vous ne pouvez plus le voir.", ephemeral=True)
try:
await interaction.channel.set_permissions(owner, read_messages=False, send_messages=False)
await interaction.channel.edit(name=f"fermé-{owner.display_name}".replace(" ", "-").lower()[:100])
# Envoi du message de fermeture dans le salon
new_view = ClosedTicketView()
await interaction.channel.send(f"🔒 Ce ticket a été fermé par {interaction.user.mention}.", view=new_view)
await interaction.followup.send("✅ Ticket fermé avec succès.", ephemeral=True)
except Exception as e:
kuby_logger.error(f"Erreur lors de la fermeture du ticket: {e}")
await interaction.followup.send(f"❌ Erreur lors de la fermeture : {e}", ephemeral=True)
# Mettre à jour la vue pour afficher uniquement les boutons Réouvrir et Supprimer
new_view = ClosedTicketView()
await interaction.channel.send("Le ticket a été fermé.", view=new_view)
@discord.ui.button(label="👤 Prendre en charge le Ticket", style=discord.ButtonStyle.blurple, custom_id="claim_ticket")
@discord.ui.button(label="👤 Claim le Ticket", style=discord.ButtonStyle.blurple, custom_id="claim_ticket")
async def claim_ticket(self, interaction: discord.Interaction, button: discord.ui.Button):
"""Un staff prend en charge le ticket"""
await interaction.response.defer(ephemeral=False)
settings = load_settings(interaction.guild.id)
staff_role_id = settings.get("staff_role_id")
if not discord.utils.get(interaction.user.roles, id=int(staff_role_id) if staff_role_id else 0) and not interaction.user.guild_permissions.administrator:
return await interaction.response.send_message("❌ Seuls les staffs peuvent claim un ticket.", ephemeral=True)
staff_role = discord.utils.get(interaction.guild.roles, id=int(staff_role_id)) if staff_role_id else None
claimed_by = interaction.user
if staff_role:
await interaction.channel.set_permissions(staff_role, send_messages=False, read_messages=True)
await interaction.channel.set_permissions(claimed_by, read_messages=True, send_messages=True)
await interaction.response.send_message(f"👤 {claimed_by.mention} a claim ce ticket.", ephemeral=False)
is_staff = any(r.id == int(staff_role_id) for r in interaction.user.roles) if staff_role_id else False
if not is_staff and not interaction.user.guild_permissions.administrator:
return await interaction.followup.send("❌ Seuls les staffs peuvent claim un ticket.")
class ClosedTicketView(discord.ui.View):
try:
staff_role = interaction.guild.get_role(int(staff_role_id)) if staff_role_id else None
# Retrait des permissions du rôle staff pour forcer le claimer à parler seul
if staff_role:
await interaction.channel.set_permissions(staff_role, send_messages=False, read_messages=True)
# Donner les permissions au claimer
await interaction.channel.set_permissions(interaction.user, read_messages=True, send_messages=True)
await interaction.followup.send(f"👥 {interaction.user.mention} a pris en charge ce ticket.")
except Exception as e:
kuby_logger.error(f"Erreur lors du claim du ticket: {e}")
await interaction.followup.send(f"❌ Erreur lors du claim : {e}")
class ClosedTicketView(discord.ui.view.View):
"""Vue pour les tickets fermés avec les boutons Réouvrir et Supprimer"""
def __init__(self):
super().__init__(timeout=None)
async def get_ticket_owner(self, interaction: discord.Interaction):
"""Récupère le propriétaire du ticket via le topic du salon"""
if interaction.channel.topic and interaction.channel.topic.startswith("Ticket de "):
"""Récupère le propriétaire du ticket via le topic du salon (robuste)"""
if interaction.channel.topic and "Ticket de" in interaction.channel.topic:
try:
owner_id = int(interaction.channel.topic.split("Ticket de ")[1])
user_id_str = interaction.channel.topic.replace("Ticket de ", "").strip()
owner_id = int(user_id_str)
member = interaction.guild.get_member(owner_id)
if not member:
try:
member = await interaction.guild.fetch_member(owner_id)
except discord.NotFound:
except (discord.NotFound, discord.HTTPException):
return None
return member
except (ValueError, IndexError):
@ -400,34 +416,60 @@ class ClosedTicketView(discord.ui.View):
@discord.ui.button(label="♻ Réouvrir le Ticket", style=discord.ButtonStyle.green, custom_id="reopen_ticket")
async def reopen_ticket(self, interaction: discord.Interaction, button: discord.ui.Button):
"""Réouvre le ticket pour le membre"""
await interaction.response.defer(ephemeral=True)
settings = load_settings(interaction.guild.id)
staff_role_id = settings.get("staff_role_id")
if not discord.utils.get(interaction.user.roles, id=int(staff_role_id) if staff_role_id else 0) and not interaction.user.guild_permissions.administrator:
return await interaction.response.send_message("❌ Seuls les staffs peuvent réouvrir un ticket.", ephemeral=True)
is_staff = any(r.id == int(staff_role_id) for r in interaction.user.roles) if staff_role_id else False
if not is_staff and not interaction.user.guild_permissions.administrator:
return await interaction.followup.send("❌ Seuls les staffs peuvent réouvrir un ticket.", ephemeral=True)
owner = await self.get_ticket_owner(interaction)
if not owner:
return await interaction.response.send_message("❌ Impossible de trouver le propriétaire du ticket à réouvrir.", ephemeral=True)
return await interaction.followup.send("❌ Impossible de trouver le propriétaire du ticket à réouvrir.", ephemeral=True)
await interaction.channel.set_permissions(owner, read_messages=True, send_messages=True)
await interaction.response.send_message("✅ Le ticket a été réouvert.", ephemeral=True)
# Mettre à jour la vue pour afficher tous les boutons
new_view = TicketManagementView()
await interaction.channel.send("Le ticket a été réouvert.", view=new_view)
try:
await interaction.channel.set_permissions(owner, read_messages=True, send_messages=True)
# Rétablir le nom original en se basant sur la validation
citoyen_role_id = settings.get("citoyen_role_id")
attente_oral_role_id = settings.get("attente_oral_role_id")
prefix = "ouvert"
if citoyen_role_id and any(r.id == int(citoyen_role_id) for r in owner.roles):
prefix = "accepté"
elif attente_oral_role_id and any(r.id == int(attente_oral_role_id) for r in owner.roles):
prefix = "oral-à-faire"
await interaction.channel.edit(name=f"{prefix}-{owner.display_name}".replace(" ", "-").lower()[:100])
new_view = TicketManagementView()
await interaction.channel.send(f"✅ Ticket réouvert par {interaction.user.mention}.", view=new_view)
await interaction.followup.send("✅ Ticket réouvert.", ephemeral=True)
except Exception as e:
kuby_logger.error(f"Erreur lors de la réouverture du ticket: {e}")
await interaction.followup.send(f"❌ Erreur lors de la réouverture : {e}", ephemeral=True)
@discord.ui.button(label="❌ Supprimer le Ticket", style=discord.ButtonStyle.danger, custom_id="delete_ticket")
async def delete_ticket(self, interaction: discord.Interaction, button: discord.ui.Button):
"""Supprime le salon du ticket"""
await interaction.response.defer(ephemeral=True)
settings = load_settings(interaction.guild.id)
staff_role_id = settings.get("staff_role_id")
if not discord.utils.get(interaction.user.roles, id=int(staff_role_id) if staff_role_id else 0) and not interaction.user.guild_permissions.administrator:
return await interaction.response.send_message("❌ Seuls les staffs peuvent supprimer un ticket.", ephemeral=True)
is_staff = any(r.id == int(staff_role_id) for r in interaction.user.roles) if staff_role_id else False
if not is_staff and not interaction.user.guild_permissions.administrator:
return await interaction.followup.send("❌ Seuls les staffs peuvent supprimer un ticket.", ephemeral=True)
await interaction.response.send_message("❌ Suppression du ticket...", ephemeral=True)
await interaction.channel.delete()
try:
await interaction.followup.send("❌ Suppression du ticket...", ephemeral=True)
await interaction.channel.delete()
except Exception as e:
kuby_logger.error(f"Erreur lors de la suppression du ticket: {e}")
try: await interaction.followup.send(f"❌ Erreur lors de la suppression : {e}", ephemeral=True)
except: pass
class TicketView(discord.ui.View):
"""Vue avec le bouton pour ouvrir le ticket"""