@elara-services/tickets 3.1.3 → 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/lib/util.js CHANGED
@@ -1,38 +1,101 @@
1
- const { AES } = require("@elara-services/packages"),
2
- { Collection, version } = require("discord.js"),
3
- Webhook = require("discord-hook");
1
+ const {
2
+ AES,
3
+ Interactions: { modal },
4
+ } = require("@elara-services/packages"),
5
+ { Collection, version } = require("discord.js"),
6
+ { DiscordWebhook: Webhook } = require("@elara-services/webhooks"),
7
+ defLang = require("../languages/en-US"),
8
+ pack = require("../package.json");
9
+
10
+ exports.getString = (name, lang = "en-US") => {
11
+ if (!lang) {
12
+ lang = "en-US";
13
+ }
14
+ let str = "[UNKNOWN STRING]";
15
+ if (!pack.languages.includes(lang)) {
16
+ lang = "en-US";
17
+ }
18
+ try {
19
+ let file = require(`../languages/${lang}.js`);
20
+ if (file[name]) {
21
+ str = file[name];
22
+ }
23
+ } catch {
24
+ if (defLang[name]) {
25
+ str = defLang[name];
26
+ }
27
+ }
28
+ return str;
29
+ };
4
30
 
5
31
  exports.code = (message, type = "d", token) => {
6
- if (!message || !type) return "";
7
- if (!token) return message;
32
+ if (!message || !type) {
33
+ return "";
34
+ }
35
+ if (!token) {
36
+ return message;
37
+ }
8
38
  try {
9
39
  const aes = new AES(token);
10
- switch (type) {
11
- case "e": return aes.encrypt(message);
12
- case "d": return aes.decrypt(message);
13
- }
40
+ return aes[type === "e" ? "encrypt" : "decrypt"](message);
14
41
  } catch {
15
42
  return message;
16
43
  }
17
- }
44
+ };
18
45
 
19
46
  exports.de = {
20
47
  user: "<:Members:860931214232125450>",
21
48
  channel: "<:Channel:841654412509839390>",
22
- transcript: "<:Log:792290922749624320>"
23
- }
49
+ transcript: "<:Log:792290922749624320>",
50
+ };
51
+
52
+ exports.perms = {
53
+ manage: {
54
+ guild: 32n,
55
+ },
56
+ members: {
57
+ ban: 4n,
58
+ },
59
+ basic: 117760n,
60
+ allows: {
61
+ support: 379969n,
62
+ ticketUser: 379968n,
63
+ client: 511040n,
64
+ },
65
+ denied: {
66
+ all: 1024n, // @everyone role
67
+ ticketUser: 131072n,
68
+ },
69
+ };
24
70
 
25
71
  exports.fetchMessages = async (channel, limit = 50, before, after, around) => {
26
72
  if (limit && limit > 100) {
27
73
  let logs = [];
28
74
  const get = async (_before, _after) => {
29
- const messages = [...(await channel.messages.fetch({ limit: 100, before: _before || undefined, after: _after || undefined }).catch(() => new Collection())).values()];
75
+ const messages = [
76
+ ...(
77
+ await channel.messages
78
+ .fetch({
79
+ limit: 100,
80
+ before: _before || undefined,
81
+ after: _after || undefined,
82
+ })
83
+ .catch(() => new Collection())
84
+ ).values(),
85
+ ];
30
86
  if (limit <= messages.length) {
31
- return (_after ? messages.slice(messages.length - limit, messages.length).map((message) => message).concat(logs) : logs.concat(messages.slice(0, limit).map((message) => message)));
87
+ return _after
88
+ ? messages
89
+ .slice(messages.length - limit, messages.length)
90
+ .map((message) => message)
91
+ .concat(logs)
92
+ : logs.concat(messages.slice(0, limit).map((message) => message));
32
93
  }
33
94
  limit -= messages.length;
34
- logs = (_after ? messages.map((message) => message).concat(logs) : logs.concat(messages.map((message) => message)));
35
- if (messages.length < 100) return logs;
95
+ logs = _after ? messages.map((message) => message).concat(logs) : logs.concat(messages.map((message) => message));
96
+ if (messages.length < 100) {
97
+ return logs;
98
+ }
36
99
  return get((_before || !_after) && messages[messages.length - 1].id, _after && messages[0].id);
37
100
  };
38
101
  return get(before, after);
@@ -40,104 +103,253 @@ exports.fetchMessages = async (channel, limit = 50, before, after, around) => {
40
103
  return [...(await channel.messages.fetch({ limit, before, after, around }).catch(() => new Collection())).values()];
41
104
  };
42
105
 
43
- exports.displayMessages = (channel, messages = [], ticketID, type) => {
106
+ exports.displayMessages = (channel, messages = [], ticketID, type, str) => {
44
107
  let users = [];
45
108
  for (const i of messages.values()) {
46
- let f = users.find(c => c.user.id === i.author.id);
47
- if (f) f.count++; else users.push({ user: i.author, count: 1 });
48
- };
49
- return [`<discord-messages>`, `<discord-message author="${type} Ticket: ${ticketID}" bot="true" verified avatar="https://cdn.discordapp.com/emojis/847397714677334066.png?v=1" role-color="#1da1f2">Total Messages: ${users.map(c => c.count).reduce((a, b) => a + b, 0).toLocaleString()}<br>${users.map(c => `<discord-mention type="role" color="${channel.guild?.members?.resolve?.(c.user.id)?.displayColor ? channel.guild?.members?.resolve?.(c.user.id)?.displayHexColor : `#ffffff`}">${c.user.tag}</discord-mention> (${c.user.id})`).join("<br>")}</discord-message></discord-messages><discord-messages>`,
50
- ...messages.map(message => {
109
+ let f = users.find((c) => c.user.id === i.author.id);
110
+ if (f) {
111
+ f.count++;
112
+ } else {
113
+ users.push({ user: i.author, count: 1 });
114
+ }
115
+ }
116
+ return [
117
+ `<discord-messages>`,
118
+ `<discord-message author="${type} ${str("TICKET")}: ${ticketID}" bot="true" verified avatar="https://cdn.discordapp.com/emojis/847397714677334066.png?v=1" role-color="#1da1f2">${str("TOTAL_MESSAGES")}: ${users
119
+ .map((c) => c.count)
120
+ .reduce((a, b) => a + b, 0)
121
+ .toLocaleString()}<br>${users.map((c) => `<discord-mention type="role" color="${channel.guild?.members?.resolve?.(c.user.id)?.displayColor ? channel.guild?.members?.resolve?.(c.user.id)?.displayHexColor : `#ffffff`}">${c.user.tag}</discord-mention> (${c.user.id})`).join("<br>")}</discord-message></discord-messages><discord-messages>`,
122
+ ...messages.map((message) => {
51
123
  let str = [
52
- `<discord-message${message.author.bot ? ` bot="true" ${message.author.flags?.has?.(version?.includes?.("14") ? 1 << 16 : "VERIFIED_BOT") ? `verified="true"` : ""}` : ""} new_timestamp="${message.createdAt.toISOString()}" author="${message.author.username}" avatar=${message.author.displayAvatarURL({ dynamic: true, format: "png" })} role-color="${channel.guild?.members?.resolve?.(message.author.id)?.displayColor ? channel.guild?.members?.resolve?.(message.author.id)?.displayHexColor : `#ffffff`}">`
124
+ `<discord-message${message.author.bot ? ` bot="true" ${message.author.flags?.has?.(version?.includes?.("14") ? 1 << 16 : "VERIFIED_BOT") ? `verified="true"` : ""}` : ""} new_timestamp="${message.createdAt.toISOString()}" author="${message.author.username}" avatar=${message.author.displayAvatarURL({
125
+ dynamic: true,
126
+ format: "png",
127
+ })} role-color="${channel.guild?.members?.resolve?.(message.author.id)?.displayColor ? channel.guild?.members?.resolve?.(message.author.id)?.displayHexColor : `#ffffff`}">`,
53
128
  ];
54
129
  if (message.content) {
55
130
  let content = message.content;
56
- if (message.mentions.users.size) for (const user of message.mentions.users.values()) content = content.replace(new RegExp(`<@!?${user.id}>`, "g"), `<discord-mention type="role" color="${message.guild?.members?.resolve?.(user?.id)?.displayHexColor ?? "#ffffff"}">${user.tag}</discord-mention>`);
57
- if (message.mentions.channels.size) for (const channel of message.mentions.channels.values()) content = content.replace(new RegExp(channel.toString(), "g"), `<discord-mention type="channel">${channel.name}</discord-mention>`);
58
- if (message.mentions.roles.size) for (const role of message.mentions.roles.values()) content = content.replace(new RegExp(role.toString(), "g"), `<discord-mention type="role" color="${role.hexColor}">${role.name}</discord-mention>`)
59
- str.push(content)
60
- };
131
+ if (message.mentions.users.size) {
132
+ for (const user of message.mentions.users.values()) {
133
+ content = content.replace(new RegExp(`<@!?${user.id}>`, "g"), `<discord-mention type="role" color="${message.guild?.members?.resolve?.(user?.id)?.displayHexColor ?? "#ffffff"}">${user.tag}</discord-mention>`);
134
+ }
135
+ }
136
+ if (message.mentions.channels.size) {
137
+ for (const channel of message.mentions.channels.values()) {
138
+ content = content.replace(new RegExp(channel.toString(), "g"), `<discord-mention type="channel">${channel.name}</discord-mention>`);
139
+ }
140
+ }
141
+ if (message.mentions.roles.size) {
142
+ for (const role of message.mentions.roles.values()) {
143
+ content = content.replace(new RegExp(role.toString(), "g"), `<discord-mention type="role" color="${role.hexColor}">${role.name}</discord-mention>`);
144
+ }
145
+ }
146
+ str.push(content);
147
+ }
61
148
  if (message.embeds?.length) {
62
149
  let arr = [`<discord-embeds slot="embeds">`];
63
150
  for (const embed of message.embeds) {
64
151
  let emb = [
65
- `<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}"` : ""}>`
152
+ `<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}"` : ""}${
153
+ embed.color ? `color="${embed.hexColor}"` : ""
154
+ }>`,
66
155
  ];
67
- if (embed.description) emb.push(`<discord-embed-description slot="description">${embed.description}</discord-embed-description>`);
156
+ if (embed.description) {
157
+ emb.push(`<discord-embed-description slot="description">${embed.description}</discord-embed-description>`);
158
+ }
68
159
  if (embed.fields?.length) {
69
- emb.push(`<discord-embed-fields slot="fields">`)
70
- for (const field of embed.fields) emb.push(`<discord-embed-field field-title="${field.name}" ${field.inline ? `inline` : ""}>${field.value}</discord-embed-field>`)
160
+ emb.push(`<discord-embed-fields slot="fields">`);
161
+ for (const field of embed.fields) {
162
+ emb.push(`<discord-embed-field field-title="${field.name}" ${field.inline ? `inline` : ""}>${field.value}</discord-embed-field>`);
163
+ }
71
164
  }
72
- arr.push(...emb, `</discord-embed>`)
165
+ arr.push(...emb, `</discord-embed>`);
73
166
  }
74
- str.push(...arr, "</discord-embeds>")
167
+ str.push(...arr, "</discord-embeds>");
168
+ }
169
+ if (message.interaction?.user) {
170
+ str.push(
171
+ `<discord-command slot="reply" command="${message.interaction.type === "APPLICATION_COMMAND" ? "/" : ""}${message.interaction.commandName}" profile="${message.interaction.user.id}" role-color="${channel.guild?.members?.resolve?.(message.interaction.user?.id)?.displayHexColor || "#fffff"}" author="${message.interaction.user.tag}" avatar="${message.interaction.user.displayAvatarURL({
172
+ dynamic: true,
173
+ })}"></discord-command>`,
174
+ );
75
175
  }
76
- if (message.interaction?.user) str.push(`<discord-command slot="reply" command="${message.interaction.type === "APPLICATION_COMMAND" ? "/" : ""}${message.interaction.commandName}" profile="${message.interaction.user.id}" role-color="${channel.guild?.members?.resolve?.(message.interaction.user?.id)?.displayHexColor || "#fffff"}" author="${message.interaction.user.tag}" avatar="${message.interaction.user.displayAvatarURL({ dynamic: true })}"></discord-command>`)
77
176
  if (message.components?.length) {
78
- let row = [
79
- `<discord-attachments slot="components">`
80
- ],
177
+ let row = [`<discord-attachments slot="components">`],
81
178
  styles = {
82
- "PRIMARY": "primary",
83
- "SECONDARY": "secondary",
84
- "SUCCESS": "success",
85
- "DANGER": "destructive",
86
- "LINK": "secondary"
87
- }
179
+ PRIMARY: "primary",
180
+ SECONDARY: "secondary",
181
+ SUCCESS: "success",
182
+ DANGER: "destructive",
183
+ LINK: "secondary",
184
+ };
88
185
  for (const components of message.components) {
89
- row.push(`<discord-action-row>`)
186
+ row.push(`<discord-action-row>`);
90
187
  for (const c of components.components) {
91
- if (c.type === "BUTTON") row.push(`<discord-button ${c.disabled ? `disabled=true` : ""} type="${styles[c.style]}" ${c.emoji?.name ? `emoji-name="${c.emoji.name}"` : ""} ${c.emoji?.id ? `emoji="https://cdn.discordapp.com/emojis/${c.emoji.id}.${c.emoji.animated ? "gif" : "png"}"` : ""} ${c.url ? `url="${c.url}"` : ""}>${c.label || ""}</discord-button>`)
188
+ if (c.type === "BUTTON") {
189
+ row.push(`<discord-button ${c.disabled ? `disabled=true` : ""} type="${styles[c.style]}" ${c.emoji?.name ? `emoji-name="${c.emoji.name}"` : ""} ${c.emoji?.id ? `emoji="https://cdn.discordapp.com/emojis/${c.emoji.id}.${c.emoji.animated ? "gif" : "png"}"` : ""} ${c.url ? `url="${c.url}"` : ""}>${c.label || ""}</discord-button>`);
190
+ }
92
191
  }
93
- row.push(`</discord-action-row>`)
192
+ row.push(`</discord-action-row>`);
94
193
  }
95
- if (row.length >= 2) str.push(...row, `</discord-attachments>`)
194
+ if (row.length >= 2) {
195
+ str.push(...row, `</discord-attachments>`);
196
+ }
197
+ }
198
+ if (message.attachments.size) {
199
+ str.push(message.attachments.map((c) => `<a href="${c.proxyURL}">${c.name}</a>`).join("<br>"));
96
200
  }
97
- if (message.attachments.size) str.push(message.attachments.map((c) => `<a href="${c.proxyURL}">${c.name}</a>`).join("<br>"))
98
- str.push(`${message.content?.length ? `<br><br>` : ""}<code style="background-color: #36393e; color: white;">ID: ${message.id}</code>`)
201
+ str.push(`${message.content?.length ? `<br><br>` : ""}<code style="background-color: #36393e; color: white;">ID: ${message.id}</code>`);
99
202
  return [...str, `</discord-message>`].join(" ");
100
203
  }),
101
- "</discord-messages>"].join(" ");
204
+ "</discord-messages>",
205
+ ].join(" ");
102
206
  };
207
+
208
+ exports.defs = {
209
+ modals: {
210
+ reason: (customId, str) =>
211
+ modal({
212
+ id: `${customId.split(":modal_submit")[0]}:modal_complete`,
213
+ title: str("REASON"),
214
+ components: [
215
+ {
216
+ type: 1,
217
+ components: [
218
+ {
219
+ type: 4,
220
+ custom_id: "reason",
221
+ label: str("REASON"),
222
+ style: 2,
223
+ min_length: 1,
224
+ max_length: 1024,
225
+ required: true,
226
+ placeholder: str("TICKET_CLOSE_PLACEHOLDER"),
227
+ },
228
+ ],
229
+ },
230
+ ],
231
+ }),
232
+ unbanReason: (customId, server, str, member, prefix) =>
233
+ modal({
234
+ id: `${prefix}:unban_modal:${customId.split(":")[1]}`,
235
+ title: `${str("UNBAN_FROM")} ${server.name}`,
236
+ components: [
237
+ {
238
+ type: 1,
239
+ components: [
240
+ {
241
+ type: 4,
242
+ label: str("REASON"),
243
+ custom_id: "reason",
244
+ style: 2,
245
+ min_length: 1,
246
+ max_length: 512,
247
+ required: true,
248
+ value: `${str("NO_REASON")} | ${str("BY")}: ${member.user.tag} (${member.id})`,
249
+ },
250
+ ],
251
+ },
252
+ ],
253
+ }),
254
+
255
+ custom: (options = { title: "", components: [] }, { prefix, str } = {}) =>
256
+ modal({
257
+ id: `${prefix}:modal_submit`,
258
+ title: options?.title || str("CREATE_TICKET"),
259
+ components:
260
+ options?.components?.length >= 1
261
+ ? options.components
262
+ : [
263
+ {
264
+ type: 1,
265
+ components: [
266
+ {
267
+ type: 4,
268
+ min_length: 10,
269
+ max_length: 4000,
270
+ custom_id: "message",
271
+ label: str("MODAL_CONTENT"),
272
+ style: 2,
273
+ placeholder: str("MODAL_CONTENT_PLACEHOLDER"),
274
+ required: true,
275
+ },
276
+ ],
277
+ },
278
+ ],
279
+ }),
280
+ },
281
+
282
+ getModalComponents: (questions) => {
283
+ return questions.length >= 1
284
+ ? questions.slice(0, 5).map((c) => ({
285
+ type: 1,
286
+ components: [
287
+ {
288
+ min_length: c.min_length || 10,
289
+ max_length: c.max_length || 4000,
290
+ type: 4,
291
+ style: c.style || 2,
292
+ label: c.label,
293
+ value: c.value,
294
+ placeholder: c.placeholder,
295
+ required: c.required,
296
+ custom_id: c.label || `random_${Math.floor(Math.random() * 10000)}`,
297
+ },
298
+ ],
299
+ }))
300
+ : [];
301
+ },
302
+ };
303
+
103
304
  /**
104
305
  * @param {object} options
105
306
  * @param {string} [options.userId]
106
307
  * @param {string} [options.token]
107
- * @param {import("discord.js").Guild} [options.guild]
308
+ * @param {import("discord.js").Guild} [options.guild]
108
309
  * @returns {boolean}
109
310
  */
110
311
  exports.hasTicket = ({ userId, guild, token, prefix } = {}) => {
111
- if (!userId || !guild || !token || !prefix || !guild?.channels?.cache?.size) return false;
112
- let channels = guild.channels.cache.filter(c => [ 0, "GUILD_TEXT" ].includes(c.type) && c.topic && exports.code(c.topic.split("ID: ")[1], "d", token) === userId && c.name?.match?.(new RegExp(prefix, "gi")));
113
- if (!channels.size) return false;
114
- return true;
312
+ if (!userId || !guild || !token || !prefix || !guild?.channels?.cache?.size) {
313
+ return false;
314
+ }
315
+ return guild.channels.cache.filter((c) => [0, "GUILD_TEXT"].includes(c.type) && c.topic && exports.code(c.topic.split("ID: ")[1], "d", token) === userId && c.name?.match?.(new RegExp(prefix, "gi"))).size ? true : false;
115
316
  };
116
317
 
117
- exports.embed = (content, { color, title, guild, footer, author } = {}) => ({
118
- title: title || "INFO", description: content,
119
- color: color || 0xFF0000, timestamp: new Date(),
318
+ exports.embed = (content, { color, title, guild, footer, author, str } = {}) => ({
319
+ title: title || str("INFO"),
320
+ description: content,
321
+ color: color || 0xff0000,
322
+ timestamp: new Date(),
120
323
  footer,
121
- author: author || { name: guild?.name ?? "Tickets", icon_url: guild?.iconURL?.({ dynamic: true }) ?? "https://cdn.discordapp.com/emojis/818757771310792704.png?v=1" }
324
+ author: author || {
325
+ name: guild?.name ?? str("TICKETS"),
326
+ icon_url: guild?.iconURL?.({ dynamic: true }) ?? "https://cdn.discordapp.com/emojis/818757771310792704.png?v=1",
327
+ },
122
328
  });
123
329
 
124
330
  exports.webhook = (options) => {
125
- const { id, token, username, avatar } = options;
126
- return new Webhook(`https://discord.com/api/webhooks/${id}/${token}`, { username, avatar_url: avatar });
331
+ const { id, token, username, avatar, threadId } = options;
332
+ return new Webhook(`https://discord.com/api/webhooks/${id}/${token}`, {
333
+ username,
334
+ avatar_url: avatar,
335
+ threadId,
336
+ });
127
337
  };
128
338
 
129
- exports.getWebhookInfo = (options) => {
339
+ exports.getWebhookInfo = (options, username = "Tickets") => {
130
340
  return {
131
341
  id: options.webhook?.id,
132
342
  token: options.webhook?.token,
133
- username: options.webhook?.username || "Tickets",
134
- avatar: options.webhook?.avatar || "https://cdn.discordapp.com/emojis/818757771310792704.png?v=1"
135
- }
343
+ threadId: options.webhook?.threadId,
344
+ username: options.webhook?.username || username,
345
+ avatar: options.webhook?.avatar || "https://cdn.discordapp.com/emojis/818757771310792704.png?v=1",
346
+ };
136
347
  };
137
348
 
138
349
  exports.getAppealServer = ({ appeals, client } = {}) => {
139
- if (!appeals?.enabled || !appeals?.mainserver?.checkIfBanned) return null;
350
+ if (!appeals?.enabled || !appeals?.mainserver?.checkIfBanned) {
351
+ return null;
352
+ }
140
353
  let server = client.guilds.resolve(appeals.mainserver?.id);
141
- if (!server?.available) return null;
142
- return server;
143
- }
354
+ return server?.available === true ? server : null;
355
+ };