@elara-services/tickets 3.1.6 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/v13.js CHANGED
@@ -1,218 +1,518 @@
1
- const { MessageEmbed } = require("discord.js"),
2
- base = require("./base"),
3
- { de, code, fetchMessages, hasTicket, embed, webhook, getAppealServer } = require("./util"),
4
- { generate } = require("@elara-services/utils"),
5
- { Interactions: { button, modal } } = require("@elara-services/packages");
1
+ const {
2
+ MessageEmbed,
3
+ Constants: { MessageComponentTypes },
4
+ MessageComponentInteraction,
5
+ } = require("discord.js"),
6
+ base = require("./base"),
7
+ { de, code, fetchMessages, hasTicket, embed, webhook, getAppealServer, perms, defs } = require("./util"),
8
+ { generate, parser, discord } = require("@elara-services/utils"),
9
+ {
10
+ Interactions: { button },
11
+ } = require("@elara-services/packages");
6
12
 
7
13
  module.exports = class Tickets extends base {
14
+ /**
15
+ * @param {import("@elara-services/tickets").TicketOptions} options
16
+ */
8
17
  constructor(options = {}) {
9
18
  super(options);
10
- };
19
+ }
11
20
  /**
12
- * @param {import("discord.js").Interaction} int
21
+ * @param {import("discord.js").Interaction} int
13
22
  */
