329 lines
No EOL
18 KiB
Python
329 lines
No EOL
18 KiB
Python
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)) |