-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtickets.py
229 lines (189 loc) · 10.6 KB
/
tickets.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
from functools import wraps
import nextcord
from nextcord import ui
from nextcord.ext import commands
from cache_data import cache_return
from data_file import save_json, tickets_data
from discord_utils import hidden_pin
from misc_classes import ConfirmationView
from utils import error_embed, get_id_str, get_textchannel, is_user_on_guild, normal_embed, question_embed, validation_embed
from variables import bot, bot_name, discord_variables, guild_ids
ticket_ignore_channels = (995064624712003584,)
ticket_permissions = nextcord.PermissionOverwrite(add_reactions=True, read_messages=True, view_channel=True, send_messages=True,
embed_links=True, attach_files=True, read_message_history=True, external_emojis=True, external_stickers=True,
use_slash_commands=True)
tickets_types = {
"report": {
"name": "Ticket Signalement",
"emoji": "🚨",
"description": "Pour signaler un utilisateur ou un projet",
"channel_format": "report-{number}-{username}"
},
"recruit": {
"name": "Ticket Recrutement",
"emoji": "🛠",
"description": "Pour demander à rejoindre le staff du serveur",
"channel_format": "recruit-{number}-{username}"
},
"help": {
"name": "Ticket Aide",
"emoji": "❔",
"description": "Si vous avez une question consernant le serveur ou les bots",
"channel_format": "help-{number}-{username}"
},
"other": {
"name": "Ticket Autre",
"emoji": "💠",
"description": "Pour un sujet ne correspondant pas à ces catégories",
"channel_format": "other-{number}-{username}"
}
}
@cache_return()
def is_ticket_channel(channel: nextcord.abc.GuildChannel):
return channel.category == discord_variables.tickets_categ and channel.id not in ticket_ignore_channels
def check_is_ticket(func):
@wraps(func)
async def overwrite(self, interaction, *args, **kwargs):
if not is_ticket_channel(interaction.channel):
await interaction.response.send_message(embed=error_embed("La commande ne peut pas être exécutée ici."), ephemeral=True)
return
await func(self, interaction, *args, **kwargs)
return overwrite
class TicketsCog(commands.Cog):
@nextcord.slash_command(name="ticket", guild_ids=guild_ids)
async def ticket_cmd(self, interaction: nextcord.Interaction):
pass
@ticket_cmd.subcommand(name='create', description="Permet de créer un ticket")
async def ticket_create_cmd(self, interaction, type_: str = nextcord.SlashOption(name="type", description="Le type de ticket à ouvrir", required=True,
choices={type_data["name"]: id_ for id_, type_data in tickets_types.items()})):
await create_ticket(interaction, type_)
@ticket_cmd.subcommand(name="close", description="Permet de fermer un ticket")
@check_is_ticket
async def ticket_close_cmd(self, interaction):
await close_ticket(interaction)
@ticket_cmd.subcommand(name="add-user", description="Permet d'ajouter un utilisateur à un ticket")
@check_is_ticket
async def ticket_add_user_cmd(self, interaction, member: nextcord.Member = nextcord.SlashOption(name="membre", description="Le membre à ajouter au ticket", required=True)):
ticket_data = tickets_data["channels"][get_id_str(interaction.channel)]
if member.id in ticket_data["members"]:
await interaction.response.send_message(embed=error_embed("L'utilisateur est déjà un membre du ticket"), ephemeral=True)
return
ticket_data["members"].append(member.id)
save_json()
if is_user_on_guild(member):
bot.loop.create_task(interaction.channel.set_permissions(member, overwrite=ticket_permissions, reason="Ajout d'un membre au ticket"))
await interaction.response.send_message(embed=validation_embed(f"{member.mention} a été ajouté au ticket"), ephemeral=True)
@ticket_cmd.subcommand(name="remove-user", description="Permet de retirer un utilisateur à un ticket")
@check_is_ticket
async def ticket_remove_user_cmd(self, interaction, member: nextcord.Member = nextcord.SlashOption(name="membre", description="Le membre à retirer du ticket", required=True)):
ticket_data = tickets_data["channels"][get_id_str(interaction.channel)]
if member.id not in ticket_data["members"]:
await interaction.response.send_message(embed=error_embed("L'utilisateur n'est pas un membre du ticket"), ephemeral=True)
return
ticket_data["members"].remove(member.id)
save_json()
if is_user_on_guild(member):
bot.loop.create_task(interaction.channel.set_permissions(member, overwrite=None, reason="Retrait d'un membre au ticket"))
await interaction.response.send_message(embed=validation_embed(f"{member.mention} a été retiré du ticket"), ephemeral=True)
@commands.Cog.listener()
async def on_ready(self):
bot.add_view(CreateTicketView())
bot.add_view(CloseTicketView())
bot.add_view(SupportControlsView())
@commands.Cog.listener()
async def on_rules_accept(self, member):
for channel_id, ticket_data in tickets_data["channels"].items():
if member.id in ticket_data["members"]:
channel = get_textchannel(channel_id)
bot.loop.create_task(channel.set_permissions(member, overwrite=ticket_permissions, reason="Ajout d'un membre au ticket lors de l'acceptation des règles"))
class CreateTicketView(ui.View):
view_name = f"{bot_name}:create_ticket"
def __init__(self):
super().__init__(timeout=None)
@ui.select(placeholder="Sélectionnez le type adéquat pour votre sujet", custom_id=f"{view_name}:create_selector",
options=[nextcord.SelectOption(label=type_data["name"], value=id_, description=type_data["description"], emoji=type_data.get("emoji"))
for id_, type_data in tickets_types.items()])
async def create_selector(self, select: ui.Select, interaction: nextcord.Interaction):
if len(select.values) != 1:
await interaction.send(embed=error_embed("Vous devez sélectionner exactement une option, comment avez vous fait autrement !?", "Erreur Impossible"))
return
await create_ticket(interaction, select.values[0])
class CloseTicketView(ui.View):
view_name = f"{bot_name}:close_ticket"
def __init__(self):
super().__init__(timeout=None)
@ui.button(label="Fermer le ticket", emoji="🗑️", style=nextcord.ButtonStyle.red, custom_id=f"{view_name}:close")
async def close_button(self, button, interaction):
await close_ticket(interaction)
class SupportControlsView(ui.View):
view_name = f"{bot_name}:support_controls"
def __init__(self):
super().__init__(timeout=None)
@ui.button(label="Réouvrir le ticket", emoji="📤", style=nextcord.ButtonStyle.green, custom_id=f"{view_name}:reopen")
async def reopen_button(self, button, interaction):
ticket_data = tickets_data["channels"][get_id_str(interaction.channel)]
if ticket_data["open"]:
bot.loop.create_task(interaction.message.delete())
await interaction.response.send_message("Le ticket est déjà réouvert", ephemeral=True)
return
ticket_data["open"] = True
save_json()
overwrites = interaction.channel.overwrites
for member_id in ticket_data["members"]:
member = discord_variables.main_guild.get_member(member_id)
if member is not None:
overwrites[member] = ticket_permissions
bot.loop.create_task(interaction.message.delete())
bot.loop.create_task(interaction.channel.edit(overwrites=overwrites, reason=f"Réouverture du ticket"))
await interaction.response.send_message(embed=normal_embed(f"Le ticket a été réouvert par {interaction.user.mention}"), allowed_mentions=nextcord.AllowedMentions.none())
@ui.button(label="Supprimer le ticket", emoji="🗑️", style=nextcord.ButtonStyle.red, custom_id=f"{view_name}:delete")
async def delete_button(self, button, interaction):
del (tickets_data["channels"][get_id_str(interaction.channel)])
save_json()
await interaction.channel.delete(reason="Suppression du ticket")
async def create_ticket(interaction, ticket_type_id):
ticket_type = tickets_types[ticket_type_id]
tickets_data["counter"] += 1
count_str = str(tickets_data["counter"]).zfill(4)
channel = await discord_variables.tickets_categ.create_text_channel(ticket_type["channel_format"].format(number=count_str, username=interaction.user.display_name), overwrites={
discord_variables.main_guild.default_role: nextcord.PermissionOverwrite(view_channel=False),
discord_variables.support_role: nextcord.PermissionOverwrite(view_channel=True), interaction.user: ticket_permissions}, reason="Création d'un ticket")
start_embed = normal_embed(f"Bienvenue {interaction.user.mention}, un membre du staff vous répondra au plus vite.\nEn attendant, vous pouvez nous expliquer votre demande.")
start_embed.add_field(name="Auteur", value=interaction.user.mention, inline=False)
start_embed.add_field(name="Aide", value="""Pour refermer le ticket, cliquez sur le button ci-dessous ou exécutez la commande `/ticket close`.
Pour ajouter ou retirer un membre de votre ticket, exécutez les commandes `/ticket add-user <membre>` ou `/ticket remove-user <membre>`.""", inline=False)
start_embed.add_field(name="Type de ticket", value=ticket_type["name"], inline=False)
await interaction.response.send_message(f"Le ticket à été créé: {channel.mention}.", ephemeral=True)
start_msg = await channel.send(embed=start_embed, view=CloseTicketView())
tickets_data["channels"][get_id_str(channel)] = {"members": [interaction.user.id], "system_messages": [start_msg.id], "open": True}
save_json()
bot.loop.create_task(hidden_pin(start_msg, reason="Épinglage du message d'informations"))
async def close_ticket(interaction):
ticket_data = tickets_data["channels"][get_id_str(interaction.channel)]
if not ticket_data["open"]:
await interaction.response.send_message(embed=error_embed("Le ticket est déjà fermé"), ephemeral=True)
return
view = ConfirmationView()
await interaction.response.send_message(embed=question_embed('Êtes-vous sur de vouloir fermer ce ticket ?'), view=view)
await view.wait()
if view.value:
if not ticket_data["open"]:
await interaction.edit_original_message(embed=error_embed("Le ticket est déjà fermé"), view=None)
await interaction.delete_original_message(delay=30)
return
ticket_data["open"] = False
save_json()
overwrites = interaction.channel.overwrites
for member_id in ticket_data["members"]:
member = discord_variables.main_guild.get_member(member_id)
if member is not None:
try:
del (overwrites[member])
except KeyError:
pass
bot.loop.create_task(interaction.channel.edit(overwrites=overwrites, reason=f"Fermeture du ticket"))
bot.loop.create_task(interaction.channel.send(embed=normal_embed("Contrôles de l'équipe de support"), view=SupportControlsView()))
await interaction.edit_original_message(embed=normal_embed(f"Ticket fermé par {interaction.user.mention}"), allowed_mentions=nextcord.AllowedMentions.none(), view=None)
else:
await interaction.edit_original_message(embed=normal_embed("Fermeture du ticket annulée"), view=None)
await interaction.delete_original_message(delay=30)