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