@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/.eslintrc.json CHANGED
@@ -1,20 +1,27 @@
1
1
  {
2
2
  "env": {
3
3
  "node": true,
4
- "commonjs": true,
5
4
  "es2021": true
6
5
  },
7
- "extends": "eslint:recommended",
6
+ "extends": [
7
+ "eslint:recommended"
8
+ ],
9
+ "overrides": [
10
+ ],
8
11
  "parserOptions": {
9
- "ecmaVersion": 12
12
+ "ecmaVersion": "latest",
13
+ "sourceType": "module"
10
14
  },
15
+ "plugins": [],
11
16
  "rules": {
12
- "no-extra-semi": 0,
13
- "no-async-promise-executor": 0,
14
- "no-warning-comments": "warn",
15
- "no-empty": 0
17
+ "no-empty-function": 0,
18
+ "semi": ["error", "always"],
19
+ "curly": ["error", "all"],
20
+ "no-var-requires": 0,
21
+ "object-shorthand": "error"
16
22
  },
17
23
  "ignorePatterns": [
18
- "*/*.json"
24
+ "**/*.json",
25
+ "node_modules/*"
19
26
  ]
20
27
  }
package/.prettierrc ADDED
@@ -0,0 +1,4 @@
1
+ {
2
+ "tabWidth": 4,
3
+ "printWidth": 500
4
+ }
package/README.md CHANGED
@@ -84,4 +84,26 @@ client.on("ready", () => {
84
84
  });
85
85
 
86
86
  client.login("BOT TOKEN HERE")
87
- ```
87
+ ```
88
+
89
+
90
+ ## Want to have a select menu instead of button(s)?
91
+ > Just use `<Ticket>.prefix` for the select menu option value
92
+ ```js
93
+ {
94
+ "custom_id": "....", // This can be anything.
95
+ "max_values": 1,
96
+ "min_values": 1,
97
+ "placeholder": "Select a ticket type below",
98
+ "options": [
99
+ { "label": "Support", "value": supportTicket.prefix, "description": "Open an Support ticket for x, y, z." },
100
+ { "label": "Moderator", "value": modTicket.prefix, "description": "Open an Moderator ticket for x, y, z." },
101
+ // etc.
102
+ // Just make sure you use `<Ticket>.prefix` for the value of the option.
103
+ ]
104
+ }
105
+ ```
106
+
107
+ # Want to make the bot / responses be in a certain lagnauge?
108
+ Make a PR request with the language you would like to see in [elara-bots/npm](https://github.com/elara-bots/npm) GitHub repo
109
+ - Copy the contents of `./languages/en-US.js`
package/index.d.ts CHANGED
@@ -1,11 +1,13 @@
1
1
  declare module "@elara-services/tickets" {
2
2
 
3
- import { Client, MessageOptions, GuildMember, Guild, User, TextBasedChannel, Message, Interaction, ModalOptions } from "discord.js";
4
- import type { DiscordWebhook } from "@elara-services/webhooks";
3
+ import { Client, MessageOptions, GuildMember, Guild, User, TextBasedChannel, Message, Interaction } from "discord.js";
4
+
5
+ type Langs = "en-US";
5
6
 
6
7
  export interface TicketOptions {
7
8
  client: Client;
8
9
  prefix: string;
10
+ lang?: Langs;
9
11
  debug?: boolean;
10
12
  encryptToken: string;
11
13
  appeals?: {
@@ -35,6 +37,7 @@ declare module "@elara-services/tickets" {
35
37
  webhook?: {
36
38
  id?: string;
37
39
  token?: string;
40
+ threadId?: string;
38
41
  username?: string;
39
42
  avatar?: string
40
43
  };
@@ -50,39 +53,98 @@ declare module "@elara-services/tickets" {
50
53
  limitOnePerUser?: boolean;
51
54
  open?: Pick<MessageOptions, "content" | "embeds">
52
55
  }
56
+ }
53
57
 
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
+ interface LangFile {
59
+ NO_BAN_PERMS_USER_IN_APPEAL_SERVER(server: Guild): string;
60
+ NOT_FOUND_IN_APPEAL_SERVER(server: Guild): string;
61
+ TICKET_LIMIT_ONE_PER_USER(name: string): string;
62
+ NO_CONSTRUCTOR_OPTIONS(name?: string): string;
63
+ NO_CHANNEL_FOUND(id: string): string;
64
+ USER_NOT_BANNED(id: string): string;
65
+ UNBAN_FAILED(id: string, serverName: string): string;
66
+ UNBAN_SUCCESS(id: string, serverName: string): string;
67
+ ID(id?: string): string;
58
68
 
59
- // reports?: {
60
- // enabled: boolean;
61
- // shouldBeTicket?: boolean;
62
-
63
- // }
69
+ OPEN_TICKET_MESSAGE_CONTENT: string;
70
+ TICKET_CLOSE_CONFIRM_BUTTON: string;
71
+ OPEN_TICKET_MESSAGE_FOOTER: string;
72
+ MODAL_CONTENT_PLACEHOLDER: string;
73
+ CLOSE_TICKET_FIELD_REASON: string;
74
+ OPEN_TICKET_AUDIT_REASON: string;
75
+ TICKET_CLOSE_PLACEHOLDER: string;
76
+ NO_APPEAL_SERVER_FOUND: string;
77
+ NOT_BANNED_MAIN_SERVER: string;
78
+ TICKET_CLOSE_CONFIRM: string;
79
+ NO_MESSAGES_FETCHED: string;
80
+ OPEN_TICKET_MESSAGE: string;
81
+ OPEN_TICKET_CREATE: string;
82
+ CLOSE_TICKET_TITLE: string;
83
+ OPEN_TICKET_TITLE: string;
84
+ NO_CHANNEL_CREATE: string;
85
+ NO_CHANNEL_DELETE: string;
86
+ NO_BAN_PERMS_USER: string;
87
+ TICKET_BLOCKED: string;
88
+ FORM_RESPONSES: string;
89
+ NO_USER_FOUND: string;
90
+ CREATE_TICKET: string;
91
+ CLOSED_TICKET: string;
92
+ FORM_RESPONSE: string;
93
+ MODAL_CONTENT: string;
94
+ ONLY_SUPPORT: string;
95
+ GO_TO_TICKET: string;
96
+ CLOSE_TICKET: string;
97
+ BAN_REASON: string;
98
+ UNBAN_FROM: string;
99
+ TRANSCRIPT: string;
100
+ TICKET_ID: string;
101
+ VIEW_HERE: string;
102
+ NO_REASON: string;
103
+ CLOSED_BY: string;
104
+ UNBANNED: string;
105
+ TICKETS: string;
106
+ CHANNEL: string;
107
+ REASON: string;
108
+ UNBAN: string;
109
+ ERROR: string;
110
+ USER: string;
111
+ INFO: string;
112
+ BY: string;
64
113
  }
65
114
 
66
115
  class Tickets {
67
116
  public constructor(options: TicketOptions);
68
117
  public options: TicketOptions;
69
118
  public prefix: string;
70
- public webhook(): typeof DiscordWebhook.prototype;
119
+
120
+ private _debug(...args: unknown[]): unknown;
121
+
122
+ public get webhookOptions(): {
123
+ id: string | undefined;
124
+ token: string | undefined;
125
+ threadId: string | undefined;
126
+ username: string;
127
+ avatar: string;
128
+ };
129
+
130
+ public get getSupportIds(): {
131
+ roles: string[];
132
+ users: string[];
133
+ };
134
+
135
+ public str(name: keyof LangFile): string;
136
+
71
137
  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
138
  public closeTicket(options: {
76
139
  member: GuildMember,
77
140
  guild: Guild,
78
141
  user: User,
79
- messages: Array<Message>,
142
+ messages: Message[],
80
143
  channel: TextBasedChannel
81
- }): Promise<void>;
144
+ }): Promise<unknown>;
82
145
 
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>;
146
+ public run(int: Interaction): Promise<unknown>;
147
+ public starterMessage(channelId: string, options?: Pick<MessageOptions, "embeds" | "content" | "components" | "attachments">): Promise<unknown>;
86
148
  };
87
149
 
88
150
  export = Tickets;
package/index.js CHANGED
@@ -1,12 +1,19 @@
1
1
  const pack = require("./package.json");
2
+ const { version } = require("discord.js");
2
3
 
3
4
  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+`)
5
+ if (!version) {
6
+ throw new Error(`[${pack.name}, v${pack.version}]: I was unable to find the discord.js version you're using.`);
7
+ }
8
+ let [major] = version.split(".");
9
+ if (major === "14") {
10
+ return require("./lib/v14");
11
+ }
12
+ if (major === "13") {
13
+ return require("./lib/v13");
14
+ }
15
+ if (["12", "11"].includes(major)) {
16
+ throw new Error(`[${pack.name}, v${pack.version}]: The discord.js version you're using is outdated and unsupported, please update to v13+`);
17
+ }
11
18
  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
- })();
19
+ })();
@@ -1,36 +1,63 @@
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
- }
1
+ const y = "✅";
2
+ const x = "";
3
+
4
+ module.exports = {
5
+ // Functions
6
+ NO_BAN_PERMS_USER_IN_APPEAL_SERVER: (server) => `${x} You need (Ban Members) in ${server.name} to complete this action!`,
7
+ NOT_FOUND_IN_APPEAL_SERVER: (server) => `${x} I was unable to find you in ${server.name}!`,
8
+ TICKET_LIMIT_ONE_PER_USER: (name = "") => `${x} You can only create one (${name}) ticket at a time.`,
9
+ NO_CONSTRUCTOR_OPTIONS: (name = "") => (name ? `You didn't provide any data in the constructor, fill it out!` : `You forgot to fill out either ${name}`),
10
+ NO_CHANNEL_FOUND: (id) => `${x} No channel found for: ${id}`,
11
+ USER_NOT_BANNED: (id) => `${x} User (<@${id}>) isn't banned in the main server!`,
12
+ UNBAN_FAILED: (id, serverName) => `${x} Unable to unban <@${id} from ${serverName}!`,
13
+ UNBAN_SUCCESS: (id, serverName) => `${y} Successfully unbanned <@${id}> from ${serverName}!`,
14
+ ID: (id = "") => `ID: ${id}`,
15
+
16
+ // Strings
17
+ OPEN_TICKET_MESSAGE_CONTENT: "👋 Hello, please explain what you need help with.",
18
+ TICKET_CLOSE_CONFIRM_BUTTON: "Yes, close the ticket!",
19
+ OPEN_TICKET_MESSAGE_FOOTER: "To close the ticket, press the button below",
20
+ MODAL_CONTENT_PLACEHOLDER: "What's the ticket about?",
21
+ CLOSE_TICKET_FIELD_REASON: "Close Reason",
22
+ OPEN_TICKET_AUDIT_REASON: "Ticket created by:",
23
+ TICKET_CLOSE_PLACEHOLDER: "What's the reason for closing the ticket?",
24
+ NO_APPEAL_SERVER_FOUND: `${x} I was unable to find the appeal server!`,
25
+ NOT_BANNED_MAIN_SERVER: `${x} You can't open this ticket due to you not being banned in the main server!`,
26
+ TICKET_CLOSE_CONFIRM: "🤔 Are you sure you want to close the ticket?",
27
+ NO_MESSAGES_FETCHED: `${x} I was unable to close the ticket, I couldn't fetch the messages in this channel.`,
28
+ OPEN_TICKET_MESSAGE: "Support will be with you shortly.",
29
+ OPEN_TICKET_CREATE: "Ticket Created!",
30
+ CLOSE_TICKET_TITLE: "Ticket: Closed",
31
+ OPEN_TICKET_TITLE: "Ticket: Opened",
32
+ NO_CHANNEL_CREATE: `${x} I was unable to create the ticket channel, if this keeps happening contact one of the staff members via their DMs!`,
33
+ NO_CHANNEL_DELETE: `${x} I was unable to delete the channel and close the ticket.`,
34
+ NO_BAN_PERMS_USER: `${x} You need (Ban Members) in this server to complete this action!`,
35
+ TICKET_BLOCKED: `${x} You can't create tickets, if you believe this is a mistake contact one of the staff members.`,
36
+ FORM_RESPONSES: "Form Responses",
37
+ TOTAL_MESSAGES: "Total Messages",
38
+ NO_USER_FOUND: `${x} I was unable to fetch the user that opened the ticket.`,
39
+ CREATE_TICKET: "Create Ticket",
40
+ CLOSED_TICKET: "closed the ticket.",
41
+ FORM_RESPONSE: "Form Response",
42
+ MODAL_CONTENT: "Content",
43
+ ONLY_SUPPORT: "Only support staff can close tickets",
44
+ GO_TO_TICKET: "Go to ticket",
45
+ CLOSE_TICKET: "Close Ticket",
46
+ BAN_REASON: "Ban Reason",
47
+ UNBAN_FROM: "Unban From",
48
+ TRANSCRIPT: "Transcript",
49
+ TICKET_ID: "Ticket ID:",
50
+ VIEW_HERE: "View here",
51
+ NO_REASON: "No Reason Provided",
52
+ CLOSED_BY: "Closed By:",
53
+ UNBANNED: "Unbanned!",
54
+ TICKETS: "Tickets",
55
+ CHANNEL: "Channel",
56
+ TICKET: "Ticket",
57
+ REASON: "Reason",
58
+ UNBAN: "Unban",
59
+ ERROR: "ERROR",
60
+ USER: "User",
61
+ INFO: "INFO",
62
+ BY: "By",
63
+ };
package/lib/base.js CHANGED
@@ -1,81 +1,204 @@
1
- const { getWebhookInfo, displayMessages, de, webhook, getString } = require("./util"),
2
- { Interactions: { button, modal } } = require("@elara-services/packages"),
3
- { WebhookClient } = require("discord.js");
1
+ const { getWebhookInfo, displayMessages, de, webhook, getString } = require("./util");
2
+ const {
3
+ Interactions: { button, modal },
4
+ } = require("@elara-services/packages");
5
+ const { is } = require("@elara-services/utils");
6
+ const { WebhookClient } = require("discord.js");
7
+ const required = ["client", "prefix", "encryptToken"];
4
8
 
