@elara-services/tickets 3.1.0 → 3.1.3
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 +20 -20
- package/README.md +86 -82
- package/index.d.ts +88 -82
- package/index.js +11 -11
- package/lib/base.js +79 -79
- package/lib/util.js +142 -142
- package/lib/v13.js +217 -217
- package/lib/v14.js +262 -262
- package/package.json +18 -2
- package/renovate.json +5 -5
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: {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
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,83 +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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
public
|
|
68
|
-
public
|
|
69
|
-
public
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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;
|
|
83
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
|
})();
|
package/lib/base.js
CHANGED
|
@@ -1,80 +1,80 @@
|
|
|
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://
|
|
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 } = 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
|
+
};
|
|
80
80
|
};
|