Première version non terminer du nouveau système de ticket § ajout du système de boutons persistant (non tester)
This commit is contained in:
parent
10173132a2
commit
93e2f9bb44
15 changed files with 3788 additions and 209 deletions
692
commandes/ticket/views/creation.py
Normal file
692
commandes/ticket/views/creation.py
Normal file
|
|
@ -0,0 +1,692 @@
|
|||
"""
|
||||
Ticket Creation Views
|
||||
=====================
|
||||
UI views for creating tickets with categories, priority, and reason.
|
||||
"""
|
||||
from datetime import datetime
|
||||
from typing import Optional, List, Dict, Any
|
||||
|
||||
import discord
|
||||
from discord.ui import View, Button, Select, Modal, TextInput
|
||||
from discord import Interaction, ButtonStyle, Color
|
||||
|
||||
from ..data.models import (
|
||||
TicketData,
|
||||
TicketCategory,
|
||||
TicketStatus,
|
||||
Priority,
|
||||
GuildTicketConfig
|
||||
)
|
||||
from ..data.storage import get_storage
|
||||
from ..utils.formatters import TicketEmbedFormatter, TicketMessageFormatter
|
||||
from ..utils.transcript import get_transcript_generator
|
||||
|
||||
|
||||
class TicketCreationView(View):
|
||||
"""
|
||||
Main view for ticket creation panel.
|
||||
Shows category selection buttons.
|
||||
"""
|
||||
|
||||
def __init__(self, bot, config: GuildTicketConfig):
|
||||
super().__init__(timeout=None)
|
||||
self.bot = bot
|
||||
self.config = config
|
||||
|
||||
# Add category buttons
|
||||
for i, category in enumerate(config.categories[:5]): # Max 5 categories
|
||||
btn = Button(
|
||||
style=ButtonStyle.blurple,
|
||||
label=category.name,
|
||||
emoji=category.emoji,
|
||||
custom_id=f"ticket_category_{category.id}"
|
||||
)
|
||||
btn.callback = self._create_category_callback(category.id)
|
||||
self.add_item(btn)
|
||||
|
||||
# Add help button
|
||||
help_btn = Button(
|
||||
style=ButtonStyle.secondary,
|
||||
label="Aide",
|
||||
emoji="❓",
|
||||
custom_id="ticket_help"
|
||||
)
|
||||
help_btn.callback = self._help_callback
|
||||
self.add_item(help_btn)
|
||||
|
||||
def _create_category_callback(self, category_id: str):
|
||||
"""Create callback for category button"""
|
||||
async def callback(interaction: Interaction):
|
||||
await self.on_category_select(interaction, category_id)
|
||||
return callback
|
||||
|
||||
async def on_category_select(self, interaction: Interaction, category_id: str):
|
||||
"""Handle category selection"""
|
||||
await interaction.response.defer(ephemeral=True)
|
||||
|
||||
category = self.config.get_category(category_id)
|
||||
if not category:
|
||||
await interaction.followup.send("Catégorie non trouvée.", ephemeral=True)
|
||||
return
|
||||
|
||||
storage = get_storage()
|
||||
|
||||
# Check if user already has a ticket
|
||||
user_tickets = storage.get_user_tickets(
|
||||
interaction.guild_id,
|
||||
interaction.user.id,
|
||||
open_only=True
|
||||
)
|
||||
|
||||
# Check limits
|
||||
user_count = len([t for t in user_tickets if t.category_id == category_id])
|
||||
if user_count >= category.max_tickets_per_user:
|
||||
await interaction.followup.send(
|
||||
TicketMessageFormatter.ticket_limit_reached(category.max_tickets_per_user),
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
# Check global limit
|
||||
if len(user_tickets) >= self.config.max_tickets_per_user:
|
||||
await interaction.followup.send(
|
||||
TicketMessageFormatter.ticket_limit_reached(self.config.max_tickets_per_user),
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
# Show priority selection modal
|
||||
modal = TicketPriorityModal(
|
||||
bot=self.bot,
|
||||
config=self.config,
|
||||
category=category
|
||||
)
|
||||
await interaction.response.send_modal(modal)
|
||||
|
||||
async def _help_callback(self, interaction: Interaction):
|
||||
"""Handle help button click"""
|
||||
embed = discord.Embed(
|
||||
title="❓ Aide - Création de Ticket",
|
||||
description="Sélectionnez une catégorie ci-dessus correspondant à votre demande:\n\n"
|
||||
"• **Support** - Questions techniques\n"
|
||||
"• **Bug Report** - Signaler un problème\n"
|
||||
"• **Partenariat** - Propositions de partenariat\n"
|
||||
"• **Autre** - Autres demandes",
|
||||
color=Color.blue()
|
||||
)
|
||||
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||
|
||||
|
||||
class TicketPriorityModal(Modal):
|
||||
"""
|
||||
Modal for selecting priority and reason when creating a ticket.
|
||||
"""
|
||||
|
||||
def __init__(self, bot, config: GuildTicketConfig, category: TicketCategory):
|
||||
super().__init__(title=f"🎫 {category.name} - Nouveau Ticket")
|
||||
self.bot = bot
|
||||
self.config = config
|
||||
self.category = category
|
||||
|
||||
# Priority selection
|
||||
priorities = ["Basse", "Normale", "Haute", "Urgente"]
|
||||
priority_placeholder = "Sélectionnez la priorité"
|
||||
|
||||
if not category.priority_enabled:
|
||||
priorities = ["Normale"]
|
||||
priority_placeholder = "Priorité par défaut"
|
||||
|
||||
self.priority_select = Select(
|
||||
placeholder=priority_placeholder,
|
||||
options=[
|
||||
discord.SelectOption(label=p, value=p.lower(), emoji=emoji)
|
||||
for p, emoji in [
|
||||
("Basse", "🟢"),
|
||||
("Normale", "🔵"),
|
||||
("Haute", "🟠"),
|
||||
("Urgente", "🔴")
|
||||
] if p in priorities or p.lower() in ["normale"]
|
||||
],
|
||||
custom_id="priority_select"
|
||||
)
|
||||
self.add_item(self.priority_select)
|
||||
|
||||
# Reason input
|
||||
reason_placeholder = "Décrivez votre demande..."
|
||||
if category.require_reason:
|
||||
reason_placeholder = "Requis - Décrivez votre demande..."
|
||||
|
||||
self.reason = TextInput(
|
||||
label="Motif de la demande",
|
||||
placeholder=reason_placeholder,
|
||||
required=category.require_reason,
|
||||
style=discord.TextStyle.paragraph,
|
||||
custom_id="reason_input"
|
||||
)
|
||||
self.add_item(self.reason)
|
||||
|
||||
async def on_submit(self, interaction: Interaction):
|
||||
"""Handle modal submission"""
|
||||
await interaction.response.defer(ephemeral=True)
|
||||
|
||||
# Map priority
|
||||
priority_map = {
|
||||
"basse": Priority.LOW,
|
||||
"normale": Priority.NORMAL,
|
||||
"haute": Priority.HIGH,
|
||||
"urgente": Priority.URGENT
|
||||
}
|
||||
priority = priority_map.get(self.priority_select.values[0], Priority.NORMAL)
|
||||
|
||||
await self.create_ticket(
|
||||
interaction=interaction,
|
||||
priority=priority,
|
||||
reason=self.reason.value
|
||||
)
|
||||
|
||||
async def create_ticket(
|
||||
self,
|
||||
interaction: Interaction,
|
||||
priority: Priority,
|
||||
reason: str
|
||||
):
|
||||
"""Create the actual ticket"""
|
||||
guild = interaction.guild
|
||||
user = interaction.user
|
||||
|
||||
# Get category for config
|
||||
category = self.category
|
||||
|
||||
# Get category channel
|
||||
category_channel = guild.get_channel(int(category.id)) if category.id.isdigit() else None
|
||||
|
||||
# Build permissions
|
||||
overwrites = {
|
||||
guild.default_role: discord.PermissionOverwrite(read_messages=False),
|
||||
user: discord.PermissionOverwrite(read_messages=True, send_messages=True, attach_files=True),
|
||||
guild.me: discord.PermissionOverwrite(read_messages=True, send_messages=True)
|
||||
}
|
||||
|
||||
# Add staff roles
|
||||
for role_id in category.staff_roles:
|
||||
role = guild.get_role(int(role_id))
|
||||
if role:
|
||||
overwrites[role] = discord.PermissionOverwrite(read_messages=True, send_messages=True)
|
||||
|
||||
# Also add global staff roles
|
||||
for role_id in self.config.staff_roles:
|
||||
role = guild.get_role(int(role_id))
|
||||
if role and role not in overwrites:
|
||||
overwrites[role] = discord.PermissionOverwrite(read_messages=True, send_messages=True)
|
||||
|
||||
# Create channel name
|
||||
timestamp = datetime.now().strftime("%m%d%H%M")
|
||||
channel_name = f"ticket-{user.id}-{timestamp}"
|
||||
|
||||
# Create ticket channel
|
||||
try:
|
||||
ticket_channel = await guild.create_text_channel(
|
||||
name=channel_name,
|
||||
category=guild.get_channel(int(self.config.default_category)) if self.config.default_category else None,
|
||||
overwrites=overwrites,
|
||||
topic=f"Ticket de {user} ({user.id}) | Catégorie: {category.name}"
|
||||
)
|
||||
except Exception as e:
|
||||
await interaction.followup.send(f"❌ Erreur lors de la création du ticket: {e}", ephemeral=True)
|
||||
return
|
||||
|
||||
# Create ticket data
|
||||
storage = get_storage()
|
||||
ticket_data = TicketData(
|
||||
channel_id=ticket_channel.id,
|
||||
guild_id=guild.id,
|
||||
user_id=user.id,
|
||||
category_id=category.id,
|
||||
priority=priority,
|
||||
status=TicketStatus.OPEN,
|
||||
reason=reason
|
||||
)
|
||||
storage.save_ticket(ticket_data)
|
||||
|
||||
# Send welcome message
|
||||
welcome_content = TicketMessageFormatter.welcome_message(user, category)
|
||||
welcome_embed = TicketEmbedFormatter.ticket_created(ticket_data, user, category, guild.name)
|
||||
|
||||
# Send initial message with management view
|
||||
view = TicketManagementView(self.bot, storage, self.config)
|
||||
await ticket_channel.send(
|
||||
content=welcome_content,
|
||||
embed=welcome_embed,
|
||||
view=view
|
||||
)
|
||||
|
||||
# Send confirmation to user
|
||||
await interaction.followup.send(
|
||||
f"✅ Votre ticket a été créé: {ticket_channel.mention}",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
# Log to log channel
|
||||
if self.config.log_channel_id:
|
||||
log_channel = guild.get_channel(self.config.log_channel_id)
|
||||
if log_channel:
|
||||
log_embed = discord.Embed(
|
||||
title="🎫 Ticket Créé",
|
||||
color=Color.green(),
|
||||
timestamp=datetime.now()
|
||||
)
|
||||
log_embed.add_field(name="👤 Utilisateur", value=user.mention, inline=True)
|
||||
log_embed.add_field(name="📁 Catégorie", value=category.name, inline=True)
|
||||
log_embed.add_field(name="⚡ Priorité", value=TicketEmbedFormatter.format_priority(priority), inline=True)
|
||||
log_embed.add_field(name="📝 Salon", value=ticket_channel.mention, inline=True)
|
||||
if reason:
|
||||
log_embed.add_field(name="📄 Raison", value=reason[:100], inline=False)
|
||||
|
||||
await log_channel.send(embed=log_embed)
|
||||
|
||||
|
||||
class TicketManagementView(View):
|
||||
"""
|
||||
View shown inside tickets for management actions.
|
||||
"""
|
||||
|
||||
def __init__(self, bot, storage, config: GuildTicketConfig):
|
||||
super().__init__(timeout=None)
|
||||
self.bot = bot
|
||||
self.storage = storage
|
||||
self.config = config
|
||||
|
||||
# Close button
|
||||
close_btn = Button(
|
||||
style=ButtonStyle.red,
|
||||
label="Fermer",
|
||||
emoji="🔒",
|
||||
custom_id="ticket_close"
|
||||
)
|
||||
close_btn.callback = self._close_callback
|
||||
self.add_item(close_btn)
|
||||
|
||||
# Claim button (if enabled)
|
||||
if config.claim_enabled:
|
||||
claim_btn = Button(
|
||||
style=ButtonStyle.gold,
|
||||
label="Réclamer",
|
||||
emoji="🙋",
|
||||
custom_id="ticket_claim"
|
||||
)
|
||||
claim_btn.callback = self._claim_callback
|
||||
self.add_item(claim_btn)
|
||||
|
||||
# Priority button
|
||||
priority_btn = Button(
|
||||
style=ButtonStyle.secondary,
|
||||
label="Priorité",
|
||||
emoji="⚡",
|
||||
custom_id="ticket_priority"
|
||||
)
|
||||
priority_btn.callback = self._priority_callback
|
||||
self.add_item(priority_btn)
|
||||
|
||||
# Transcript button
|
||||
transcript_btn = Button(
|
||||
style=ButtonStyle.secondary,
|
||||
label="Transcript",
|
||||
emoji="📄",
|
||||
custom_id="ticket_transcript"
|
||||
)
|
||||
transcript_btn.callback = self._transcript_callback
|
||||
self.add_item(transcript_btn)
|
||||
|
||||
async def _close_callback(self, interaction: Interaction):
|
||||
"""Handle close button click"""
|
||||
await interaction.response.defer(ephemeral=True)
|
||||
|
||||
storage = get_storage()
|
||||
ticket = storage.load_ticket(interaction.channel.id)
|
||||
|
||||
if not ticket:
|
||||
await interaction.followup.send("Ticket non trouvé.", ephemeral=True)
|
||||
return
|
||||
|
||||
# Check if user can close (owner or staff)
|
||||
can_close = (
|
||||
interaction.user.id == ticket.user_id or
|
||||
self._is_staff(interaction)
|
||||
)
|
||||
|
||||
if not can_close:
|
||||
await interaction.followup.send(
|
||||
"Vous ne pouvez pas fermer ce ticket.",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
# Show close modal
|
||||
modal = TicketCloseModal(self.bot, storage, self.config, ticket)
|
||||
await interaction.response.send_modal(modal)
|
||||
|
||||
async def _claim_callback(self, interaction: Interaction):
|
||||
"""Handle claim button click"""
|
||||
await interaction.response.defer(ephemeral=True)
|
||||
|
||||
if not self._is_staff(interaction):
|
||||
await interaction.followup.send(
|
||||
"Vous n'êtes pas staff.",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
storage = get_storage()
|
||||
ticket = storage.load_ticket(interaction.channel.id)
|
||||
|
||||
if not ticket:
|
||||
await interaction.followup.send("Ticket non trouvé.", ephemeral=True)
|
||||
return
|
||||
|
||||
if ticket.status == TicketStatus.CLAIMED and ticket.claimed_by == interaction.user.id:
|
||||
# Unclaim
|
||||
ticket.claimed_by = None
|
||||
ticket.status = TicketStatus.OPEN
|
||||
storage.save_ticket(ticket)
|
||||
|
||||
await interaction.followup.send("Ticket non réclamé.", ephemeral=True)
|
||||
await interaction.channel.send(
|
||||
embed=TicketEmbedFormatter.ticket_unclaimed(ticket, interaction.user)
|
||||
)
|
||||
elif ticket.status == TicketStatus.CLAIMED:
|
||||
await interaction.followup.send(
|
||||
"Ce ticket est déjà réclamé par quelqu'un d'autre.",
|
||||
ephemeral=True
|
||||
)
|
||||
else:
|
||||
# Claim
|
||||
ticket.claimed_by = interaction.user.id
|
||||
ticket.status = TicketStatus.CLAIMED
|
||||
storage.save_ticket(ticket)
|
||||
|
||||
await interaction.followup.send("Ticket réclamé!", ephemeral=True)
|
||||
await interaction.channel.send(
|
||||
embed=TicketEmbedFormatter.ticket_claimed(ticket, interaction.user)
|
||||
)
|
||||
|
||||
async def _priority_callback(self, interaction: Interaction):
|
||||
"""Handle priority button click"""
|
||||
await interaction.response.defer(ephemeral=True)
|
||||
|
||||
if not self._is_staff(interaction):
|
||||
await interaction.followup.send(
|
||||
"Vous n'êtes pas staff.",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
modal = TicketPriorityChangeModal(self.bot, get_storage(), self.config)
|
||||
await interaction.response.send_modal(modal)
|
||||
|
||||
async def _transcript_callback(self, interaction: Interaction):
|
||||
"""Handle transcript button click"""
|
||||
await interaction.response.defer(ephemeral=True)
|
||||
|
||||
if not self._is_staff(interaction):
|
||||
await interaction.followup.send(
|
||||
"Vous n'êtes pas staff.",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
storage = get_storage()
|
||||
ticket = storage.load_ticket(interaction.channel.id)
|
||||
|
||||
if not ticket:
|
||||
await interaction.followup.send("Ticket non trouvé.", ephemeral=True)
|
||||
return
|
||||
|
||||
# Generate transcript
|
||||
transcript_gen = get_transcript_generator()
|
||||
|
||||
# Collect messages
|
||||
messages = []
|
||||
async for msg in interaction.channel.history(limit=1000, oldest_first=True):
|
||||
if msg.author.bot:
|
||||
continue
|
||||
messages.append({
|
||||
"id": str(msg.id),
|
||||
"author_id": msg.author.id,
|
||||
"author_name": str(msg.author),
|
||||
"content": msg.content,
|
||||
"timestamp": msg.created_at.isoformat(),
|
||||
"attachments": [a.url for a in msg.attachments],
|
||||
"is_staff": self._is_staff_member(msg.author)
|
||||
})
|
||||
|
||||
# Save transcript
|
||||
filepath = transcript_gen.save_transcript(ticket, messages, format="html")
|
||||
|
||||
if filepath:
|
||||
await interaction.followup.send(
|
||||
f"✅ Transcript sauvegardé: `{filepath}`",
|
||||
ephemeral=True
|
||||
)
|
||||
else:
|
||||
await interaction.followup.send(
|
||||
"❌ Erreur lors de la génération du transcript.",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
def _is_staff(self, interaction: Interaction) -> bool:
|
||||
"""Check if user is staff"""
|
||||
guild = interaction.guild
|
||||
user = interaction.user
|
||||
|
||||
for role_id in self.config.staff_roles:
|
||||
role = guild.get_role(int(role_id))
|
||||
if role and role in user.roles:
|
||||
return True
|
||||
|
||||
# Also check category-specific roles
|
||||
storage = get_storage()
|
||||
ticket = storage.load_ticket(interaction.channel.id)
|
||||
if ticket:
|
||||
category = self.config.get_category(ticket.category_id)
|
||||
if category:
|
||||
for role_id in category.staff_roles:
|
||||
role = guild.get_role(int(role_id))
|
||||
if role and role in user.roles:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _is_staff_member(self, member) -> bool:
|
||||
"""Check if member is staff"""
|
||||
guild = member.guild
|
||||
for role_id in self.config.staff_roles:
|
||||
role = guild.get_role(int(role_id))
|
||||
if role and role in member.roles:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class TicketCloseModal(Modal):
|
||||
"""Modal for closing a ticket with reason"""
|
||||
|
||||
def __init__(self, bot, storage, config: GuildTicketConfig, ticket: TicketData):
|
||||
super().__init__(title="🔒 Fermer le Ticket")
|
||||
self.bot = bot
|
||||
self.storage = storage
|
||||
self.config = config
|
||||
self.ticket = ticket
|
||||
|
||||
self.reason = TextInput(
|
||||
label="Raison de la fermeture",
|
||||
placeholder="Pourquoi fermez-vous ce ticket?",
|
||||
required=False,
|
||||
style=discord.TextStyle.paragraph,
|
||||
custom_id="close_reason"
|
||||
)
|
||||
self.add_item(self.reason)
|
||||
|
||||
async def on_submit(self, interaction: Interaction):
|
||||
await interaction.response.defer(ephemeral=True)
|
||||
|
||||
# Update ticket
|
||||
self.ticket.status = TicketStatus.CLOSED
|
||||
self.ticket.closed_at = datetime.now()
|
||||
self.storage.save_ticket(self.ticket)
|
||||
|
||||
# Calculate duration
|
||||
duration_minutes = self.ticket.duration_minutes
|
||||
|
||||
# Send close embed
|
||||
close_embed = TicketEmbedFormatter.ticket_closed(
|
||||
self.ticket,
|
||||
interaction.user,
|
||||
duration_minutes,
|
||||
self.reason.value
|
||||
)
|
||||
|
||||
# Update channel permissions
|
||||
overwrites = interaction.channel.overwrites.copy()
|
||||
for target, perms in overwrites.items():
|
||||
if isinstance(target, discord.Member) and target.id != interaction.guild.me.id:
|
||||
overwrites[target] = discord.PermissionOverwrite(
|
||||
read_messages=True,
|
||||
send_messages=False
|
||||
)
|
||||
|
||||
await interaction.channel.edit(
|
||||
name=f"closed-{interaction.channel.name}",
|
||||
overwrites=overwrites
|
||||
)
|
||||
|
||||
# Send close message
|
||||
await interaction.channel.send(
|
||||
content=TicketMessageFormatter.ticket_closed_notification(
|
||||
interaction.user,
|
||||
self.reason.value
|
||||
),
|
||||
embed=close_embed
|
||||
)
|
||||
|
||||
# Show survey if enabled
|
||||
if self.config.survey_enabled:
|
||||
survey_view = SurveyView(self.bot, self.storage, self.config, self.ticket)
|
||||
survey_embed = TicketEmbedFormatter.survey_embed()
|
||||
await interaction.channel.send(embed=survey_embed, view=survey_view)
|
||||
|
||||
# Log
|
||||
if self.config.log_channel_id:
|
||||
log_channel = interaction.guild.get_channel(self.config.log_channel_id)
|
||||
if log_channel:
|
||||
log_embed = discord.Embed(
|
||||
title="🔴 Ticket Fermé",
|
||||
color=Color.red(),
|
||||
timestamp=datetime.now()
|
||||
)
|
||||
log_embed.add_field(name="👤 Fermé par", value=interaction.user.mention, inline=True)
|
||||
log_embed.add_field(name="📝 Salon", value=interaction.channel.mention, inline=True)
|
||||
log_embed.add_field(name="⏱️ Durée", value=TicketEmbedFormatter._format_duration(duration_minutes), inline=True)
|
||||
|
||||
await log_channel.send(embed=log_embed)
|
||||
|
||||
await interaction.followup.send("Ticket fermé!", ephemeral=True)
|
||||
|
||||
|
||||
class TicketPriorityChangeModal(Modal):
|
||||
"""Modal for changing ticket priority"""
|
||||
|
||||
def __init__(self, bot, storage, config: GuildTicketConfig):
|
||||
super().__init__(title="⚡ Changer la Priorité")
|
||||
self.bot = bot
|
||||
self.storage = storage
|
||||
self.config = config
|
||||
|
||||
self.priority = Select(
|
||||
placeholder="Sélectionnez la nouvelle priorité",
|
||||
options=[
|
||||
discord.SelectOption(label="Basse", value="low", emoji="🟢"),
|
||||
discord.SelectOption(label="Normale", value="normal", emoji="🔵"),
|
||||
discord.SelectOption(label="Haute", value="high", emoji="🟠"),
|
||||
discord.SelectOption(label="Urgente", value="urgent", emoji="🔴"),
|
||||
],
|
||||
custom_id="priority_change"
|
||||
)
|
||||
self.add_item(self.priority)
|
||||
|
||||
async def on_submit(self, interaction: Interaction):
|
||||
await interaction.response.defer(ephemeral=True)
|
||||
|
||||
ticket = self.storage.load_ticket(interaction.channel.id)
|
||||
if not ticket:
|
||||
await interaction.followup.send("Ticket non trouvé.", ephemeral=True)
|
||||
return
|
||||
|
||||
priority_map = {
|
||||
"low": Priority.LOW,
|
||||
"normal": Priority.NORMAL,
|
||||
"high": Priority.HIGH,
|
||||
"urgent": Priority.URGENT
|
||||
}
|
||||
|
||||
old_priority = ticket.priority
|
||||
ticket.priority = priority_map[self.priority.values[0]]
|
||||
self.storage.save_ticket(ticket)
|
||||
|
||||
embed = discord.Embed(
|
||||
title="⚡ Priorité Changée",
|
||||
description=f"La priorité a été changée de **{old_priority.value}** à **{ticket.priority.value}**",
|
||||
color=TicketEmbedFormatter.get_priority_color(ticket.priority)
|
||||
)
|
||||
|
||||
await interaction.channel.send(embed=embed)
|
||||
await interaction.followup.send("Priorité mise à jour!", ephemeral=True)
|
||||
|
||||
|
||||
class SurveyView(View):
|
||||
"""View for satisfaction survey"""
|
||||
|
||||
def __init__(self, bot, storage, config: GuildTicketConfig, ticket: TicketData):
|
||||
super().__init__(timeout=None) # Persistent view
|
||||
self.bot = bot
|
||||
self.storage = storage
|
||||
self.config = config
|
||||
self.ticket = ticket
|
||||
|
||||
for i in range(1, 6):
|
||||
btn = Button(
|
||||
style=ButtonStyle.secondary,
|
||||
label=f"{i} ⭐",
|
||||
emoji="⭐" if i == 5 else None,
|
||||
custom_id=f"survey_{i}"
|
||||
)
|
||||
btn.callback = self._create_rating_callback(i)
|
||||
self.add_item(btn)
|
||||
|
||||
def _create_rating_callback(self, rating: int):
|
||||
async def callback(interaction: Interaction):
|
||||
await self.on_rating(interaction, rating)
|
||||
return callback
|
||||
|
||||
async def on_rating(self, interaction: Interaction, rating: int):
|
||||
"""Handle rating selection"""
|
||||
# Only allow ticket creator to rate
|
||||
if interaction.user.id != self.ticket.user_id:
|
||||
await interaction.response.send_message(
|
||||
"Seul le créateur du ticket peut voter.",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
# Update ticket
|
||||
self.ticket.rating = rating
|
||||
self.storage.save_ticket(self.ticket)
|
||||
|
||||
# Show thanks
|
||||
embed = TicketEmbedFormatter.survey_thanks_embed(rating)
|
||||
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||
|
||||
# Disable buttons
|
||||
for item in self.children:
|
||||
item.disabled = True
|
||||
|
||||
await interaction.message.edit(view=self)
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue