@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 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,26 +1,28 @@
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 type { Client, MessageOptions, GuildMember, Guild, User, TextBasedChannel, Message, Interaction } from "discord.js";
4
+
5
+ export type Langs = "en-US";
5
6
 
6
7
  export interface TicketOptions {
7
8
  client: Client;
8
9
  prefix: string;
9
- debug?: boolean;
10
10
  encryptToken: string;
11
+ lang?: Langs;
12
+ debug?: boolean;
11
13
  appeals?: {
12
- enabled: boolean;
14
+ enabled?: boolean;
13
15
  sendBanResults?: boolean;
14
16
  mainserver: {
15
17
  id: string;
16
- checkIfBanned: boolean;
18
+ checkIfBanned?: boolean;
17
19
  };
18
20
  embeds?: {
19
21
  not_banned: Pick<MessageOptions, "content" | "embeds" | "components">
20
22
  }
21
23
  };
22
24
  modal?: {
23
- enabled: boolean;
25
+ enabled?: boolean;
24
26
  title?: string;
25
27
  questions?: {
26
28
  label: string;
@@ -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,13 @@
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 (["13", "14"].includes(major)) {
10
+ return require(`./lib/v${major}`);
11
+ }
11
12
  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
- })();
13
+ })();
@@ -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,191 @@
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 },
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
+
25
+ get prefix() {
26
+ return `system:ticket:${this.options.prefix}`;
27
+ }
28
+
29
+ get webhookOptions() {
30
+ return getWebhookInfo(this.options, this.str("TICKETS"));
31
+ }
32
+
13
33
  get getSupportIds() {
14
34
  return {
15
35
  roles: this.options.support?.roles || [],
16
- users: this.options.support?.users || []
36
+ users: this.options.support?.users || [],
37
+ };
38
+ }
39
+
40
+ /**
41
+ *
42
+ * @param {import("discord.js").Interaction} interation
43
+ * @param {Tickets[]} tickets
44
+ * @returns
45
+ */
46
+ runMultiple(interation, tickets = []) {
47
+ if (!interation || !is.array(tickets)) {
48
+ return this;
49
+ }
50
+ for (const ticket of tickets) {
51
+ ticket.run(interation);
17
52
  }
53
+ return this;
54
+ }
55
+
56
+ /**
57
+ * @param {keyof typeof import("../languages/en-US")} name
58
+ */
59
+ str(name) {
60
+ return getString(name, this.options?.lang || "en-US");
18
61
  }
19
- str(name) { return getString(name, this.options?.lang || "en-US"); }
20
-
62
+
21
63
  /** @private */
22
64
  _debug(...args) {
23
- if (this.options?.debug) console.log(...args);
65
+ if (this.options?.debug) {
66
+ console.log(...args);
67
+ }
24
68
  return null;
25
69
  }
