@elara-services/tickets 2.2.1 → 2.3.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/index.d.ts +1 -0
- package/index.js +109 -46
- package/package.json +1 -1
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
const { Collection, WebhookClient, MessageEmbed } = require("discord.js"),
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
{ generate } = require("shortid"),
|
|
3
|
+
{ Interactions: { button, modal }, AES } = require("@elara-services/packages"),
|
|
4
|
+
Webhook = require("discord-hook"),
|
|
5
|
+
de = {
|
|
6
|
+
user: "<:Members:860931214232125450>",
|
|
7
|
+
channel: "<:Channel:841654412509839390>",
|
|
8
|
+
transcript: "<:Log:792290922749624320>"
|
|
9
|
+
};
|
|
10
10
|
|
|
11
11
|
module.exports = class Tickets {
|
|
12
12
|
constructor(options = {}) {
|
|
@@ -26,7 +26,7 @@ module.exports = class Tickets {
|
|
|
26
26
|
avatar: this.options.webhook?.avatar || this.options.webhookAvatar || "https://cdn.discordapp.com/emojis/818757771310792704.png?v=1"
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
webhook() {
|
|
31
31
|
const { id, token, username, avatar } = this.webhookOptions;
|
|
32
32
|
return new Webhook(`https://discord.com/api/webhooks/${id}/${token}`, { username, avatar_url: avatar });
|
|
@@ -59,7 +59,7 @@ module.exports = class Tickets {
|
|
|
59
59
|
|
|
60
60
|
case `${this.prefix}:close`: {
|
|
61
61
|
if (this.options.support?.canOnlyCloseTickets && !member.permissions.has("MANAGE_GUILD")) {
|
|
62
|
-
let [
|
|
62
|
+
let [support, staffOnly] = [this.getSupportIds(), () => send({ ephemeral: true, embeds: [{ author: { name: `Only support staff can close tickets`, iconURL: "https://cdn.discordapp.com/emojis/781955502035697745.gif" }, color: 0xFF0000 }] })];
|
|
63
63
|
if (!support.users?.includes?.(member.id)) {
|
|
64
64
|
if (!support.roles?.some?.(c => member.roles.cache.has(c))) return staffOnly()
|
|
65
65
|
}
|
|
@@ -68,7 +68,7 @@ module.exports = class Tickets {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
case `${this.prefix}:modal_submit`: {
|
|
71
|
-
let [
|
|
71
|
+
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];
|
|
72
72
|
for (const c of int.fields.components) {
|
|
73
73
|
for (const cc of c.components) {
|
|
74
74
|
if (cc.value && cc.customId) {
|
|
@@ -79,36 +79,82 @@ module.exports = class Tickets {
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
if (embed.length >= 6000 || split) {
|
|
82
|
-
return this.handleCreate({
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
return this.handleCreate({
|
|
83
|
+
guild, member, category, send, embeds: fields.map((v, i) => ({
|
|
84
|
+
title: `Form Response: ${v.name}`, color: embed.color, description: v.value,
|
|
85
|
+
author: i === 0 ? { name: member.user.username, iconURL: member.user.displayAvatarURL({ dynamic: true }) } : undefined,
|
|
86
|
+
timestamp: fields.length - 1 === i ? new Date() : undefined,
|
|
87
|
+
footer: fields.length - 1 === i ? { text: `ID: ${member.id}` } : undefined
|
|
88
|
+
}))
|
|
89
|
+
})
|
|
88
90
|
};
|
|
89
|
-
return this.handleCreate({ guild, member, category, send, embeds: [
|
|
91
|
+
return this.handleCreate({ guild, member, category, send, embeds: [embed] })
|
|
90
92
|
}
|
|
91
93
|
};
|
|
92
94
|
if (customId.startsWith(`${this.prefix}:close:confirm`)) {
|
|
93
95
|
await send({ ephemeral: true }, true);
|
|
94
|
-
let user = await this.options.client.users.fetch(customId.split("close:confirm:")[1]).catch(
|
|
96
|
+
let user = await this.options.client.users.fetch(customId.split("close:confirm:")[1]).catch(e => this._debug(e));
|
|
95
97
|
if (!user) return send({ content: `❌ I was unable to fetch the user that opened the ticket.` })
|
|
96
98
|
let messages = await this.fetchMessages(channel, 5000);
|
|
97
99
|
if (!messages?.length) return send({ content: `❌ I was unable to close the ticket, I couldn't fetch the messages in this channel.` })
|
|
98
100
|
let closed = await channel.delete(`${member.user.tag} (${member.id}) closed the ticket.`).catch(e => this._debug(e));
|
|
99
101
|
if (!closed) return send({ content: `❌ I was unable to delete the channel & close the ticket.` })
|
|
100
102
|
return this.closeTicket({ channel, guild, user, member, messages });
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
if (customId.startsWith("unban:")) {
|
|
106
|
+
if (!int.memberPermissions?.has?.([ "BAN_MEMBERS" ])) return send({ content: `❌ You need (Ban Members) in this server to complete this action!`, ephemeral: true });
|
|
107
|
+
let server = this.getAppealServer();
|
|
108
|
+
if (!server) return send({ content: `❌ I was unable to find the appeal server!`, ephemeral: true });
|
|
109
|
+
let mod = server.members.resolve(member.id) || await server.members.fetch(member.id).catch(e => this._debug(e));
|
|
110
|
+
if (!mod) return send({ content: `❌ I was unable to find you in ${server.name}!`, ephemeral: true });
|
|
111
|
+
if (!mod.permissions?.has?.([ "BAN_MEMBERS" ])) return send({ content: `❌ You need (Ban Members) in ${server.name} to complete this action!`, ephemeral: true });
|
|
112
|
+
return int.showModal(modal({
|
|
113
|
+
id: `unban_modal:${customId.split(":")[1]}`,
|
|
114
|
+
title: `Unban From ${server.name}`,
|
|
115
|
+
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})` } ] } ]
|
|
116
|
+
})).catch(e => this._debug(e));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (customId.startsWith("unban_modal:")) {
|
|
120
|
+
await send({ ephemeral: true }, true);
|
|
121
|
+
const [ , id ] = customId.split(":");
|
|
122
|
+
if (!int.memberPermissions?.has?.([ "BAN_MEMBERS" ])) return send({ content: `❌ You need (Ban Members) in this server to complete this action!` });
|
|
123
|
+
let server = this.getAppealServer();
|
|
124
|
+
if (!server) return send({ content: `❌ I was unable to find the appeal server!` });
|
|
125
|
+
let mod = server.members.resolve(member.id) || await server.members.fetch(member.id).catch(e => this._debug(e));
|
|
126
|
+
if (!mod) return send({ content: `❌ I was unable to find you in ${server.name}!` });
|
|
127
|
+
if (!mod.permissions?.has?.([ "BAN_MEMBERS" ])) return send({ content: `❌ You need (Ban Members) in ${server.name} to complete this action!` });
|
|
128
|
+
let isBanned = await server.bans.fetch({ user: id, force: true }).catch(e => this._debug(e));
|
|
129
|
+
if (!isBanned) return send({ content: `❌ User (<@${id}>) isn't banned in the main server!` });
|
|
130
|
+
return server.bans.remove(id, int.fields.getTextInputValue("reason") ?? `No Reason Provided | By: ${member.user.tag} (${member.id})`)
|
|
131
|
+
.then(() => {
|
|
132
|
+
int.message.edit({ components: [ { type: 1, components: [ button({ title: "Unbanned!", style: 3, id: "_ _", disabled: true, emoji: { id: `476629550797684736` } }) ] } ] }).catch(e => this._debug(e));
|
|
133
|
+
send({ content: `✅ Successfully unbanned <@${id}> from ${server.name}!` })
|
|
134
|
+
})
|
|
135
|
+
.catch(e => send({ content: `❌ Unable to unban <@${id} from ${server.name}!`, embeds: [ { title: "ERROR", description: `\`\`\`js\n${e.message ?? e.stack}\`\`\``, color: 0xFF0000 } ] }))
|
|
101
136
|
}
|
|
102
137
|
};
|
|
103
138
|
};
|
|
139
|
+
/**
|
|
140
|
+
* @returns {import("discord.js").Guild|null}
|
|
141
|
+
*/
|
|
142
|
+
getAppealServer() {
|
|
143
|
+
const { appeals, client } = this.options;
|
|
144
|
+
if (!appeals?.enabled || !appeals?.mainserver?.checkIfBanned) return null;
|
|
145
|
+
let server = client.guilds.resolve(appeals.mainserver?.id);
|
|
146
|
+
if (!server?.available) return null;
|
|
147
|
+
return server;
|
|
148
|
+
}
|
|
104
149
|
|
|
105
150
|
/** @private */
|
|
106
151
|
async handleCreate({ guild, member, category, send, embeds = [] } = {}) {
|
|
107
152
|
await send({ ephemeral: true }, true);
|
|
108
|
-
let [
|
|
153
|
+
let [supportIds, permissions, allow, { appeals }, sendBanReason] = [
|
|
109
154
|
this.getSupportIds(), [],
|
|
110
155
|
["ADD_REACTIONS", "ATTACH_FILES", "CREATE_INSTANT_INVITE", "EMBED_LINKS", "READ_MESSAGE_HISTORY", "VIEW_CHANNEL", "USE_EXTERNAL_EMOJIS", "SEND_MESSAGES"],
|
|
111
|
-
this.options ?? {}
|
|
156
|
+
this.options ?? {},
|
|
157
|
+
null
|
|
112
158
|
];
|
|
113
159
|
if (supportIds.roles.length) for (const sup of supportIds.roles) {
|
|
114
160
|
let role = guild.roles.resolve(sup);
|
|
@@ -123,25 +169,41 @@ module.exports = class Tickets {
|
|
|
123
169
|
if (member) permissions.push({ type: "member", id: uId, allow });
|
|
124
170
|
}
|
|
125
171
|
if (appeals?.enabled) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
{
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
172
|
+
let server = this.getAppealServer();
|
|
173
|
+
if (server) {
|
|
174
|
+
let ban = await server.bans.fetch({ user: member.id, force: true }).catch(e => this._debug(e));
|
|
175
|
+
if (!ban) return send(
|
|
176
|
+
typeof appeals.embeds?.not_banned === "object" ?
|
|
177
|
+
appeals.embeds.not_banned :
|
|
178
|
+
{
|
|
179
|
+
embeds: [
|
|
180
|
+
{
|
|
181
|
+
author: { name: guild.name, icon_url: guild.iconURL({ dynamic: true }) },
|
|
182
|
+
title: "INFO",
|
|
183
|
+
description: `❌ You can't open this ticket due to you not being banned in the main server!`,
|
|
184
|
+
color: 0xFF0000,
|
|
185
|
+
timestamp: new Date()
|
|
186
|
+
}
|
|
187
|
+
]
|
|
188
|
+
}
|
|
189
|
+
);
|
|
190
|
+
sendBanReason = {
|
|
191
|
+
embeds: [
|
|
192
|
+
{
|
|
193
|
+
author: { name: server.name, iconURL: server.iconURL({ dynamic: true }) },
|
|
194
|
+
title: "Ban Reason",
|
|
195
|
+
description: ban.reason ?? "No Reason Provided?",
|
|
196
|
+
color: 0xFF0000,
|
|
197
|
+
timestamp: new Date()
|
|
198
|
+
}
|
|
199
|
+
],
|
|
200
|
+
components: [
|
|
201
|
+
{
|
|
202
|
+
type: 1, components: [
|
|
203
|
+
button({ id: `unban:${member.id}`, style: 4, title: "Unban", emoji: { name: "🔒" } })
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
]
|
|
145
207
|
}
|
|
146
208
|
}
|
|
147
209
|
}
|
|
@@ -168,7 +230,8 @@ module.exports = class Tickets {
|
|
|
168
230
|
components: [{ type: 1, components: [{ type: 2, custom_id: `${this.prefix}:close`, label: "Close Ticket", style: 4, emoji: { name: "🔒" } }] }]
|
|
169
231
|
}).catch(e => this._debug(e));
|
|
170
232
|
if (!msg) return null;
|
|
171
|
-
if (
|
|
233
|
+
if (sendBanReason) await channel.send(sendBanReason).catch(e => this._debug(e));
|
|
234
|
+
if (embeds?.length <= 10) for await (const embed of embeds) await channel.send({ embeds: [embed] }).catch(e => this._debug(e));
|
|
172
235
|
if (this.webhookOptions.id && this.webhookOptions.token) this.webhook()
|
|
173
236
|
.embed({
|
|
174
237
|
author: { name: guild.name, icon_url: guild.iconURL({ dynamic: true }) },
|
|
@@ -179,8 +242,8 @@ module.exports = class Tickets {
|
|
|
179
242
|
footer: { text: `Ticket ID: ${channel.name.split("-")[1]}` },
|
|
180
243
|
}).send().catch(e => this._debug(e));
|
|
181
244
|
return send({
|
|
182
|
-
embeds: [
|
|
183
|
-
components: [
|
|
245
|
+
embeds: [{ author: { name: `Ticket Created!`, icon_url: `https://cdn.discordapp.com/emojis/476629550797684736.gif` }, description: channel.toString(), color: 0xFF000 }],
|
|
246
|
+
components: [{ type: 1, components: [button({ title: "Go to ticket", url: msg.url })] }]
|
|
184
247
|
})
|
|
185
248
|
}
|
|
186
249
|
|
|
@@ -194,7 +257,7 @@ module.exports = class Tickets {
|
|
|
194
257
|
* @param {import("@elara-services/packages").Modal['components']} [options.components]
|
|
195
258
|
*/
|
|
196
259
|
modal(options = { title: "", components: [] }) {
|
|
197
|
-
return modal({ id: `${this.prefix}:modal_submit`, title: options?.title || "Create Ticket", components: options?.components?.length >= 1 ? options.components : [
|
|
260
|
+
return modal({ id: `${this.prefix}:modal_submit`, title: options?.title || "Create Ticket", components: options?.components?.length >= 1 ? options.components : [{ type: 1, components: [{ type: 4, min_length: 10, max_length: 4000, custom_id: "message", label: "Content", style: 2, placeholder: "What's the ticket about?", required: true }] }] })
|
|
198
261
|
}
|
|
199
262
|
|
|
200
263
|
async starterMessage(channelId, options) {
|
|
@@ -255,7 +318,7 @@ module.exports = class Tickets {
|
|
|
255
318
|
str.push(content)
|
|
256
319
|
};
|
|
257
320
|
if (message.embeds?.length) {
|
|
258
|
-
let arr = [
|
|
321
|
+
let arr = [`<discord-embeds slot="embeds">`];
|
|
259
322
|
for (const embed of message.embeds) {
|
|
260
323
|
let emb = [
|
|
261
324
|
`<discord-embed slot="embed" ${embed.thumbnail?.url ? `thumbnail="${embed.thumbnail.url}"` : ""} ${embed.image?.url ? `image="${embed.image.url}"` : ""} ${embed.author ? `${embed.author.name ? `author-name="${embed.author.name}"` : ""} ${embed.author.iconURL ? `author-image="${embed.author.iconURL}"` : ""} ${embed.author.url ? `author-url="${embed.author.url}"` : ""}` : ""} ${embed.title ? `embed-title="${embed.title}"` : ""}${embed.color ? `color="${embed.hexColor}"` : ""}>`
|
|
@@ -291,7 +354,7 @@ module.exports = class Tickets {
|
|
|
291
354
|
if (row.length >= 2) str.push(...row, `</discord-attachments>`)
|
|
292
355
|
}
|
|
293
356
|
if (message.attachments.size) str.push(message.attachments.map((c) => `<a href="${c.proxyURL}">${c.name}</a>`).join("<br>"))
|
|
294
|
-
str.push(`${message.content?.length ? `<br><br>` : ""
|
|
357
|
+
str.push(`${message.content?.length ? `<br><br>` : ""}<code style="background-color: #36393e; color: white;">ID: ${message.id}</code>`)
|
|
295
358
|
return [...str, `</discord-message>`].join(" ");
|
|
296
359
|
}),
|
|
297
360
|
"</discord-messages>"].join(" ");
|