5
9
  module.exports = class Tickets {
10
+ /**
11
+ * @param {import("@elara-services/tickets").TicketOptions} options
12
+ */
6
13
  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'"));
14
+ if (!is.object(options)) {
15
+ throw new Error(this.str("NO_CONSTRUCTOR_OPTIONS")());
16
+ }
17
+ for (const r of required) {
18
+ if (!(r in options)) {
19
+ throw new Error(this.str("NO_CONSTRUCTOR_OPTIONS")(`'${r}'`));
20
+ }
21
+ }
9
22
  this.options = options;
10
23
  }
11
- get prefix() { return `system:ticket:${this.options.prefix}`; };
12
- get webhookOptions() { return getWebhookInfo(this.options); };
24
+ get prefix() {
25
+ return `system:ticket:${this.options.prefix}`;
26
+ }
27
+ get webhookOptions() {
28
+ return getWebhookInfo(this.options, this.str("TICKETS"));
29
+ }
13
30
  get getSupportIds() {
14
31
  return {
15
32
  roles: this.options.support?.roles || [],
16
- users: this.options.support?.users || []
17
- }
33
+ users: this.options.support?.users || [],
34
+ };
35
+ }
36
+ /**
37
+ * @param {keyof typeof import("../languages/en-US")} name
38
+ */
39
+ str(name) {
40
+ return getString(name, this.options?.lang || "en-US");
18
41
  }
