@elara-services/tickets 2.0.3 → 2.1.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/README.md +1 -0
- package/index.d.ts +2 -1
- package/index.js +36 -57
- package/package.json +5 -2
- package/post.js +12 -0
package/README.md
CHANGED
|
@@ -51,6 +51,7 @@ const { Client } = require("discord.js"),
|
|
|
51
51
|
avatar: "", // 'webhookAvatar' support will be removed in the next major version
|
|
52
52
|
},
|
|
53
53
|
support: {
|
|
54
|
+
canOnlyCloseTickets: true, // If 'true' only roles and users listed below can close tickets. (OR people with 'Manage Server' permission)
|
|
54
55
|
roles: [ // 'supportRoleIds' support will be removed in the next major version
|
|
55
56
|
"123456789"
|
|
56
57
|
],
|
package/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ declare module "@elara-services/tickets" {
|
|
|
12
12
|
ticketOpen?: Pick<MessageOptions, "content" | "embeds">
|
|
13
13
|
appeals?: {
|
|
14
14
|
enabled: boolean;
|
|
15
|
-
|
|
15
|
+
mainserver: {
|
|
16
16
|
id: string;
|
|
17
17
|
checkIfBanned: boolean;
|
|
18
18
|
};
|
|
@@ -42,6 +42,7 @@ declare module "@elara-services/tickets" {
|
|
|
42
42
|
support?: {
|
|
43
43
|
roles?: string[];
|
|
44
44
|
users?: string[];
|
|
45
|
+
canOnlyCloseTickets?: boolean;
|
|
45
46
|
};
|
|
46
47
|
|
|
47
48
|
/** @deprecated Use 'webhook.id' */
|
package/index.js
CHANGED
|
@@ -10,11 +10,12 @@ const { Collection, WebhookClient, MessageEmbed } = require("discord.js"),
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
module.exports = class Tickets {
|
|
13
|
-
constructor(options) {
|
|
13
|
+
constructor(options = {}) {
|
|
14
|
+
if (typeof options !== "object") throw new Error(`You didn't provide any data in the constructor, fill it out!`);
|
|
15
|
+
if (!("client" in options) || !("prefix" in options) || !("encryptToken" in options)) throw new Error(`You forgot to fill out either 'client', 'prefix' or 'encryptToken'`)
|
|
14
16
|
this.options = options;
|
|
15
17
|
};
|
|
16
18
|
get prefix() { return `system:ticket:${this.options.prefix}`; };
|
|
17
|
-
|
|
18
19
|
/** @private */
|
|
19
20
|
get webhookOptions() {
|
|
20
21
|
return {
|
|
@@ -36,7 +37,6 @@ module.exports = class Tickets {
|
|
|
36
37
|
if (int?.isButton?.() || int?.isModalSubmit()) {
|
|
37
38
|
let { guild, channel, member, customId } = int,
|
|
38
39
|
category = guild?.channels?.resolve?.(this.options.ticketCategory || channel?.parentId);
|
|
39
|
-
|
|
40
40
|
if (!guild || !guild.available || !channel || !member || !category) return;
|
|
41
41
|
|
|
42
42
|
/**
|
|
@@ -54,18 +54,28 @@ module.exports = class Tickets {
|
|
|
54
54
|
if (this.options.modal?.enabled) {
|
|
55
55
|
return int.showModal(this.modal({
|
|
56
56
|
title: this.options.modal.title,
|
|
57
|
-
components: this.options.modal.questions?.length >= 1 ?
|
|
58
|
-
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)}` }] })) :
|
|
59
|
-
[]
|
|
57
|
+
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)}` }] })) : []
|
|
60
58
|
})).catch(e => this._debug(e));
|
|
61
59
|
}
|
|
62
60
|
return this.handleCreate({ guild, member, category, send })
|
|
63
61
|
};
|
|
64
62
|
|
|
65
|
-
case `${this.prefix}:close`:
|
|
63
|
+
case `${this.prefix}:close`: {
|
|
64
|
+
if (this.options.support?.canOnlyCloseTickets && !member.permissions.has("MANAGE_GUILD")) {
|
|
65
|
+
let [ support, staffOnly ] = [
|
|
66
|
+
this.getSupportIds(),
|
|
67
|
+
() => send({ ephemeral: true, embeds: [ { author: { name: `Only support staff can close tickets`, iconURL: "https://cdn.discordapp.com/emojis/781955502035697745.gif" }, color: 0xFF0000 } ] })
|
|
68
|
+
];
|
|
69
|
+
if (!support.users?.includes?.(member.id)) return staffOnly();
|
|
70
|
+
if (support.roles?.length && !support.roles.some(c => member.roles.cache.has(c))) return staffOnly()
|
|
71
|
+
}
|
|
72
|
+
return send({ ephemeral: true, content: `🤔 Are you sure you want to close this ticket?`, components: [{ type: 1, components: [{ type: 2, custom_id: `${this.prefix}:close:confirm:${this.code(channel.topic?.split?.("ID: ")?.[1])}`, label: "Yes close the ticket", style: 4, emoji: { id: "807031399563264030" } }] }] })
|
|
73
|
+
}
|
|
66
74
|
|
|
67
75
|
case `${this.prefix}:modal_submit`: {
|
|
68
|
-
let [embed, fields, split] = [
|
|
76
|
+
let [embed, fields, split] = [
|
|
77
|
+
new MessageEmbed().setColor("ORANGE").setTimestamp().setTitle(`For Responses`).setFooter({ text: `ID: ${member.id}` }).setAuthor({ name: member.user.username, iconURL: member.user.displayAvatarURL({ dynamic: true }) }),
|
|
78
|
+
[], false];
|
|
69
79
|
for (const c of int.fields.components) {
|
|
70
80
|
for (const cc of c.components) {
|
|
71
81
|
if (cc.value && cc.customId) {
|
|
@@ -77,31 +87,22 @@ module.exports = class Tickets {
|
|
|
77
87
|
}
|
|
78
88
|
if (embed.length >= 6000 || split) {
|
|
79
89
|
return this.handleCreate({ guild, member, category, send, embeds: fields.map((v, i) => ({
|
|
80
|
-
title: `Form Response: ${v.name}`,
|
|
81
|
-
color: embed.color,
|
|
82
|
-
description: v.value,
|
|
90
|
+
title: `Form Response: ${v.name}`, color: embed.color, description: v.value,
|
|
83
91
|
author: i === 0 ? { name: member.user.username, iconURL: member.user.displayAvatarURL({ dynamic: true }) } : undefined,
|
|
84
92
|
timestamp: fields.length - 1 === i ? new Date() : undefined,
|
|
85
93
|
footer: fields.length - 1 === i ? { text: `ID: ${member.id}` } : undefined
|
|
86
94
|
})) })
|
|
87
95
|
};
|
|
88
|
-
|
|
89
|
-
return this.handleCreate({ guild, member, category, send, embeds: [
|
|
90
|
-
embed
|
|
91
|
-
.setTitle(`Form Responses`)
|
|
92
|
-
.setTimestamp()
|
|
93
|
-
.setAuthor({ name: member.user.username, iconURL: member.user.displayAvatarURL({ dynamic: true }) })
|
|
94
|
-
.setFooter({ text: `ID: ${member.id}` })
|
|
95
|
-
]})
|
|
96
|
+
return this.handleCreate({ guild, member, category, send, embeds: [ embed ]})
|
|
96
97
|
}
|
|
97
98
|
};
|
|
98
99
|
if (customId.startsWith(`${this.prefix}:close:confirm`)) {
|
|
99
100
|
let user = this.options.client.users.resolve(customId.split("close:confirm:")[1]) ?? await this.options.client.users.fetch(customId.split("close:confirm:")[1]).catch(() => null);
|
|
100
101
|
if (!user) return send({ content: `❌ I was unable to fetch the user that opened the ticket.`, ephemeral: true })
|
|
101
102
|
let messages = await this.fetchMessages(channel, 5000);
|
|
102
|
-
if (!messages
|
|
103
|
+
if (!messages?.length) return send({ ephemeral: true, content: `❌ I was unable to close the ticket, I couldn't fetch the messages in this channel.` })
|
|
103
104
|
let closed = await channel.delete(`${member.user.tag} (${member.id}) closed the ticket.`).catch(e => this._debug(e));
|
|
104
|
-
if (!closed) return send({ ephemeral: true, content:
|
|
105
|
+
if (!closed) return send({ ephemeral: true, content: `❌ I was unable to delete the channel & close the ticket.` })
|
|
105
106
|
return this.closeTicket({ channel, guild, user, member, messages });
|
|
106
107
|
}
|
|
107
108
|
};
|
|
@@ -109,10 +110,15 @@ module.exports = class Tickets {
|
|
|
109
110
|
|
|
110
111
|
/** @private */
|
|
111
112
|
async handleCreate({ guild, member, category, send, embeds = [] } = {}) {
|
|
112
|
-
|
|
113
|
+
await send({ ephemeral: true }, true);
|
|
114
|
+
let [ supportIds, permissions, allow, { appeals } ] = [
|
|
115
|
+
this.getSupportIds(), [],
|
|
116
|
+
["ADD_REACTIONS", "ATTACH_FILES", "CREATE_INSTANT_INVITE", "EMBED_LINKS", "READ_MESSAGE_HISTORY", "VIEW_CHANNEL", "USE_EXTERNAL_EMOJIS", "SEND_MESSAGES"],
|
|
117
|
+
this.options ?? {}
|
|
118
|
+
];
|
|
113
119
|
if (supportIds.roles.length) for (const sup of supportIds.roles) {
|
|
114
120
|
let role = guild.roles.resolve(sup);
|
|
115
|
-
if (role)
|
|
121
|
+
if (role) permissions.push({ type: "role", id: sup, allow });
|
|
116
122
|
};
|
|
117
123
|
|
|
118
124
|
if (supportIds.users.length) for (const uId of supportIds.users) {
|
|
@@ -120,11 +126,9 @@ module.exports = class Tickets {
|
|
|
120
126
|
if (e?.stack?.includes?.("Unknown Member")) this.options.support.users = this.options.support.users.filter(c => c !== uId);
|
|
121
127
|
return this._debug(e);
|
|
122
128
|
});
|
|
123
|
-
if (member)
|
|
129
|
+
if (member) permissions.push({ type: "member", id: uId, allow });
|
|
124
130
|
}
|
|
125
|
-
|
|
126
|
-
if (this.options.appeals?.enabled) {
|
|
127
|
-
let appeals = this.options.appeals;
|
|
131
|
+
if (appeals?.enabled) {
|
|
128
132
|
if (appeals.mainserver?.id && appeals.mainserver.checkIfBanned) {
|
|
129
133
|
let server = this.options.client.guilds.resolve(appeals.mainserver.id);
|
|
130
134
|
if (server?.available) {
|
|
@@ -147,12 +151,6 @@ module.exports = class Tickets {
|
|
|
147
151
|
}
|
|
148
152
|
}
|
|
149
153
|
}
|
|
150
|
-
let [permissions, allow] = [
|
|
151
|
-
[],
|
|
152
|
-
["ADD_REACTIONS", "ATTACH_FILES", "CREATE_INSTANT_INVITE", "EMBED_LINKS", "READ_MESSAGE_HISTORY", "VIEW_CHANNEL", "USE_EXTERNAL_EMOJIS", "SEND_MESSAGES"]
|
|
153
|
-
];
|
|
154
|
-
if (support.length) for (const sup of support) permissions.push({ type: "role", id: sup, allow });
|
|
155
|
-
if (supportUsers.length) for (const user of supportUsers) permissions.push({ type: "member", id: user, allow });
|
|
156
154
|
|
|
157
155
|
/** @type {import("discord.js").TextChannel} */
|
|
158
156
|
let channel = await guild.channels.create(`${this.options.prefix}-${generate().slice(0, 5).replace(/-|_/g, "")}`, {
|
|
@@ -165,7 +163,7 @@ module.exports = class Tickets {
|
|
|
165
163
|
...permissions
|
|
166
164
|
]
|
|
167
165
|
}).catch(e => this._debug(e));
|
|
168
|
-
if (!channel) return send({ content:
|
|
166
|
+
if (!channel) return send({ content: `❌ I was unable to create the ticket channel, if this keeps happening contact one of the staff members via their DMs!` });
|
|
169
167
|
let msg = await channel.send({
|
|
170
168
|
content: this.options.ticketOpen?.content?.replace?.(/%user%/gi, member.user.toString())?.replace?.(/%server%/gi, guild.name) || `${member.user.toString()} 👋 Hello, please explain what you need help with.`,
|
|
171
169
|
embeds: this.options.ticketOpen?.embeds || [{
|
|
@@ -189,24 +187,13 @@ module.exports = class Tickets {
|
|
|
189
187
|
footer: { text: `Ticket ID: ${channel.name.split("-")[1]}` },
|
|
190
188
|
}).send().catch(e => this._debug(e));
|
|
191
189
|
return send({
|
|
192
|
-
embeds: [
|
|
193
|
-
{
|
|
194
|
-
author: { name: `Ticket Created!`, icon_url: `https://cdn.discordapp.com/emojis/476629550797684736.gif` },
|
|
195
|
-
description: channel.toString(),
|
|
196
|
-
color: 0xFF000
|
|
197
|
-
}
|
|
198
|
-
],
|
|
190
|
+
embeds: [ { author: { name: `Ticket Created!`, icon_url: `https://cdn.discordapp.com/emojis/476629550797684736.gif` }, description: channel.toString(), color: 0xFF000 } ],
|
|
199
191
|
components: [ { type: 1, components: [ button({ title: "Go to ticket", url: msg.url }) ] } ]
|
|
200
192
|
})
|
|
201
193
|
}
|
|
202
194
|
|
|
203
195
|
button(options = { style: 3, label: "Create Ticket", emoji: { name: "📩" } }) {
|
|
204
|
-
return button({
|
|
205
|
-
id: options?.id || this.prefix,
|
|
206
|
-
style: options.style || 3,
|
|
207
|
-
title: options.label,
|
|
208
|
-
emoji: options.emoji
|
|
209
|
-
});
|
|
196
|
+
return button({ id: options?.id || this.prefix, style: options.style || 3, title: options.label, emoji: options.emoji });
|
|
210
197
|
};
|
|
211
198
|
|
|
212
199
|
/**
|
|
@@ -218,13 +205,7 @@ module.exports = class Tickets {
|
|
|
218
205
|
return modal({
|
|
219
206
|
id: `${this.prefix}:modal_submit`,
|
|
220
207
|
title: options?.title || "Create Ticket",
|
|
221
|
-
components: options?.components?.length >= 1 ? options.components : [
|
|
222
|
-
{
|
|
223
|
-
type: 1, components: [
|
|
224
|
-
{ type: 4, min_length: 10, max_length: 4000, custom_id: "message", label: "Content", style: 2, placeholder: "What's the ticket about?", required: true }
|
|
225
|
-
]
|
|
226
|
-
}
|
|
227
|
-
]
|
|
208
|
+
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 } ] } ]
|
|
228
209
|
})
|
|
229
210
|
}
|
|
230
211
|
|
|
@@ -396,9 +377,7 @@ module.exports = class Tickets {
|
|
|
396
377
|
|
|
397
378
|
/** @private */
|
|
398
379
|
_debug(...args) {
|
|
399
|
-
if (
|
|
400
|
-
console.log(...args);
|
|
380
|
+
if (this.options?.debug) console.log(...args);
|
|
401
381
|
return null;
|
|
402
382
|
}
|
|
403
|
-
|
|
404
383
|
};
|
package/package.json
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elara-services/tickets",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "Helper for tickets",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
7
|
"typings": "index.d.ts",
|
|
8
8
|
"author": "SUPERCHIEFYT (Elara-Discord-Bots, Elara-Services)",
|
|
9
9
|
"license": "MIT",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"postinstall": "node post.js"
|
|
12
|
+
},
|
|
10
13
|
"optionalDependencies": {
|
|
11
|
-
"discord.js": "13.8.
|
|
14
|
+
"discord.js": "13.8.1"
|
|
12
15
|
},
|
|
13
16
|
"dependencies": {
|
|
14
17
|
"@elara-services/packages": "5.0.0",
|
package/post.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const package = require("./package.json");
|
|
2
|
+
console.log([
|
|
3
|
+
`Package: ${package.name}`,
|
|
4
|
+
`────────────────────────`,
|
|
5
|
+
`Thanks for installing the package!`,
|
|
6
|
+
`Version you installed: ${package.version}`,
|
|
7
|
+
`─────────────────────────────────────────`,
|
|
8
|
+
`To get started look at the 'Getting Started' section on the npm page here: https://www.npmjs.com/package/@elara-services/tickets`,
|
|
9
|
+
`Here is some helpful links:`,
|
|
10
|
+
`Source Code: https://github.com/elara-bots/tickets`,
|
|
11
|
+
`Support: https://discord.gg/qafHJ63`
|
|
12
|
+
].join("\n"))
|