26
70
 
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
-
71
+ button(
72
+ options = {
73
+ style: 3,
74
+ label: this.str("CREATE_TICKET"),
75
+ emoji: { name: "📩" },
76
+ },
77
+ ) {
78
+ return button({
79
+ id: options?.id || this.prefix,
80
+ style: options.style || 3,
81
+ title: options.label,
82
+ emoji: options.emoji,
83
+ });
84
+ }
40
85
  async closeTicket({ member, messages, channel, guild, user, reason } = {}) {
41
- const { id, token, username, avatar: avatarURL } = this.webhookOptions;
42
- if (!id || !token) return;
86
+ const { id, token, username, avatar: avatarURL, threadId } = this.webhookOptions;
87
+ if (!id || !token) {
88
+ return;
89
+ }
43
90
  let embeds = [
44
91
  {
45
- author: { name: guild.name, icon_url: guild.iconURL({ dynamic: true }) },
92
+ author: {
93
+ name: guild.name,
94
+ icon_url: guild.iconURL({ dynamic: true }),
95
+ },
46
96
  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,
97
+ 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})`,
98
+ color: 0xff0000,
99
+ fields: reason
100
+ ? [
101
+ {
102
+ name: this.str("CLOSE_TICKET_FIELD_REASON"),
103
+ value: reason?.slice?.(0, 1024) ?? this.str("NO_REASON"),
104
+ },
105
+ ]
106
+ : undefined,
50
107
  timestamp: new Date(),
51
- footer: { text: `${this.str("TICKET_ID")} ${channel.name.split("-")[1]}` },
52
- }
108
+ footer: {
109
+ text: `${this.str("TICKET_ID")} ${channel.name.split("-")[1]}`,
110
+ },
111
+ },
53
112
  ];
54
113
  new WebhookClient({ id, token })
55
114
  .send({
56
- username, avatarURL,
115
+ username,
116
+ avatarURL,
57
117
  embeds,
58
- files: [{ name: "transcript.txt", attachment: Buffer.from(displayMessages(channel, messages.reverse(), channel.name.split("-")[1], this.options.prefix)) }]
118
+ threadId,
119
+ files: [
120
+ {
121
+ name: `${this.str("TRANSCRIPT")}.txt`,
122
+ attachment: Buffer.from(displayMessages(channel, messages.reverse(), channel.name.split("-")[1], this.options.prefix, this.str)),
123
+ },
124
+ ],
59
125
  })
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})`
126
+ .then((m) => {
127
+ let components = [
128
+ {
129
+ type: 2,
130
+ style: 5,
131
+ label: this.str("TRANSCRIPT"),
132
+ emoji: { id: "792290922749624320" },
133
+ url: `https://view.elara.workers.dev/tickets?url=${Array.isArray(m.attachments) ? m.attachments?.[0]?.url : m.attachments?.first?.()?.url ?? "URL_NOT_FOUND"}`,
134
+ },
135
+ ];
136
+ embeds[0].description += `\n${de.transcript} ${this.str("TRANSCRIPT")}: [${this.str("VIEW_HERE")}](${components[0].url})`;
63
137
  webhook(this.webhookOptions)
64
138
  .embeds(embeds)
65
139
  .button({ type: 1, components })
66
140
  .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
- };
141
+ .catch((e) => this._debug(e));
142
+ if (user) {
143
+ user.send({
144
+ embeds: [
145
+ {
146
+ author: {
147
+ name: guild.name,
148
+ icon_url: guild.iconURL({ dynamic: true }),
149
+ },
150
+ title: this.str("CLOSE_TICKET_TITLE"),
151
+ color: 0xff0000,
152
+ fields: reason
153
+ ? [
154
+ {
155
+ name: this.str("CLOSE_TICKET_FIELD_REASON"),
156
+ value: reason?.slice?.(0, 1024) ?? this.str("NO_REASON"),
157
+ },
158
+ ]
159
+ : undefined,
160
+ timestamp: new Date(),
161
+ footer: {
162
+ text: `${this.str("TICKET_ID")} ${channel.name.split("-")[1]}`,
163
+ },
164
+ },
165
+ ],
166
+ components: [{ type: 1, components }],
167
+ }).catch((e) => this._debug(e));
168
+ }
169
+ })
170
+ .catch((e) => this._debug(e));
171
+ }
172
+
173
+ /**
174
+ * @param {string} channelId
175
+ * @param {import("discord.js").MessageOptions} options
176
+ */
177
+ async starterMessage(channelId, options) {
178
+ let channel = this.options.client.channels.resolve(channelId);
179
+ if (!channel) {
180
+ return Promise.reject(this.str("NO_CHANNEL_FOUND")(channelId));
181
+ }
182
+ return channel
183
+ .send({
184
+ content: options?.content,
185
+ files: options?.attachments,
186
+ embeds: options?.embeds,
187
+ components: options?.components || [{ type: 1, components: [this.button()] }],
188
+ })
189
+ .then(() => console.log(`✅`));
190
+ }
191
+ };