19
- str(name) { return getString(name, this.options?.lang || "en-US"); }
20
-
42
+
21
43
  /** @private */
22
44
  _debug(...args) {
23
- if (this.options?.debug) console.log(...args);
45
+ if (this.options?.debug) {
46
+ console.log(...args);
47
+ }
24
48
  return null;
25
49
  }
26
50
 
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
- };
51
+ button(
52
+ options = {
53
+ style: 3,
54
+ label: this.str("CREATE_TICKET"),
55
+ emoji: { name: "📩" },
56
+ },
57
+ ) {
58
+ return button({
59
+ id: options?.id || this.prefix,
60
+ style: options.style || 3,
61
+ title: options.label,
62
+ emoji: options.emoji,
63
+ });
64
+ }
30
65
 
31
66
  /**
32
- * @param {object} options
33
- * @param {string} [options.title] The title of the modal submit form
67
+ * @param {object} options
68
+ * @param {string} [options.title] The title of the modal submit form
34
69
  * @param {import("@elara-services/packages").Modal['components']} [options.components]
35
70
  */
36
71
  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
- };
72
+ return modal({
73
+ id: `${this.prefix}:modal_submit`,
74
+ title: options?.title || this.str("CREATE_TICKET"),
75
+ components:
76
+ options?.components?.length >= 1
77
+ ? options.components
78
+ : [
79
+ {
80
+ type: 1,
81
+ components: [
82
+ {
83
+ type: 4,
84
+ min_length: 10,
85
+ max_length: 4000,
86
+ custom_id: "message",
87
+ label: this.str("MODAL_CONTENT"),
88
+ style: 2,
89
+ placeholder: this.str("MODAL_CONTENT_PLACEHOLDER"),
90
+ required: true,
91
+ },
92
+ ],
93
+ },
94
+ ],
95
+ });
96
+ }
39
97
 
