import discord from discord.ext import commands from discord import app_commands TICKET_CATEGORY_ID = 1450001640127205388 # ID de la catégorie des tickets STAFF_ROLE_ID = 1454042474141192316 # ID du rôle staff TEAM_STAFF_ROLE_ID = 1454042474141192316 # ID du rôle équipe staff ATTENTE_ORAL_ROLE_ID = 11464424211442307279 # ID du rôle "attente oral" CANDIDATURE_A_FAIRE_ROLE_ID = 1464428034906919038 # ID du rôle "candidature à faire" CITOYEN_ROLE_ID = 1453708386674806835 # ID du rôle "citoyen" class ContinueFormView(discord.ui.View): """Vue avec un bouton pour continuer à l'étape suivante""" def __init__(self, current_step, step1_data=None, step2_part1_data=None, step2_part2_data=None): super().__init__(timeout=180.0) # Définir un timeout pour la vue self.current_step = current_step self.step1_data = step1_data self.step2_part1_data = step2_part1_data self.step2_part2_data = step2_part2_data @discord.ui.button(label="📋 Continuer le formulaire", style=discord.ButtonStyle.green, custom_id="continue_form") async def continue_form(self, interaction: discord.Interaction, button: discord.ui.Button): """Passe à l'étape suivante du formulaire""" if self.current_step == 1: await interaction.response.send_modal(TicketStep2Part1(self.step1_data)) elif self.current_step == 2: await interaction.response.send_modal(TicketStep2Part2(self.step1_data, self.step2_part1_data)) elif self.current_step == 3: await interaction.response.send_modal(TicketStep3(self.step1_data, self.step2_part1_data, self.step2_part2_data)) # Vérifier si le message existe toujours avant de le modifier try: await interaction.message.edit(view=self) except discord.errors.NotFound: # Si le message n'existe plus, nous ne faisons rien pass class TicketStep1(discord.ui.Modal, title="📋 Informations Personnelles"): """Étape 1 du formulaire - Infos personnelles""" pseudo = discord.ui.TextInput(label="Pseudo Epic (Fortnite)", required=True, max_length=16) age = discord.ui.TextInput(label="Âge", required=True, max_length=2) experience = discord.ui.TextInput(label="Expérience RP ?", style=discord.TextStyle.paragraph, required=True, max_length=50) decouverte = discord.ui.TextInput(label="Comment as-tu découvert le serveur ?", required=True, max_length=20) micro = discord.ui.TextInput(label="As-tu un micro de qualité ?", required=True, max_length=3) async def on_submit(self, interaction: discord.Interaction): """Envoie un bouton pour passer à l'étape 2""" view = ContinueFormView(current_step=1, step1_data=self) await interaction.response.send_message("✅ Première étape terminée ! Cliquez ci-dessous pour continuer.", view=view, ephemeral=True) class TicketStep2Part1(discord.ui.Modal, title="👤 Infos sur ton personnage (Partie 1)"): """Étape 2 du formulaire - Infos RP (Partie 1)""" def __init__(self, step1_data): super().__init__() self.step1_data = step1_data prenom = discord.ui.TextInput(label="Prénom", required=True) nom = discord.ui.TextInput(label="Nom", required=True) age_perso = discord.ui.TextInput(label="Âge du personnage", required=True) genre = discord.ui.TextInput(label="Genre", required=True, max_length=5) naissance = discord.ui.TextInput(label="Date et lieu de naissance", required=True) async def on_submit(self, interaction: discord.Interaction): """Envoie un bouton pour passer à l'étape suivante""" view = ContinueFormView(current_step=2, step1_data=self.step1_data, step2_part1_data=self) await interaction.response.send_message("✅ Deuxième partie terminée ! Cliquez ci-dessous pour continuer.", view=view, ephemeral=True) class TicketStep2Part2(discord.ui.Modal, title="👤 Infos sur ton personnage (Partie 2)"): """Étape 2 du formulaire - Infos RP (Partie 2)""" def __init__(self, step1_data, step2_part1_data): super().__init__() self.step1_data = step1_data self.step2_part1_data = step2_part1_data traits = discord.ui.TextInput(label="Traits de caractère", required=True) nationalite = discord.ui.TextInput(label="Nationalité", required=True) skin_rp = discord.ui.TextInput(label="Skin RP", required=True) metier_souhaite = discord.ui.TextInput(label="Métier souhaité", required=True) async def on_submit(self, interaction: discord.Interaction): """Envoie un bouton pour passer à l'étape 3""" view = ContinueFormView(current_step=3, step1_data=self.step1_data, step2_part1_data=self.step2_part1_data, step2_part2_data=self) await interaction.response.send_message("✅ Deuxième étape terminée ! Cliquez ci-dessous pour continuer.", view=view, ephemeral=True) class TicketStep3(discord.ui.Modal, title="📋 Développement du Personnage"): """Étape 3 du formulaire - Histoire du personnage""" def __init__(self, step1_data, step2_part1_data, step2_part2_data): super().__init__() self.step1_data = step1_data self.step2_part1_data = step2_part1_data self.step2_part2_data = step2_part2_data histoire = discord.ui.TextInput( label="Histoire du personnage", style=discord.TextStyle.paragraph, required=True, min_length=425, max_length=500 # Limite de caractères maximum ) objectifs = discord.ui.TextInput(label="Objectifs RP (court et long terme)", style=discord.TextStyle.paragraph, required=True, max_length=100) async def on_submit(self, interaction: discord.Interaction): """Création du ticket après validation""" guild = interaction.guild user = interaction.user category = discord.utils.get(guild.categories, id=TICKET_CATEGORY_ID) # Vérifier si la catégorie existe if category is None: await interaction.response.send_message("❌ Erreur : La catégorie des tickets n'existe pas !", ephemeral=True) return # Vérifier si le rôle staff existe staff_role = discord.utils.get(guild.roles, id=STAFF_ROLE_ID) if staff_role is None: await interaction.response.send_message("❌ Erreur : Le rôle staff n'existe pas !", ephemeral=True) return # Vérifier si l'utilisateur a déjà un ticket ouvert for channel in category.text_channels: if channel.topic == f"Ticket de {user.id}": await interaction.response.send_message(f"❌ Vous avez déjà un ticket ouvert : {channel.mention}", ephemeral=True) return # Définir les permissions du salon du ticket overwrites = { guild.default_role: discord.PermissionOverwrite(read_messages=False), user: discord.PermissionOverwrite(read_messages=True, send_messages=True), staff_role: discord.PermissionOverwrite(read_messages=True, send_messages=True), discord.utils.get(guild.roles, id=TEAM_STAFF_ROLE_ID): discord.PermissionOverwrite(read_messages=True, send_messages=False) } # Créer un salon de ticket avec le nom [pseudo_du_membre]-écrit ticket_channel = await category.create_text_channel( name=f"{user.name}-écrit", topic=f"Ticket de {user.id}", overwrites=overwrites ) # Récupérer le rôle "équipe staff" team_staff_role = discord.utils.get(guild.roles, id=TEAM_STAFF_ROLE_ID) # Création de l'embed avec les infos du formulaire embed = discord.Embed(title="📩 Ticket Whitelist", color=0x00ff00) embed.add_field(name="📋 - Informations Personnelles", value=( f"> - Pseudo Epic : {self.step1_data.pseudo.value}\n" f"> - Âge : {self.step1_data.age.value}\n" f"> - Expérience RP : {self.step1_data.experience.value}\n" f"> - Découverte du serveur : {self.step1_data.decouverte.value}\n" f"> - Micro de qualité : {self.step1_data.micro.value}" ), inline=False) embed.add_field(name="👤 - Informations RP", value=( f"> - Prénom : {self.step2_part1_data.prenom.value}\n" f"> - Nom : {self.step2_part1_data.nom.value}\n" f"> - Âge du personnage : {self.step2_part1_data.age_perso.value}\n" f"> - Genre : {self.step2_part1_data.genre.value}\n" f"> - Naissance : {self.step2_part1_data.naissance.value}\n" f"> - Traits de caractère : {self.step2_part2_data.traits.value}\n" f"> - Nationalité : {self.step2_part2_data.nationalite.value}\n" f"> - Skin RP : {self.step2_part2_data.skin_rp.value}\n" f"> - Métier souhaité : {self.step2_part2_data.metier_souhaite.value}" ), inline=False) embed.add_field(name="📋 - Développement du Personnage", value=( f"> - Histoire : {self.histoire.value}\n" f"> - Objectifs : {self.objectifs.value}" ), inline=False) # Envoyer l'embed avec les boutons d'actions pour les staff await ticket_channel.send(embed=embed, view=TicketManagementView(user)) # Envoyer un message pour mentionner l'équipe staff await ticket_channel.send(f"{team_staff_role.mention} - Nouveau ticket créé !") # Mettre à jour le pseudo du joueur si le bot a les permissions nécessaires if guild.me.guild_permissions.manage_nicknames: new_nickname = f"{self.step2_part1_data.prenom.value} {self.step2_part1_data.nom.value} | {self.step1_data.pseudo.value}" if len(new_nickname) > 32: new_nickname = new_nickname[:32] await user.edit(nick=new_nickname) else: await interaction.followup.send("❌ Le bot n'a pas les permissions nécessaires pour modifier le pseudo.", ephemeral=True) # Envoyer un message de confirmation try: await interaction.response.send_message(f"✅ Ticket ouvert : {ticket_channel.mention}", ephemeral=True) except discord.errors.NotFound: await interaction.followup.send(f"✅ Ticket ouvert : {ticket_channel.mention}", ephemeral=True) class TicketManagementView(discord.ui.View): """Vue pour gérer le ticket avec les boutons Fermer, Réouvrir, Claim et Supprimer""" def __init__(self, ticket_owner): super().__init__(timeout=None) self.ticket_owner = ticket_owner self.claimed_by = None # Stocke le staff qui claim le ticket @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""" if not discord.utils.get(interaction.user.roles, id=STAFF_ROLE_ID): await interaction.response.send_message("❌ Seuls les staffs peuvent fermer un ticket.", ephemeral=True) return await interaction.channel.set_permissions(self.ticket_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) # Mettre à jour la vue pour afficher uniquement les boutons Réouvrir et Supprimer new_view = ClosedTicketView(self.ticket_owner) 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") async def claim_ticket(self, interaction: discord.Interaction, button: discord.ui.Button): """Un staff prend en charge le ticket""" if not discord.utils.get(interaction.user.roles, id=STAFF_ROLE_ID): await interaction.response.send_message("❌ Seuls les staffs peuvent claim un ticket.", ephemeral=True) return self.claimed_by = interaction.user await interaction.channel.set_permissions(discord.utils.get(interaction.guild.roles, id=STAFF_ROLE_ID), send_messages=False, read_messages=True) await interaction.channel.set_permissions(self.claimed_by, read_messages=True, send_messages=True) await interaction.response.send_message(f"👤 {self.claimed_by.mention} a claim ce ticket.", ephemeral=False) class ClosedTicketView(discord.ui.View): """Vue pour les tickets fermés avec les boutons Réouvrir et Supprimer""" def __init__(self, ticket_owner): super().__init__(timeout=None) self.ticket_owner = ticket_owner @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""" if not discord.utils.get(interaction.user.roles, id=STAFF_ROLE_ID): await interaction.response.send_message("❌ Seuls les staffs peuvent réouvrir un ticket.", ephemeral=True) return await interaction.channel.set_permissions(self.ticket_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(self.ticket_owner) await interaction.channel.send("Le ticket a été réouvert.", view=new_view) @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""" if not discord.utils.get(interaction.user.roles, id=STAFF_ROLE_ID): await interaction.response.send_message("❌ Seuls les staffs peuvent supprimer un ticket.", ephemeral=True) return await interaction.response.send_message("❌ Suppression du ticket...", ephemeral=True) await interaction.channel.delete() class TicketView(discord.ui.View): """Vue avec le bouton pour ouvrir le ticket""" def __init__(self): super().__init__(timeout=None) @discord.ui.button(label="📑 Ouvrir un Ticket Whitelist", style=discord.ButtonStyle.red, custom_id="open_ticket") async def open_ticket(self, interaction: discord.Interaction, button: discord.ui.Button): """Affiche le premier formulaire""" await interaction.response.send_modal(TicketStep1()) class Ticket(commands.Cog): """Commande pour envoyer l'embed de ticket""" def __init__(self, bot): self.bot = bot @app_commands.command(name="ticket_whitelist", description="Envoie l'embed pour ouvrir un ticket de whitelist.") async def ticket_whitelist(self, interaction: discord.Interaction): """Envoie l'embed avec le bouton d'ouverture de ticket""" embed = discord.Embed( title="📩 Ticket Whitelist", description="Pour réaliser votre whitelist, ouvrez un ticket et remplissez le formulaire.", color=0x00ff00 ) view = TicketView() await interaction.channel.send(embed=embed, view=view) await interaction.response.send_message("✅ Embed des tickets envoyé.", ephemeral=True) @commands.Cog.listener() async def on_message(self, message): """Surveille les messages des staffs dans les tickets""" if message.guild is None or message.author.bot: return if not message.channel.topic or not message.channel.topic.startswith("Ticket de"): return staff_role = discord.utils.get(message.guild.roles, id=STAFF_ROLE_ID) if staff_role in message.author.roles and "validé" in message.content.lower(): try: user_id = message.channel.topic.split("Ticket de ")[1] user = await message.guild.fetch_member(user_id) # Vérifier si le rôle "attente oral" est déjà attribué attente_oral_role = discord.utils.get(message.guild.roles, id=ATTENTE_ORAL_ROLE_ID) candidature_a_faire_role = discord.utils.get(message.guild.roles, id=CANDIDATURE_A_FAIRE_ROLE_ID) citoyen_role = discord.utils.get(message.guild.roles, id=CITOYEN_ROLE_ID) if attente_oral_role in user.roles: # Deuxième "validé" détecté await user.remove_roles(attente_oral_role) await user.add_roles(citoyen_role) await message.channel.edit(name=f"{user.name}-citoyen") else: # Premier "validé" détecté await user.remove_roles(candidature_a_faire_role) await user.add_roles(attente_oral_role) await message.channel.edit(name=f"{user.name}-oral") # Mettre à jour le pseudo du joueur si le bot a les permissions nécessaires if message.guild.me.guild_permissions.manage_nicknames: new_nickname = f"{self.step2_part1_data.prenom.value} {self.step2_part1_data.nom.value} | {self.step1_data.pseudo.value}" if len(new_nickname) > 32: new_nickname = new_nickname[:32] await user.edit(nick=new_nickname) else: await message.channel.send("❌ Le bot n'a pas les permissions nécessaires pour modifier le pseudo.", delete_after=10) except Exception as e: print(f"Erreur lors du renommage du ticket: {e}") async def setup(bot): await bot.add_cog(Ticket(bot))