blob: d86c14aa71116a61d11782b65d76bfb32848c1bd [file] [log] [blame]
TheCodedProff86ba092023-01-27 17:10:07 -05001import { getCommandMentionByName } from './../utils/getCommandDataByName.js';
TheCodedProf21c08592022-09-13 14:14:43 -04002import Discord, { ActionRowBuilder, ButtonBuilder, OverwriteType, ChannelType, ButtonStyle } from "discord.js";
pineafan63fc5e22022-08-04 22:04:10 +01003import EmojiEmbed from "../utils/generateEmojiEmbed.js";
pineafan813bdf42022-07-24 10:39:10 +01004import getEmojiByName from "../utils/getEmojiByName.js";
5import client from "../utils/client.js";
6
Skyler Grey75ea9172022-08-06 10:22:23 +01007export async function create(
8 guild: Discord.Guild,
PineaFane6ba7882023-01-18 20:41:16 +00009 user: Discord.User,
Skyler Grey75ea9172022-08-06 10:22:23 +010010 createdBy: Discord.User,
pineafan62ce1922022-08-25 20:34:45 +010011 reason: string | null,
Skyler Grey75ea9172022-08-06 10:22:23 +010012 customReason?: string
13) {
pineafan63fc5e22022-08-04 22:04:10 +010014 const config = await client.database.guilds.read(guild.id);
Skyler Grey11236ba2022-08-08 21:13:33 +010015 const { log, NucleusColors, entry, renderUser, renderChannel, renderDelta } = client.logger;
TheCodedProf21c08592022-09-13 14:14:43 -040016 const overwrites = [{
PineaFane6ba7882023-01-18 20:41:16 +000017 id: user,
TheCodedProf21c08592022-09-13 14:14:43 -040018 allow: ["ViewChannel", "SendMessages", "AttachFiles", "AddReactions", "ReadMessageHistory"],
19 type: OverwriteType.Member
20 }] as unknown as Discord.OverwriteResolvable[];
pineafan813bdf42022-07-24 10:39:10 +010021 overwrites.push({
22 id: guild.roles.everyone,
TheCodedProf21c08592022-09-13 14:14:43 -040023 deny: ["ViewChannel"],
24 type: OverwriteType.Role
pineafan63fc5e22022-08-04 22:04:10 +010025 });
pineafane23c4ec2022-07-27 21:56:27 +010026 if (config.tickets.supportRole !== null) {
pineafan813bdf42022-07-24 10:39:10 +010027 overwrites.push({
pineafan62ce1922022-08-25 20:34:45 +010028 id: guild.roles.cache.get(config.tickets.supportRole)!,
TheCodedProf21c08592022-09-13 14:14:43 -040029 allow: ["ViewChannel", "SendMessages", "AttachFiles", "AddReactions", "ReadMessageHistory"],
30 type: OverwriteType.Role
pineafan63fc5e22022-08-04 22:04:10 +010031 });
pineafan813bdf42022-07-24 10:39:10 +010032 }
PineaFane6ba7882023-01-18 20:41:16 +000033 const targetChannel: Discord.CategoryChannel | Discord.TextChannel = (await guild.channels.fetch(config.tickets.category!))! as Discord.CategoryChannel | Discord.TextChannel;
pineafan813bdf42022-07-24 10:39:10 +010034
PineaFane6ba7882023-01-18 20:41:16 +000035 let c: Discord.TextChannel | Discord.PrivateThreadChannel;
36 if (targetChannel.type === Discord.ChannelType.GuildCategory) {
37 const overwrites = [
38 {
39 id: user,
40 allow: ["ViewChannel", "SendMessages", "AttachFiles", "AddReactions", "ReadMessageHistory"],
41 type: Discord.OverwriteType.Member
pineafan813bdf42022-07-24 10:39:10 +010042 }
PineaFane6ba7882023-01-18 20:41:16 +000043 ] as Discord.OverwriteResolvable[];
44 overwrites.push({
45 id: guild.roles.everyone,
46 deny: ["ViewChannel"],
47 type: Discord.OverwriteType.Role
Skyler Grey75ea9172022-08-06 10:22:23 +010048 });
PineaFane6ba7882023-01-18 20:41:16 +000049 if (config.tickets.supportRole !== null) {
50 overwrites.push({
51 id: guild.roles.cache.get(config.tickets.supportRole)!,
52 allow: ["ViewChannel", "SendMessages", "AttachFiles", "AddReactions", "ReadMessageHistory"],
53 type: Discord.OverwriteType.Role
54 });
55 }
56
57 try {
58 c = await guild.channels.create({
59 name: `${user.username.toLowerCase()}`,
60 type: ChannelType.GuildText,
61 topic: `${user.id} Active`,
62 parent: config.tickets.category,
63 nsfw: false,
64 permissionOverwrites: overwrites as Discord.OverwriteResolvable[],
65 reason: "Creating ticket"
66 });
67 } catch (e) {
68 return null;
69 }
70 try {
71 await c.send({
72 content:
73 `<@${user.id}>` +
74 (config.tickets.supportRole !== null ? ` • <@&${config.tickets.supportRole}>` : ""),
75 allowedMentions: {
76 users: [user.id],
77 roles: config.tickets.supportRole !== null ? [config.tickets.supportRole] : []
78 }
79 });
80 await c.send({
81 embeds: [
82 new EmojiEmbed()
83 .setTitle("New Ticket")
84 .setDescription(
85 "Ticket created by a Moderator\n" +
Skyler Grey11236ba2022-08-08 21:13:33 +010086 `**Support type:** ${customReason ? customReason : "Appeal submission"}\n` +
87 (reason !== null ? `**Reason:**\n> ${reason}\n` : "") +
Skyler Grey75ea9172022-08-06 10:22:23 +010088 `**Ticket ID:** \`${c.id}\`\n` +
TheCodedProff86ba092023-01-27 17:10:07 -050089 `Type ${getCommandMentionByName("ticket/close")} to close this ticket.`
PineaFane6ba7882023-01-18 20:41:16 +000090 )
91 .setStatus("Success")
92 .setEmoji("GUILD.TICKET.OPEN")
93 ],
94 components: [
95 new ActionRowBuilder<ButtonBuilder>().addComponents([
96 new ButtonBuilder()
97 .setLabel("Close")
98 .setStyle(ButtonStyle.Danger)
99 .setCustomId("closeticket")
100 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
101 ])
102 ]
103 });
104 } catch (e) {
105 return null;
106 }
107 } else {
108 c = await targetChannel.threads.create({name: `${user.username} - ${user.id} - Active`,
109 autoArchiveDuration: 60 * 24 * 7,
110 type: Discord.ChannelType.PrivateThread,
111 reason: "Creating ticket"
112 }) as Discord.PrivateThreadChannel;
113 c.members.add(user.id);
114 c.members.add(createdBy.id);
115 try {
116 await c.send({
117 content:
118 `<@${user.id}>` +
119 (config.tickets.supportRole !== null ? ` • <@&${config.tickets.supportRole}>` : ""),
120 allowedMentions: {
121 users: [user.id],
122 roles: config.tickets.supportRole !== null ? [config.tickets.supportRole] : []
123 }
124 });
125 await c.send({
126 embeds: [
127 new EmojiEmbed()
128 .setTitle("New Ticket")
129 .setDescription(
130 "Ticket created by a Moderator\n" +
131 `**Support type:** ${customReason ? customReason : "Appeal submission"}\n` +
132 (reason !== null ? `**Reason:**\n> ${reason}\n` : "") +
133 `**Ticket ID:** \`${c.id}\`\n` +
TheCodedProff86ba092023-01-27 17:10:07 -0500134 `Type ${getCommandMentionByName("ticket/close")} to close this ticket.`
PineaFane6ba7882023-01-18 20:41:16 +0000135 )
136 .setStatus("Success")
137 .setEmoji("GUILD.TICKET.OPEN")
138 ],
139 components: [
140 new ActionRowBuilder<ButtonBuilder>().addComponents([
141 new ButtonBuilder()
142 .setLabel("Close")
143 .setStyle(ButtonStyle.Danger)
144 .setCustomId("closeticket")
145 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
146 ])
147 ]
148 });
149 } catch (e) {
150 return null;
151 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100152 }
PineaFane6ba7882023-01-18 20:41:16 +0000153 const data = {
154 meta: {
155 type: "ticketCreate",
156 displayName: "Ticket Created",
157 calculateType: "ticketUpdate",
158 color: NucleusColors.green,
159 emoji: "GUILD.TICKET.OPEN",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500160 timestamp: Date.now()
PineaFane6ba7882023-01-18 20:41:16 +0000161 },
162 list: {
163 ticketFor: entry(user.id, renderUser(user)),
164 createdBy: entry(createdBy.id, renderUser(createdBy)),
TheCodedProf6ec331b2023-02-20 12:13:06 -0500165 created: entry((Date.now()).toString(), renderDelta(Date.now())),
PineaFane6ba7882023-01-18 20:41:16 +0000166 ticketChannel: entry(c.id, renderChannel(c))
167 },
168 hidden: {
169 guild: guild.id
170 }
171 };
172 log(data);
pineafan63fc5e22022-08-04 22:04:10 +0100173 return c.id;
pineafan813bdf42022-07-24 10:39:10 +0100174}
175
176export async function areTicketsEnabled(guild: string) {
pineafan63fc5e22022-08-04 22:04:10 +0100177 const config = await client.database.guilds.read(guild);
pineafan813bdf42022-07-24 10:39:10 +0100178 return config.tickets.enabled;
Skyler Grey75ea9172022-08-06 10:22:23 +0100179}