14
23
  async run(int) {
15
- if (int?.isButton?.() || int?.isModalSubmit()) {
24
+ if (!int || !int.guild) {
25
+ return;
26
+ }
27
+ if (int.isSelectMenu()) {
28
+ if (int.values[0] === this.prefix) {
29
+ int.customId = this.prefix;
30
+ int.componentType = MessageComponentInteraction.resolveType(MessageComponentTypes.BUTTON);
31
+ }
32
+ }
33
+ if (int.isButton() || int.isModalSubmit()) {
16
34
  let { guild, channel, member, customId } = int,
17
- category = guild?.channels?.resolve?.(this.options.ticket?.category || this.options.ticketCategory || channel?.parentId);
18
- if (!guild?.available || !channel || !member || !category) return;
35
+ category = guild?.channels?.resolve?.(this.options.ticket?.category || channel?.parentId);
36
+ if (!guild?.available || !channel || !member || !category) {
37
+ return;
38
+ }
19
39
 
20
40
  /**
21
- * @param {import("discord.js").InteractionDeferReplyOptions|import("discord.js").InteractionReplyOptions} options
22
- * @param {boolean} edit
23
- * @param {boolean} defer
41
+ * @param {import("discord.js").InteractionDeferReplyOptions|import("discord.js").InteractionReplyOptions} options
42
+ * @param {boolean} edit
43
+ * @param {boolean} defer
24
44
  */
25
45
  const send = async (options = {}, defer = false) => {
26
- if (defer) return int.deferReply(options).catch(e => this._debug(e));
27
- if (int.replied || int.deferred) return int.editReply(options).catch(e => this._debug(e));
28
- return int.reply(options).catch(e => this._debug(e));
46
+ if (defer) {
47
+ return int.deferReply(options).catch(this._debug);
48
+ }
49
+ if (int.replied || int.deferred) {
50
+ return int.editReply(options).catch(this._debug);
51
+ }
52
+ return int.reply(options).catch(this._debug);
29
53
  };
30
54
  switch (customId) {
31
55
  case this.prefix: {
32
- if (this.options?.ticket?.limitOnePerUser && hasTicket({ userId: member.id, guild, token: this.options.encryptToken, prefix: this.options.prefix })) return send({ embeds: [ embed(`❌ You can only create one (${this.options.prefix}) ticket at a time.`, { guild }) ], ephemeral: true })
56
+ if (
57
+ this.options?.ticket?.limitOnePerUser &&
58
+ hasTicket({
59
+ userId: member.id,
60
+ guild,
61
+ token: this.options.encryptToken,
62
+ prefix: this.options.prefix,
63
+ })
64
+ ) {
65
+ return send({
66
+ embeds: [embed(this.str("TICKET_LIMIT_ONE_PER_USER")(this.options.prefix), { guild, str: this.str })],
67
+ ephemeral: true,
68
+ });
69
+ }
33
70
  if (this.options.support?.ignore?.length) {
34
- if (this.options.support.ignore.some(c => member.roles.cache.has(c))) return send({ embeds: [embed(`❌ You can no longer create tickets, if you believe this is a mistake contact one of the staff members.`)], ephemeral: true });
71
+ if (this.options.support.ignore.some((c) => member.roles.cache.has(c))) {
72
+ return send({
73
+ embeds: [embed(this.str("TICKET_BLOCKED"), { str: this.str })],
74
+ ephemeral: true,
75
+ });
76
+ }
35
77
  }
36
- if (this.options.modal?.enabled) return int.showModal(this.modal({ title: this.options.modal.title, components: this.options.modal.questions?.length >= 1 ? this.options.modal.questions.slice(0, 5).map(c => ({ type: 1, components: [{ min_length: c.min_length || 10, max_length: c.max_length || 4000, type: 4, style: c.style || 2, label: c.label, value: c.value, placeholder: c.placeholder, required: c.required, custom_id: c.label || `random_${Math.floor(Math.random() * 10000)}` }] })) : [] })).catch(e => this._debug(e));
37
- return this.handleCreate({ guild, member, category, send })
38
- };
78
+ if (this.options.modal?.enabled) {
79
+ return int
80
+ .showModal(
81
+ defs.modals.custom(
82
+ {
83
+ title: this.options.modal?.title,
84
+ components: defs.getModalComponents(this.options.modal?.questions || []),
85
+ },
86
+ { prefix: this.prefix, str: this.str },
87
+ ),
88
+ )
89
+ .catch(this._debug);
90
+ }
91
+ return this.handleCreate({ guild, member, category, send });
92
+ }
39
93
 
40
94
  case `${this.prefix}:close`: {
41
- if (this.options.support?.canOnlyCloseTickets && !member.permissions.has("MANAGE_GUILD")) {
95
+ if (this.options.support?.canOnlyCloseTickets && !member.permissions.has(perms.manage.guild)) {
42
96
  if (!this.getSupportIds.users?.includes?.(member.id)) {
43
- if (!this.getSupportIds.roles?.some?.(c => member.roles.cache.has(c))) return send({ ephemeral: true, embeds: [{ author: { name: `Only support staff can close tickets`, iconURL: "https://cdn.discordapp.com/emojis/781955502035697745.gif" }, color: 0xFF0000 }] })
97
+ if (!this.getSupportIds.roles?.some?.((c) => member.roles.cache.has(c))) {
98
+ return send({
99
+ ephemeral: true,
100
+ embeds: [
101
+ {
102
+ author: {
103
+ name: this.str("ONLY_SUPPORT"),
104
+ iconURL: "https://cdn.discordapp.com/emojis/781955502035697745.gif",
105
+ },
106
+ color: 0xff0000,
107
+ },
108
+ ],
109
+ });
110
+ }
44
111
  }
45
112
  }
46
- return send({
47
- ephemeral: true,
48
- embeds: [ embed(`🤔 Are you sure you want to close the ticket?`, { color: 0xFF000, guild }) ],
113
+ return send({
114
+ ephemeral: true,
115
+ embeds: [
116
+ embed(this.str("TICKET_CLOSE_CONFIRM"), {
117
+ color: 0xff000,
118
+ guild,
119
+ str: this.str,
120
+ }),
121
+ ],
49
122
  components: [
50
- { type: 1, components: [
51
- button({ title: "Yes, close the ticket!", style: 3, emoji: { id: "807031399563264030" }, id: `${this.prefix}:close:confirm:${code(channel.topic?.split?.("ID: ")?.[1], "d", this.options.encryptToken)}${this.options?.ticket?.closeReason ? `:modal_submit` : ""}` })
52
- ]
53
- }]
54
- })
123
+ {
124
+ type: 1,
125
+ components: [
126
+ button({
127
+ title: this.str("TICKET_CLOSE_CONFIRM_BUTTON"),
128
+ style: 3,
129
+ emoji: { id: "807031399563264030" },
130
+ id: `${this.prefix}:close:confirm:${code(channel.topic?.split?.("ID: ")?.[1], "d", this.options.encryptToken)}${this.options?.ticket?.closeReason ? `:modal_submit` : ""}`,
131
+ }),
132
+ ],
133
+ },
134
+ ],
135
+ });
55
136
  }
56
137
 
57
138
  case `${this.prefix}:modal_submit`: {
58
- let [embed, fields, split] = [new MessageEmbed().setColor("ORANGE").setTimestamp().setTitle(`For Responses`).setFooter({ text: `ID: ${member.id}` }).setAuthor({ name: member.user.username, iconURL: member.user.displayAvatarURL({ dynamic: true }) }), [], false];
139
+ let [embed, fields, split] = [
140
+ new MessageEmbed()
141
+ .setColor("ORANGE")
142
+ .setTimestamp()
143
+ .setTitle(this.str("FORM_RESPONSES"))
144
+ .setFooter({ text: this.str("ID")(member.id) })
145
+ .setAuthor({
146
+ name: member.user.username,
147
+ iconURL: member.user.displayAvatarURL({ dynamic: true }),
148
+ }),
149
+ [],
150
+ false,
151
+ ];
59
152
  for (const c of int.fields.components) {
60
153
  for (const cc of c.components) {
61
154
  if (cc.value && cc.customId) {
62
155
  fields.push({ name: cc.customId, value: cc.value });
63
- if (cc.value.length <= 1024) embed.addField(cc.customId, cc.value);
64
- else split = true
156
+ if (cc.value.length <= 1024) {
157
+ embed.addFields({ name: cc.customId, value: cc.value });
158
+ } else {
159
+ split = true;
160
+ }
65
161
  }
66
162
  }
67
163
  }
68
164
  if (embed.length >= 6000 || split) {
69
165
  return this.handleCreate({
70
- guild, member, category, send, embeds: fields.map((v, i) => ({
71
- title: `Form Response: ${v.name}`, color: embed.color, description: v.value,
72
- author: i === 0 ? { name: member.user.username, iconURL: member.user.displayAvatarURL({ dynamic: true }) } : undefined,
166
+ guild,
167
+ member,
168
+ category,
169
+ send,
170
+ embeds: fields.map((v, i) => ({
171
+ title: `${this.str("FORM_RESPONSE")}: ${v.name}`,
172
+ color: embed.color,
173
+ description: v.value,
174
+ author:
175
+ i === 0
176
+ ? {
177
+ name: member.user.username,
178
+ iconURL: member.user.displayAvatarURL({
179
+ dynamic: true,
180
+ }),
181
+ }
182
+ : undefined,
73
183
  timestamp: fields.length - 1 === i ? new Date() : undefined,
74
- footer: fields.length - 1 === i ? { text: `ID: ${member.id}` } : undefined
75
- }))
76
- })
77
- };
78
- return this.handleCreate({ guild, member, category, send, embeds: [embed] })
184
+ footer: fields.length - 1 === i ? { text: this.str("ID")(member.id) } : undefined,
185
+ })),
186
+ });
187
+ }
188
+ return this.handleCreate({
189
+ guild,
190
+ member,
191
+ category,
192
+ send,
193
+ embeds: [embed],
194
+ });
79
195
  }
80
- };
196
+ }
81
197
  if (customId.startsWith(`${this.prefix}:close:confirm`)) {
82
198
  if (customId.includes(`:modal_submit`)) {
83
- return int.showModal(modal({
84
- id: `${customId.split(":modal_submit")[0]}:modal_complete`,
85
- title: "Reason",
86
- components: [ { type: 1, components: [ { type: 4, custom_id: "reason", label: "Reason", style: 2, min_length: 1, max_length: 1024, required: true, placeholder: "What's the reason for closing the ticket?" } ] } ]
87
- }))
199
+ return int.showModal(defs.modals.reason(customId, this.str));
88
200
  }
89
201
  await send({ ephemeral: true }, true);
90
- let reason = "No Reason Provided";
91
- if (int.isModalSubmit()) reason = int.fields.getTextInputValue("reason")
92
- let user = await this.options.client.users.fetch(customId.split("close:confirm:")[1].replace(/:modal_complete/gi, "")).catch(e => this._debug(e));
93
- if (!user) return send({ embeds: [ embed(`❌ I was unable to fetch the user that opened the ticket.`) ] });
202
+ let reason = this.str("NO_REASON");
203
+ if (int.isModalSubmit()) {
204
+ reason = int.fields.getTextInputValue("reason");
205
+ }
206
+ const user = await discord.user(this.options.client, customId.split("close:confirm:")[1].replace(/:modal_complete/gi, ""), { fetch: true, mock: false });
207
+ if (!user) {
208
+ return send({
209
+ embeds: [embed(this.str("NO_USER_FOUND", { str: this.str }))],
210
+ });
211
+ }
94
212
  let messages = await fetchMessages(channel, 5000);
95
- if (!messages?.length) return send({ embeds: [ embed(`❌ I was unable to close the ticket, I couldn't fetch the messages in this channel.`) ] });
96
- let closed = await channel.delete(`${member.user.tag} (${member.id}) closed the ticket.`).catch(e => this._debug(e));
97
- if (!closed) return send({ embeds: [ embed(`❌ I was unable to delete the channel and close the ticket.`) ] });
98
- return this.closeTicket({ channel, guild, user, member, messages, reason });
99
- };
213
+ if (!messages?.length) {
214
+ return send({
215
+ embeds: [embed(this.str("NO_MESSAGES_FETCHED"), { str: this.str })],
216
+ });
217
+ }
218
+ let closed = await channel.delete(`${member.user.tag} (${member.id}) ${this.str("CLOSED_TICKET")}`).catch(this._debug);
219
+ if (!closed) {
220
+ return send({
221
+ embeds: [embed(this.str("NO_CHANNEL_DELETE"), { str: this.str })],
222
+ });
223
+ }
224
+ return this.closeTicket({
225
+ channel,
226
+ guild,
227
+ user,
228
+ member,
229
+ messages,
230
+ reason,
231
+ });
232
+ }
100
233
 
101
- if (customId.startsWith("unban:")) {
102
- if (!int.memberPermissions?.has?.([ "BAN_MEMBERS" ])) return send({ embeds: [ embed(`❌ You need (Ban Members) in this server to complete this action!`) ], ephemeral: true });
234
+ if (customId.startsWith(`${this.prefix}:unban:`)) {
235
+ if (!int.memberPermissions?.has?.([perms.members.ban])) {
236
+ return send({
237
+ embeds: [embed(this.str("NO_BAN_PERMS_USER"), { str: this.str })],
238
+ ephemeral: true,
239
+ });
240
+ }
103
241
  let server = getAppealServer(this.options);
104
- if (!server) return send({ embeds: [embed(`❌ I was unable to find the appeal server!`)], ephemeral: true });
105
- let mod = server.members.resolve(member.id) || await server.members.fetch(member.id).catch(e => this._debug(e));
106
- if (!mod) return send({ embeds: [embed(`❌ I was unable to find you in ${server.name}!`)], ephemeral: true });
107
- if (!mod.permissions?.has?.([ "BAN_MEMBERS" ])) return send({ embeds: [embed(`❌ You need (Ban Members) in ${server.name} to complete this action!`)], ephemeral: true });
108
- return int.showModal(modal({
109
- id: `unban_modal:${customId.split(":")[1]}`,
110
- title: `Unban From ${server.name}`,
111
- components: [ { type: 1, components: [ { type: 4, label: "Reason", custom_id: "reason", style: 2, min_length: 1, max_length: 512, required: true, value: `No Reason Provided | By: ${member.user.tag} (${member.id})` } ] } ]
112
- })).catch(e => this._debug(e));
242
+ if (!server) {
243
+ return send({
244
+ embeds: [embed(this.str("NO_APPEAL_SERVER_FOUND"), { str: this.str })],
245
+ ephemeral: true,
246
+ });
247
+ }
248
+ const mod = await discord.member(server, member.id, true);
249
+ if (!mod) {
250
+ return send({
251
+ embeds: [embed(this.str("NOT_FOUND_IN_APPEAL_SERVER")(server), { str: this.str })],
252
+ ephemeral: true,
253
+ });
254
+ }
255
+ if (!mod.permissions?.has?.([perms.members.ban])) {
256
+ return send({
257
+ embeds: [embed(this.str("NO_BAN_PERMS_USER_IN_APPEAL_SERVER")(server), { str: this.str })],
258
+ ephemeral: true,
259
+ });
260
+ }
261
+ return int.showModal(defs.modals.unbanReason(customId, server, this.str, member, this.prefix)).catch(this._debug);
113
262
  }
114
263
 
115
- if (customId.startsWith("unban_modal:")) {
264
+ if (customId.startsWith(`${this.prefix}:unban_modal:`)) {
116
265
  await send({ ephemeral: true }, true);
117
- const [ , id ] = customId.split(":");
118
- if (!int.memberPermissions?.has?.([ "BAN_MEMBERS" ])) return send({ embeds: [ embed(`❌ You need (Ban Members) in this server to complete this action!`)] });
266
+ const [, , id] = customId.split(":");
267
+ if (!int.memberPermissions?.has?.([perms.members.ban])) {
268
+ return send({
269
+ embeds: [embed(this.str("NO_BAN_PERMS_USER"), { str: this.str })],
270
+ });
271
+ }
119
272
  let server = getAppealServer(this.options);
120
- if (!server) return send({ embeds: [embed(`❌ I was unable to find the appeal server!`)] });
121
- let mod = server.members.resolve(member.id) || await server.members.fetch(member.id).catch(e => this._debug(e));
122
- if (!mod) return send({ embeds: [embed(`❌ I was unable to find you in ${server.name}!`)] });
123
- if (!mod.permissions?.has?.([ "BAN_MEMBERS" ])) return send({ embeds: [embed(`❌ You need (Ban Members) in ${server.name} to complete this action!`)] });
124
- let isBanned = await server.bans.fetch({ user: id, force: true }).catch(e => this._debug(e));
125
- if (!isBanned) return send({ embeds: [embed(`❌ User (<@${id}>) isn't banned in the main server!`)] });
126
- return server.bans.remove(id, int.fields.getTextInputValue("reason") ?? `No Reason Provided | By: ${member.user.tag} (${member.id})`)
127
- .then(() => {
128
- int.message.edit({ components: [ { type: 1, components: [ button({ title: "Unbanned!", style: 3, id: "_ _", disabled: true, emoji: { id: `476629550797684736` } }) ] } ] }).catch(e => this._debug(e));
129
- send({ embeds: [embed(`✅ Successfully unbanned <@${id}> from ${server.name}!`)] })
130
- })
131
- .catch(e => send({ embeds: [ { title: "ERROR", fields: [ { name: "\u200b", value: `❌ Unable to unban <@${id} from ${server.name}!` } ], description: `\`\`\`js\n${e.message ?? e.stack}\`\`\``, color: 0xFF0000 } ] }))
273
+ if (!server) {
274
+ return send({
275
+ embeds: [embed(this.str("NO_APPEAL_SERVER_FOUND"), { str: this.str })],
276
+ });
277
+ }
278
+ const mod = await discord.member(server, member.id, true);
279
+ if (!mod) {
280
+ return send({
281
+ embeds: [embed(this.str("NOT_FOUND_IN_APPEAL_SERVER")(server), { str: this.str })],
282
+ });
283
+ }
284
+ if (!mod.permissions?.has?.([perms.members.ban])) {
285
+ return send({
286
+ embeds: [embed(this.str("NO_BAN_PERMS_USER_IN_APPEAL_SERVER")(server), { str: this.str })],
287
+ });
288
+ }
289
+ let isBanned = await server.bans.fetch({ user: id, force: true }).catch(this._debug);
290
+ if (!isBanned) {
291
+ return send({
292
+ embeds: [embed(this.str("USER_NOT_BANNED")(id), { str: this.str })],
293
+ });
294
+ }
295
+ return server.bans
296
+ .remove(id, int.fields.getTextInputValue("reason") ?? `${this.str("NO_REASON")} | ${this.str("BY")}: ${member.user.tag} (${member.id})`)
297
+ .then(() => {
298
+ int.message
299
+ .edit({
300
+ components: [
301
+ {
302
+ type: 1,
303
+ components: [
304
+ button({
305
+ title: this.str("UNBANNED"),
306
+ style: 3,
307
+ id: "_ _",
308
+ disabled: true,
309
+ emoji: { id: `476629550797684736` },
310
+ }),
311
+ ],
312
+ },
313
+ ],
314
+ })
315
+ .catch(this._debug);
316
+ send({
317
+ embeds: [embed(this.str("UNBAN_SUCCESS")(id, server.name), { str: this.str })],
318
+ });
319
+ })
320
+ .catch((e) =>
321
+ send({
322
+ embeds: [
323
+ {
324
+ title: this.str("ERROR"),
325
+ fields: [
326
+ {
327
+ name: "\u200b",
328
+ value: this.str("UNBAN_FAILED")(id, server.name),
329
+ },
330
+ ],
331
+ description: `\`\`\`js\n${e.message ?? e.stack}\`\`\``,
332
+ color: 0xff0000,
333
+ },
334
+ ],
335
+ }),
336
+ );
132
337
  }
133
- };
134
- };
338
+ }
339
+ }
135
340
 
136
341
  /** @private */
137
342
  async handleCreate({ guild, member, category, send, embeds = [] } = {}) {
138
343
  await send({ ephemeral: true }, true);
139
- let [ permissions, allow, { appeals }, sendBanReason ] = [
140
- [],
141
- ["ADD_REACTIONS", "ATTACH_FILES", "CREATE_INSTANT_INVITE", "EMBED_LINKS", "READ_MESSAGE_HISTORY", "VIEW_CHANNEL", "USE_EXTERNAL_EMOJIS", "SEND_MESSAGES"],
142
- this.options ?? {},
143
- null
144
- ];
145
- if (this.getSupportIds.roles.length) for (const sup of this.getSupportIds.roles) {
146
- let role = guild.roles.resolve(sup);
147
- if (role) permissions.push({ type: "role", id: sup, allow });
148
- };
344
+ let [permissions, { appeals }, sendBanReason] = [[], this.options ?? {}, null];
345
+ if (this.getSupportIds.roles.length) {
346
+ for (const sup of this.getSupportIds.roles) {
347
+ let role = guild.roles.resolve(sup);
348
+ if (role) {
349
+ permissions.push({
350
+ type: "role",
351
+ id: sup,
352
+ allow: perms.allows.support,
353
+ });
354
+ }
355
+ }
356
+ }
149
357
 
150
- if (this.getSupportIds.users.length) for (const uId of this.getSupportIds.users) {
151
- let member = guild.members.resolve(uId) || await guild.members.fetch(uId).catch((e) => {
152
- if (e?.stack?.includes?.("Unknown Member")) this.options.support.users = this.options.support.users.filter(c => c !== uId);
153
- return this._debug(e);
154
- });
155
- if (member) permissions.push({ type: "member", id: uId, allow });
358
+ if (this.getSupportIds.users.length) {
359
+ for await (const uId of this.getSupportIds.users) {
360
+ const member = await discord.member(guild, uId, true);
361
+ if (member) {
362
+ permissions.push({
363
+ type: "member",
364
+ id: uId,
365
+ allow: perms.allows.support,
366
+ });
367
+ }
368
+ }
156
369
  }
157
370
  if (appeals?.enabled) {
158
371
  let server = getAppealServer(this.options);
159
372
  if (server) {
160
- let ban = await server.bans.fetch({ user: member.id, force: true }).catch(e => this._debug(e));
161
- if (!ban) return send(
162
- typeof appeals.embeds?.not_banned === "object" ?
163
- appeals.embeds.not_banned :
164
- { embeds: [ embed(this.str("NOT_BANNED_MAIN_SERVER"), { guild, color: 0xFF0000 }) ] }
165
- );
373
+ let ban = await server.bans.fetch({ user: member.id, force: true }).catch(this._debug);
374
+ if (!ban) {
375
+ return send(
376
+ typeof appeals.embeds?.not_banned === "object"
377
+ ? await parser(appeals.embeds.not_banned, { guild: server, member, user: member.user })
378
+ : {
379
+ embeds: [
380
+ embed(this.str("NOT_BANNED_MAIN_SERVER"), {
381
+ guild,
382
+ color: 0xff0000,
383
+ str: this.str,
384
+ }),
385
+ ],
386
+ },
387
+ );
388
+ }
166
389
  sendBanReason = {
167
- embeds: [ embed(ban?.reason ?? this.str("NO_REASON"), { title: this.str("BAN_REASON"), guild: server }) ],
390
+ embeds: [
391
+ embed(ban?.reason ?? this.str("NO_REASON"), {
392
+ title: this.str("BAN_REASON"),
393
+ guild: server,
394
+ str: this.str,
395
+ }),
396
+ ],
168
397
  components: [
169
398
  {
170
- type: 1, components: [
171
- button({ id: `unban:${member.id}`, style: 4, title: this.str("UNBAN"), emoji: { name: "🔒" } })
172
- ]
173
- }
174
- ]
175
- }
399
+ type: 1,
400
+ components: [
401
+ button({
402
+ id: `${this.prefix}:unban:${member.id}`,
403
+ style: 4,
404
+ title: this.str("UNBAN"),
405
+ emoji: { name: "🔒" },
406
+ }),
407
+ ],
408
+ },
409
+ ],
410
+ };
411
+ }
412
+ }
413
+ let channel = await guild.channels
414
+ .create(`${this.options.prefix}-${generate(5)}`, {
415
+ type: "GUILD_TEXT",
416
+ parent: category,
417
+ reason: `${this.str("OPEN_TICKET_AUDIT_REASON")} @${member.user.tag} (${member.id})`,
418
+ topic: `ID: ${code(member.id, "e", this.options.encryptToken)}`,
419
+ permissionOverwrites: [
420
+ {
421
+ type: "member",
422
+ id: this.options.client.user.id,
423
+ allow: perms.allows.client,
424
+ },
425
+ {
426
+ type: "member",
427
+ id: member.id,
428
+ allow: perms.allows.ticketUser,
429
+ deny: perms.denied.ticketUser,
430
+ },
431
+ { type: "role", id: guild.id, deny: perms.denied.all },
432
+ ...permissions,
433
+ ],
434
+ })
435
+ .catch(this._debug);
436
+ if (!channel) {
437
+ return send({ embeds: [embed(this.str("NO_CHANNEL_CREATE"), { str: this.str })] });
438
+ }
439
+ let embs = await Promise.all(
440
+ (
441
+ this.options.ticket?.open?.embeds || [
442
+ embed(undefined, {
443
+ title: this.str("OPEN_TICKET_MESSAGE"),
444
+ color: 0xf50de3,
445
+ guild,
446
+ footer: { text: this.str("OPEN_TICKET_MESSAGE_FOOTER") },
447
+ str: this.str,
448
+ }),
449
+ ]
450
+ ).map((c) => parser(c, { guild, member, user: member.user })),
451
+ );
452
+ const content = this.options.ticket?.open?.content || `${member.user.toString()} ${this.str("OPEN_TICKET_MESSAGE_CONTENT")}`;
453
+ let msg = await channel
454
+ .send({
455
+ content: await parser(content, { guild, member, user: member.user }),
456
+ embeds: embs,
457
+ components: [
458
+ {
459
+ type: 1,
460
+ components: [
461
+ button({
462
+ id: `${this.prefix}:close`,
463
+ title: this.str("CLOSE_TICKET"),
464
+ style: 4,
465
+ emoji: { name: "🔒" },
466
+ }),
467
+ ],
468
+ },
469
+ ],
470
+ })
471
+ .catch(this._debug);
472
+ if (!msg) {
473
+ return null;
474
+ }
475
+ if (sendBanReason) {
476
+ await channel.send(sendBanReason).catch(this._debug);
477
+ }
478
+ if (embeds?.length <= 10) {
479
+ for await (const embed of embeds) {
480
+ await channel.send({ embeds: [embed] }).catch(this._debug);
176
481
  }
177
482
  }
