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