Première version non terminer du nouveau système de ticket § ajout du système de boutons persistant (non tester)

This commit is contained in:
Mathis 2026-01-04 00:01:15 +01:00
parent 10173132a2
commit 93e2f9bb44
15 changed files with 3788 additions and 209 deletions

View file

@ -1,207 +1,23 @@
import discord
from discord.ext import commands, tasks
from discord.ui import View, Button, Modal, TextInput
import json
"""
Legacy Ticket Module
====================
This file now serves as a compatibility wrapper for the new modular ticket system.
The main implementation has been moved to the 'commandes/ticket' package.
To use the new modular system, import from the ticket package:
from commandes.ticket import Ticket
Or use the setup function directly:
from commandes.ticket import setup
"""
import sys
import os
from datetime import datetime
import asyncio
# --- Fonctions de gestion de données ---
# Add parent directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
def load_config():
"""Charge la configuration des tickets"""
path = "data/tickets/config.json"
if not os.path.exists("data/tickets"):
os.makedirs("data/tickets")
if not os.path.exists(path):
with open(path, "w") as f:
json.dump({}, f, indent=4)
with open(path, "r") as f:
return json.load(f)
# Import from the new modular ticket system
from ticket import setup
def save_config(config):
"""Sauvegarde la configuration des tickets"""
path = "data/tickets/config.json"
with open(path, "w", encoding="utf-8") as f:
json.dump(config, f, indent=4, ensure_ascii=False)
__all__ = ["setup"]
# --- Vues (Interactions) ---
class TicketView(View):
def __init__(self, bot, config):
super().__init__(timeout=None)
self.bot = bot
self.config = config
@discord.ui.button(label="Créer un ticket", style=discord.ButtonStyle.blurple, custom_id="create_ticket")
async def create_ticket(self, interaction: discord.Interaction, button: Button):
await interaction.response.defer(ephemeral=True)
guild_id = str(interaction.guild_id)
if guild_id not in self.config:
return await interaction.followup.send("Le système n'est pas configuré.", ephemeral=True)
guild_config = self.config[guild_id]
# Vérifier si l'utilisateur a déjà un ticket
for channel in interaction.guild.text_channels:
if channel.name.startswith(f"ticket-{interaction.user.id}"):
return await interaction.followup.send(f"Vous avez déjà un ticket : {channel.mention}", ephemeral=True)
# Configuration des permissions
category = interaction.guild.get_channel(int(guild_config["category_id"]))
overwrites = {
interaction.guild.default_role: discord.PermissionOverwrite(read_messages=False),
interaction.user: discord.PermissionOverwrite(read_messages=True, send_messages=True, attach_files=True),
interaction.guild.me: discord.PermissionOverwrite(read_messages=True, send_messages=True)
}
for role_id in guild_config["staff_roles"]:
role = interaction.guild.get_role(int(role_id))
if role:
overwrites[role] = discord.PermissionOverwrite(read_messages=True, send_messages=True)
# Création du salon
channel_name = f"ticket-{interaction.user.id}-{datetime.now().strftime('%m%d%H%M')}"
ticket_channel = await interaction.guild.create_text_channel(
name=channel_name,
category=category,
overwrites=overwrites,
topic=f"Ticket de {interaction.user} ({interaction.user.id})"
)
embed = discord.Embed(
title="Nouveau Ticket",
description=guild_config["ticket_message"],
color=discord.Color.blue(),
timestamp=datetime.now()
)
embed.set_author(name=interaction.user.display_name, icon_url=interaction.user.display_avatar.url)
await ticket_channel.send(embed=embed, view=TicketCloseView(self.bot, self.config))
# Logs
if guild_config.get("log_channel"):
log_ch = self.bot.get_channel(int(guild_config["log_channel"]))
if log_ch:
log_embed = discord.Embed(title="Ticket Créé", color=discord.Color.green())
log_embed.add_field(name="Auteur", value=interaction.user.mention)
log_embed.add_field(name="Salon", value=ticket_channel.mention)
await log_ch.send(embed=log_embed)
await interaction.followup.send(f"Ticket créé : {ticket_channel.mention}", ephemeral=True)
class TicketCloseView(View):
def __init__(self, bot, config):
super().__init__(timeout=None)
self.bot = bot
self.config = config
@discord.ui.button(label="Fermer le ticket", style=discord.ButtonStyle.red, custom_id="close_ticket")
async def close_ticket(self, interaction: discord.Interaction, button: Button):
await interaction.response.defer(ephemeral=True)
guild_config = self.config.get(str(interaction.guild_id))
# Modifier permissions (bloquer l'écriture)
overwrites = interaction.channel.overwrites
for target in overwrites:
if isinstance(target, discord.Member) and target != interaction.guild.me:
overwrites[target] = discord.PermissionOverwrite(read_messages=True, send_messages=False)
await interaction.channel.edit(name=f"closed-{interaction.channel.name}", overwrites=overwrites)
embed = discord.Embed(title="Ticket Fermé", description=f"Fermé par {interaction.user.mention}", color=discord.Color.red())
await interaction.channel.send(embed=embed, view=TicketReopenView(self.bot, self.config))
await interaction.followup.send("Ticket fermé.", ephemeral=True)
class TicketReopenView(View):
def __init__(self, bot, config):
super().__init__(timeout=None)
self.bot = bot
self.config = config
@discord.ui.button(label="Rouvrir", style=discord.ButtonStyle.green, custom_id="reopen_ticket")
async def reopen(self, interaction: discord.Interaction, button: Button):
await interaction.response.defer(ephemeral=True)
new_name = interaction.channel.name.replace("closed-", "")
await interaction.channel.edit(name=new_name)
await interaction.channel.send(f"Ticket rouvert par {interaction.user.mention}", view=TicketCloseView(self.bot, self.config))
@discord.ui.button(label="Supprimer", style=discord.ButtonStyle.grey, custom_id="delete_ticket")
async def delete(self, interaction: discord.Interaction, button: Button):
await interaction.response.send_message("Suppression dans 3s...")
await asyncio.sleep(3)
await interaction.channel.delete()
# --- Modale de Configuration ---
class TicketConfigModal(Modal):
def __init__(self, bot, config, guild_id):
super().__init__(title="Configuration Tickets")
self.bot = bot
self.config = config
self.guild_id = str(guild_id)
self.category_id = TextInput(label="ID Catégorie", placeholder="Ex: 123456789", required=True)
self.staff_roles = TextInput(label="IDs Rôles Staff (virgule)", placeholder="ID1, ID2", required=True)
self.log_channel = TextInput(label="ID Salon Logs", required=False)
self.ticket_msg = TextInput(label="Message Ticket", style=discord.TextStyle.paragraph, required=True)
self.welcome_msg = TextInput(label="Message Panel", required=True)
for item in [self.category_id, self.staff_roles, self.log_channel, self.ticket_msg, self.welcome_msg]:
self.add_item(item)
async def on_submit(self, interaction: discord.Interaction):
role_ids = [r.strip() for r in self.staff_roles.value.split(",")]
self.config[self.guild_id] = {
"category_id": self.category_id.value,
"staff_roles": role_ids,
"log_channel": self.log_channel.value,
"ticket_message": self.ticket_msg.value,
"welcome_message": self.welcome_msg.value
}
save_config(self.config)
await interaction.response.send_message("Configuration sauvegardée !", ephemeral=True)
# --- Le Cog Principal ---
class Ticket(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.config = load_config()
@commands.Cog.listener()
async def on_ready(self):
# Enregistrer les vues persistantes (pour qu'elles marchent après reboot)
self.bot.add_view(TicketView(self.bot, self.config))
self.bot.add_view(TicketCloseView(self.bot, self.config))
self.bot.add_view(TicketReopenView(self.bot, self.config))
print("Module Ticket prêt")
@commands.hybrid_group(name="ticket")
@commands.has_permissions(administrator=True)
async def ticket(self, ctx):
if ctx.invoked_subcommand is None:
await ctx.send("Utilisez `/ticket setup` ou `/ticket panel`", ephemeral=True)
@ticket.command(name="setup")
async def setup_cmd(self, ctx):
await ctx.interaction.response.send_modal(TicketConfigModal(self.bot, self.config, ctx.guild.id))
@ticket.command(name="panel")
async def panel_cmd(self, ctx, channel: discord.TextChannel = None):
guild_id = str(ctx.guild.id)
if guild_id not in self.config:
return await ctx.send("Configurez d'abord le système via `/ticket setup`.")
target = channel or ctx.channel
embed = discord.Embed(
title="Support",
description=self.config[guild_id]["welcome_message"],
color=discord.Color.blue()
)
await target.send(embed=embed, view=TicketView(self.bot, self.config))
await ctx.send("Panel envoyé !", ephemeral=True)
async def setup(bot):
await bot.add_cog(Ticket(bot))