@elara-services/tickets 3.1.2 → 3.1.6

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 CHANGED
@@ -1,20 +1,20 @@
1
- {
2
- "env": {
3
- "node": true,
4
- "commonjs": true,
5
- "es2021": true
6
- },
7
- "extends": "eslint:recommended",
8
- "parserOptions": {
9
- "ecmaVersion": 12
10
- },
11
- "rules": {
12
- "no-extra-semi": 0,
13
- "no-async-promise-executor": 0,
14
- "no-warning-comments": "warn",
15
- "no-empty": 0
16
- },
17
- "ignorePatterns": [
18
- "*/*.json"
19
- ]
20
- }
1
+ {
2
+ "env": {
3
+ "node": true,
4
+ "commonjs": true,
5
+ "es2021": true
6
+ },
7
+ "extends": "eslint:recommended",
8
+ "parserOptions": {
9
+ "ecmaVersion": 12
10
+ },
11
+ "rules": {
12
+ "no-extra-semi": 0,
13
+ "no-async-promise-executor": 0,
14
+ "no-warning-comments": "warn",
15
+ "no-empty": 0
16
+ },
17
+ "ignorePatterns": [
18
+ "*/*.json"
19
+ ]
20
+ }
package/README.md CHANGED
@@ -1,83 +1,87 @@
1
- # Elara Services: Tickets
2
-
3
- This is a customizable ticket system that uses interactions and discord.js
4
-
5
-
6
- # Getting Started
7
- ```js
8
- const { Client } = require("discord.js"),
9
- Tickets = require(`@elara-services/tickets`),
10
- client = new Client({ intents: ["GUILDS"] }),
11
- tickets = new Tickets({
12
- client,
13
- prefix: "support", // This is what is used for interactions (buttons) and the start of the channel name
14
- encryptToken: "ASB!@#$%^&*(B", // This is to encrypt/decrypt the user IDs in the channel topic, to avoid non-staff from seeing who's ticket it is
15
- debug: true, // Only use if you want errors logged.
16
- appeals: { // OPTIONAL
17
- enabled: true, // If the appeals server checks should be enabled.
18
- mainserver: {
19
- id: "", // The main server's id
20
- checkIfBanned: true // Check if the user is banned in the main server, if not they can't open a ticket.
21
- },
22
- embeds: {
23
- not_banned: {} // The embeds, content and components for the not banned message.
24
- }
25
- },
26
-
27
- modal: {
28
- enabled: true, // If this form should be enabled / shown
29
- title: "", // The top title of the modal / form
30
- questions: [
31
- {
32
- label: "[NAME]", // The name of this question
33
- style: 2, // 1 (SHORT ANSWER) | 2 (LONG ANSWER)
34
- placeholder: "", // The placeholder of the question
35
- value: "", // The default value for the question
36
- required: true, // If the question should be required
37
- min_length: 20, // The min length for the question response
38
- max_length: 4000, // The max length for the question response
39
- }
40
- ]
41
- },
42
- webhook: {
43
- id: "", // 'webhookId' support will be removed in the next major version
44
- token: "", // 'webhookToken' support will be removed in the next major version
45
- username: "Webhook Username Here", // 'webhookUsername' support will be removed in the next major version
46
- avatar: "", // 'webhookAvatar' support will be removed in the next major version
47
- },
48
- support: {
49
- canOnlyCloseTickets: true, // If 'true' only roles and users listed below can close tickets. (OR people with 'Manage Server' permission)
50
- roles: [ // 'supportRoleIds' support will be removed in the next major version
51
- "123456789"
52
- ],
53
- users: [ // 'supportUserIds' support will be removed in the next major version
54
- "123456789"
55
- ]
56
- },
57
- ticket: {
58
- closeReason: true, // This will enforce users or support staff to provide a reason for closing the ticket
59
- limitOnePerUser: true, // This will block users from creating more than one ticket.
60
- category: "", // When tickets get created they get created in this category, (OPTIONAL) - Default is the category ID for the starter message's channel.
61
- open: {
62
- content: "", // The content of the ticket message once it gets created, use "%user%" or "%server%" for the user mention or server name
63
- embeds: [], // View https://discord.com/developers/docs/resources/channel#embed-object
64
- }
65
- }
66
- })
67
-
68
- client.on("interactionCreate", (int) => tickets.run(int))
69
-
70
- client.on("ready", () => {
71
- console.log(`Client is ready`);
72
- // Use it as "node bot.js --starter" or just create a command in your bot to manage the starter message
73
- if (process.argv.find(c => c === "--starter")) {
74
- return tickets.starterMessage(`HELP OR SUPPORT CHANNEL ID HERE`, {
75
- embeds: [
76
- { title: "Support Tickets", description: `Click the button below to create a support ticket!`, color: 0xFF000 }
77
- ]
78
- })
79
- }
80
- });
81
-
82
- client.login("BOT TOKEN HERE")
1
+ # Elara Services: Tickets
2
+
3
+ This is a customizable ticket system that uses interactions and discord.js
4
+
5
+
6
+ # Getting Started
7
+ ```js
8
+ const { Client } = require("discord.js"),
9
+ Tickets = require(`@elara-services/tickets`),
10
+ client = new Client({ intents: ["GUILDS"] }),
11
+ tickets = new Tickets({
12
+ client,
13
+ prefix: "support", // This is what is used for interactions (buttons) and the start of the channel name
14
+ encryptToken: "ASB!@#$%^&*(B", // This is to encrypt/decrypt the user IDs in the channel topic, to avoid non-staff from seeing who's ticket it is
15
+ debug: true, // Only use if you want errors logged.
16
+ appeals: { // [OPTIONAL]
17
+ enabled: true, // If the appeals server checks should be enabled.
18
+ mainserver: {
19
+ id: "", // The main server's id
20
+ checkIfBanned: true // Check if the user is banned in the main server, if not they can't open a ticket.
21
+ },
22
+ embeds: {
23
+ not_banned: {
24
+ content: "",
25
+ embeds: [], // View https://discord.com/developers/docs/resources/channel#embed-object
26
+ components: [] // View https://discord.com/developers/docs/interactions/message-components#what-is-a-component
27
+ } // The embeds, content and components for the not banned message.
28
+ }
29
+ },
30
+
31
+ modal: { // [OPTIONAL]
32
+ enabled: true, // If this form should be enabled / shown
33
+ title: "", // The top title of the modal / form
34
+ questions: [
35
+ {
36
+ label: "[NAME]", // The name of this question
37
+ style: 2, // 1 (SHORT ANSWER) | 2 (LONG ANSWER)
38
+ placeholder: "", // The placeholder of the question
39
+ value: "", // The default value for the question
40
+ required: true, // If the question should be required
41
+ min_length: 20, // The min length for the question response
42
+ max_length: 4000, // The max length for the question response
43
+ }
44
+ ]
45
+ },
46
+ webhook: { // [OPTIONAL]
47
+ id: "", // The webhook ID for this ticket's open and closed logs.
48
+ token: "", // The webhook Token for this ticket's open and closed logs.
49
+ username: "Webhook Username Here", // The webhook username for this ticket's logs.
50
+ avatar: "", // The webhook avatar for this ticket's logs.
51
+ },
52
+ support: { // [OPTIONAL]
53
+ canOnlyCloseTickets: true, // If 'true' only roles and users listed below can close tickets. (OR people with 'Manage Server' permission)
54
+ roles: [ // The role ids for the 'support' members
55
+ "123456789"
56
+ ],
57
+ users: [ // The user ids for the 'support' users
58
+ "123456789"
59
+ ]
60
+ },
61
+ ticket: { // [OPTIONAL]
62
+ closeReason: true, // This will enforce users or support staff to provide a reason for closing the ticket
63
+ limitOnePerUser: true, // This will block users from creating more than one ticket.
64
+ category: "", // When tickets get created they get created in this category, (OPTIONAL) - Default is the category ID for the starter message's channel.
65
+ open: {
66
+ content: "", // The content of the ticket message once it gets created, use "%user%" or "%server%" for the user mention or server name
67
+ embeds: [], // View https://discord.com/developers/docs/resources/channel#embed-object
68
+ }
69
+ }
70
+ })
71
+
72
+ client.on("interactionCreate", (int) => tickets.run(int))
73
+
74
+ client.on("ready", () => {
75
+ console.log(`Client is ready`);
76
+ // Use it as "node bot.js --starter" or just create a command in your bot to manage the starter message
77
+ if (process.argv.find(c => c === "--starter")) {
78
+ return tickets.starterMessage(`HELP OR SUPPORT CHANNEL ID HERE`, {
79
+ embeds: [
80
+ { title: "Support Tickets", description: `Click the button below to create a support ticket!`, color: 0xFF000 }
81
+ ]
82
+ })
83
+ }
84
+ });
85
+
86
+ client.login("BOT TOKEN HERE")
83
87
  ```
package/index.d.ts CHANGED
@@ -1,89 +1,89 @@
1
- declare module "@elara-services/tickets" {
2
-
3
- import { Client, MessageOptions, GuildMember, Guild, User, TextBasedChannel, Message, Interaction, ModalOptions } from "discord.js";
4
- import Webhook from "discord-hook";
5
-
6
- export interface TicketOptions {
7
- client: Client;
8
- prefix: string;
9
- debug?: boolean;
10
- encryptToken: string;
11
- appeals?: {
12
- enabled: boolean;
13
- sendBanResults?: boolean;
14
- mainserver: {
15
- id: string;
16
- checkIfBanned: boolean;
17
- };
18
- embeds?: {
19
- not_banned: Pick<MessageOptions, "content" | "embeds" | "components">
20
- }
21
- };
22
- modal?: {
23
- enabled: boolean;
24
- title?: string;
25
- questions?: {
26
- label: string;
27
- style: 1 | 2;
28
- placeholder?: string;
29
- value?: string;
30
- required?: boolean;
31
- min_length?: number;
32
- max_length?: number;
33
- }[]
34
- };
35
- webhook?: {
36
- id?: string;
37
- token?: string;
38
- username?: string;
39
- avatar?: string
40
- };
41
- support?: {
42
- roles?: string[];
43
- users?: string[];
44
- canOnlyCloseTickets?: boolean;
45
- ignore?: string[]
46
- };
47
- ticket?: {
48
- category?: string;
49
- closeReason?: boolean;
50
- limitOnePerUser?: boolean;
51
- open?: Pick<MessageOptions, "content" | "embeds">
52
- }
53
-
54
- /** @deprecated Use 'ticket.category', 'ticketCategory' will be removed in the next major version */
55
- ticketCategory?: string;
56
- /** @deprecated Use 'ticket.open', 'ticketOpen' will be removed in the next major version */
57
- ticketOpen?: Pick<MessageOptions, "content" | "embeds">
58
-
59
- // reports?: {
60
- // enabled: boolean;
61
- // shouldBeTicket?: boolean;
62
-
63
- // }
64
- }
65
-
66
- class Tickets {
67
- public constructor(options: TicketOptions);
68
- public options: TicketOptions;
69
- public prefix: string;
70
- public webhook(): typeof Webhook.prototype;
71
- public button(options: { style: 1 | 2 | 3 | 4 | 5 | number, id?: string, label?: string, emoji?: { name?: string, id?: string } }): { type: number, custom_id: string, style: number, label?: string, emoji?: { name?: string, id?: string } }
72
-
73
- public fetchMessages(channel: TextBasedChannel, limit?: number, before?: string, after?: string, around?: string): Promise<Array<Message>>
74
- public displayMessages(channel: TextBasedChannel, messages: Array<Message>, ticketID: string, type: string): string;
75
- public closeTicket(options: {
76
- member: GuildMember,
77
- guild: Guild,
78
- user: User,
79
- messages: Array<Message>,
80
- channel: TextBasedChannel
81
- }): Promise<void>;
82
-
83
- public code(id: string, type: string): string;
84
- public run(int: Interaction): Promise<void>;
85
- public starterMessage(channelId: string, options?: Pick<MessageOptions, "embeds" | "content" | "components" | "attachments">): Promise<void>;
86
- };
87
-
88
- export = Tickets;
1
+ declare module "@elara-services/tickets" {
2
+
3
+ import { Client, MessageOptions, GuildMember, Guild, User, TextBasedChannel, Message, Interaction, ModalOptions } from "discord.js";
4
+ import type { DiscordWebhook } from "@elara-services/webhooks";
5
+
6
+ export interface TicketOptions {
7
+ client: Client;
8
+ prefix: string;
9
+ debug?: boolean;
10
+ encryptToken: string;
11
+ appeals?: {
12
+ enabled: boolean;
13
+ sendBanResults?: boolean;
14
+ mainserver: {
15
+ id: string;
16
+ checkIfBanned: boolean;
17
+ };
18
+ embeds?: {
19
+ not_banned: Pick<MessageOptions, "content" | "embeds" | "components">
20
+ }
21
+ };
22
+ modal?: {
23
+ enabled: boolean;
24
+ title?: string;
25
+ questions?: {
26
+ label: string;
27
+ style: 1 | 2;
28
+ placeholder?: string;
29
+ value?: string;
30
+ required?: boolean;
31
+ min_length?: number;
32
+ max_length?: number;
33
+ }[]
34
+ };
35
+ webhook?: {
36
+ id?: string;
37
+ token?: string;
38
+ username?: string;
39
+ avatar?: string
40
+ };
41
+ support?: {
42
+ roles?: string[];
43
+ users?: string[];
44
+ canOnlyCloseTickets?: boolean;
45
+ ignore?: string[]
46
+ };
47
+ ticket?: {
48
+ category?: string;
49
+ closeReason?: boolean;
50
+ limitOnePerUser?: boolean;
51
+ open?: Pick<MessageOptions, "content" | "embeds">
52
+ }
53
+
54
+ /** @deprecated Use 'ticket.category', 'ticketCategory' will be removed in the next major version */
55
+ ticketCategory?: string;
56
+ /** @deprecated Use 'ticket.open', 'ticketOpen' will be removed in the next major version */
57
+ ticketOpen?: Pick<MessageOptions, "content" | "embeds">
58
+
59
+ // reports?: {
60
+ // enabled: boolean;
61
+ // shouldBeTicket?: boolean;
62
+
63
+ // }
64
+ }
65
+
66
+ class Tickets {
67
+ public constructor(options: TicketOptions);
68
+ public options: TicketOptions;
69
+ public prefix: string;
70
+ public webhook(): typeof DiscordWebhook.prototype;
71
+ public button(options: { style: 1 | 2 | 3 | 4 | 5 | number, id?: string, label?: string, emoji?: { name?: string, id?: string } }): { type: number, custom_id: string, style: number, label?: string, emoji?: { name?: string, id?: string } }
72
+
73
+ public fetchMessages(channel: TextBasedChannel, limit?: number, before?: string, after?: string, around?: string): Promise<Array<Message>>
74
+ public displayMessages(channel: TextBasedChannel, messages: Array<Message>, ticketID: string, type: string): string;
75
+ public closeTicket(options: {
76
+ member: GuildMember,
77
+ guild: Guild,
78
+ user: User,
79
+ messages: Array<Message>,
80
+ channel: TextBasedChannel
81
+ }): Promise<void>;
82
+
83
+ public code(id: string, type: string): string;
84
+ public run(int: Interaction): Promise<void>;
85
+ public starterMessage(channelId: string, options?: Pick<MessageOptions, "embeds" | "content" | "components" | "attachments">): Promise<void>;
86
+ };
87
+
88
+ export = Tickets;
89
89
  }
package/index.js CHANGED
@@ -1,12 +1,12 @@
1
- const pack = require("./package.json");
2
-
3
- module.exports = (() => {
4
- let version = null;
5
- try { version = require("discord.js").version; } catch {}
6
- if (!version) throw new Error(`[${pack.name}, v${pack.version}]: I was unable to find the discord.js version you're using.`);
7
- let [ major ] = version.split(".");
8
- if (major === "14") return require("./lib/v14");
9
- if (major === "13") return require("./lib/v13");
10
- if ([ "12", "11" ].includes(major)) throw new Error(`[${pack.name}, v${pack.version}]: The discord.js version you're using is outdated and unsupported, please update to v13+`)
11
- throw new Error(`[${pack.name}, v${pack.version}]: The discord.js version you're using isn't supported by this package. (currently supported: v13, v14)`);
1
+ const pack = require("./package.json");
2
+
3
+ module.exports = (() => {
4
+ let version = null;
5
+ try { version = require("discord.js").version; } catch {}
6
+ if (!version) throw new Error(`[${pack.name}, v${pack.version}]: I was unable to find the discord.js version you're using.`);
7
+ let [ major ] = version.split(".");
8
+ if (major === "14") return require("./lib/v14");
9
+ if (major === "13") return require("./lib/v13");
10
+ if ([ "12", "11" ].includes(major)) throw new Error(`[${pack.name}, v${pack.version}]: The discord.js version you're using is outdated and unsupported, please update to v13+`)
11
+ throw new Error(`[${pack.name}, v${pack.version}]: The discord.js version you're using isn't supported by this package. (currently supported: v13, v14)`);
12
12
  })();
