blob: af5ac0dc00c6a4007de630bbdaba28315c638c56 [file] [log] [blame]
pineafanad54d752022-04-18 19:01:43 +01001import Discord, { MessageActionRow, MessageButton } from "discord.js";
2import { tickets, toHexArray } from "../../utils/calculate.js";
pineafan6702cef2022-06-13 17:52:37 +01003import client from "../../utils/client.js";
pineafanad54d752022-04-18 19:01:43 +01004import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
5import getEmojiByName from "../../utils/getEmojiByName.js";
6
7function capitalize(s: string) {
8 s = s.replace(/([A-Z])/g, ' $1');
9 return s.length < 3 ? s.toUpperCase() : s[0].toUpperCase() + s.slice(1).toLowerCase();
10}
11
12export default async function (interaction) {
13 // @ts-ignore
14 const { log, NucleusColors, entry, renderUser, renderChannel, renderDelta } = interaction.client.logger
15
pineafan6702cef2022-06-13 17:52:37 +010016 let config = await client.database.read(interaction.guild.id);
pineafanad54d752022-04-18 19:01:43 +010017 if (!config.tickets.enabled || !config.tickets.category) {
18 return await interaction.reply({embeds: [new generateEmojiEmbed()
19 .setTitle("Tickets are disabled")
20 .setDescription("Please enable tickets in the configuration to use this command.")
21 .setStatus("Danger")
22 .setEmoji("CONTROL.BLOCKCROSS")
23 ], ephemeral: true});
24 }
25 let category = interaction.guild.channels.cache.get(config.tickets.category) as Discord.CategoryChannel;
26 let count = 0;
27 category.children.forEach(element => {
28 if (!(element.type == "GUILD_TEXT")) return;
29 if ((element as Discord.TextChannel).topic.includes(`${interaction.member.user.id}`)) {
30 if ((element as Discord.TextChannel).topic.endsWith("Active")) {
31 count++;
32 }
33 }
34 });
35 if (count >= config.tickets.maxTickets) {
36 return await interaction.reply({embeds: [new generateEmojiEmbed()
37 .setTitle("Create Ticket")
38 .setDescription(`You have reached the maximum amount of tickets (${config.tickets.maxTickets}). Please close one of your active tickets before creating a new one.`)
39 .setStatus("Danger")
40 .setEmoji("CONTROL.BLOCKCROSS")
41 ], ephemeral: true});
42 }
43 let ticketTypes;
44 let custom = false
45 if (config.tickets.customTypes) { ticketTypes = config.tickets.customTypes; custom = true }
46 else if (config.tickets.types) ticketTypes = toHexArray(config.tickets.types, tickets);
47 else ticketTypes = [];
48 let chosenType;
49 let splitFormattedTicketTypes = [];
50 if (ticketTypes.length > 0) {
51 let formattedTicketTypes = [];
52 formattedTicketTypes = ticketTypes.map(type => {
53 if (custom) {
54 return new MessageButton()
55 .setLabel(type)
56 .setStyle("PRIMARY")
57 .setCustomId(type)
58 } else {
59 return new MessageButton()
60 .setLabel(capitalize(type))
61 .setStyle("PRIMARY")
62 .setCustomId(type)
63 .setEmoji(getEmojiByName(("TICKETS." + type.toString().toUpperCase()), "id"));
64 }
65 });
pineafan6702cef2022-06-13 17:52:37 +010066 for (let i = 0; i < formattedTicketTypes.length; i += 5) {
67 splitFormattedTicketTypes.push(new MessageActionRow().addComponents(formattedTicketTypes.slice(i, i + 5)));
pineafanad54d752022-04-18 19:01:43 +010068 }
69 let m = await interaction.reply({embeds: [new generateEmojiEmbed()
70 .setTitle("Create Ticket")
71 .setDescription("Select a ticket type")
72 .setStatus("Success")
73 .setEmoji("GUILD.TICKET.OPEN")
74 ], ephemeral: true, fetchReply: true, components: splitFormattedTicketTypes});
75 let component;
76 try {
pineafanc6158ab2022-06-17 16:34:07 +010077 component = await (m as Discord.Message).awaitMessageComponent({time: 300000});
pineafanad54d752022-04-18 19:01:43 +010078 } catch (e) {
79 return;
80 }
81 chosenType = component.customId;
82 splitFormattedTicketTypes = [];
83 formattedTicketTypes = [];
84 formattedTicketTypes = ticketTypes.map(type => {
85 if (custom) {
86 return new MessageButton()
87 .setLabel(type)
88 .setStyle(chosenType == type ? "SUCCESS" : "SECONDARY")
89 .setCustomId(type)
90 .setDisabled(true)
91 } else {
92 return new MessageButton()
93 .setLabel(capitalize(type))
94 .setStyle(chosenType == type ? "SUCCESS" : "SECONDARY")
95 .setCustomId(type)
96 .setEmoji(getEmojiByName(("TICKETS." + type.toString().toUpperCase()), "id"))
97 .setDisabled(true)
98 }
99 });
pineafan6702cef2022-06-13 17:52:37 +0100100 for (let i = 0; i < formattedTicketTypes.length; i += 5) {
101 splitFormattedTicketTypes.push(new MessageActionRow().addComponents(formattedTicketTypes.slice(i, i + 5)));
pineafanad54d752022-04-18 19:01:43 +0100102 }
103 component.update({embeds: [new generateEmojiEmbed()
104 .setTitle("Create Ticket")
105 .setDescription("Select a ticket type")
106 .setStatus("Success")
107 .setEmoji("GUILD.TICKET.OPEN")
108 ], components: splitFormattedTicketTypes});
109 } else {
110 chosenType = null
111 await interaction.reply({embeds: [new generateEmojiEmbed()
112 .setTitle("Create Ticket")
113 .setEmoji("GUILD.TICKET.OPEN")
114 ], ephemeral: true, components: splitFormattedTicketTypes})
115 }
116 let overwrites = [{
117 id: interaction.member,
118 allow: ["VIEW_CHANNEL", "SEND_MESSAGES", "ATTACH_FILES", "ADD_REACTIONS", "READ_MESSAGE_HISTORY"],
119 type: "member"
120 }] as Discord.OverwriteResolvable[];
pineafan5be5eca2022-05-19 21:37:08 +0100121 overwrites.push({
122 id: interaction.guild.roles.everyone,
123 deny: ["VIEW_CHANNEL"],
124 type: "role"
125 })
pineafanad54d752022-04-18 19:01:43 +0100126 if (config.tickets.supportRole != null) {
127 overwrites.push({
128 id: interaction.guild.roles.cache.get(config.tickets.supportRole),
129 allow: ["VIEW_CHANNEL", "SEND_MESSAGES", "ATTACH_FILES", "ADD_REACTIONS", "READ_MESSAGE_HISTORY"],
130 type: "role"
131 })
132 }
133
134 let c;
135 try {
136 c = await interaction.guild.channels.create(interaction.member.user.username, {
137 type: "GUILD_TEXT",
138 topic: `${interaction.member.user.id} Active`,
139 parent: config.tickets.category,
140 nsfw: false,
141 permissionOverwrites: (overwrites as Discord.OverwriteResolvable[]),
142 reason: "Creating ticket"
143 })
144 } catch (e) {
145 return await interaction.editReply({embeds: [new generateEmojiEmbed()
146 .setTitle("Create Ticket")
147 .setDescription("Failed to create ticket")
148 .setStatus("Danger")
149 .setEmoji("CONTROL.BLOCKCROSS")
150 ]});
151 }
152 try {
153 await c.send(
154 {
155 content: (`<@${interaction.member.user.id}>` + (config.tickets.supportRole != null ? ` • <@&${config.tickets.supportRole}>` : "")),
156 allowedMentions: {
157 users: [(interaction.member as Discord.GuildMember).id],
158 roles: (config.tickets.supportRole != null ? [config.tickets.supportRole] : [])
159 }
160 }
161 )
162 let content = interaction.options ? interaction.options.getString("message") || "" : "";
163 if (content) content = `**Message:**\n> ${content}\n`;
164 let emoji = custom ? "" : getEmojiByName("TICKETS." + chosenType.toUpperCase());
165 await c.send({ embeds: [new generateEmojiEmbed()
166 .setTitle("New Ticket")
167 .setDescription(
168 `Ticket created by <@${interaction.member.user.id}>\n` +
169 `**Support type:** ${chosenType != null ? (emoji) + " " + capitalize(chosenType) : "General"}\n` +
170 `**Ticket ID:** \`${c.id}\`\n${content}\n` +
171 `Type \`/ticket close\` to archive this ticket.`,
172 )
173 .setStatus("Success")
174 .setEmoji("GUILD.TICKET.OPEN")
175 ], components: [new MessageActionRow().addComponents([new MessageButton()
176 .setLabel("Close")
177 .setStyle("DANGER")
178 .setCustomId("closeticket")
179 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
180 ])]})
181 let data = {
182 meta:{
183 type: 'ticketCreate',
184 displayName: 'Ticket Created',
185 calculateType: true,
186 color: NucleusColors.green,
187 emoji: 'GUILD.TICKET.OPEN',
188 timestamp: new Date().getTime()
189 },
190 list: {
191 ticketFor: entry(interaction.member.user.id, renderUser(interaction.member.user)),
192 created: entry(new Date().getTime(), renderDelta(new Date().getTime())),
193 ticketChannel: entry(c.id, renderChannel(c)),
194 },
195 hidden: {
196 guild: interaction.guild.id
197 }
198 }
199 log(data, interaction.client);
200 } catch (e) { console.log(e)}
201 await interaction.editReply({embeds: [new generateEmojiEmbed()
202 .setTitle("Create Ticket")
203 .setDescription(`Ticket created. You can view it here: <#${c.id}>`)
204 .setStatus("Success")
205 .setEmoji("GUILD.TICKET.OPEN")
206 ], components: splitFormattedTicketTypes});
207}