178
- let channel = await guild.channels.create(`${this.options.prefix}-${generate(5)}`, {
179
- type: "GUILD_TEXT", parent: category, reason: `${this.str("OPEN_TICKET_AUDIT_REASON")} @${member.user.tag} (${member.id})`,
180
- topic: `ID: ${code(member.id, "e", this.options.encryptToken)}`,
181
- permissionOverwrites: [
182
- { type: "member", id: this.options.client.user.id, allow: ["ADD_REACTIONS", "ATTACH_FILES", "SEND_MESSAGES", "READ_MESSAGE_HISTORY", "EMBED_LINKS", "USE_EXTERNAL_EMOJIS", "VIEW_CHANNEL", "MENTION_EVERYONE"] },
183
- { type: "member", id: member.id, allow: ["ADD_REACTIONS", "ATTACH_FILES", "SEND_MESSAGES", "READ_MESSAGE_HISTORY", "EMBED_LINKS", "USE_EXTERNAL_EMOJIS", "VIEW_CHANNEL"], deny: ["MENTION_EVERYONE"] },
184
- { type: "role", id: guild.id, deny: ["VIEW_CHANNEL"] },
185
- ...permissions
186
- ]
187
- }).catch(e => this._debug(e));
188
- if (!channel) return send({ embeds: [embed(this.str("NO_CHANNEL_CREATE"))] });
189
- let msg = await channel.send({
190
- content: (this.options.ticket?.open || this.options.ticketOpen)?.content?.replace?.(/%user%/gi, member.user.toString())?.replace?.(/%server%/gi, guild.name) || `${member.user.toString()} ${this.str("OPEN_TICKET_MESSAGE_CONTENT")}`,
191
- embeds: (this.options.ticket?.open || this.options.ticketOpen)?.embeds || [ embed(undefined, { title: this.str("OPEN_TICKET_MESSAGE"), color: 0xF50DE3, guild, footer: { text: this.str("OPEN_TICKET_MESSAGE_FOOTER") } }) ],
192
- components: [ { type: 1, components: [ button({ id: `${this.prefix}:close`, title: this.str("CLOSE_TICKET"), style: 4, emoji: { name: "🔒" } }) ] }]
193
- }).catch(e => this._debug(e));
194
- if (!msg) return null;
195
- if (sendBanReason) await channel.send(sendBanReason).catch(e => this._debug(e));
196
- if (embeds?.length <= 10) for await (const embed of embeds) await channel.send({ embeds: [embed] }).catch(e => this._debug(e));
197
- if (this.webhookOptions.id && this.webhookOptions.token) webhook(this.webhookOptions)
198
- .embed(embed(`${de.user} User: ${member.user.toString()} \`@${member.user.tag}\` (${member.id})\n${de.channel} Channel: \`#${channel.name}\` (${channel.id})`, {
199
- title: this.str("OPEN_TICKET_TITLE"),
200
- color: 0xFF000,
201
- footer: { text: `${this.str("TICKET_ID")} ${channel.name.split("-")[1]}` },
202
- guild
203
- })).send().catch(e => this._debug(e));
483
+ if (this.webhookOptions.id && this.webhookOptions.token) {
484
+ webhook(this.webhookOptions)
485
+ .embed(
486
+ embed(`${de.user} ${this.str("USER")}: ${member.user.toString()} \`@${member.user.tag}\` (${member.id})\n${de.channel} ${this.str("CHANNEL")}: \`#${channel.name}\` (${channel.id})`, {
487
+ title: this.str("OPEN_TICKET_TITLE"),
488
+ color: 0xff000,
489
+ footer: {
490
+ text: `${this.str("TICKET_ID")} ${channel.name.split("-")[1]}`,
491
+ },
492
+ guild,
493
+ str: this.str,
494
+ }),
495
+ )
496
+ .send()
497
+ .catch(this._debug);
498
+ }
204
499
  return send({
205
- embeds: [ embed(channel.toString(), { color: 0xFF000, author: { name: this.str("OPEN_TICKET_CREATE"), icon_url: `https://cdn.discordapp.com/emojis/476629550797684736.gif` } }) ],
206
- components: [{ type: 1, components: [button({ title: this.str("GO_TO_TICKET"), url: msg.url })] }]
207
- })
500
+ embeds: [
501
+ embed(channel.toString(), {
502
+ color: 0xff000,
503
+ author: {
504
+ name: this.str("OPEN_TICKET_CREATE"),
505
+ icon_url: `https://cdn.discordapp.com/emojis/476629550797684736.gif`,
506
+ },
507
+ str: this.str,
508
+ }),
509
+ ],
510
+ components: [
511
+ {
512
+ type: 1,
513
+ components: [button({ title: this.str("GO_TO_TICKET"), url: msg.url })],
514
+ },
515
+ ],
516
+ });
208
517
  }
209
-
210
- async starterMessage(channelId, options) {
211
- let channel = this.options.client.channels.resolve(channelId);
212
- if (!channel) return Promise.reject(`No channel found for: ${channelId}`);
213
- if (!channel.isText()) return Promise.reject(`The channel ID provided isn't a text-based-channel`);
214
- if (!channel.permissionsFor?.(this.options.client.user.id)?.has?.(["VIEW_CHANNEL", "SEND_MESSAGES", "EMBED_LINKS", "ATTACH_FILES", "READ_MESSAGE_HISTORY"])) return Promise.reject(`I'm missing permissions in ${channel.name} (${channelId})`);
215
- return channel.send({ content: options?.content, files: options?.attachments, embeds: options?.embeds, components: options?.components || [{ type: 1, components: [this.button()] }] })
216
- .then(() => console.log(`Sent the starter message in ${channel.name} (${channel.id})`))
217
- };
218
- }
518
+ };