@@ -0,0 +1,36 @@
1
+ module.exports = {
2
+ NO_CONSTRUCTOR_OPTIONS: (name = "") => name ? `You didn't provide any data in the constructor, fill it out!` : `You forgot to fill out either ${name}`,
3
+
4
+ CREATE_TICKET: "Create Ticket",
5
+ MODAL_CONTENT: "Content",
6
+ MODAL_CONTENT_PLACEHOLDER: "What's the ticket about?",
7
+ OPEN_TICKET_TITLE: "Ticket: Opened",
8
+ OPEN_TICKET_CREATE: "Ticket Created!",
9
+ OPEN_TICKET_AUDIT_REASON: "Ticket created by:",
10
+ OPEN_TICKET_MESSAGE_CONTENT: "👋 Hello, please explain what you need help with.",
11
+ OPEN_TICKET_MESSAGE_FOOTER: "To close the ticket, press the button below",
12
+ OPEN_TICKET_MESSAGE: "Support will be with you shortly.",
13
+ CLOSE_TICKET_TITLE: `Ticket: Closed`,
14
+ CLOSE_TICKET: "Close Ticket",
15
+ CLOSE_TICKET_FIELD_REASON: "Close Reason",
16
+ NO_CHANNEL_CREATE: `❌ I was unable to create the ticket channel, if this keeps happening contact one of the staff members via their DMs!`,
17
+ NO_CHANNEL_DELETE: "",
18
+ GO_TO_TICKET: "Go to ticket",
19
+ TICKET_ID: "Ticket ID:",
20
+ TRANSCRIPT: "Transcript",
21
+ VIEW_HERE: "View here",
22
+ NO_REASON: "No Reason Provided",
23
+ TICKET_LIMIT_ONE_PER_USER: (name = "") => `❌ You can only create one (${name}) ticket at a time.`,
24
+ TICKET_BLOCKED: `❌ You can't create tickets, if you believe this is a mistake contact one of the staff members.`,
25
+ ONLY_SUPPORT: "Only support staff can close tickets",
26
+ TICKET_CLOSE_CONFIRM: `🤔 Are you sure you want to close the ticket?`,
27
+ TICKET_CLOSE_CONFIRM_BUTTON: `Yes, close the ticket!`,
28
+ TICKET_CLOSE_PLACEHOLDER: "What's the reason for closing the ticket?",
29
+ FORM_RESPONSES: "Form Responses",
30
+ FORM_RESPONSE: "Form Response",
31
+ ID: (id) => `ID: ${id}`,
32
+ REASON: "Reason",
33
+ BAN_REASON: "Ban Reason",
34
+ NOT_BANNED_MAIN_SERVER: `❌ You can't open this ticket due to you not being banned in the main server!`,
35
+ UNBAN: "Unban"
36
+ }
package/lib/base.js CHANGED
@@ -1,80 +1,81 @@
1
- const { getWebhookInfo, displayMessages, de, webhook } = require("./util"),
2
- { Interactions: { button, modal } } = require("@elara-services/packages"),
3
- { WebhookClient } = require("discord.js");
4
-
5
- module.exports = class Tickets {
6
- constructor(options) {
7
- if (typeof options !== "object") throw new Error(`You didn't provide any data in the constructor, fill it out!`);
8
- if (!("client" in options) || !("prefix" in options) || !("encryptToken" in options)) throw new Error(`You forgot to fill out either 'client', 'prefix' or 'encryptToken'`)
9
- this.options = options;
10
- }
11
- get prefix() { return `system:ticket:${this.options.prefix}`; };
12
- get webhookOptions() { return getWebhookInfo(this.options); };
13
- get getSupportIds() {
14
- return {
15
- roles: this.options.support?.roles || [],
16
- users: this.options.support?.users || []
17
- }
18
- }
19
-
20
- /** @private */
21
- _debug(...args) {
22
- if (this.options?.debug) console.log(...args);
23
- return null;
24
- }
25
-
26
- button(options = { style: 3, label: "Create Ticket", emoji: { name: "📩" } }) {
27
- return button({ id: options?.id || this.prefix, style: options.style || 3, title: options.label, emoji: options.emoji });
28
- };
29
-
30
- /**
31
- * @param {object} options
32
- * @param {string} [options.title] The title of the modal submit form
33
- * @param {import("@elara-services/packages").Modal['components']} [options.components]
34
- */
35
- modal(options = { title: "", components: [] }) {
36
- 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 }] }] })
37
- };
38
-
39
- async closeTicket({ member, messages, channel, guild, user, reason } = {}) {
40
- const { id, token, username, avatar: avatarURL } = this.webhookOptions;
41
- if (!id || !token) return;
42
- let embeds = [
43
- {
44
- author: { name: guild.name, icon_url: guild.iconURL({ dynamic: true }) },
45
- title: "Ticket: Closed",
46
- description: `${de.user}User: ${user.toString()} \`@${user.tag}\` (${user.id})\n${de.user}Closed By: ${member.toString()} (${member.id})\n${de.channel}Channel: \`#${channel.name}\` (${channel.id})`,
47
- color: 0xFF0000,
48
- fields: reason ? [ { name: "Close Reason", value: reason?.slice?.(0, 1024) ?? "No Reason Provided" } ] : undefined,
49
- timestamp: new Date(),
50
- footer: { text: `Ticket ID: ${channel.name.split("-")[1]}` },
51
- }
52
- ];
53
- new WebhookClient({ id, token })
54
- .send({
55
- username, avatarURL,
56
- embeds,
57
- files: [{ name: "transcript.txt", attachment: Buffer.from(displayMessages(channel, messages.reverse(), channel.name.split("-")[1], this.options.prefix)) }]
58
- })
59
- .then(m => {
60
- let components = [{ type: 2, style: 5, label: "Transcript", emoji: { id: "792290922749624320" }, url: `https://view.elara.workers.dev/tickets?url=${Array.isArray(m.attachments) ? m.attachments?.[0]?.url : m.attachments?.first?.()?.url ?? "URL_NOT_FOUND"}` }];
61
- embeds[0].description += `\n${de.transcript} Transcript: [View here](${components[0].url})`
62
- webhook(this.webhookOptions)
63
- .embeds(embeds)
64
- .button({ type: 1, components })
65
- .edit(m.id)
66
- .catch(e => this._debug(e));
67
- if (user) user.send({
68
- embeds: [{
69
- author: { name: guild.name, icon_url: guild.iconURL({ dynamic: true }) },
70
- title: `Ticket: Closed`,
71
- color: 0xFF0000,
72
- fields: reason ? [ { name: "Close Reason", value: reason?.slice?.(0, 1024) ?? "No Reason Provided" } ] : undefined,
73
- timestamp: new Date(),
74
- footer: { text: `Ticket ID: ${channel.name.split("-")[1]}` }
75
- }],
76
- components: [{ type: 1, components }]
77
- }).catch(e => this._debug(e));
78
- }).catch(e => this._debug(e));
79
- };
1
+ const { getWebhookInfo, displayMessages, de, webhook, getString } = require("./util"),
2
+ { Interactions: { button, modal } } = require("@elara-services/packages"),
3
+ { WebhookClient } = require("discord.js");
4
+
5
+ module.exports = class Tickets {
6
+ constructor(options) {
7
+ if (typeof options !== "object") throw new Error(this.str("NO_CONSTRUCTOR_OPTIONS")());
8
+ if (!("client" in options) || !("prefix" in options) || !("encryptToken" in options)) throw new Error(this.str("NO_CONSTRUCTOR_OPTIONS")("'client', 'prefix' or 'encryptToken'"));
9
+ this.options = options;
10
+ }
11
+ get prefix() { return `system:ticket:${this.options.prefix}`; };
12
+ get webhookOptions() { return getWebhookInfo(this.options); };
13
+ get getSupportIds() {
14
+ return {
15
+ roles: this.options.support?.roles || [],
16
+ users: this.options.support?.users || []
17
+ }
18
+ }
19
+ str(name) { return getString(name, this.options?.lang || "en-US"); }
20
+
21
+ /** @private */
22
+ _debug(...args) {
23
+ if (this.options?.debug) console.log(...args);
24
+ return null;
25
+ }
26
+
27
+ button(options = { style: 3, label: this.str("CREATE_TICKET"), emoji: { name: "📩" } }) {
28
+ return button({ id: options?.id || this.prefix, style: options.style || 3, title: options.label, emoji: options.emoji });
29
+ };
30
+
31
+ /**
32
+ * @param {object} options
33
+ * @param {string} [options.title] The title of the modal submit form
34
+ * @param {import("@elara-services/packages").Modal['components']} [options.components]
35
+ */
36
+ modal(options = { title: "", components: [] }) {
37
+ return modal({ id: `${this.prefix}:modal_submit`, title: options?.title || this.str("CREATE_TICKET"), components: options?.components?.length >= 1 ? options.components : [{ type: 1, components: [{ type: 4, min_length: 10, max_length: 4000, custom_id: "message", label: this.str("MODAL_CONTENT"), style: 2, placeholder: this.str("MODAL_CONTENT_PLACEHOLDER"), required: true }] }] })
38
+ };
39
+
40
+ async closeTicket({ member, messages, channel, guild, user, reason } = {}) {
41
+ const { id, token, username, avatar: avatarURL } = this.webhookOptions;
42
+ if (!id || !token) return;
43
+ let embeds = [
44
+ {
45
+ author: { name: guild.name, icon_url: guild.iconURL({ dynamic: true }) },
46
+ title: this.str("CLOSE_TICKET_TITLE"),
47
+ description: `${de.user}User: ${user.toString()} \`@${user.tag}\` (${user.id})\n${de.user}Closed By: ${member.toString()} (${member.id})\n${de.channel}Channel: \`#${channel.name}\` (${channel.id})`,
48
+ color: 0xFF0000,
49
+ fields: reason ? [ { name: this.str("CLOSE_TICKET_FIELD_REASON"), value: reason?.slice?.(0, 1024) ?? this.str("NO_REASON") } ] : undefined,
50
+ timestamp: new Date(),
51
+ footer: { text: `${this.str("TICKET_ID")} ${channel.name.split("-")[1]}` },
52
+ }
53
+ ];
54
+ new WebhookClient({ id, token })
55
+ .send({
56
+ username, avatarURL,
57
+ embeds,
58
+ files: [{ name: "transcript.txt", attachment: Buffer.from(displayMessages(channel, messages.reverse(), channel.name.split("-")[1], this.options.prefix)) }]
59
+ })
60
+ .then(m => {
61
+ let components = [{ type: 2, style: 5, label: "Transcript", emoji: { id: "792290922749624320" }, url: `https://view.elara.workers.dev/tickets?url=${Array.isArray(m.attachments) ? m.attachments?.[0]?.url : m.attachments?.first?.()?.url ?? "URL_NOT_FOUND"}` }];
62
+ embeds[0].description += `\n${de.transcript} Transcript: [View here](${components[0].url})`
63
+ webhook(this.webhookOptions)
64
+ .embeds(embeds)
65
+ .button({ type: 1, components })
66
+ .edit(m.id)
67
+ .catch(e => this._debug(e));
68
+ if (user) user.send({
69
+ embeds: [{
70
+ author: { name: guild.name, icon_url: guild.iconURL({ dynamic: true }) },
71
+ title: this.str("CLOSE_TICKET_TITLE"),
72
+ color: 0xFF0000,
73
+ fields: reason ? [ { name: this.str("CLOSE_TICKET_FIELD_REASON"), value: reason?.slice?.(0, 1024) ?? this.str("NO_REASON") } ] : undefined,
74
+ timestamp: new Date(),
75
+ footer: { text: `${this.str("TICKET_ID")} ${channel.name.split("-")[1]}` }
76
+ }],
77
+ components: [{ type: 1, components }]
78
+ }).catch(e => this._debug(e));
79
+ }).catch(e => this._debug(e));
80
+ };
80
81
  };