feat(ticket): add claim, add member, persistent management view
All checks were successful
ci / ci (push) Successful in 47s

- ClaimButton: staff claim/unclaim with log
- AddMemberButton: UserSelect to add member to ticket channel
- TicketManagementView: persistent LayoutView with all 3 buttons
- claimed_by field in TicketData
- Buttons registered as persistent views for bot restart survival
This commit is contained in:
Mathis 2026-09-25 19:28:15 +02:00
parent 80daeae55c
commit 4d1e265848
3 changed files with 135 additions and 2 deletions

View file

@ -185,7 +185,13 @@ class TicketModal(discord.ui.Modal, title="Nouveau Ticket"):
)
)
container.add_item(discord.ui.Separator())
container.add_item(discord.ui.ActionRow(CloseButton()))
container.add_item(
discord.ui.ActionRow(
ClaimButton(),
AddMemberButton(),
CloseButton(),
)
)
view = discord.ui.LayoutView()
view.add_item(container)
@ -208,6 +214,122 @@ class TicketModal(discord.ui.Modal, title="Nouveau Ticket"):
await _send_log(guild, config, embed)
class ClaimButton(discord.ui.Button):
def __init__(self):
super().__init__(
label="Claim",
style=discord.ButtonStyle.success,
custom_id="ticket_claim",
emoji="Claim",
)
async def callback(self, interaction: discord.Interaction):
config = storage.get_config(interaction.guild_id)
ticket = storage.get_ticket(interaction.channel.id)
if not ticket:
await interaction.response.send_message("Ce n'est pas un ticket.", ephemeral=True)
return
member = interaction.guild.get_member(interaction.user.id)
if not member or not _is_staff(member, config):
await interaction.response.send_message("Seul le staff peut claim un ticket.", ephemeral=True)
return
if ticket.claimed_by:
if ticket.claimed_by == interaction.user.id:
ticket.claimed_by = None
storage.save_ticket(ticket)
await interaction.response.send_message(
f"{interaction.user.mention} a retire son claim.", ephemeral=True
)
else:
await interaction.response.send_message(
f"Ce ticket est deja claim par <@{ticket.claimed_by}>.", ephemeral=True
)
return
ticket.claimed_by = interaction.user.id
storage.save_ticket(ticket)
embed = discord.Embed(
title="Ticket claim",
description=f"Claim par {interaction.user.mention}",
color=discord.Color.green(),
timestamp=datetime.now(timezone.utc),
)
await _send_log(interaction.guild, config, embed)
container = discord.ui.Container()
container.add_item(discord.ui.TextDisplay(f"## Ticket claim\nClaim par {interaction.user.mention}"))
view = discord.ui.LayoutView()
view.add_item(container)
await interaction.response.send_message(view=view)
class AddMemberButton(discord.ui.Button):
def __init__(self):
super().__init__(
label="Ajouter un membre",
style=discord.ButtonStyle.secondary,
custom_id="ticket_add_member",
emoji="Ajouter",
)
async def callback(self, interaction: discord.Interaction):
config = storage.get_config(interaction.guild_id)
ticket = storage.get_ticket(interaction.channel.id)
if not ticket:
await interaction.response.send_message("Ce n'est pas un ticket.", ephemeral=True)
return
member = interaction.guild.get_member(interaction.user.id)
if not member or not _is_staff(member, config):
await interaction.response.send_message("Seul le staff peut ajouter des membres.", ephemeral=True)
return
await interaction.response.send_message(
"Selectionnez le membre a ajouter :",
view=AddMemberSelectView(),
ephemeral=True,
)
class AddMemberSelect(discord.ui.UserSelect):
def __init__(self):
super().__init__(
placeholder="Selectionnez un membre...",
custom_id="ticket_add_member_select",
min_values=1,
max_values=1,
)
async def callback(self, interaction: discord.Interaction):
user = self.values[0]
await interaction.channel.set_permissions(
user,
view_channel=True,
send_messages=True,
read_message_history=True,
)
await interaction.response.edit_message(
content=f"{user.mention} a ete ajoute au ticket.",
view=None,
)
embed = discord.Embed(
title="Membre ajoute",
description=f"{user.mention} a ete ajoute par {interaction.user.mention}",
color=discord.Color.blue(),
timestamp=datetime.now(timezone.utc),
)
await _send_log(interaction.guild, storage.get_config(interaction.guild_id), embed)
class AddMemberSelectView(discord.ui.View):
def __init__(self):
super().__init__(timeout=300)
self.add_item(AddMemberSelect())
class CloseButton(discord.ui.Button):
def __init__(self):
super().__init__(