40
98
  async closeTicket({ member, messages, channel, guild, user, reason } = {}) {
41
- const { id, token, username, avatar: avatarURL } = this.webhookOptions;
42
- if (!id || !token) return;
99
+ const { id, token, username, avatar: avatarURL, threadId } = this.webhookOptions;
100
+ if (!id || !token) {
101
+ return;
102
+ }
43
103
  let embeds = [
44
104
  {
45
- author: { name: guild.name, icon_url: guild.iconURL({ dynamic: true }) },
105
+ author: {
106
+ name: guild.name,
107
+ icon_url: guild.iconURL({ dynamic: true }),
108
+ },
46
109
  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,
110
+ description: `${de.user} ${this.str("USER")}: ${user.toString()} \`@${user.tag}\` (${user.id})\n${de.user} ${this.str("CLOSED_BY")} ${member.toString()} (${member.id})\n${de.channel} ${this.str("CHANNEL")}: \`#${channel.name}\` (${channel.id})`,
111
+ color: 0xff0000,
112
+ fields: reason
113
+ ? [
114
+ {
115
+ name: this.str("CLOSE_TICKET_FIELD_REASON"),
116
+ value: reason?.slice?.(0, 1024) ?? this.str("NO_REASON"),
117
+ },
118
+ ]
119
+ : undefined,
50
120
  timestamp: new Date(),
51
- footer: { text: `${this.str("TICKET_ID")} ${channel.name.split("-")[1]}` },
52
- }
121
+ footer: {
122
+ text: `${this.str("TICKET_ID")} ${channel.name.split("-")[1]}`,
123
+ },
124
+ },
53
125
  ];
54
126
  new WebhookClient({ id, token })
55
127
  .send({
56
- username, avatarURL,
128
+ username,
129
+ avatarURL,
57
130
  embeds,
58
- files: [{ name: "transcript.txt", attachment: Buffer.from(displayMessages(channel, messages.reverse(), channel.name.split("-")[1], this.options.prefix)) }]
131
+ threadId,
132
+ files: [
133
+ {
134
+ name: `${this.str("TRANSCRIPT")}.txt`,
135
+ attachment: Buffer.from(displayMessages(channel, messages.reverse(), channel.name.split("-")[1], this.options.prefix, this.str)),
136
+ },
137
+ ],
59
138
  })
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})`
139
+ .then((m) => {
140
+ let components = [
141
+ {
142
+ type: 2,
143
+ style: 5,
144
+ label: this.str("TRANSCRIPT"),
145
+ emoji: { id: "792290922749624320" },
146
+ url: `https://view.elara.workers.dev/tickets?url=${Array.isArray(m.attachments) ? m.attachments?.[0]?.url : m.attachments?.first?.()?.url ?? "URL_NOT_FOUND"}`,
147
+ },
148
+ ];
149
+ embeds[0].description += `\n${de.transcript} ${this.str("TRANSCRIPT")}: [${this.str("VIEW_HERE")}](${components[0].url})`;
63
150
  webhook(this.webhookOptions)
64
151
  .embeds(embeds)
65
152
  .button({ type: 1, components })
66
153
  .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
- };
81
- };
154
+ .catch((e) => this._debug(e));
155
+ if (user) {
156
+ user.send({
157
+ embeds: [
158
+ {
159
+ author: {
160
+ name: guild.name,
161
+ icon_url: guild.iconURL({ dynamic: true }),
162
+ },
163
+ title: this.str("CLOSE_TICKET_TITLE"),
164
+ color: 0xff0000,
165
+ fields: reason
166
+ ? [
167
+ {
168
+ name: this.str("CLOSE_TICKET_FIELD_REASON"),
169
+ value: reason?.slice?.(0, 1024) ?? this.str("NO_REASON"),
170
+ },
171
+ ]
172
+ : undefined,
173
+ timestamp: new Date(),
174
+ footer: {
175
+ text: `${this.str("TICKET_ID")} ${channel.name.split("-")[1]}`,
176
+ },
177
+ },
178
+ ],
179
+ components: [{ type: 1, components }],
180
+ }).catch((e) => this._debug(e));
181
+ }
182
+ })
183
+ .catch((e) => this._debug(e));
184
+ }
185
+
186
+ /**
187
+ * @param {string} channelId
188
+ * @param {import("discord.js").MessageOptions} options
189
+ */
190
+ async starterMessage(channelId, options) {
191
+ let channel = this.options.client.channels.resolve(channelId);
192
+ if (!channel) {
193
+ return Promise.reject(this.str("NO_CHANNEL_FOUND")(channelId));
194
+ }
195
+ return channel
196
+ .send({
197
+ content: options?.content,
198
+ files: options?.attachments,
199
+ embeds: options?.embeds,
200
+ components: options?.components || [{ type: 1, components: [this.button()] }],
201
+ })
202
+ .then(() => console.log(`✅`));
203
+ }
204
+ };