Maintenance de routine

This commit is contained in:
Mathis 2026-02-07 14:42:39 +01:00
parent c330b9a1cc
commit 99ab16098f
62 changed files with 52172 additions and 144 deletions

3
.gitignore vendored
View file

@ -22,4 +22,5 @@ env/
.idea/
# Logs
*.log
*.Logs
.data

1
bot.py
View file

@ -63,6 +63,7 @@ class MyBot(commands.Bot):
"commandes.modules_security.antiraid",
"commandes.modules_security.logs_manager",
"commandes.modules_security.rules",
"commandes.ticket_whitelist"
]
for extension in extensions:

View file

@ -100,9 +100,9 @@ class TicketPanelView(discord.ui.View):
# Reload config to ensure we have latest permissions/categories
self.config = self.storage.load_config(interaction.guild_id)
if not self._is_whitelisted(interaction):
await interaction.response.send_message("❌ Vous n'êtes pas autorisé à utiliser cette fonctionnalité. Veuillez demander à être ajouté à la whitelist.", ephemeral=True)
return
# Reload config to ensure we have latest permissions/categories
self.config = self.storage.load_config(interaction.guild_id)
if not self.config.enabled:
await interaction.response.send_message("Le système de tickets est désactivé.", ephemeral=True)
@ -135,9 +135,9 @@ class TicketPanelView(discord.ui.View):
# Reload config
self.config = self.storage.load_config(interaction.guild_id)
if not self._is_whitelisted(interaction):
await interaction.response.send_message("❌ Vous n'êtes pas autorisé à utiliser cette fonctionnalité. Veuillez demander à être ajouté à la whitelist.", ephemeral=True)
return
# Reload config
self.config = self.storage.load_config(interaction.guild_id)
storage = get_storage()
tickets = storage.get_user_tickets(interaction.guild_id, interaction.user.id, open_only=True)
@ -356,9 +356,7 @@ class CategorySelectionView(discord.ui.View):
async def _on_category_select(self, interaction: discord.Interaction, category_id: str):
"""Handle category selection"""
try:
if not self._is_whitelisted(interaction):
await interaction.response.send_message("❌ Vous n'êtes pas autorisé à utiliser cette fonctionnalité. Veuillez demander à être ajouté à la whitelist.", ephemeral=True)
return
category = self.config.get_category(category_id)
if not category:
@ -536,6 +534,43 @@ class TicketPriorityModal(discord.ui.Modal):
await interaction.response.send_message(f"Ticket créé: {ticket_channel.mention}", ephemeral=True)
class SetCategoryModal(discord.ui.Modal):
"""Modal pour définir la catégorie Discord où les tickets seront créés"""
def __init__(self, bot, storage, config: GuildTicketConfig):
super().__init__(title="Définir la Catégorie Discord")
self.bot = bot
self.storage = storage
self.config = config
self.category = discord.ui.TextInput(
label="Catégorie Discord",
placeholder="Entrez l'ID de la catégorie (clic droit -> Copier l'ID)",
required=True,
max_length=20
)
self.add_item(self.category)
async def on_submit(self, interaction: discord.Interaction):
cat_id = self.category.value.strip()
# Verify it's a valid ID
if not cat_id.isdigit():
await interaction.response.send_message("❌ Veuillez entrer un ID de catégorie valide (que des chiffres).", ephemeral=True)
return
# Check if category exists
category = interaction.guild.get_channel(int(cat_id))
if not category or not isinstance(category, discord.CategoryChannel):
await interaction.response.send_message("❌ Catégorie introuvable ou ce n'est pas une catégorie.", ephemeral=True)
return
self.config.default_category = cat_id
self.storage.save_config(interaction.guild_id, self.config)
await interaction.response.send_message(f"📁 Les tickets seront désormais créés dans la catégorie **{category.name}**!", ephemeral=True)
class TicketManagementView(discord.ui.View):
"""Gestion du ticket (dans le salon du ticket)"""
@ -883,6 +918,27 @@ class CloseDelayView(discord.ui.View):
duration = self.ticket.duration_minutes
# Send Feedback Request to User via DM
try:
user = interaction.guild.get_member(self.ticket.user_id)
if user:
from .feedback_view import FeedbackView
dm_embed = discord.Embed(
title="📝 Votre avis nous intéresse !",
description=f"Votre ticket **#{self.ticket.channel_id}** a été fermé.\nMerci de prendre un moment pour noter la qualité du support.",
color=discord.Color.green(),
timestamp=datetime.now()
)
dm_embed.add_field(name="Durée du ticket", value=f"{duration:.1f} minutes", inline=True)
if self.close_reason:
dm_embed.add_field(name="Raison de fermeture", value=self.close_reason, inline=False)
view = FeedbackView(self.bot, self.storage, self.ticket)
await user.send(embed=dm_embed, view=view)
except Exception as e:
print(f"Failed to send feedback DM: {e}")
# Send transcript to log channel
if self.config.log_channel_id and transcript_file and os.path.exists(transcript_file):
try:
@ -1642,14 +1698,23 @@ class ConfigPanelView(discord.ui.View):
toggle_btn.callback = self._toggle_callback
self.add_item(toggle_btn)
# Default category
self.category_btn = discord.ui.Button(
label="📁 Catégorie par défaut",
style=discord.ButtonStyle.secondary,
custom_id="config_category"
)
self.category_btn.callback = self._category_callback
self.add_item(self.category_btn)
# Ajouter catégorie
add_cat_btn = discord.ui.Button(
self.add_cat_btn = discord.ui.Button(
style=discord.ButtonStyle.blurple,
label="Ajouter Catégorie",
custom_id="config_add_cat"
)
add_cat_btn.callback = self._add_cat_callback
self.add_item(add_cat_btn)
self.add_cat_btn.callback = self._add_cat_callback
self.add_item(self.add_cat_btn)
# Staff permissions
staff_btn = discord.ui.Button(
@ -1737,6 +1802,10 @@ class ConfigPanelView(discord.ui.View):
embed.add_field(name="Rôles", value=", ".join(role_mentions) if role_mentions else "Aucun", inline=False)
embed.add_field(name="Utilisateurs", value=", ".join(user_mentions) if user_mentions else "Aucun", inline=False)
async def _category_callback(self, interaction: discord.Interaction):
modal = SetCategoryModal(self.bot, self.storage, self.config)
await interaction.response.send_modal(modal)
async def _log_channel_callback(self, interaction: discord.Interaction):
modal = SetChannelModal(self.bot, self.storage, self.config, "log")
await interaction.response.send_modal(modal)
@ -1944,6 +2013,7 @@ class PermissionConfigView(discord.ui.View):
# Add components
self._add_role_select()
self._add_user_select()
self._add_remove_select()
def _add_role_select(self):
select = discord.ui.RoleSelect(
@ -1966,118 +2036,102 @@ class PermissionConfigView(discord.ui.View):
self.add_item(select)
async def _role_callback(self, interaction: discord.Interaction):
# Determine which list to update
if self.config_type == "staff":
target_list = self.config.staff_roles
else:
target_list = self.config.config_roles
try:
# Determine which list to update
if self.config_type == "staff":
target_list = self.config.staff_roles
else:
target_list = self.config.config_roles
# Get new selected IDs
# Note: RoleSelect/UserSelect returns the objects, not IDs directly in values sometimes depending on lib version,
# but interaction.data['values'] is reliable for IDs if we want raw.
# However, interaction.values which is bound to callback by library usually contains the objects.
# Let's use the view item's values.
# Get new selected IDs
new_ids = interaction.data.get('values', [])
added_count = 0
# Actually standard lib behavior: interaction.data['values'] contains IDs.
# But let's use the argument 'interaction' and the component.
for new_id in new_ids:
if new_id not in target_list:
target_list.append(new_id)
added_count += 1
# Better: use the values from the specific component that triggered this
# But since we have separate callbacks we can just read interaction.data
self.storage.save_config(interaction.guild_id, self.config)
selected_ids = [str(r.id) for r in interaction.data.get('values', [])] # But wait, select menu interactions return objects in the view item's values property if mapped? NO, interaction.values is for string selects.
# For Entity Select Menus (Role/User), interaction.data['values'] contains IDs.
# BUT, discord.py 2.0 uses select.values for string selects.
# For RoleSelect, values are the list of Role objects.
# Let's try to trust the interaction object's resolution.
# Wait, standard discord.py RoleSelect callback receives interaction.
# The select object itself will have 'values' populated with Role objects after processing.
# But we need to reference the select item.
# Since we added it dynamically, we can't easily reference 'self.role_select'.
# Workaround: Re-read from interaction.data['values'] which are IDs.
values = interaction.data.get('values', [])
# WE NEED TO MERGE with existing? No, select menu usually replaces selection if it shows current selection.
# BUT Discord UI Selects don't show "current selection" natively pre-filled unless we set defaults.
# AND we can only set defaults for StringSelect, NOT for RoleSelect/UserSelect (API Limitation).
# So RoleSelect/UserSelect always start empty.
# This implies we can only ADD/REMOVE or we have to handle it as "Add these", "Remove these"?
# OR we treat valid input as "Append these to existing" or "Replace existing"?
# Given we can't show pre-selected items, "Replace" is dangerous because user can't see what was there.
# "Append" is safer but how to remove?
# Modification: Make it "Toggle" or just "Add/Remove" via specific actions?
# A common pattern is: The select menu creates a list. We Add them.
# But how to remove?
# Maybe we should stick to STRING SELECT for removal if we want to show lists.
# But the user issue is "Can't see all roles".
# Better approach for Entity Selects:
# They are usually used for "Add these items".
# To remove, we might need a separate "Remove" workflow or a StringSelect of *current* items to remove.
# Let's implement: "Add selected roles/users to permission".
# And provide a way to "Clear/Remove" via a StringSelect of *existing* configured items.
# So:
# 1. RoleSelect (Add)
# 2. UserSelect (Add)
# 3. StringSelect (Remove) - Populated with currently configured items.
new_ids = interaction.data.get('values', [])
added_count = 0
for new_id in new_ids:
if new_id not in target_list:
target_list.append(new_id)
added_count += 1
self.storage.save_config(interaction.guild_id, self.config)
await interaction.response.send_message(
f"✅ **{added_count}** rôle(s) ajouté(s) à la configuration {self.config_type}.",
ephemeral=True
)
# Refresh view to update Remove dropdown if we add it
await self._refresh_view(interaction)
await self._refresh_view(interaction)
except Exception as e:
# Assuming kuby_logger is defined elsewhere, if not, replace with print or logging.error
# import kuby_logger # Uncomment if kuby_logger is not globally available
# kuby_logger.error(f"Error in _role_callback: {e}")
import traceback
traceback.print_exc()
await interaction.response.send_message("Une erreur est survenue lors de la mise à jour des rôles.", ephemeral=True)
async def _user_callback(self, interaction: discord.Interaction):
if self.config_type == "staff":
target_list = self.config.staff_users
else:
target_list = self.config.config_users
try:
if self.config_type == "staff":
target_list = self.config.staff_users
else:
target_list = self.config.config_users
new_ids = [int(uid) for uid in interaction.data.get('values', [])]
added_count = 0
new_ids = [int(uid) for uid in interaction.data.get('values', [])]
added_count = 0
for new_id in new_ids:
if new_id not in target_list:
target_list.append(new_id)
added_count += 1
for new_id in new_ids:
if new_id not in target_list:
target_list.append(new_id)
added_count += 1
self.storage.save_config(interaction.guild_id, self.config)
self.storage.save_config(interaction.guild_id, self.config)
await interaction.response.send_message(
f"✅ **{added_count}** utilisateur(s) ajouté(s) à la configuration {self.config_type}.",
ephemeral=True
)
await self._refresh_view(interaction)
await self._refresh_view(interaction)
except Exception as e:
# Assuming kuby_logger is defined elsewhere
# import kuby_logger
# kuby_logger.error(f"Error in _user_callback: {e}")
import traceback
traceback.print_exc()
await interaction.response.send_message("Une erreur est survenue lors de la mise à jour des utilisateurs.", ephemeral=True)
async def _refresh_view(self, interaction):
# Re-render the view?
# We can't easily edit the ephemeral message with a new view from here without 'response.edit_message'
# But we already responded to interaction.
# So we can followup edit?
# Actually we just want to update the "Remove" select menu.
# Let's add the Remove Select Menu.
self.clear_items()
self._add_role_select()
self._add_user_select()
self._add_remove_select()
await interaction.message.edit(view=self)
# Rebuild Embed
if self.config_type == "staff":
title = "Permissions Staff"
description = "Configurez qui peut gérer les tickets (répondre, fermer, etc.)"
color = discord.Color.blue()
target_roles = self.config.staff_roles
target_users = self.config.staff_users
else:
title = "Permissions Configuration"
description = "Configurez qui peut modifier les paramètres du bot (/ticketconfig)"
color = discord.Color.orange()
target_roles = self.config.config_roles
target_users = self.config.config_users
embed = discord.Embed(title=title, description=description, color=color)
# Add fields logic (inline reuse)
role_mentions = []
for role_id in target_roles:
role = self.guild.get_role(int(role_id))
if role:
role_mentions.append(role.mention)
user_mentions = []
for user_id in target_users:
user = self.guild.get_member(user_id)
if user:
user_mentions.append(user.mention)
else:
user_mentions.append(f"<@{user_id}>")
embed.add_field(name="Rôles", value=", ".join(role_mentions) if role_mentions else "Aucun", inline=False)
embed.add_field(name="Utilisateurs", value=", ".join(user_mentions) if user_mentions else "Aucun", inline=False)
await interaction.response.edit_message(embed=embed, view=self)
def _add_remove_select(self):
# Build options from current config
@ -2131,31 +2185,36 @@ class PermissionConfigView(discord.ui.View):
self.add_item(select)
async def _remove_callback(self, interaction: discord.Interaction):
values = interaction.data.get('values', [])
try:
values = interaction.data.get('values', [])
removed_count = 0
for val in values:
prefix, id_str = val.split('_')
id_val = int(id_str)
removed_count = 0
for val in values:
prefix, id_str = val.split('_')
id_val = int(id_str)
if prefix == 'r': # Role
target_list = self.config.staff_roles if self.config_type == "staff" else self.config.config_roles
if str(id_val) in target_list:
target_list.remove(str(id_val))
removed_count += 1
elif prefix == 'u': # User
target_list = self.config.staff_users if self.config_type == "staff" else self.config.config_users
if id_val in target_list:
target_list.remove(id_val)
removed_count += 1
if prefix == 'r': # Role
target_list = self.config.staff_roles if self.config_type == "staff" else self.config.config_roles
if str(id_val) in target_list:
target_list.remove(str(id_val))
removed_count += 1
elif prefix == 'u': # User
target_list = self.config.staff_users if self.config_type == "staff" else self.config.config_users
if id_val in target_list:
target_list.remove(id_val)
removed_count += 1
self.storage.save_config(interaction.guild_id, self.config)
self.storage.save_config(interaction.guild_id, self.config)
await interaction.response.send_message(
f"🗑️ **{removed_count}** permission(s) retirée(s).",
ephemeral=True
)
await self._refresh_view(interaction)
await self._refresh_view(interaction)
except Exception as e:
# Assuming kuby_logger is defined elsewhere
# import kuby_logger
# kuby_logger.error(f"Error in _remove_callback: {e}")
import traceback
traceback.print_exc()
await interaction.response.send_message("Une erreur est survenue lors de la suppression des permissions.", ephemeral=True)
class TicketCommands(commands.Cog):
@ -2289,7 +2348,7 @@ class TicketCommands(commands.Cog):
embed.set_footer(text="Utilisez les boutons ci-dessous pour configurer le système")
view = TicketSetupView(self.bot, self.storage, config)
view = ConfigPanelView(self.bot, self.storage, config)
await ctx.send(embed=embed, view=view, ephemeral=True)

View file

@ -0,0 +1,139 @@
import discord
from .data.models import TicketData
class FeedbackView(discord.ui.View):
def __init__(self, bot, storage, ticket: TicketData):
super().__init__(timeout=86400) # 24h timeout
self.bot = bot
self.storage = storage
self.ticket = ticket
self.rating = 0
self.comment = ""
# Add Select Menu for Rating
self.add_item(RatingSelect())
@discord.ui.button(label="📝 Laisser un commentaire", style=discord.ButtonStyle.secondary, custom_id="feedback_comment", row=1)
async def comment_button(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.send_modal(FeedbackModal(self))
@discord.ui.button(label="✅ Envoyer", style=discord.ButtonStyle.green, custom_id="feedback_submit", row=1)
async def submit_button(self, interaction: discord.Interaction, button: discord.ui.Button):
if self.rating == 0:
await interaction.response.send_message("❌ Veuillez sélectionner une note avant d'envoyer.", ephemeral=True)
return
# Save feedback
self.ticket.rating = self.rating
self.ticket.feedback = self.comment if self.comment else "Aucun commentaire"
self.storage.save_ticket(self.ticket)
# Disable view
for child in self.children:
child.disabled = True
await interaction.response.edit_message(content="✅ Merci pour votre retour !", view=self, embed=None)
# Log feedback if configured
try:
# Reload ticket to ensure we have latest data (especially claimed_by)
# We need to use the channel_id to find the ticket
reloaded_ticket = self.storage.load_ticket(self.ticket.channel_id)
if reloaded_ticket:
self.ticket = reloaded_ticket
print(f"DEBUG: Reloaded ticket {self.ticket.channel_id}. Claimed by: {self.ticket.claimed_by}", flush=True)
else:
print(f"DEBUG: Could not reload ticket {self.ticket.channel_id}", flush=True)
print(f"DEBUG: Feedback submitted for {self.ticket.channel_id}", flush=True)
if self.ticket.claimed_by:
staff_user = self.bot.get_user(self.ticket.claimed_by)
print(f"DEBUG: Staff user from cache: {staff_user}", flush=True)
if not staff_user:
# Try fetching if not in cache
try:
staff_user = await self.bot.fetch_user(self.ticket.claimed_by)
print(f"DEBUG: Staff user fetched: {staff_user}", flush=True)
except Exception as e:
print(f"DEBUG: Failed to fetch staff user: {e}", flush=True)
pass
if staff_user:
# Create feedback embed
embed = discord.Embed(
title="📝 Nouveau Commentaire Reçu",
description=f"Un utilisateur a laissé un avis sur le ticket #{self.ticket.channel_id}",
color=discord.Color.gold() if self.rating < 3 else discord.Color.green(),
timestamp=discord.utils.utcnow()
)
embed.add_field(
name="Note",
value=f"{'' * self.rating} ({self.rating}/5)",
inline=True
)
# Add user info if possible
user = self.bot.get_user(self.ticket.user_id)
user_name = f"{user.name} ({user.id})" if user else f"Utilisateur {self.ticket.user_id}"
embed.add_field(
name="Utilisateur",
value=user_name,
inline=True
)
feedback_text = self.comment if self.comment else "Aucun commentaire écrit."
embed.add_field(
name="Commentaire",
value=feedback_text,
inline=False
)
try:
await staff_user.send(embed=embed)
print(f"DEBUG: DM sent successfully to {staff_user}", flush=True)
except discord.Forbidden:
print(f"DEBUG: DM failed - Forbidden (DMs closed)", flush=True)
except Exception as e:
print(f"DEBUG: Error sending feedback DM: {e}", flush=True)
else:
print("DEBUG: Staff user object is None", flush=True)
else:
print("DEBUG: Ticket has no claimed_by value", flush=True)
except Exception as e:
print(f"Error in feedback notification: {e}", flush=True)
class RatingSelect(discord.ui.Select):
def __init__(self):
options = [
discord.SelectOption(label="⭐⭐⭐⭐⭐ (Excellent)", value="5", description="Service parfait !"),
discord.SelectOption(label="⭐⭐⭐⭐ (Très bien)", value="4", description="Très bon service"),
discord.SelectOption(label="⭐⭐⭐ (Bien)", value="3", description="Correct"),
discord.SelectOption(label="⭐⭐ (Moyen)", value="2", description="Peut mieux faire"),
discord.SelectOption(label="⭐ (Mauvais)", value="1", description="Insatisfaisant")
]
super().__init__(placeholder="Notez le service...", min_values=1, max_values=1, options=options, row=0)
async def callback(self, interaction: discord.Interaction):
self.view.rating = int(self.values[0])
await interaction.response.defer()
class FeedbackModal(discord.ui.Modal):
def __init__(self, view):
super().__init__(title="Votre avis")
self.view = view
self.comment = discord.ui.TextInput(
label="Commentaire",
style=discord.TextStyle.paragraph,
placeholder="Dites-nous ce que vous avez pensé du support...",
required=True,
max_length=1000
)
self.add_item(self.comment)
async def on_submit(self, interaction: discord.Interaction):
self.view.comment = self.comment.value
await interaction.response.send_message("Commentaire enregistré ! N'oubliez pas de valider avec 'Envoyer'.", ephemeral=True)

View file

@ -0,0 +1,329 @@
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))

View file

@ -0,0 +1,10 @@
[
{
"timestamp": "2026-01-24T15:13:01.488356",
"event_type": "member_join",
"member_id": 1038035891450556507,
"member_name": "celness",
"member_discriminator": "0",
"member_avatar": "https://cdn.discordapp.com/avatars/1038035891450556507/e57596b7be5db3a5f3baf75f5fd4720b.png?size=1024"
}
]

View file

@ -0,0 +1,77 @@
[
{
"timestamp": "2026-01-24T15:05:23.725825",
"event_type": "edited",
"message_id": 1464622068598575155,
"channel_id": 1464621977376522291,
"channel_name": "gameurpro12-écrit",
"author_id": 971446412690722826,
"author_name": "gameurpro12",
"author_roles": [
1366461904976871565,
1453708383235473459,
1454035592391299234,
1454034686979346495,
1453708344526246071,
1454034988080038040,
1366876636259024946
],
"content": "Les tickets prendront cette forme",
"attachments": [],
"embeds": [],
"details": {
"before_content": "Les tickets prendront cette forme",
"after_content": "Les tickets whitelist prendront cette forme"
}
},
{
"timestamp": "2026-01-24T15:05:52.316927",
"event_type": "edited",
"message_id": 1464622206439919658,
"channel_id": 1460048825665454344,
"channel_name": "🔢・nombres-infinis",
"author_id": 1355564506754973767,
"author_name": "alto1500",
"author_roles": [
1366461904976871565,
1453708383235473459,
1454042474141192316,
1453708358417912075
],
"content": "24",
"attachments": [],
"embeds": [],
"details": {
"before_content": "24",
"after_content": "240"
}
},
{
"timestamp": "2026-01-24T15:23:49.868209",
"event_type": "edited",
"message_id": 1464626575415705761,
"channel_id": 1453386193311105188,
"channel_name": "📡・annonces",
"author_id": 983747660265693258,
"author_name": "mr_reiko_",
"author_roles": [
1366461904976871565,
1453708383235473459,
1454035592391299234,
1454033803998920769,
1454034686979346495,
1464424459393040667,
1454034988080038040,
1453395626128707656,
1369003041927200858,
1366876636259024946
],
"content": "> # **__Annonce Ouverture officielle des Whitelist__** <:emoji_1:1458776441041850430> \n> \n> **Nous vous informons que les Whitelist sont officiellement ouvertes.** <a:56125loading:1413178655038902482> \n> \n> - Pour effectuer votre WL,** il vous suffit de créer un ticket dans le salon** <#1450002116537090149> / <#1463081283679817822> prévu à cet effet.\n> Une fois le ticket ouvert, **un membre du staff prendra votre demande en charge,** vous expliquera lensemble de la procédure et **vous accompagnera tout au long du processus.** \n> \n> - __**Rôles disponibles en semi FA**__\n> **Les rôles suivants sont actuellement disponibles en semi FA pour les joueurs WL ecrite effectuée :**\n> \n> <@&1453708467700502561> \n> \n> <@&1453708401933553849> \n> \n> <@&1453708560511926273> \n> \n> <@&1453708517302337695> \n> \n> <@&1453708475132674070> \n> \n> <@&1453708562474860617> \n> \n> - **Merci de respecter les consignes et de faire preuve de sérieux lors de votre démarche.**\n> **Nous restons à votre disposition via les tickets pour toute question.** <:50773approvedids:1464433520301572096> £\n> \n> **Cordialement <@&1458084692803981354> / <@&1453708378336399392> /** <t:1769264525:S> \n> \n> ||@everyone ||",
"attachments": [],
"embeds": [],
"details": {
"before_content": "> # **__Annonce Ouverture officielle des Whitelist__** <:emoji_1:1458776441041850430> \n> \n> **Nous vous informons que les Whitelist sont officiellement ouvertes.** <a:56125loading:1413178655038902482> \n> \n> - Pour effectuer votre WL,** il vous suffit de créer un ticket dans le salon** <#1450002116537090149> / <#1463081283679817822> prévu à cet effet.\n> Une fois le ticket ouvert, **un membre du staff prendra votre demande en charge,** vous expliquera lensemble de la procédure et **vous accompagnera tout au long du processus.** \n> \n> - __**Rôles disponibles en semi FA**__\n> **Les rôles suivants sont actuellement disponibles en semi FA pour les joueurs WL ecrite effectuée :**\n> \n> <@&1453708467700502561> \n> \n> <@&1453708401933553849> \n> \n> <@&1453708560511926273> \n> \n> <@&1453708517302337695> \n> \n> <@&1453708475132674070> \n> \n> <@&1453708562474860617> \n> \n> - **Merci de respecter les consignes et de faire preuve de sérieux lors de votre démarche.**\n> **Nous restons à votre disposition via les tickets pour toute question.** <:50773approvedids:1464433520301572096> £\n> \n> **Cordialement <@&1458084692803981354> / <@&1453708378336399392> /** <t:1769264525:S> \n> \n> ||@everyone ||",
"after_content": "> # **__Annonce Ouverture officielle des Whitelist__** <:emoji_1:1458776441041850430> \n> \n> **Nous vous informons que les Whitelist sont officiellement ouvertes.** <a:56125loading:1413178655038902482> \n> \n> - Pour effectuer votre WL,** il vous suffit de créer un ticket dans le salon** <#1450002116537090149> / <#1463081283679817822> prévu à cet effet.\n> Une fois le ticket ouvert, **un membre du staff prendra votre demande en charge,** vous expliquera lensemble de la procédure et **vous accompagnera tout au long du processus.** \n> \n> - __**Rôles disponibles en semi FA**__\n> **Les rôles suivants sont actuellement disponibles en semi FA pour les joueurs WL ecrite effectuée :**\n> \n> <@&1453708467700502561> \n> \n> <@&1453708401933553849> \n> \n> <@&1453708560511926273> \n> \n> <@&1453708517302337695> \n> \n> <@&1453708475132674070> \n> \n> <@&1453708562474860617> \n> \n> - **Merci de respecter les consignes et de faire preuve de sérieux lors de votre démarche.**\n> **Nous restons à votre disposition via les tickets pour toute question.** <:50773approvedids:1464433520301572096> \n> \n> **Cordialement <@&1458084692803981354> / <@&1453708378336399392> /** <t:1769264525:S> \n> \n> ||@everyone ||"
}
}
]

View file

@ -0,0 +1,245 @@
[
{
"timestamp": "2026-01-24T15:04:34.353302",
"event_type": "left",
"member_id": 1453734314088075306,
"member_name": "patalhuile",
"channel_id": 1407722372588376084,
"channel_name": "〚🌟〛𝐊𝐀𝐘𝐑𝐈𝐗",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:06:06.060691",
"event_type": "joined",
"member_id": 971446412690722826,
"member_name": "gameurpro12",
"channel_id": 1457073413616046080,
"channel_name": "👑・Bureau Fondation",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:06:12.905500",
"event_type": "left",
"member_id": 971446412690722826,
"member_name": "gameurpro12",
"channel_id": 1457073413616046080,
"channel_name": "👑・Bureau Fondation",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:12:23.224137",
"event_type": "joined",
"member_id": 983747660265693258,
"member_name": "mr_reiko_",
"channel_id": 1453397135234957442,
"channel_name": "📓・Bureaux 1",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:12:25.430175",
"event_type": "left",
"member_id": 983747660265693258,
"member_name": "mr_reiko_",
"channel_id": 1453397135234957442,
"channel_name": "📓・Bureaux 1",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:12:30.909163",
"event_type": "left",
"member_id": 1263573205268828231,
"member_name": "arthena_931",
"channel_id": 1457073413616046080,
"channel_name": "👑・Bureau Fondation",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:13:02.024297",
"event_type": "left",
"member_id": 353942721997832195,
"member_name": "mg_studios_",
"channel_id": 1457073413616046080,
"channel_name": "👑・Bureau Fondation",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:13:17.531634",
"event_type": "joined",
"member_id": 1263573205268828231,
"member_name": "arthena_931",
"channel_id": 1447649079952802055,
"channel_name": "🔊・Publique 1",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:13:26.906602",
"event_type": "left",
"member_id": 1263573205268828231,
"member_name": "arthena_931",
"channel_id": 1447649079952802055,
"channel_name": "🔊・Publique 1",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:15:50.817844",
"event_type": "joined",
"member_id": 1453734314088075306,
"member_name": "patalhuile",
"channel_id": 1407722372588376084,
"channel_name": "〚🌟〛𝐊𝐀𝐘𝐑𝐈𝐗",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:18:40.775427",
"event_type": "left",
"member_id": 945580436732641320,
"member_name": "melhoan",
"channel_id": 1407722372588376084,
"channel_name": "〚🌟〛𝐊𝐀𝐘𝐑𝐈𝐗",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:18:44.516024",
"event_type": "joined",
"member_id": 945580436732641320,
"member_name": "melhoan",
"channel_id": 1407722372588376084,
"channel_name": "〚🌟〛𝐊𝐀𝐘𝐑𝐈𝐗",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:20:36.058676",
"event_type": "left",
"member_id": 1453734314088075306,
"member_name": "patalhuile",
"channel_id": 1407722372588376084,
"channel_name": "〚🌟〛𝐊𝐀𝐘𝐑𝐈𝐗",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:27:14.017625",
"event_type": "left",
"member_id": 945580436732641320,
"member_name": "melhoan",
"channel_id": 1407722372588376084,
"channel_name": "〚🌟〛𝐊𝐀𝐘𝐑𝐈𝐗",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:29:52.855600",
"event_type": "joined",
"member_id": 1263573205268828231,
"member_name": "arthena_931",
"channel_id": 1407780201462497522,
"channel_name": "〚🔈〛𝐀𝐓𝐓𝐄𝐍𝐓𝐄 𝐌𝐎𝐎𝐕",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:31:33.895832",
"event_type": "joined",
"member_id": 1296914730669183066,
"member_name": "iikileur_02378",
"channel_id": 1447649079952802055,
"channel_name": "🔊・Publique 1",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:31:44.051002",
"event_type": "moved_from",
"member_id": 534003230435442690,
"member_name": "nixfix06",
"channel_id": 1457073413616046080,
"channel_name": "👑・Bureau Fondation",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:31:44.051366",
"event_type": "moved_to",
"member_id": 534003230435442690,
"member_name": "nixfix06",
"channel_id": 1447649079952802055,
"channel_name": "🔊・Publique 1",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:33:48.580429",
"event_type": "joined",
"member_id": 1320118755090759711,
"member_name": "jl_xixo",
"channel_id": 1447649079952802055,
"channel_name": "🔊・Publique 1",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:33:51.104140",
"event_type": "joined",
"member_id": 1389671060902777056,
"member_name": "elite_v.2_70323",
"channel_id": 1407780201462497522,
"channel_name": "〚🔈〛𝐀𝐓𝐓𝐄𝐍𝐓𝐄 𝐌𝐎𝐎𝐕",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:35:01.627777",
"event_type": "left",
"member_id": 1389671060902777056,
"member_name": "elite_v.2_70323",
"channel_id": 1407780201462497522,
"channel_name": "〚🔈〛𝐀𝐓𝐓𝐄𝐍𝐓𝐄 𝐌𝐎𝐎𝐕",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:35:02.783293",
"event_type": "left",
"member_id": 1296914730669183066,
"member_name": "iikileur_02378",
"channel_id": 1447649079952802055,
"channel_name": "🔊・Publique 1",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:35:09.067327",
"event_type": "left",
"member_id": 1263573205268828231,
"member_name": "arthena_931",
"channel_id": 1407780201462497522,
"channel_name": "〚🔈〛𝐀𝐓𝐓𝐄𝐍𝐓𝐄 𝐌𝐎𝐎𝐕",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:35:15.317831",
"event_type": "moved_from",
"member_id": 534003230435442690,
"member_name": "nixfix06",
"channel_id": 1447649079952802055,
"channel_name": "🔊・Publique 1",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:35:15.318377",
"event_type": "moved_to",
"member_id": 534003230435442690,
"member_name": "nixfix06",
"channel_id": 1457073756764639355,
"channel_name": "👔・Bureau Direction",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:35:20.522454",
"event_type": "left",
"member_id": 1320118755090759711,
"member_name": "jl_xixo",
"channel_id": 1447649079952802055,
"channel_name": "🔊・Publique 1",
"channel_type": "voice"
},
{
"timestamp": "2026-01-24T15:37:06.015710",
"event_type": "joined",
"member_id": 1433834565042180149,
"member_name": "alexandre07_08_13804",
"channel_id": 1447649079952802055,
"channel_name": "🔊・Publique 1",
"channel_type": "voice"
}
]

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461099541884567765,
"guild_id": 1369669999345537145,
"user_id": 1459567012031234198,
"category_id": "3b0b9bc1",
"status": "open",
"priority": "normal",
"created_at": "2026-01-14T21:47:56.842444",
"closed_at": null,
"claimed_by": null,
"messages": [],
"reason": "dzqddqz",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461101515270783147,
"guild_id": 1369669999345537145,
"user_id": 1459567012031234198,
"category_id": "3b0b9bc1",
"status": "open",
"priority": "normal",
"created_at": "2026-01-14T21:55:47.336657",
"closed_at": null,
"claimed_by": null,
"messages": [],
"reason": "fesfsfe",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,58 @@
{
"1369669999345537145": {
"guild_id": 1369669999345537145,
"enabled": true,
"categories": [
{
"id": "3b0b9bc1",
"name": "Mon cul",
"description": "Mon Anus",
"emoji": "🎫",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
},
{
"id": "91522e2c",
"name": "claudo",
"description": "un clochard",
"emoji": "📋",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
}
],
"default_category": null,
"log_channel_id": 1369669999677145103,
"archive_channel_id": null,
"staff_roles": [
"1369769836028231730"
],
"staff_users": [],
"config_roles": [
"1369769836028231730"
],
"config_users": [],
"max_tickets_per_user": 5,
"auto_close_enabled": false,
"auto_close_days": 7,
"transcript_enabled": true,
"claim_enabled": true,
"survey_enabled": true,
"panel_channel_id": null,
"welcome_enabled": true,
"priority_enabled": true
}
}

View file

@ -0,0 +1,60 @@
{
"1369669999345537145": {
"guild_id": 1369669999345537145,
"enabled": true,
"categories": [
{
"id": "3b0b9bc1",
"name": "Mon cul",
"description": "Mon Anus",
"emoji": "🎫",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
},
{
"id": "91522e2c",
"name": "claudo",
"description": "un clochard",
"emoji": "📋",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
}
],
"default_category": null,
"log_channel_id": 1369669999677145103,
"archive_channel_id": null,
"staff_roles": [
"1369769836028231730"
],
"staff_users": [],
"config_roles": [
"1369769836028231730"
],
"config_users": [
727188532669448509
],
"max_tickets_per_user": 5,
"auto_close_enabled": false,
"auto_close_days": 7,
"transcript_enabled": true,
"claim_enabled": true,
"survey_enabled": true,
"panel_channel_id": null,
"welcome_enabled": true,
"priority_enabled": true
}
}

View file

@ -0,0 +1,60 @@
{
"1369669999345537145": {
"guild_id": 1369669999345537145,
"enabled": true,
"categories": [
{
"id": "3b0b9bc1",
"name": "Mon cul",
"description": "Mon Anus",
"emoji": "🎫",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
},
{
"id": "91522e2c",
"name": "claudo",
"description": "un clochard",
"emoji": "📋",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
}
],
"default_category": null,
"log_channel_id": 1369669999677145103,
"archive_channel_id": null,
"staff_roles": [
"1369769836028231730"
],
"staff_users": [],
"config_roles": [
"1369769836028231730"
],
"config_users": [
727188532669448509
],
"max_tickets_per_user": 5,
"auto_close_enabled": false,
"auto_close_days": 7,
"transcript_enabled": true,
"claim_enabled": true,
"survey_enabled": true,
"panel_channel_id": null,
"welcome_enabled": true,
"priority_enabled": true
}
}

View file

@ -0,0 +1,60 @@
{
"1369669999345537145": {
"guild_id": 1369669999345537145,
"enabled": true,
"categories": [
{
"id": "3b0b9bc1",
"name": "Mon cul",
"description": "Mon Anus",
"emoji": "🎫",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
},
{
"id": "91522e2c",
"name": "claudo",
"description": "un clochard",
"emoji": "📋",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
}
],
"default_category": null,
"log_channel_id": 1369669999677145103,
"archive_channel_id": null,
"staff_roles": [
"1369769836028231730"
],
"staff_users": [],
"config_roles": [
"1369769836028231730"
],
"config_users": [
727188532669448509
],
"max_tickets_per_user": 5,
"auto_close_enabled": false,
"auto_close_days": 7,
"transcript_enabled": true,
"claim_enabled": true,
"survey_enabled": true,
"panel_channel_id": null,
"welcome_enabled": true,
"priority_enabled": true
}
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461102167132737781,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "3b0b9bc1",
"status": "open",
"priority": "normal",
"created_at": "2026-01-14T21:58:22.810654",
"closed_at": null,
"claimed_by": null,
"messages": [],
"reason": "fesghesqh",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,60 @@
{
"1369669999345537145": {
"guild_id": 1369669999345537145,
"enabled": true,
"categories": [
{
"id": "3b0b9bc1",
"name": "Mon cul",
"description": "Mon Anus",
"emoji": "🎫",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
},
{
"id": "91522e2c",
"name": "claudo",
"description": "un clochard",
"emoji": "📋",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
}
],
"default_category": "1369669999677145104",
"log_channel_id": 1369669999677145103,
"archive_channel_id": null,
"staff_roles": [
"1369769836028231730"
],
"staff_users": [],
"config_roles": [
"1369769836028231730"
],
"config_users": [
727188532669448509
],
"max_tickets_per_user": 5,
"auto_close_enabled": false,
"auto_close_days": 7,
"transcript_enabled": true,
"claim_enabled": true,
"survey_enabled": true,
"panel_channel_id": null,
"welcome_enabled": true,
"priority_enabled": true
}
}

View file

@ -0,0 +1,58 @@
{
"1369669999345537145": {
"guild_id": 1369669999345537145,
"enabled": true,
"categories": [
{
"id": "3b0b9bc1",
"name": "Mon cul",
"description": "Mon Anus",
"emoji": "🎫",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
},
{
"id": "91522e2c",
"name": "claudo",
"description": "un clochard",
"emoji": "📋",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
}
],
"default_category": "1369669999677145104",
"log_channel_id": 1369669999677145103,
"archive_channel_id": null,
"staff_roles": [],
"staff_users": [],
"config_roles": [
"1369769836028231730"
],
"config_users": [
727188532669448509
],
"max_tickets_per_user": 5,
"auto_close_enabled": false,
"auto_close_days": 7,
"transcript_enabled": true,
"claim_enabled": true,
"survey_enabled": true,
"panel_channel_id": null,
"welcome_enabled": true,
"priority_enabled": true
}
}

View file

@ -0,0 +1,56 @@
{
"1369669999345537145": {
"guild_id": 1369669999345537145,
"enabled": true,
"categories": [
{
"id": "3b0b9bc1",
"name": "Mon cul",
"description": "Mon Anus",
"emoji": "🎫",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
},
{
"id": "91522e2c",
"name": "claudo",
"description": "un clochard",
"emoji": "📋",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
}
],
"default_category": "1369669999677145104",
"log_channel_id": 1369669999677145103,
"archive_channel_id": null,
"staff_roles": [],
"staff_users": [],
"config_roles": [
"1369769836028231730"
],
"config_users": [],
"max_tickets_per_user": 5,
"auto_close_enabled": false,
"auto_close_days": 7,
"transcript_enabled": true,
"claim_enabled": true,
"survey_enabled": true,
"panel_channel_id": null,
"welcome_enabled": true,
"priority_enabled": true
}
}

View file

@ -0,0 +1,54 @@
{
"1369669999345537145": {
"guild_id": 1369669999345537145,
"enabled": true,
"categories": [
{
"id": "3b0b9bc1",
"name": "Mon cul",
"description": "Mon Anus",
"emoji": "🎫",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
},
{
"id": "91522e2c",
"name": "claudo",
"description": "un clochard",
"emoji": "📋",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
}
],
"default_category": "1369669999677145104",
"log_channel_id": 1369669999677145103,
"archive_channel_id": null,
"staff_roles": [],
"staff_users": [],
"config_roles": [],
"config_users": [],
"max_tickets_per_user": 5,
"auto_close_enabled": false,
"auto_close_days": 7,
"transcript_enabled": true,
"claim_enabled": true,
"survey_enabled": true,
"panel_channel_id": null,
"welcome_enabled": true,
"priority_enabled": true
}
}

View file

@ -0,0 +1,54 @@
{
"1369669999345537145": {
"guild_id": 1369669999345537145,
"enabled": true,
"categories": [
{
"id": "3b0b9bc1",
"name": "Mon cul",
"description": "Mon Anus",
"emoji": "🎫",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
},
{
"id": "91522e2c",
"name": "claudo",
"description": "un clochard",
"emoji": "📋",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
}
],
"default_category": "1369669999677145104",
"log_channel_id": 1369669999677145103,
"archive_channel_id": null,
"staff_roles": [],
"staff_users": [],
"config_roles": [],
"config_users": [],
"max_tickets_per_user": 5,
"auto_close_enabled": false,
"auto_close_days": 7,
"transcript_enabled": true,
"claim_enabled": true,
"survey_enabled": true,
"panel_channel_id": null,
"welcome_enabled": true,
"priority_enabled": true
}
}

View file

@ -0,0 +1,56 @@
{
"1369669999345537145": {
"guild_id": 1369669999345537145,
"enabled": true,
"categories": [
{
"id": "3b0b9bc1",
"name": "Mon cul",
"description": "Mon Anus",
"emoji": "🎫",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
},
{
"id": "91522e2c",
"name": "claudo",
"description": "un clochard",
"emoji": "📋",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
}
],
"default_category": "1369669999677145104",
"log_channel_id": 1369669999677145103,
"archive_channel_id": null,
"staff_roles": [
"1369769836028231730"
],
"staff_users": [],
"config_roles": [],
"config_users": [],
"max_tickets_per_user": 5,
"auto_close_enabled": false,
"auto_close_days": 7,
"transcript_enabled": true,
"claim_enabled": true,
"survey_enabled": true,
"panel_channel_id": null,
"welcome_enabled": true,
"priority_enabled": true
}
}

View file

@ -0,0 +1,56 @@
{
"1369669999345537145": {
"guild_id": 1369669999345537145,
"enabled": true,
"categories": [
{
"id": "3b0b9bc1",
"name": "Mon cul",
"description": "Mon Anus",
"emoji": "🎫",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
},
{
"id": "91522e2c",
"name": "claudo",
"description": "un clochard",
"emoji": "📋",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
}
],
"default_category": "1369669999677145104",
"log_channel_id": 1369669999677145103,
"archive_channel_id": null,
"staff_roles": [
"1369769836028231730"
],
"staff_users": [],
"config_roles": [],
"config_users": [],
"max_tickets_per_user": 5,
"auto_close_enabled": false,
"auto_close_days": 7,
"transcript_enabled": true,
"claim_enabled": true,
"survey_enabled": true,
"panel_channel_id": null,
"welcome_enabled": true,
"priority_enabled": true
}
}

View file

@ -0,0 +1,58 @@
{
"1369669999345537145": {
"guild_id": 1369669999345537145,
"enabled": true,
"categories": [
{
"id": "3b0b9bc1",
"name": "Mon cul",
"description": "Mon Anus",
"emoji": "🎫",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
},
{
"id": "91522e2c",
"name": "claudo",
"description": "un clochard",
"emoji": "📋",
"color": "#3498db",
"staff_roles": [],
"welcome_message": "Merci d'avoir créé un ticket. Notre équipe va vous répondre sous peu.",
"require_reason": false,
"max_tickets_per_user": 5,
"auto_close_days": 7,
"priority_enabled": true,
"allow_claims": true,
"survey_enabled": true
}
],
"default_category": "1369669999677145104",
"log_channel_id": 1369669999677145103,
"archive_channel_id": null,
"staff_roles": [
"1369769836028231730"
],
"staff_users": [],
"config_roles": [
"1369769836028231730"
],
"config_users": [],
"max_tickets_per_user": 5,
"auto_close_enabled": false,
"auto_close_days": 7,
"transcript_enabled": true,
"claim_enabled": true,
"survey_enabled": true,
"panel_channel_id": null,
"welcome_enabled": true,
"priority_enabled": true
}
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461105087840649403,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "91522e2c",
"status": "open",
"priority": "normal",
"created_at": "2026-01-14T22:09:59.255828",
"closed_at": null,
"claimed_by": null,
"messages": [],
"reason": "esfse",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461105782194962634,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "91522e2c",
"status": "open",
"priority": "normal",
"created_at": "2026-01-14T22:12:44.756426",
"closed_at": null,
"claimed_by": null,
"messages": [],
"reason": "sgdfhg",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461105782194962634,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "91522e2c",
"status": "claimed",
"priority": "normal",
"created_at": "2026-01-14T22:12:44.756426",
"closed_at": null,
"claimed_by": 971446412690722826,
"messages": [],
"reason": "sgdfhg",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461106046088122481,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "91522e2c",
"status": "open",
"priority": "normal",
"created_at": "2026-01-14T22:13:48.463486",
"closed_at": null,
"claimed_by": null,
"messages": [],
"reason": "gezqetwh",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461106046088122481,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "91522e2c",
"status": "claimed",
"priority": "normal",
"created_at": "2026-01-14T22:13:48.463486",
"closed_at": null,
"claimed_by": 971446412690722826,
"messages": [],
"reason": "gezqetwh",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461106046088122481,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "91522e2c",
"status": "closed",
"priority": "normal",
"created_at": "2026-01-14T22:13:48.463486",
"closed_at": "2026-01-14T22:14:01.855699",
"claimed_by": 971446412690722826,
"messages": [],
"reason": "gezqetwh",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461110002814029906,
"guild_id": 1369669999345537145,
"user_id": 353942721997832195,
"category_id": "3b0b9bc1",
"status": "open",
"priority": "normal",
"created_at": "2026-01-14T22:29:30.989520",
"closed_at": null,
"claimed_by": null,
"messages": [],
"reason": "bouh",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461110002814029906,
"guild_id": 1369669999345537145,
"user_id": 353942721997832195,
"category_id": "3b0b9bc1",
"status": "closed",
"priority": "normal",
"created_at": "2026-01-14T22:29:30.989520",
"closed_at": "2026-01-14T22:29:45.646518",
"claimed_by": null,
"messages": [],
"reason": "bouh",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461775280107687966,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "91522e2c",
"status": "open",
"priority": "normal",
"created_at": "2026-01-16T18:33:05.351747",
"closed_at": null,
"claimed_by": null,
"messages": [],
"reason": "gyt,njy",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461775280107687966,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "91522e2c",
"status": "closed",
"priority": "normal",
"created_at": "2026-01-16T18:33:05.351747",
"closed_at": "2026-01-16T18:33:17.062053",
"claimed_by": null,
"messages": [],
"reason": "gyt,njy",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1459546304333086802,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "3b0b9bc1",
"status": "open",
"priority": "normal",
"created_at": "2026-01-10T14:55:56.156555",
"closed_at": null,
"claimed_by": null,
"messages": [],
"reason": "eqqe",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1459546304333086802,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "3b0b9bc1",
"status": "closed",
"priority": "normal",
"created_at": "2026-01-10T14:55:56.156555",
"closed_at": "2026-01-16T18:39:32.843410",
"claimed_by": null,
"messages": [],
"reason": "eqqe",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461776856721391758,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "3b0b9bc1",
"status": "open",
"priority": "normal",
"created_at": "2026-01-16T18:39:21.262335",
"closed_at": null,
"claimed_by": null,
"messages": [],
"reason": "rdshgsthd",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461776856721391758,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "3b0b9bc1",
"status": "closed",
"priority": "normal",
"created_at": "2026-01-16T18:39:21.262335",
"closed_at": "2026-01-16T18:43:52.750006",
"claimed_by": null,
"messages": [],
"reason": "rdshgsthd",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -3,14 +3,14 @@
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "3b0b9bc1",
"status": "open",
"status": "closed",
"priority": "normal",
"created_at": "2026-01-10T14:55:56.156555",
"closed_at": null,
"closed_at": "2026-01-16T18:39:32.843410",
"claimed_by": null,
"messages": [],
"reason": "eqqe",
"transcript_path": null,
"rating": null,
"feedback": null
"rating": 2,
"feedback": "qztgtg"
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461099541884567765,
"guild_id": 1369669999345537145,
"user_id": 1459567012031234198,
"category_id": "3b0b9bc1",
"status": "closed",
"priority": "normal",
"created_at": "2026-01-14T21:47:56.842444",
"closed_at": "2026-01-14T21:48:07.370706",
"claimed_by": null,
"messages": [],
"reason": "dzqddqz",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461101515270783147,
"guild_id": 1369669999345537145,
"user_id": 1459567012031234198,
"category_id": "3b0b9bc1",
"status": "closed",
"priority": "normal",
"created_at": "2026-01-14T21:55:47.336657",
"closed_at": "2026-01-14T21:56:13.233056",
"claimed_by": null,
"messages": [],
"reason": "fesfsfe",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461102167132737781,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "3b0b9bc1",
"status": "closed",
"priority": "normal",
"created_at": "2026-01-14T21:58:22.810654",
"closed_at": "2026-01-14T21:58:36.784815",
"claimed_by": null,
"messages": [],
"reason": "fesghesqh",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461105087840649403,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "91522e2c",
"status": "closed",
"priority": "normal",
"created_at": "2026-01-14T22:09:59.255828",
"closed_at": "2026-01-14T22:10:13.207505",
"claimed_by": null,
"messages": [],
"reason": "esfse",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461105782194962634,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "91522e2c",
"status": "closed",
"priority": "normal",
"created_at": "2026-01-14T22:12:44.756426",
"closed_at": "2026-01-14T22:13:02.370351",
"claimed_by": 971446412690722826,
"messages": [],
"reason": "sgdfhg",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461106046088122481,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "91522e2c",
"status": "closed",
"priority": "normal",
"created_at": "2026-01-14T22:13:48.463486",
"closed_at": "2026-01-14T22:14:01.855699",
"claimed_by": 971446412690722826,
"messages": [],
"reason": "gezqetwh",
"transcript_path": null,
"rating": 3,
"feedback": "Cool !"
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461110002814029906,
"guild_id": 1369669999345537145,
"user_id": 353942721997832195,
"category_id": "3b0b9bc1",
"status": "closed",
"priority": "normal",
"created_at": "2026-01-14T22:29:30.989520",
"closed_at": "2026-01-14T22:29:45.646518",
"claimed_by": null,
"messages": [],
"reason": "bouh",
"transcript_path": null,
"rating": 3,
"feedback": "fuck gameur"
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461775280107687966,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "91522e2c",
"status": "closed",
"priority": "normal",
"created_at": "2026-01-16T18:33:05.351747",
"closed_at": "2026-01-16T18:33:17.062053",
"claimed_by": null,
"messages": [],
"reason": "gyt,njy",
"transcript_path": null,
"rating": 5,
"feedback": "Cool"
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461776856721391758,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "3b0b9bc1",
"status": "closed",
"priority": "normal",
"created_at": "2026-01-16T18:39:21.262335",
"closed_at": "2026-01-16T18:43:52.750006",
"claimed_by": null,
"messages": [],
"reason": "rdshgsthd",
"transcript_path": null,
"rating": 3,
"feedback": "dsgrq"
}

View file

@ -0,0 +1,16 @@
{
"channel_id": 1461777953376698398,
"guild_id": 1369669999345537145,
"user_id": 971446412690722826,
"category_id": "91522e2c",
"status": "open",
"priority": "normal",
"created_at": "2026-01-16T18:43:42.737852",
"closed_at": null,
"claimed_by": null,
"messages": [],
"reason": "grdswgrdgrd",
"transcript_path": null,
"rating": null,
"feedback": null
}

View file

@ -0,0 +1,210 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Transcript - Ticket #1459546304333086802</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f5f6fa;
color: #2c3e50;
line-height: 1.6;
}
.container {
max-width: 900px;
margin: 0 auto;
padding: 20px;
}
.header {
background: linear-gradient(135deg, #3498db, #34495e);
color: white;
padding: 30px;
border-radius: 10px;
margin-bottom: 20px;
}
.header h1 {
font-size: 24px;
margin-bottom: 10px;
}
.header-meta {
display: flex;
flex-wrap: wrap;
gap: 20px;
font-size: 14px;
opacity: 0.9;
}
.meta-item {
display: flex;
align-items: center;
gap: 5px;
}
.status-badge {
display: inline-block;
padding: 3px 10px;
border-radius: 15px;
font-size: 12px;
font-weight: bold;
text-transform: uppercase;
}
.status-open { background: #27ae60; }
.status-closed { background: #e74c3c; }
.status-claimed { background: #f39c12; }
.messages-section {
background: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.messages-section h3 {
margin-bottom: 15px;
color: #3498db;
border-bottom: 2px solid #ecf0f1;
padding-bottom: 10px;
}
.message {
padding: 15px;
border-bottom: 1px solid #ecf0f1;
}
.message:last-child {
border-bottom: none;
}
.message.staff-message {
background: #f8f9fa;
border-left: 3px solid #3498db;
}
.message-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
}
.author {
font-weight: bold;
color: #2c3e50;
}
.staff-badge {
background: #3498db;
color: white;
padding: 2px 6px;
border-radius: 3px;
font-size: 10px;
font-weight: bold;
}
.timestamp {
color: #95a5a6;
font-size: 12px;
}
.message-content {
color: #34495e;
word-break: break-word;
}
.stats-section {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.stats-section h3 {
margin-bottom: 15px;
color: #3498db;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
}
.stat-item {
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
text-align: center;
}
.stat-label {
display: block;
font-size: 12px;
color: #7f8c8d;
margin-bottom: 5px;
}
.stat-value {
font-size: 18px;
font-weight: bold;
color: #3498db;
}
.footer {
text-align: center;
padding: 20px;
color: #95a5a6;
font-size: 12px;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎫 Transcript de Ticket</h1>
<div class="header-meta">
<div class="meta-item">
<span>📌 ID:</span>
<span>1459546304333086802</span>
</div>
<div class="meta-item">
<span>📁 Catégorie:</span>
<span>3b0b9bc1</span>
</div>
<div class="meta-item">
<span>⚡ Priorité:</span>
<span style="color: #3498db; font-weight: bold;">NORMAL</span>
</div>
<div class="meta-item">
<span>📊 Statut:</span>
<span class="status-badge status-open">open</span>
</div>
<div class="meta-item">
<span>📅 Créé:</span>
<span>10/01/2026 14:55</span>
</div>
</div>
</div>
<div class="messages-section">
<h3>💬 Messages (0)</h3>
</div>
<div class="stats-section">
<h3>📊 Statistiques</h3>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-label">Durée</span>
<span class="stat-value">6.2 j</span>
</div>
<div class="stat-item">
<span class="stat-label">Messages</span>
<span class="stat-value">0</span>
</div>
<div class="stat-item">
<span class="stat-label">Note</span>
<span class="stat-value">Pas de note</span>
</div>
</div>
</div>
<div class="footer">
<p>Généré le 16/01/2026 à 18:39:32</p>
<p>Système de Tickets - Kuby Bot</p>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,210 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Transcript - Ticket #1461099541884567765</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f5f6fa;
color: #2c3e50;
line-height: 1.6;
}
.container {
max-width: 900px;
margin: 0 auto;
padding: 20px;
}
.header {
background: linear-gradient(135deg, #3498db, #34495e);
color: white;
padding: 30px;
border-radius: 10px;
margin-bottom: 20px;
}
.header h1 {
font-size: 24px;
margin-bottom: 10px;
}
.header-meta {
display: flex;
flex-wrap: wrap;
gap: 20px;
font-size: 14px;
opacity: 0.9;
}
.meta-item {
display: flex;
align-items: center;
gap: 5px;
}
.status-badge {
display: inline-block;
padding: 3px 10px;
border-radius: 15px;
font-size: 12px;
font-weight: bold;
text-transform: uppercase;
}
.status-open { background: #27ae60; }
.status-closed { background: #e74c3c; }
.status-claimed { background: #f39c12; }
.messages-section {
background: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.messages-section h3 {
margin-bottom: 15px;
color: #3498db;
border-bottom: 2px solid #ecf0f1;
padding-bottom: 10px;
}
.message {
padding: 15px;
border-bottom: 1px solid #ecf0f1;
}
.message:last-child {
border-bottom: none;
}
.message.staff-message {
background: #f8f9fa;
border-left: 3px solid #3498db;
}
.message-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
}
.author {
font-weight: bold;
color: #2c3e50;
}
.staff-badge {
background: #3498db;
color: white;
padding: 2px 6px;
border-radius: 3px;
font-size: 10px;
font-weight: bold;
}
.timestamp {
color: #95a5a6;
font-size: 12px;
}
.message-content {
color: #34495e;
word-break: break-word;
}
.stats-section {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.stats-section h3 {
margin-bottom: 15px;
color: #3498db;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
}
.stat-item {
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
text-align: center;
}
.stat-label {
display: block;
font-size: 12px;
color: #7f8c8d;
margin-bottom: 5px;
}
.stat-value {
font-size: 18px;
font-weight: bold;
color: #3498db;
}
.footer {
text-align: center;
padding: 20px;
color: #95a5a6;
font-size: 12px;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎫 Transcript de Ticket</h1>
<div class="header-meta">
<div class="meta-item">
<span>📌 ID:</span>
<span>1461099541884567765</span>
</div>
<div class="meta-item">
<span>📁 Catégorie:</span>
<span>3b0b9bc1</span>
</div>
<div class="meta-item">
<span>⚡ Priorité:</span>
<span style="color: #3498db; font-weight: bold;">NORMAL</span>
</div>
<div class="meta-item">
<span>📊 Statut:</span>
<span class="status-badge status-open">open</span>
</div>
<div class="meta-item">
<span>📅 Créé:</span>
<span>14/01/2026 21:47</span>
</div>
</div>
</div>
<div class="messages-section">
<h3>💬 Messages (0)</h3>
</div>
<div class="stats-section">
<h3>📊 Statistiques</h3>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-label">Durée</span>
<span class="stat-value">0 min</span>
</div>
<div class="stat-item">
<span class="stat-label">Messages</span>
<span class="stat-value">0</span>
</div>
<div class="stat-item">
<span class="stat-label">Note</span>
<span class="stat-value">Pas de note</span>
</div>
</div>
</div>
<div class="footer">
<p>Généré le 14/01/2026 à 21:48:07</p>
<p>Système de Tickets - Kuby Bot</p>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,210 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Transcript - Ticket #1461101515270783147</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f5f6fa;
color: #2c3e50;
line-height: 1.6;
}
.container {
max-width: 900px;
margin: 0 auto;
padding: 20px;
}
.header {
background: linear-gradient(135deg, #3498db, #34495e);
color: white;
padding: 30px;
border-radius: 10px;
margin-bottom: 20px;
}
.header h1 {
font-size: 24px;
margin-bottom: 10px;
}
.header-meta {
display: flex;
flex-wrap: wrap;
gap: 20px;
font-size: 14px;
opacity: 0.9;
}
.meta-item {
display: flex;
align-items: center;
gap: 5px;
}
.status-badge {
display: inline-block;
padding: 3px 10px;
border-radius: 15px;
font-size: 12px;
font-weight: bold;
text-transform: uppercase;
}
.status-open { background: #27ae60; }
.status-closed { background: #e74c3c; }
.status-claimed { background: #f39c12; }
.messages-section {
background: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.messages-section h3 {
margin-bottom: 15px;
color: #3498db;
border-bottom: 2px solid #ecf0f1;
padding-bottom: 10px;
}
.message {
padding: 15px;
border-bottom: 1px solid #ecf0f1;
}
.message:last-child {
border-bottom: none;
}
.message.staff-message {
background: #f8f9fa;
border-left: 3px solid #3498db;
}
.message-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
}
.author {
font-weight: bold;
color: #2c3e50;
}
.staff-badge {
background: #3498db;
color: white;
padding: 2px 6px;
border-radius: 3px;
font-size: 10px;
font-weight: bold;
}
.timestamp {
color: #95a5a6;
font-size: 12px;
}
.message-content {
color: #34495e;
word-break: break-word;
}
.stats-section {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.stats-section h3 {
margin-bottom: 15px;
color: #3498db;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
}
.stat-item {
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
text-align: center;
}
.stat-label {
display: block;
font-size: 12px;
color: #7f8c8d;
margin-bottom: 5px;
}
.stat-value {
font-size: 18px;
font-weight: bold;
color: #3498db;
}
.footer {
text-align: center;
padding: 20px;
color: #95a5a6;
font-size: 12px;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎫 Transcript de Ticket</h1>
<div class="header-meta">
<div class="meta-item">
<span>📌 ID:</span>
<span>1461101515270783147</span>
</div>
<div class="meta-item">
<span>📁 Catégorie:</span>
<span>3b0b9bc1</span>
</div>
<div class="meta-item">
<span>⚡ Priorité:</span>
<span style="color: #3498db; font-weight: bold;">NORMAL</span>
</div>
<div class="meta-item">
<span>📊 Statut:</span>
<span class="status-badge status-open">open</span>
</div>
<div class="meta-item">
<span>📅 Créé:</span>
<span>14/01/2026 21:55</span>
</div>
</div>
</div>
<div class="messages-section">
<h3>💬 Messages (0)</h3>
</div>
<div class="stats-section">
<h3>📊 Statistiques</h3>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-label">Durée</span>
<span class="stat-value">0 min</span>
</div>
<div class="stat-item">
<span class="stat-label">Messages</span>
<span class="stat-value">0</span>
</div>
<div class="stat-item">
<span class="stat-label">Note</span>
<span class="stat-value">Pas de note</span>
</div>
</div>
</div>
<div class="footer">
<p>Généré le 14/01/2026 à 21:56:13</p>
<p>Système de Tickets - Kuby Bot</p>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,210 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Transcript - Ticket #1461102167132737781</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f5f6fa;
color: #2c3e50;
line-height: 1.6;
}
.container {
max-width: 900px;
margin: 0 auto;
padding: 20px;
}
.header {
background: linear-gradient(135deg, #3498db, #34495e);
color: white;
padding: 30px;
border-radius: 10px;
margin-bottom: 20px;
}
.header h1 {
font-size: 24px;
margin-bottom: 10px;
}
.header-meta {
display: flex;
flex-wrap: wrap;
gap: 20px;
font-size: 14px;
opacity: 0.9;
}
.meta-item {
display: flex;
align-items: center;
gap: 5px;
}
.status-badge {
display: inline-block;
padding: 3px 10px;
border-radius: 15px;
font-size: 12px;
font-weight: bold;
text-transform: uppercase;
}
.status-open { background: #27ae60; }
.status-closed { background: #e74c3c; }
.status-claimed { background: #f39c12; }
.messages-section {
background: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.messages-section h3 {
margin-bottom: 15px;
color: #3498db;
border-bottom: 2px solid #ecf0f1;
padding-bottom: 10px;
}
.message {
padding: 15px;
border-bottom: 1px solid #ecf0f1;
}
.message:last-child {
border-bottom: none;
}
.message.staff-message {
background: #f8f9fa;
border-left: 3px solid #3498db;
}
.message-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
}
.author {
font-weight: bold;
color: #2c3e50;
}
.staff-badge {
background: #3498db;
color: white;
padding: 2px 6px;
border-radius: 3px;
font-size: 10px;
font-weight: bold;
}
.timestamp {
color: #95a5a6;
font-size: 12px;
}
.message-content {
color: #34495e;
word-break: break-word;
}
.stats-section {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.stats-section h3 {
margin-bottom: 15px;
color: #3498db;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
}
.stat-item {
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
text-align: center;
}
.stat-label {
display: block;
font-size: 12px;
color: #7f8c8d;
margin-bottom: 5px;
}
.stat-value {
font-size: 18px;
font-weight: bold;
color: #3498db;
}
.footer {
text-align: center;
padding: 20px;
color: #95a5a6;
font-size: 12px;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎫 Transcript de Ticket</h1>
<div class="header-meta">
<div class="meta-item">
<span>📌 ID:</span>
<span>1461102167132737781</span>
</div>
<div class="meta-item">
<span>📁 Catégorie:</span>
<span>3b0b9bc1</span>
</div>
<div class="meta-item">
<span>⚡ Priorité:</span>
<span style="color: #3498db; font-weight: bold;">NORMAL</span>
</div>
<div class="meta-item">
<span>📊 Statut:</span>
<span class="status-badge status-open">open</span>
</div>
<div class="meta-item">
<span>📅 Créé:</span>
<span>14/01/2026 21:58</span>
</div>
</div>
</div>
<div class="messages-section">
<h3>💬 Messages (0)</h3>
</div>
<div class="stats-section">
<h3>📊 Statistiques</h3>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-label">Durée</span>
<span class="stat-value">0 min</span>
</div>
<div class="stat-item">
<span class="stat-label">Messages</span>
<span class="stat-value">0</span>
</div>
<div class="stat-item">
<span class="stat-label">Note</span>
<span class="stat-value">Pas de note</span>
</div>
</div>
</div>
<div class="footer">
<p>Généré le 14/01/2026 à 21:58:36</p>
<p>Système de Tickets - Kuby Bot</p>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,210 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Transcript - Ticket #1461105087840649403</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f5f6fa;
color: #2c3e50;
line-height: 1.6;
}
.container {
max-width: 900px;
margin: 0 auto;
padding: 20px;
}
.header {
background: linear-gradient(135deg, #3498db, #34495e);
color: white;
padding: 30px;
border-radius: 10px;
margin-bottom: 20px;
}
.header h1 {
font-size: 24px;
margin-bottom: 10px;
}
.header-meta {
display: flex;
flex-wrap: wrap;
gap: 20px;
font-size: 14px;
opacity: 0.9;
}
.meta-item {
display: flex;
align-items: center;
gap: 5px;
}
.status-badge {
display: inline-block;
padding: 3px 10px;
border-radius: 15px;
font-size: 12px;
font-weight: bold;
text-transform: uppercase;
}
.status-open { background: #27ae60; }
.status-closed { background: #e74c3c; }
.status-claimed { background: #f39c12; }
.messages-section {
background: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.messages-section h3 {
margin-bottom: 15px;
color: #3498db;
border-bottom: 2px solid #ecf0f1;
padding-bottom: 10px;
}
.message {
padding: 15px;
border-bottom: 1px solid #ecf0f1;
}
.message:last-child {
border-bottom: none;
}
.message.staff-message {
background: #f8f9fa;
border-left: 3px solid #3498db;
}
.message-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
}
.author {
font-weight: bold;
color: #2c3e50;
}
.staff-badge {
background: #3498db;
color: white;
padding: 2px 6px;
border-radius: 3px;
font-size: 10px;
font-weight: bold;
}
.timestamp {
color: #95a5a6;
font-size: 12px;
}
.message-content {
color: #34495e;
word-break: break-word;
}
.stats-section {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.stats-section h3 {
margin-bottom: 15px;
color: #3498db;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
}
.stat-item {
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
text-align: center;
}
.stat-label {
display: block;
font-size: 12px;
color: #7f8c8d;
margin-bottom: 5px;
}
.stat-value {
font-size: 18px;
font-weight: bold;
color: #3498db;
}
.footer {
text-align: center;
padding: 20px;
color: #95a5a6;
font-size: 12px;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎫 Transcript de Ticket</h1>
<div class="header-meta">
<div class="meta-item">
<span>📌 ID:</span>
<span>1461105087840649403</span>
</div>
<div class="meta-item">
<span>📁 Catégorie:</span>
<span>91522e2c</span>
</div>
<div class="meta-item">
<span>⚡ Priorité:</span>
<span style="color: #3498db; font-weight: bold;">NORMAL</span>
</div>
<div class="meta-item">
<span>📊 Statut:</span>
<span class="status-badge status-open">open</span>
</div>
<div class="meta-item">
<span>📅 Créé:</span>
<span>14/01/2026 22:09</span>
</div>
</div>
</div>
<div class="messages-section">
<h3>💬 Messages (0)</h3>
</div>
<div class="stats-section">
<h3>📊 Statistiques</h3>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-label">Durée</span>
<span class="stat-value">0 min</span>
</div>
<div class="stat-item">
<span class="stat-label">Messages</span>
<span class="stat-value">0</span>
</div>
<div class="stat-item">
<span class="stat-label">Note</span>
<span class="stat-value">Pas de note</span>
</div>
</div>
</div>
<div class="footer">
<p>Généré le 14/01/2026 à 22:10:13</p>
<p>Système de Tickets - Kuby Bot</p>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,210 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Transcript - Ticket #1461105782194962634</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f5f6fa;
color: #2c3e50;
line-height: 1.6;
}
.container {
max-width: 900px;
margin: 0 auto;
padding: 20px;
}
.header {
background: linear-gradient(135deg, #3498db, #34495e);
color: white;
padding: 30px;
border-radius: 10px;
margin-bottom: 20px;
}
.header h1 {
font-size: 24px;
margin-bottom: 10px;
}
.header-meta {
display: flex;
flex-wrap: wrap;
gap: 20px;
font-size: 14px;
opacity: 0.9;
}
.meta-item {
display: flex;
align-items: center;
gap: 5px;
}
.status-badge {
display: inline-block;
padding: 3px 10px;
border-radius: 15px;
font-size: 12px;
font-weight: bold;
text-transform: uppercase;
}
.status-open { background: #27ae60; }
.status-closed { background: #e74c3c; }
.status-claimed { background: #f39c12; }
.messages-section {
background: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.messages-section h3 {
margin-bottom: 15px;
color: #3498db;
border-bottom: 2px solid #ecf0f1;
padding-bottom: 10px;
}
.message {
padding: 15px;
border-bottom: 1px solid #ecf0f1;
}
.message:last-child {
border-bottom: none;
}
.message.staff-message {
background: #f8f9fa;
border-left: 3px solid #3498db;
}
.message-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
}
.author {
font-weight: bold;
color: #2c3e50;
}
.staff-badge {
background: #3498db;
color: white;
padding: 2px 6px;
border-radius: 3px;
font-size: 10px;
font-weight: bold;
}
.timestamp {
color: #95a5a6;
font-size: 12px;
}
.message-content {
color: #34495e;
word-break: break-word;
}
.stats-section {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.stats-section h3 {
margin-bottom: 15px;
color: #3498db;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
}
.stat-item {
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
text-align: center;
}
.stat-label {
display: block;
font-size: 12px;
color: #7f8c8d;
margin-bottom: 5px;
}
.stat-value {
font-size: 18px;
font-weight: bold;
color: #3498db;
}
.footer {
text-align: center;
padding: 20px;
color: #95a5a6;
font-size: 12px;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎫 Transcript de Ticket</h1>
<div class="header-meta">
<div class="meta-item">
<span>📌 ID:</span>
<span>1461105782194962634</span>
</div>
<div class="meta-item">
<span>📁 Catégorie:</span>
<span>91522e2c</span>
</div>
<div class="meta-item">
<span>⚡ Priorité:</span>
<span style="color: #3498db; font-weight: bold;">NORMAL</span>
</div>
<div class="meta-item">
<span>📊 Statut:</span>
<span class="status-badge status-claimed">claimed</span>
</div>
<div class="meta-item">
<span>📅 Créé:</span>
<span>14/01/2026 22:12</span>
</div>
</div>
</div>
<div class="messages-section">
<h3>💬 Messages (0)</h3>
</div>
<div class="stats-section">
<h3>📊 Statistiques</h3>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-label">Durée</span>
<span class="stat-value">0 min</span>
</div>
<div class="stat-item">
<span class="stat-label">Messages</span>
<span class="stat-value">0</span>
</div>
<div class="stat-item">
<span class="stat-label">Note</span>
<span class="stat-value">Pas de note</span>
</div>
</div>
</div>
<div class="footer">
<p>Généré le 14/01/2026 à 22:13:02</p>
<p>Système de Tickets - Kuby Bot</p>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,210 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Transcript - Ticket #1461106046088122481</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f5f6fa;
color: #2c3e50;
line-height: 1.6;
}
.container {
max-width: 900px;
margin: 0 auto;
padding: 20px;
}
.header {
background: linear-gradient(135deg, #3498db, #34495e);
color: white;
padding: 30px;
border-radius: 10px;
margin-bottom: 20px;
}
.header h1 {
font-size: 24px;
margin-bottom: 10px;
}
.header-meta {
display: flex;
flex-wrap: wrap;
gap: 20px;
font-size: 14px;
opacity: 0.9;
}
.meta-item {
display: flex;
align-items: center;
gap: 5px;
}
.status-badge {
display: inline-block;
padding: 3px 10px;
border-radius: 15px;
font-size: 12px;
font-weight: bold;
text-transform: uppercase;
}
.status-open { background: #27ae60; }
.status-closed { background: #e74c3c; }
.status-claimed { background: #f39c12; }
.messages-section {
background: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.messages-section h3 {
margin-bottom: 15px;
color: #3498db;
border-bottom: 2px solid #ecf0f1;
padding-bottom: 10px;
}
.message {
padding: 15px;
border-bottom: 1px solid #ecf0f1;
}
.message:last-child {
border-bottom: none;
}
.message.staff-message {
background: #f8f9fa;
border-left: 3px solid #3498db;
}
.message-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
}
.author {
font-weight: bold;
color: #2c3e50;
}
.staff-badge {
background: #3498db;
color: white;
padding: 2px 6px;
border-radius: 3px;
font-size: 10px;
font-weight: bold;
}
.timestamp {
color: #95a5a6;
font-size: 12px;
}
.message-content {
color: #34495e;
word-break: break-word;
}
.stats-section {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.stats-section h3 {
margin-bottom: 15px;
color: #3498db;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
}
.stat-item {
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
text-align: center;
}
.stat-label {
display: block;
font-size: 12px;
color: #7f8c8d;
margin-bottom: 5px;
}
.stat-value {
font-size: 18px;
font-weight: bold;
color: #3498db;
}
.footer {
text-align: center;
padding: 20px;
color: #95a5a6;
font-size: 12px;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎫 Transcript de Ticket</h1>
<div class="header-meta">
<div class="meta-item">
<span>📌 ID:</span>
<span>1461106046088122481</span>
</div>
<div class="meta-item">
<span>📁 Catégorie:</span>
<span>91522e2c</span>
</div>
<div class="meta-item">
<span>⚡ Priorité:</span>
<span style="color: #3498db; font-weight: bold;">NORMAL</span>
</div>
<div class="meta-item">
<span>📊 Statut:</span>
<span class="status-badge status-claimed">claimed</span>
</div>
<div class="meta-item">
<span>📅 Créé:</span>
<span>14/01/2026 22:13</span>
</div>
</div>
</div>
<div class="messages-section">
<h3>💬 Messages (0)</h3>
</div>
<div class="stats-section">
<h3>📊 Statistiques</h3>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-label">Durée</span>
<span class="stat-value">0 min</span>
</div>
<div class="stat-item">
<span class="stat-label">Messages</span>
<span class="stat-value">0</span>
</div>
<div class="stat-item">
<span class="stat-label">Note</span>
<span class="stat-value">Pas de note</span>
</div>
</div>
</div>
<div class="footer">
<p>Généré le 14/01/2026 à 22:14:01</p>
<p>Système de Tickets - Kuby Bot</p>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,210 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Transcript - Ticket #1461110002814029906</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f5f6fa;
color: #2c3e50;
line-height: 1.6;
}
.container {
max-width: 900px;
margin: 0 auto;
padding: 20px;
}
.header {
background: linear-gradient(135deg, #3498db, #34495e);
color: white;
padding: 30px;
border-radius: 10px;
margin-bottom: 20px;
}
.header h1 {
font-size: 24px;
margin-bottom: 10px;
}
.header-meta {
display: flex;
flex-wrap: wrap;
gap: 20px;
font-size: 14px;
opacity: 0.9;
}
.meta-item {
display: flex;
align-items: center;
gap: 5px;
}
.status-badge {
display: inline-block;
padding: 3px 10px;
border-radius: 15px;
font-size: 12px;
font-weight: bold;
text-transform: uppercase;
}
.status-open { background: #27ae60; }
.status-closed { background: #e74c3c; }
.status-claimed { background: #f39c12; }
.messages-section {
background: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.messages-section h3 {
margin-bottom: 15px;
color: #3498db;
border-bottom: 2px solid #ecf0f1;
padding-bottom: 10px;
}
.message {
padding: 15px;
border-bottom: 1px solid #ecf0f1;
}
.message:last-child {
border-bottom: none;
}
.message.staff-message {
background: #f8f9fa;
border-left: 3px solid #3498db;
}
.message-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
}
.author {
font-weight: bold;
color: #2c3e50;
}
.staff-badge {
background: #3498db;
color: white;
padding: 2px 6px;
border-radius: 3px;
font-size: 10px;
font-weight: bold;
}
.timestamp {
color: #95a5a6;
font-size: 12px;
}
.message-content {
color: #34495e;
word-break: break-word;
}
.stats-section {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.stats-section h3 {
margin-bottom: 15px;
color: #3498db;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
}
.stat-item {
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
text-align: center;
}
.stat-label {
display: block;
font-size: 12px;
color: #7f8c8d;
margin-bottom: 5px;
}
.stat-value {
font-size: 18px;
font-weight: bold;
color: #3498db;
}
.footer {
text-align: center;
padding: 20px;
color: #95a5a6;
font-size: 12px;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎫 Transcript de Ticket</h1>
<div class="header-meta">
<div class="meta-item">
<span>📌 ID:</span>
<span>1461110002814029906</span>
</div>
<div class="meta-item">
<span>📁 Catégorie:</span>
<span>3b0b9bc1</span>
</div>
<div class="meta-item">
<span>⚡ Priorité:</span>
<span style="color: #3498db; font-weight: bold;">NORMAL</span>
</div>
<div class="meta-item">
<span>📊 Statut:</span>
<span class="status-badge status-open">open</span>
</div>
<div class="meta-item">
<span>📅 Créé:</span>
<span>14/01/2026 22:29</span>
</div>
</div>
</div>
<div class="messages-section">
<h3>💬 Messages (0)</h3>
</div>
<div class="stats-section">
<h3>📊 Statistiques</h3>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-label">Durée</span>
<span class="stat-value">0 min</span>
</div>
<div class="stat-item">
<span class="stat-label">Messages</span>
<span class="stat-value">0</span>
</div>
<div class="stat-item">
<span class="stat-label">Note</span>
<span class="stat-value">Pas de note</span>
</div>
</div>
</div>
<div class="footer">
<p>Généré le 14/01/2026 à 22:29:45</p>
<p>Système de Tickets - Kuby Bot</p>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,210 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Transcript - Ticket #1461775280107687966</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f5f6fa;
color: #2c3e50;
line-height: 1.6;
}
.container {
max-width: 900px;
margin: 0 auto;
padding: 20px;
}
.header {
background: linear-gradient(135deg, #3498db, #34495e);
color: white;
padding: 30px;
border-radius: 10px;
margin-bottom: 20px;
}
.header h1 {
font-size: 24px;
margin-bottom: 10px;
}
.header-meta {
display: flex;
flex-wrap: wrap;
gap: 20px;
font-size: 14px;
opacity: 0.9;
}
.meta-item {
display: flex;
align-items: center;
gap: 5px;
}
.status-badge {
display: inline-block;
padding: 3px 10px;
border-radius: 15px;
font-size: 12px;
font-weight: bold;
text-transform: uppercase;
}
.status-open { background: #27ae60; }
.status-closed { background: #e74c3c; }
.status-claimed { background: #f39c12; }
.messages-section {
background: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.messages-section h3 {
margin-bottom: 15px;
color: #3498db;
border-bottom: 2px solid #ecf0f1;
padding-bottom: 10px;
}
.message {
padding: 15px;
border-bottom: 1px solid #ecf0f1;
}
.message:last-child {
border-bottom: none;
}
.message.staff-message {
background: #f8f9fa;
border-left: 3px solid #3498db;
}
.message-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
}
.author {
font-weight: bold;
color: #2c3e50;
}
.staff-badge {
background: #3498db;
color: white;
padding: 2px 6px;
border-radius: 3px;
font-size: 10px;
font-weight: bold;
}
.timestamp {
color: #95a5a6;
font-size: 12px;
}
.message-content {
color: #34495e;
word-break: break-word;
}
.stats-section {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.stats-section h3 {
margin-bottom: 15px;
color: #3498db;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
}
.stat-item {
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
text-align: center;
}
.stat-label {
display: block;
font-size: 12px;
color: #7f8c8d;
margin-bottom: 5px;
}
.stat-value {
font-size: 18px;
font-weight: bold;
color: #3498db;
}
.footer {
text-align: center;
padding: 20px;
color: #95a5a6;
font-size: 12px;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎫 Transcript de Ticket</h1>
<div class="header-meta">
<div class="meta-item">
<span>📌 ID:</span>
<span>1461775280107687966</span>
</div>
<div class="meta-item">
<span>📁 Catégorie:</span>
<span>91522e2c</span>
</div>
<div class="meta-item">
<span>⚡ Priorité:</span>
<span style="color: #3498db; font-weight: bold;">NORMAL</span>
</div>
<div class="meta-item">
<span>📊 Statut:</span>
<span class="status-badge status-open">open</span>
</div>
<div class="meta-item">
<span>📅 Créé:</span>
<span>16/01/2026 18:33</span>
</div>
</div>
</div>
<div class="messages-section">
<h3>💬 Messages (0)</h3>
</div>
<div class="stats-section">
<h3>📊 Statistiques</h3>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-label">Durée</span>
<span class="stat-value">0 min</span>
</div>
<div class="stat-item">
<span class="stat-label">Messages</span>
<span class="stat-value">0</span>
</div>
<div class="stat-item">
<span class="stat-label">Note</span>
<span class="stat-value">Pas de note</span>
</div>
</div>
</div>
<div class="footer">
<p>Généré le 16/01/2026 à 18:33:17</p>
<p>Système de Tickets - Kuby Bot</p>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,210 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Transcript - Ticket #1461776856721391758</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f5f6fa;
color: #2c3e50;
line-height: 1.6;
}
.container {
max-width: 900px;
margin: 0 auto;
padding: 20px;
}
.header {
background: linear-gradient(135deg, #3498db, #34495e);
color: white;
padding: 30px;
border-radius: 10px;
margin-bottom: 20px;
}
.header h1 {
font-size: 24px;
margin-bottom: 10px;
}
.header-meta {
display: flex;
flex-wrap: wrap;
gap: 20px;
font-size: 14px;
opacity: 0.9;
}
.meta-item {
display: flex;
align-items: center;
gap: 5px;
}
.status-badge {
display: inline-block;
padding: 3px 10px;
border-radius: 15px;
font-size: 12px;
font-weight: bold;
text-transform: uppercase;
}
.status-open { background: #27ae60; }
.status-closed { background: #e74c3c; }
.status-claimed { background: #f39c12; }
.messages-section {
background: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.messages-section h3 {
margin-bottom: 15px;
color: #3498db;
border-bottom: 2px solid #ecf0f1;
padding-bottom: 10px;
}
.message {
padding: 15px;
border-bottom: 1px solid #ecf0f1;
}
.message:last-child {
border-bottom: none;
}
.message.staff-message {
background: #f8f9fa;
border-left: 3px solid #3498db;
}
.message-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
}
.author {
font-weight: bold;
color: #2c3e50;
}
.staff-badge {
background: #3498db;
color: white;
padding: 2px 6px;
border-radius: 3px;
font-size: 10px;
font-weight: bold;
}
.timestamp {
color: #95a5a6;
font-size: 12px;
}
.message-content {
color: #34495e;
word-break: break-word;
}
.stats-section {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.stats-section h3 {
margin-bottom: 15px;
color: #3498db;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
}
.stat-item {
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
text-align: center;
}
.stat-label {
display: block;
font-size: 12px;
color: #7f8c8d;
margin-bottom: 5px;
}
.stat-value {
font-size: 18px;
font-weight: bold;
color: #3498db;
}
.footer {
text-align: center;
padding: 20px;
color: #95a5a6;
font-size: 12px;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎫 Transcript de Ticket</h1>
<div class="header-meta">
<div class="meta-item">
<span>📌 ID:</span>
<span>1461776856721391758</span>
</div>
<div class="meta-item">
<span>📁 Catégorie:</span>
<span>3b0b9bc1</span>
</div>
<div class="meta-item">
<span>⚡ Priorité:</span>
<span style="color: #3498db; font-weight: bold;">NORMAL</span>
</div>
<div class="meta-item">
<span>📊 Statut:</span>
<span class="status-badge status-open">open</span>
</div>
<div class="meta-item">
<span>📅 Créé:</span>
<span>16/01/2026 18:39</span>
</div>
</div>
</div>
<div class="messages-section">
<h3>💬 Messages (0)</h3>
</div>
<div class="stats-section">
<h3>📊 Statistiques</h3>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-label">Durée</span>
<span class="stat-value">5 min</span>
</div>
<div class="stat-item">
<span class="stat-label">Messages</span>
<span class="stat-value">0</span>
</div>
<div class="stat-item">
<span class="stat-label">Note</span>
<span class="stat-value">Pas de note</span>
</div>
</div>
</div>
<div class="footer">
<p>Généré le 16/01/2026 à 18:43:52</p>
<p>Système de Tickets - Kuby Bot</p>
</div>
</div>
</body>
</html>

44
debug.log Normal file
View file

@ -0,0 +1,44 @@
nohup: les entrées sont ignorées
[2026-01-16 18:41:19] [DEBUG] [KubyBot] [debug:50] Raw APPLICATION_ID: 1390778748097527808
[2026-01-16 18:41:19] [INFO] [KubyBot] [info:53] ✅ APPLICATION_ID loaded successfully: 1390778748097527808
[2026-01-16 18:41:19] [DEBUG] [KubyBot] [debug:50] Discord intents configured: <Intents value=53608191>
[2026-01-16 18:41:19] [DEBUG] [KubyBot] [debug:50] Initializing MyBot class
[2026-01-16 18:41:19] [INFO] [KubyBot] [info:53] MyBot instance created successfully
[2026-01-16 18:41:19] [INFO] [KubyBot] [info:53] 🚀 Lancement du bot Kuby...
[2026-01-16 18:41:19] [DEBUG] [KubyBot] [debug:50] Starting __main__.py execution
[2026-01-16 18:41:19] [INFO] [KubyBot] [info:53] 📋 Chargement des variables d'environnement...
[2026-01-16 18:41:19] [DEBUG] [KubyBot] [debug:50] Environment variables loaded
[2026-01-16 18:41:19] [DEBUG] [KubyBot] [debug:50] Token retrieved from environment: ***
[2026-01-16 18:41:19] [INFO] [KubyBot] [info:53] ✅ Token Discord chargé avec succès
[2026-01-16 18:41:19] [INFO] [KubyBot] [info:53] 🚀 Lancement du bot Kuby...
[2026-01-16 18:41:19] [DEBUG] [KubyBot] [debug:50] Entering main with args: (), kwargs: {}
[2026-01-16 18:41:19] [INFO] [KubyBot] [info:53] 🔄 Démarrage de la connexion Discord...
[2026-01-16 18:41:19] [DEBUG] [KubyBot] [debug:50] Starting async context manager
[2026-01-16 18:41:19] [INFO] [KubyBot] [info:53] 🔗 Connexion établie avec Discord...
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] 🚀 Démarrage du bot Kuby...
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] ✅ Advanced logger initialized
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] ✅ Extension chargée : commandes.whitelist
[WhitelistMonitor] Persistent view registered
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] ✅ Extension chargée : commandes.whitelist_monitor
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] ✅ Extension chargée : commandes.sendbotmessages
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] ✅ Extension chargée : commandes.goodbye
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] ✅ Extension chargée : commandes.welcome
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] ✅ Extension chargée : commandes.security
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] ✅ Extension chargée : commandes.snipe
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] ✅ Extension chargée : commandes.scan
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] ✅ Extension chargée : commandes.no_link
[Blacklist] 0 vues de tickets enregistrées
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] ✅ Extension chargée : commandes.blacklist
[Ticket] Views registered for guild 1369669999345537145
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] ✅ Extension chargée : commandes.ticket
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] ✅ Extension chargée : commandes.modules_security.antispam
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] ✅ Extension chargée : commandes.modules_security.antiraid
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] ✅ Extension chargée : commandes.modules_security.logs_manager
[Rules] View registered for guild 1369669999345537145
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] ✅ Extension chargée : commandes.modules_security.rules
[2026-01-16 18:41:20] [INFO] [KubyBot] [info:53] ✅ Commandes slash synchronisées avec Discord
[2026-01-16 18:41:22] [INFO] [KubyBot] [info:53] 🤖 Bot connecté : Kuby Alpha#6731 (ID : 1390778748097527808)
[2026-01-16 18:41:22] [INFO] [KubyBot] [info:53] 📊 Serveurs : 1
[2026-01-16 18:41:22] [DEBUG] [KubyBot] [debug:50] Guild: Omega Kube Bêta Test (ID: 1369669999345537145) - Members: 19
[2026-01-16 18:41:22] [INFO] [KubyBot] [info:53] 📊 Total members across all guilds: 19
[2026-01-16 18:41:22] [INFO] [KubyBot] [info:53] ✅ Bot prêt et opérationnel !

17273
kuby_audit.log Executable file

File diff suppressed because it is too large Load diff

9662
kuby_errors.log Executable file

File diff suppressed because it is too large Load diff

20966
kuby_logs.log Executable file

File diff suppressed because it is too large Load diff