Migration de Kuby vers disnake
This commit is contained in:
parent
dc6e235f27
commit
c8c579eefe
36 changed files with 1205 additions and 1253 deletions
|
|
@ -1,7 +1,7 @@
|
|||
import discord
|
||||
import disnake
|
||||
import re
|
||||
from discord.ext import commands
|
||||
from discord import app_commands, ui
|
||||
from disnake.ext import commands
|
||||
from disnake import ui
|
||||
import json
|
||||
import os
|
||||
import asyncio
|
||||
|
|
@ -63,12 +63,12 @@ def save_settings(guild_id: int, settings: dict) -> None:
|
|||
with open(TICKET_WHITELIST_SETTINGS_FILE, "w", encoding='utf-8') as f:
|
||||
json.dump(data, f, indent=4, ensure_ascii=False)
|
||||
|
||||
async def get_ticket_user_id(channel: discord.TextChannel) -> Optional[int]:
|
||||
async def get_ticket_user_id(channel: disnake.TextChannel) -> Optional[int]:
|
||||
"""Récupère l'ID du propriétaire du ticket de manière robuste (gère le lag de cache)"""
|
||||
import re
|
||||
topic = getattr(channel, "topic", None)
|
||||
|
||||
# Tentative d'utilisation du cache d.py (plus rapide)
|
||||
# Tentative d'utilisation du cache (plus rapide)
|
||||
if topic:
|
||||
match = re.search(r"(\d{17,20})", topic)
|
||||
if match:
|
||||
|
|
@ -88,12 +88,12 @@ async def get_ticket_user_id(channel: discord.TextChannel) -> Optional[int]:
|
|||
|
||||
return None
|
||||
|
||||
class TicketWhitelistConfigView(ui.View):
|
||||
class TicketWhitelistConfigView(disnake.ui.View):
|
||||
def __init__(self, guild_id: int):
|
||||
super().__init__(timeout=60)
|
||||
self.guild_id = guild_id
|
||||
|
||||
async def prompt_for_id(self, interaction: discord.Interaction, prompt_text: str, is_category: bool = False):
|
||||
async def prompt_for_id(self, interaction: disnake.Interaction, prompt_text: str, is_category: bool = False):
|
||||
await interaction.response.send_message(prompt_text, ephemeral=True)
|
||||
|
||||
def check(m):
|
||||
|
|
@ -104,7 +104,7 @@ class TicketWhitelistConfigView(ui.View):
|
|||
target = None
|
||||
if is_category:
|
||||
if msg.content.isdigit():
|
||||
target = discord.utils.get(interaction.guild.categories, id=int(msg.content))
|
||||
target = disnake.utils.get(interaction.guild.categories, id=int(msg.content))
|
||||
if not target:
|
||||
await interaction.followup.send("❌ Catégorie introuvable avec cet ID.", ephemeral=True)
|
||||
return None
|
||||
|
|
@ -129,8 +129,8 @@ class TicketWhitelistConfigView(ui.View):
|
|||
await interaction.followup.send("❌ Temps écoulé.", ephemeral=True)
|
||||
return None
|
||||
|
||||
@ui.button(label="Catégorie Tickets", style=discord.ButtonStyle.primary, row=0, emoji="📁")
|
||||
async def set_category(self, interaction: discord.Interaction, button: ui.Button):
|
||||
@ui.button(label="Catégorie Tickets", style=disnake.ButtonStyle.primary, row=0, emoji="📁")
|
||||
async def set_category(self, interaction: disnake.Interaction, button: ui.Button):
|
||||
category = await self.prompt_for_id(interaction, "Envoie l'ID de la **catégorie** où créer les tickets :", is_category=True)
|
||||
if category:
|
||||
settings = load_settings(self.guild_id)
|
||||
|
|
@ -138,8 +138,8 @@ class TicketWhitelistConfigView(ui.View):
|
|||
save_settings(self.guild_id, settings)
|
||||
await interaction.followup.send(f"✅ Catégorie configurée sur **{category.name}**", ephemeral=True)
|
||||
|
||||
@ui.button(label="Rôle Staff", style=discord.ButtonStyle.primary, row=0, emoji="🛡️")
|
||||
async def set_staff_role(self, interaction: discord.Interaction, button: ui.Button):
|
||||
@ui.button(label="Rôle Staff", style=disnake.ButtonStyle.primary, row=0, emoji="🛡️")
|
||||
async def set_staff_role(self, interaction: disnake.Interaction, button: ui.Button):
|
||||
role = await self.prompt_for_id(interaction, "Mentionne le **rôle Staff** ou envoie son ID :")
|
||||
if role:
|
||||
settings = load_settings(self.guild_id)
|
||||
|
|
@ -147,8 +147,8 @@ class TicketWhitelistConfigView(ui.View):
|
|||
save_settings(self.guild_id, settings)
|
||||
await interaction.followup.send(f"✅ Rôle Staff configuré sur **{role.name}**", ephemeral=True)
|
||||
|
||||
@ui.button(label="Rôle Équipe Staff", style=discord.ButtonStyle.primary, row=0, emoji="👥")
|
||||
async def set_team_staff_role(self, interaction: discord.Interaction, button: ui.Button):
|
||||
@ui.button(label="Rôle Équipe Staff", style=disnake.ButtonStyle.primary, row=0, emoji="👥")
|
||||
async def set_team_staff_role(self, interaction: disnake.Interaction, button: ui.Button):
|
||||
role = await self.prompt_for_id(interaction, "Mentionne le **rôle Équipe Staff** (à ping pour les nouveaux tickets) ou envoie son ID :")
|
||||
if role:
|
||||
settings = load_settings(self.guild_id)
|
||||
|
|
@ -156,8 +156,8 @@ class TicketWhitelistConfigView(ui.View):
|
|||
save_settings(self.guild_id, settings)
|
||||
await interaction.followup.send(f"✅ Rôle Équipe Staff configuré sur **{role.name}**", ephemeral=True)
|
||||
|
||||
@ui.button(label="Rôle Attente Oral", style=discord.ButtonStyle.secondary, row=1, emoji="🎤")
|
||||
async def set_attente_oral_role(self, interaction: discord.Interaction, button: ui.Button):
|
||||
@ui.button(label="Rôle Attente Oral", style=disnake.ButtonStyle.secondary, row=1, emoji="🎤")
|
||||
async def set_attente_oral_role(self, interaction: disnake.Interaction, button: ui.Button):
|
||||
role = await self.prompt_for_id(interaction, "Mentionne le rôle **Attente Oral** ou envoie son ID :")
|
||||
if role:
|
||||
settings = load_settings(self.guild_id)
|
||||
|
|
@ -165,8 +165,8 @@ class TicketWhitelistConfigView(ui.View):
|
|||
save_settings(self.guild_id, settings)
|
||||
await interaction.followup.send(f"✅ Rôle Attente Oral configuré sur **{role.name}**", ephemeral=True)
|
||||
|
||||
@ui.button(label="Rôle Candidature à faire", style=discord.ButtonStyle.secondary, row=1, emoji="📝")
|
||||
async def set_candidature_a_faire_role(self, interaction: discord.Interaction, button: ui.Button):
|
||||
@ui.button(label="Rôle Candidature à faire", style=disnake.ButtonStyle.secondary, row=1, emoji="📝")
|
||||
async def set_candidature_a_faire_role(self, interaction: disnake.Interaction, button: ui.Button):
|
||||
role = await self.prompt_for_id(interaction, "Mentionne le rôle **Candidature à faire** ou envoie son ID :")
|
||||
if role:
|
||||
settings = load_settings(self.guild_id)
|
||||
|
|
@ -174,8 +174,8 @@ class TicketWhitelistConfigView(ui.View):
|
|||
save_settings(self.guild_id, settings)
|
||||
await interaction.followup.send(f"✅ Rôle Candidature à faire configuré sur **{role.name}**", ephemeral=True)
|
||||
|
||||
@ui.button(label="Rôle Citoyen", style=discord.ButtonStyle.success, row=1, emoji="🏙️")
|
||||
async def set_citoyen_role(self, interaction: discord.Interaction, button: ui.Button):
|
||||
@ui.button(label="Rôle Citoyen", style=disnake.ButtonStyle.success, row=1, emoji="🏙️")
|
||||
async def set_citoyen_role(self, interaction: disnake.Interaction, button: ui.Button):
|
||||
role = await self.prompt_for_id(interaction, "Mentionne le rôle **Citoyen** ou envoie son ID :")
|
||||
if role:
|
||||
settings = load_settings(self.guild_id)
|
||||
|
|
@ -184,7 +184,7 @@ class TicketWhitelistConfigView(ui.View):
|
|||
await interaction.followup.send(f"✅ Rôle Citoyen configuré sur **{role.name}**", ephemeral=True)
|
||||
|
||||
|
||||
class ContinueFormView(discord.ui.View):
|
||||
class ContinueFormView(disnake.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):
|
||||
|
|
@ -194,8 +194,8 @@ class ContinueFormView(discord.ui.View):
|
|||
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):
|
||||
@disnake.ui.button(label="📋 Continuer le formulaire", style=disnake.ButtonStyle.green, custom_id="continue_form")
|
||||
async def continue_form(self, interaction: disnake.Interaction, button: disnake.ui.Button):
|
||||
"""Passe à l'étape suivante du formulaire"""
|
||||
if self.current_step == 1:
|
||||
await interaction.response.send_modal(TicketStep2Part1(self.step1_data))
|
||||
|
|
@ -207,79 +207,99 @@ class ContinueFormView(discord.ui.View):
|
|||
# Vérifier si le message existe toujours avant de le modifier
|
||||
try:
|
||||
await interaction.message.edit(view=self)
|
||||
except discord.errors.NotFound:
|
||||
except disnake.errors.NotFound:
|
||||
# Si le message n'existe plus, nous ne faisons rien
|
||||
pass
|
||||
|
||||
class TicketStep1(discord.ui.Modal, title="📋 Informations Personnelles"):
|
||||
class TicketStep1(disnake.ui.Modal):
|
||||
"""É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)
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
title="📋 Informations Personnelles",
|
||||
custom_id="ticket_step1",
|
||||
components=[
|
||||
disnake.ui.TextInput(label="Pseudo Epic (Fortnite)", custom_id="pseudo", required=True, max_length=16),
|
||||
disnake.ui.TextInput(label="Âge", custom_id="age", required=True, max_length=2),
|
||||
disnake.ui.TextInput(label="Expérience RP ?", custom_id="experience", style=disnake.TextInputStyle.paragraph, required=True, max_length=50),
|
||||
disnake.ui.TextInput(label="Comment as-tu découvert le serveur ?", custom_id="decouverte", required=True, max_length=20),
|
||||
disnake.ui.TextInput(label="As-tu un micro de qualité ?", custom_id="micro", required=True, max_length=3),
|
||||
]
|
||||
)
|
||||
|
||||
async def on_submit(self, interaction: discord.Interaction):
|
||||
async def callback(self, interaction: disnake.ModalInteraction):
|
||||
"""Envoie un bouton pour passer à l'étape 2"""
|
||||
view = ContinueFormView(current_step=1, step1_data=self)
|
||||
view = ContinueFormView(current_step=1, step1_data=interaction.text_values)
|
||||
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)"):
|
||||
class TicketStep2Part1(disnake.ui.Modal):
|
||||
"""Étape 2 du formulaire - Infos RP (Partie 1)"""
|
||||
|
||||
def __init__(self, step1_data):
|
||||
super().__init__()
|
||||
self.step1_data = step1_data
|
||||
super().__init__(
|
||||
title="👤 Infos sur ton personnage (Partie 1)",
|
||||
custom_id="ticket_step2_part1",
|
||||
components=[
|
||||
disnake.ui.TextInput(label="Prénom", custom_id="prenom", required=True),
|
||||
disnake.ui.TextInput(label="Nom", custom_id="nom", required=True),
|
||||
disnake.ui.TextInput(label="Âge du personnage", custom_id="age_perso", required=True),
|
||||
disnake.ui.TextInput(label="Genre", custom_id="genre", required=True, max_length=5),
|
||||
disnake.ui.TextInput(label="Date et lieu de naissance", custom_id="naissance", required=True),
|
||||
]
|
||||
)
|
||||
|
||||
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):
|
||||
async def callback(self, interaction: disnake.ModalInteraction):
|
||||
"""Envoie un bouton pour passer à l'étape suivante"""
|
||||
view = ContinueFormView(current_step=2, step1_data=self.step1_data, step2_part1_data=self)
|
||||
view = ContinueFormView(current_step=2, step1_data=self.step1_data, step2_part1_data=interaction.text_values)
|
||||
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)"):
|
||||
class TicketStep2Part2(disnake.ui.Modal):
|
||||
"""É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
|
||||
super().__init__(
|
||||
title="👤 Infos sur ton personnage (Partie 2)",
|
||||
custom_id="ticket_step2_part2",
|
||||
components=[
|
||||
disnake.ui.TextInput(label="Traits de caractère", custom_id="traits", required=True),
|
||||
disnake.ui.TextInput(label="Nationalité", custom_id="nationalite", required=True),
|
||||
disnake.ui.TextInput(label="Skin RP", custom_id="skin_rp", required=True),
|
||||
disnake.ui.TextInput(label="Métier souhaité", custom_id="metier_souhaite", required=True),
|
||||
]
|
||||
)
|
||||
|
||||
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):
|
||||
async def callback(self, interaction: disnake.ModalInteraction):
|
||||
"""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)
|
||||
view = ContinueFormView(current_step=3, step1_data=self.step1_data, step2_part1_data=self.step2_part1_data, step2_part2_data=interaction.text_values)
|
||||
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"):
|
||||
class TicketStep3(disnake.ui.Modal):
|
||||
"""É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
|
||||
super().__init__(
|
||||
title="📋 Développement du Personnage",
|
||||
custom_id="ticket_step3",
|
||||
components=[
|
||||
disnake.ui.TextInput(
|
||||
label="Histoire du personnage",
|
||||
custom_id="histoire",
|
||||
style=disnake.TextInputStyle.paragraph,
|
||||
required=True,
|
||||
min_length=425,
|
||||
max_length=500
|
||||
),
|
||||
disnake.ui.TextInput(label="Objectifs RP (court et long terme)", custom_id="objectifs", style=disnake.TextInputStyle.paragraph, required=True, max_length=100),
|
||||
]
|
||||
)
|
||||
|
||||
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):
|
||||
async def callback(self, interaction: disnake.ModalInteraction):
|
||||
"""Création du ticket après validation"""
|
||||
guild = interaction.guild
|
||||
user = interaction.user
|
||||
|
|
@ -292,12 +312,12 @@ class TicketStep3(discord.ui.Modal, title="📋 Développement du Personnage"):
|
|||
if not category_id or not staff_role_id or not team_staff_role_id:
|
||||
return await interaction.response.send_message("❌ Erreur : Le système de tickets n'est pas entièrement configuré sur ce serveur (Catégorie, Rôle Staff ou Rôle Équipe Staff manquant).", ephemeral=True)
|
||||
|
||||
category = discord.utils.get(guild.categories, id=int(category_id))
|
||||
category = disnake.utils.get(guild.categories, id=int(category_id))
|
||||
if category is None:
|
||||
return await interaction.response.send_message("❌ Erreur : La catégorie des tickets configurée n'existe plus !", ephemeral=True)
|
||||
|
||||
staff_role = discord.utils.get(guild.roles, id=int(staff_role_id))
|
||||
team_staff_role = discord.utils.get(guild.roles, id=int(team_staff_role_id))
|
||||
staff_role = disnake.utils.get(guild.roles, id=int(staff_role_id))
|
||||
team_staff_role = disnake.utils.get(guild.roles, id=int(team_staff_role_id))
|
||||
|
||||
if staff_role is None or team_staff_role is None:
|
||||
return await interaction.response.send_message("❌ Erreur : L'un des rôles staff configurés n'existe plus !", ephemeral=True)
|
||||
|
|
@ -309,10 +329,10 @@ class TicketStep3(discord.ui.Modal, title="📋 Développement du Personnage"):
|
|||
|
||||
# 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),
|
||||
team_staff_role: discord.PermissionOverwrite(read_messages=True, send_messages=False)
|
||||
guild.default_role: disnake.PermissionOverwrite(read_messages=False),
|
||||
user: disnake.PermissionOverwrite(read_messages=True, send_messages=True),
|
||||
staff_role: disnake.PermissionOverwrite(read_messages=True, send_messages=True),
|
||||
team_staff_role: disnake.PermissionOverwrite(read_messages=True, send_messages=False)
|
||||
}
|
||||
|
||||
# Créer un salon de ticket avec le nom [pseudo]-écrit
|
||||
|
|
@ -323,28 +343,35 @@ class TicketStep3(discord.ui.Modal, title="📋 Développement du Personnage"):
|
|||
)
|
||||
|
||||
# Création de l'embed avec les infos du formulaire
|
||||
embed = discord.Embed(title="📩 Ticket Whitelist", color=0x00ff00)
|
||||
embed = disnake.Embed(title="📩 Ticket Whitelist", color=0x00ff00)
|
||||
|
||||
# Helper to get value from data
|
||||
s1 = self.step1_data
|
||||
s2p1 = self.step2_part1_data
|
||||
s2p2 = self.step2_part2_data
|
||||
s3 = interaction.text_values
|
||||
|
||||
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}"
|
||||
f"> - Pseudo Epic : {s1['pseudo']}\n"
|
||||
f"> - Âge : {s1['age']}\n"
|
||||
f"> - Expérience RP : {s1['experience']}\n"
|
||||
f"> - Découverte du serveur : {s1['decouverte']}\n"
|
||||
f"> - Micro de qualité : {s1['micro']}"
|
||||
), 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}"
|
||||
f"> - Prénom : {s2p1['prenom']}\n"
|
||||
f"> - Nom : {s2p1['nom']}\n"
|
||||
f"> - Âge du personnage : {s2p1['age_perso']}\n"
|
||||
f"> - Genre : {s2p1['genre']}\n"
|
||||
f"> - Naissance : {s2p1['naissance']}\n"
|
||||
f"> - Traits de caractère : {s2p2['traits']}\n"
|
||||
f"> - Nationalité : {s2p2['nationalite']}\n"
|
||||
f"> - Skin RP : {s2p2['skin_rp']}\n"
|
||||
f"> - Métier souhaité : {s2p2['metier_souhaite']}"
|
||||
), inline=False)
|
||||
embed.add_field(name="📋 - Développement du Personnage", value=(
|
||||
f"> - Histoire : {self.histoire.value}\n"
|
||||
f"> - Objectifs : {self.objectifs.value}"
|
||||
f"> - Histoire : {s3['histoire']}\n"
|
||||
f"> - Objectifs : {s3['objectifs']}"
|
||||
), inline=False)
|
||||
|
||||
# Envoyer l'embed avec les boutons d'actions pour les staff
|
||||
|
|
@ -355,25 +382,25 @@ class TicketStep3(discord.ui.Modal, title="📋 Développement du Personnage"):
|
|||
|
||||
# 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}"
|
||||
new_nickname = f"{s2p1['prenom']} {s2p1['nom']} | {s1['pseudo']}"
|
||||
if len(new_nickname) > 32:
|
||||
new_nickname = new_nickname[:32]
|
||||
try: await user.edit(nick=new_nickname)
|
||||
except discord.Forbidden: pass
|
||||
except disnake.Forbidden: pass
|
||||
|
||||
# Envoyer un message de confirmation
|
||||
try:
|
||||
await interaction.response.send_message(f"✅ Ticket ouvert : {ticket_channel.mention}", ephemeral=True)
|
||||
except discord.errors.NotFound:
|
||||
except disnake.errors.NotFound:
|
||||
await interaction.followup.send(f"✅ Ticket ouvert : {ticket_channel.mention}", ephemeral=True)
|
||||
|
||||
class TicketManagementView(discord.ui.View):
|
||||
class TicketManagementView(disnake.ui.View):
|
||||
"""Vue pour gérer le ticket avec les boutons Fermer, Réouvrir, Claim et Supprimer"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(timeout=None)
|
||||
|
||||
async def get_ticket_owner(self, interaction: discord.Interaction):
|
||||
async def get_ticket_owner(self, interaction: disnake.Interaction):
|
||||
"""Récupère le propriétaire du ticket via le helper robuste"""
|
||||
owner_id = await get_ticket_user_id(interaction.channel)
|
||||
if owner_id:
|
||||
|
|
@ -386,8 +413,8 @@ class TicketManagementView(discord.ui.View):
|
|||
return None
|
||||
return None
|
||||
|
||||
@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):
|
||||
@disnake.ui.button(label="🔒 Fermer le Ticket", style=disnake.ButtonStyle.red, custom_id="close_ticket")
|
||||
async def close_ticket(self, interaction: disnake.Interaction, button: disnake.ui.Button):
|
||||
"""Ferme le ticket en désactivant l'envoi de messages pour le membre"""
|
||||
await interaction.response.defer(ephemeral=True)
|
||||
|
||||
|
|
@ -411,12 +438,14 @@ class TicketManagementView(discord.ui.View):
|
|||
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 disnake.errors.RateLimited as e:
|
||||
await interaction.followup.send(f"⚠️ Limite de débit Discord : Réessayez dans {e.retry_after:.1f}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)
|
||||
|
||||
@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):
|
||||
@disnake.ui.button(label="👤 Claim le Ticket", style=disnake.ButtonStyle.blurple, custom_id="claim_ticket")
|
||||
async def claim_ticket(self, interaction: disnake.Interaction, button: disnake.ui.Button):
|
||||
"""Un staff prend en charge le ticket"""
|
||||
await interaction.response.defer(ephemeral=False)
|
||||
|
||||
|
|
@ -441,13 +470,13 @@ class TicketManagementView(discord.ui.View):
|
|||
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):
|
||||
class ClosedTicketView(disnake.ui.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):
|
||||
async def get_ticket_owner(self, interaction: disnake.Interaction):
|
||||
"""Récupère le propriétaire du ticket via le helper robuste"""
|
||||
owner_id = await get_ticket_user_id(interaction.channel)
|
||||
if owner_id:
|
||||
|
|
@ -460,8 +489,8 @@ class ClosedTicketView(discord.ui.View):
|
|||
return None
|
||||
return None
|
||||
|
||||
@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):
|
||||
@disnake.ui.button(label="♻ Réouvrir le Ticket", style=disnake.ButtonStyle.green, custom_id="reopen_ticket")
|
||||
async def reopen_ticket(self, interaction: disnake.Interaction, button: disnake.ui.Button):
|
||||
"""Réouvre le ticket pour le membre"""
|
||||
await interaction.response.defer(ephemeral=True)
|
||||
|
||||
|
|
@ -478,10 +507,10 @@ class ClosedTicketView(discord.ui.View):
|
|||
|
||||
try:
|
||||
# On demande au staff quel statut remettre
|
||||
embed = discord.Embed(
|
||||
embed = disnake.Embed(
|
||||
title="♻️ Réouverture du Ticket",
|
||||
description=f"Choisissez le statut à appliquer pour **{owner.display_name}**.",
|
||||
color=discord.Color.blue()
|
||||
color=disnake.Color.blue()
|
||||
)
|
||||
view = ReopenStatusView(owner)
|
||||
await interaction.channel.send(embed=embed, view=view)
|
||||
|
|
@ -490,25 +519,25 @@ class ClosedTicketView(discord.ui.View):
|
|||
kuby_logger.error(f"Erreur lors de la préparation de réouverture: {e}")
|
||||
await interaction.followup.send(f"❌ Erreur : {e}", ephemeral=True)
|
||||
|
||||
class ReopenStatusView(discord.ui.View):
|
||||
class ReopenStatusView(disnake.ui.View):
|
||||
"""Vue pour choisir le statut lors d'une réouverture"""
|
||||
def __init__(self, owner: discord.Member):
|
||||
def __init__(self, owner: disnake.Member):
|
||||
super().__init__(timeout=180)
|
||||
self.owner = owner
|
||||
|
||||
@discord.ui.button(label="Écrit (Ouvert)", style=discord.ButtonStyle.secondary)
|
||||
async def set_written(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||
@disnake.ui.button(label="Écrit (Ouvert)", style=disnake.ButtonStyle.secondary)
|
||||
async def set_written(self, interaction: disnake.Interaction, button: disnake.ui.Button):
|
||||
await self.apply_status(interaction, "ouvert")
|
||||
|
||||
@discord.ui.button(label="Oral (À faire)", style=discord.ButtonStyle.primary)
|
||||
async def set_oral(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||
@disnake.ui.button(label="Oral (À faire)", style=disnake.ButtonStyle.primary)
|
||||
async def set_oral(self, interaction: disnake.Interaction, button: disnake.ui.Button):
|
||||
await self.apply_status(interaction, "oral-à-faire")
|
||||
|
||||
@discord.ui.button(label="Accepté", style=discord.ButtonStyle.success)
|
||||
async def set_accepted(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||
@disnake.ui.button(label="Accepté", style=disnake.ButtonStyle.success)
|
||||
async def set_accepted(self, interaction: disnake.Interaction, button: disnake.ui.Button):
|
||||
await self.apply_status(interaction, "accepté")
|
||||
|
||||
async def apply_status(self, interaction: discord.Interaction, prefix: str):
|
||||
async def apply_status(self, interaction: disnake.Interaction, prefix: str):
|
||||
await interaction.response.defer(ephemeral=True)
|
||||
try:
|
||||
settings = load_settings(interaction.guild.id)
|
||||
|
|
@ -555,8 +584,8 @@ class ReopenStatusView(discord.ui.View):
|
|||
kuby_logger.error(f"Erreur lors de la réouverture/synchro: {e}")
|
||||
await interaction.followup.send(f"❌ Erreur système : {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):
|
||||
@disnake.ui.button(label="❌ Supprimer le Ticket", style=disnake.ButtonStyle.danger, custom_id="delete_ticket")
|
||||
async def delete_ticket(self, interaction: disnake.Interaction, button: disnake.ui.Button):
|
||||
"""Supprime le salon du ticket"""
|
||||
await interaction.response.defer(ephemeral=True)
|
||||
|
||||
|
|
@ -575,14 +604,14 @@ class ReopenStatusView(discord.ui.View):
|
|||
try: await interaction.followup.send(f"❌ Erreur lors de la suppression : {e}", ephemeral=True)
|
||||
except: pass
|
||||
|
||||
class TicketView(discord.ui.View):
|
||||
class TicketView(disnake.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):
|
||||
@disnake.ui.button(label="📑 Ouvrir un Ticket Whitelist", style=disnake.ButtonStyle.red, custom_id="open_ticket")
|
||||
async def open_ticket(self, interaction: disnake.Interaction, button: disnake.ui.Button):
|
||||
"""Affiche le premier formulaire"""
|
||||
await interaction.response.send_modal(TicketStep1())
|
||||
|
||||
|
|
@ -598,11 +627,11 @@ class Ticket(commands.Cog):
|
|||
self.bot.add_view(TicketManagementView())
|
||||
self.bot.add_view(ClosedTicketView())
|
||||
|
||||
@app_commands.command(name="ticket_whitelist", description="Envoie l'embed pour ouvrir un ticket de whitelist.")
|
||||
@app_commands.checks.has_permissions(administrator=True)
|
||||
async def ticket_whitelist(self, interaction: discord.Interaction):
|
||||
@commands.slash_command(name="ticket_whitelist", description="Envoie l'embed pour ouvrir un ticket de whitelist.")
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def ticket_whitelist(self, interaction: disnake.ApplicationCommandInteraction):
|
||||
"""Envoie l'embed avec le bouton d'ouverture de ticket"""
|
||||
embed = discord.Embed(
|
||||
embed = disnake.Embed(
|
||||
title="📩 Ticket Whitelist",
|
||||
description="Pour réaliser votre whitelist, ouvrez un ticket et remplissez le formulaire.",
|
||||
color=0x00ff00
|
||||
|
|
@ -611,16 +640,16 @@ class Ticket(commands.Cog):
|
|||
await interaction.channel.send(embed=embed, view=view)
|
||||
await interaction.response.send_message("✅ Embed des tickets envoyé.", ephemeral=True)
|
||||
|
||||
@app_commands.command(name="ticket_whitelist_config", description="Configurer le système de tickets whitelist (Admin)")
|
||||
@app_commands.checks.has_permissions(administrator=True)
|
||||
async def ticket_whitelist_config(self, interaction: discord.Interaction):
|
||||
@commands.slash_command(name="ticket_whitelist_config", description="Configurer le système de tickets whitelist (Admin)")
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def ticket_whitelist_config(self, interaction: disnake.ApplicationCommandInteraction):
|
||||
"""Interface de configuration des tickets"""
|
||||
settings = load_settings(interaction.guild.id)
|
||||
|
||||
embed = discord.Embed(
|
||||
embed = disnake.Embed(
|
||||
title="⚙️ Configuration Tickets Whitelist",
|
||||
description="Utilisez les boutons ci-dessous pour lier la catégorie et les rôles.",
|
||||
color=discord.Color.blue()
|
||||
color=disnake.Color.blue()
|
||||
)
|
||||
|
||||
cat_id = settings.get("ticket_category_id")
|
||||
|
|
@ -673,7 +702,7 @@ class Ticket(commands.Cog):
|
|||
user_id = user_id
|
||||
try:
|
||||
user = await message.guild.fetch_member(user_id)
|
||||
except (discord.NotFound, discord.HTTPException):
|
||||
except (disnake.NotFound, disnake.HTTPException):
|
||||
await message.channel.send("❌ Utilisateur introuvable. A-t-il quitté le serveur ?", delete_after=10)
|
||||
return
|
||||
|
||||
|
|
@ -701,19 +730,19 @@ class Ticket(commands.Cog):
|
|||
asyncio.create_task(message.channel.edit(name=new_name))
|
||||
|
||||
# Confirmation dans le salon (Feedback visuel)
|
||||
embed_val = discord.Embed(
|
||||
embed_val = disnake.Embed(
|
||||
title="🎉 Whitelist Validée !",
|
||||
description=f"Félicitations {user.mention}, ton entretien oral a été validé par {message.author.mention} !\nTu es désormais **Citoyen**.",
|
||||
color=discord.Color.green()
|
||||
color=disnake.Color.green()
|
||||
)
|
||||
await message.channel.send(embed=embed_val)
|
||||
|
||||
# DM au joueur (RESTAURATION DESIGN CAPTURE)
|
||||
try:
|
||||
embed_dm = discord.Embed(
|
||||
embed_dm = disnake.Embed(
|
||||
title="🎉 Félicitations - Citoyenneté Validée !",
|
||||
description=f"Nous avons le plaisir de t'annoncer que ton passage sur **{message.guild.name}** a été validé avec succès !",
|
||||
color=discord.Color.green()
|
||||
color=disnake.Color.green()
|
||||
)
|
||||
embed_dm.add_field(name="🏙️ Nouveau Statut", value="Citoyen", inline=True)
|
||||
embed_dm.add_field(name="📍 Serveur", value=message.guild.name, inline=True)
|
||||
|
|
@ -740,19 +769,19 @@ class Ticket(commands.Cog):
|
|||
asyncio.create_task(message.channel.edit(name=new_name))
|
||||
|
||||
# Confirmation dans le salon
|
||||
embed_val = discord.Embed(
|
||||
embed_val = disnake.Embed(
|
||||
title="📝 Étape Écrite Validée !",
|
||||
description=f"Ta candidature écrite a été validée par {message.author.mention}.\nTu passes désormais en **Attente Oral**.",
|
||||
color=discord.Color.orange()
|
||||
color=disnake.Color.orange()
|
||||
)
|
||||
await message.channel.send(embed=embed_val)
|
||||
|
||||
# DM au joueur (RESTAURATION DESIGN CAPTURE)
|
||||
try:
|
||||
embed_dm = discord.Embed(
|
||||
embed_dm = disnake.Embed(
|
||||
title="📝 Validation Étape Écrite",
|
||||
description=f"Ta candidature écrite sur **{message.guild.name}** a été examinée et validée par notre équipe !",
|
||||
color=discord.Color.orange()
|
||||
color=disnake.Color.orange()
|
||||
)
|
||||
embed_dm.add_field(name="🎤 Statut Actuel", value="Attente Oral", inline=True)
|
||||
embed_dm.add_field(name="🛠️ Action Requise", value="Merci de te rendre dans le salon vocal 'Attente Oral' dès que tu es disponible pour passer ton entretien.", inline=False)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue