blob: be891ec3ea0e60fc49afa281abb09be84ba7c85d [file] [log] [blame]
TheCodedProff86ba092023-01-27 17:10:07 -05001import { getCommandMentionByName } from '../../utils/getCommandDataByName.js';
PineaFan9b2ac4d2023-01-18 14:41:07 +00002import Discord, { ActionRowBuilder, ButtonBuilder, ButtonInteraction, PrivateThreadChannel, TextChannel, ButtonStyle, CategoryChannel } from "discord.js";
pineafan813bdf42022-07-24 10:39:10 +01003import client from "../../utils/client.js";
4import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
5import getEmojiByName from "../../utils/getEmojiByName.js";
PineaFan0d06edc2023-01-17 22:10:31 +00006import { preloadPage } from '../../utils/createTemporaryStorage.js';
TheCodedProf9c51a7e2023-02-27 17:11:13 -05007import { LoadingEmbed } from '../../utils/defaults.js';
pineafan813bdf42022-07-24 10:39:10 +01008
PineaFan538d3752023-01-12 21:48:23 +00009export default async function (interaction: Discord.CommandInteraction | ButtonInteraction) {
PineaFana00db1b2023-01-02 15:32:54 +000010 if (!interaction.guild) return;
PineaFan0d06edc2023-01-17 22:10:31 +000011 const config = await client.database.guilds.read(interaction.guild.id);
Skyler Grey11236ba2022-08-08 21:13:33 +010012 const { log, NucleusColors, entry, renderUser, renderChannel, renderDelta } = client.logger;
PineaFan0d06edc2023-01-17 22:10:31 +000013 const ticketChannel = config.tickets.category;
14 if (!("parent" in interaction.channel!)) {
15 return await interaction.reply({
Skyler Grey75ea9172022-08-06 10:22:23 +010016 embeds: [
17 new EmojiEmbed()
PineaFan0d06edc2023-01-17 22:10:31 +000018 .setTitle("Not a ticket")
19 .setDescription("This channel isn't a ticket, so you can't delete it.")
Skyler Grey75ea9172022-08-06 10:22:23 +010020 .setStatus("Danger")
21 .setEmoji("CONTROL.BLOCKCROSS")
PineaFan0d06edc2023-01-17 22:10:31 +000022 ], ephemeral: true
Skyler Grey75ea9172022-08-06 10:22:23 +010023 });
PineaFan0d06edc2023-01-17 22:10:31 +000024 } else if (interaction.channel!.parent!.id !== ticketChannel) {
25 return await interaction.reply({
Skyler Grey75ea9172022-08-06 10:22:23 +010026 embeds: [
27 new EmojiEmbed()
PineaFan0d06edc2023-01-17 22:10:31 +000028 .setTitle("Not a ticket")
29 .setDescription("This channel isn't a ticket, so you can't delete it.")
Skyler Grey75ea9172022-08-06 10:22:23 +010030 .setStatus("Danger")
PineaFan0d06edc2023-01-17 22:10:31 +000031 .setEmoji("CONTROL.BLOCKCROSS")
32 ], ephemeral: true
Skyler Grey75ea9172022-08-06 10:22:23 +010033 });
PineaFan0d06edc2023-01-17 22:10:31 +000034 }
35 const channel: PrivateThreadChannel | TextChannel = interaction.channel as PrivateThreadChannel | TextChannel;
36 let status: string | null = ("topic" in interaction.channel) ? interaction.channel!.topic : interaction.channel.name;
37 status = status ?? "";
38 if (status.endsWith("Archived")) { status = "Archived"; }
39 else { status = "Active"; }
40
41 const uID = channel.type === Discord.ChannelType.PrivateThread ? channel.name.split(" - ")[1] : channel.topic!.split(" ")[0];
42
43 if (status === "Archived") {
44 // Delete the ticket
45
pineafan63fc5e22022-08-04 22:04:10 +010046 const data = {
Skyler Grey75ea9172022-08-06 10:22:23 +010047 meta: {
PineaFan0d06edc2023-01-17 22:10:31 +000048 type: "ticketClosed",
49 displayName: "Ticket Closed",
pineafan813bdf42022-07-24 10:39:10 +010050 calculateType: "ticketUpdate",
51 color: NucleusColors.red,
pineafan63fc5e22022-08-04 22:04:10 +010052 emoji: "GUILD.TICKET.CLOSE",
TheCodedProf6ec331b2023-02-20 12:13:06 -050053 timestamp: Date.now()
pineafan813bdf42022-07-24 10:39:10 +010054 },
55 list: {
Skyler Grey75ea9172022-08-06 10:22:23 +010056 ticketFor: entry(
PineaFan0d06edc2023-01-17 22:10:31 +000057 uID!,
58 renderUser((await interaction.guild.members.fetch(uID!)).user)
Skyler Grey75ea9172022-08-06 10:22:23 +010059 ),
PineaFan0d06edc2023-01-17 22:10:31 +000060 closedBy: entry(interaction.member!.user.id, renderUser(interaction.member!.user as Discord.User)),
TheCodedProf6ec331b2023-02-20 12:13:06 -050061 closed: entry(Date.now(), renderDelta(Date.now())),
PineaFan0d06edc2023-01-17 22:10:31 +000062 ticketChannel: entry(channel.id, channel.name)
pineafan813bdf42022-07-24 10:39:10 +010063 },
64 hidden: {
65 guild: interaction.guild.id
66 }
pineafan63fc5e22022-08-04 22:04:10 +010067 };
pineafan813bdf42022-07-24 10:39:10 +010068 log(data);
PineaFan0d06edc2023-01-17 22:10:31 +000069
70 await channel.delete();
pineafane23c4ec2022-07-27 21:56:27 +010071 } else if (status === "Active") {
TheCodedProf9c51a7e2023-02-27 17:11:13 -050072 await interaction.reply({embeds: LoadingEmbed, fetchReply: true});
73 // Archive the ticket
74 await interaction.channel.fetch()
PineaFan0d06edc2023-01-17 22:10:31 +000075 if (channel.isThread()) {
76 channel.setName(`${channel.name.replace("Active", "Archived")}`);
77 channel.members.remove(channel.name.split(" - ")[1]!);
78 } else {
79 channel.setTopic(`${(channel.topic ?? "").replace("Active", "Archived")}`);
80 if (!channel.topic!.includes("Archived")) { channel.setTopic("0 Archived"); }
81 await channel.permissionOverwrites.delete(channel.topic!.split(" ")[0]!);
82 }
83 preloadPage(interaction.channel.id, "privacy", "2")
TheCodedProf9c51a7e2023-02-27 17:11:13 -050084 const hasPremium = await client.database.premium.hasPremium(interaction.guild.id);
85 await interaction.editReply({
Skyler Grey75ea9172022-08-06 10:22:23 +010086 embeds: [
87 new EmojiEmbed()
PineaFan0d06edc2023-01-17 22:10:31 +000088 .setTitle("Archived Ticket")
TheCodedProfcfe8e9a2023-02-26 17:28:09 -050089 .setDescription(`This ticket has been Archived. Type ${getCommandMentionByName("ticket/close")} to delete it.\n` +
90 "Creating a transcript will delete all messages in this ticket" +
TheCodedProf9c51a7e2023-02-27 17:11:13 -050091 hasPremium ?
TheCodedProff86ba092023-01-27 17:10:07 -050092 `\n\nFor more info on transcripts, check ${getCommandMentionByName("privacy")}` :
PineaFan0d06edc2023-01-17 22:10:31 +000093 "")
Skyler Grey75ea9172022-08-06 10:22:23 +010094 .setStatus("Warning")
95 .setEmoji("GUILD.TICKET.ARCHIVED")
96 ],
97 components: [
PineaFan0d06edc2023-01-17 22:10:31 +000098 new ActionRowBuilder<ButtonBuilder>().addComponents(
Skyler Grey75ea9172022-08-06 10:22:23 +010099 [
TheCodedProf21c08592022-09-13 14:14:43 -0400100 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100101 .setLabel("Delete")
TheCodedProf21c08592022-09-13 14:14:43 -0400102 .setStyle(ButtonStyle.Danger)
Skyler Grey75ea9172022-08-06 10:22:23 +0100103 .setCustomId("closeticket")
104 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
105 ].concat(
TheCodedProf9c51a7e2023-02-27 17:11:13 -0500106 hasPremium
Skyler Grey75ea9172022-08-06 10:22:23 +0100107 ? [
PineaFan0d06edc2023-01-17 22:10:31 +0000108 new ButtonBuilder()
109 .setLabel("Create Transcript and Delete")
110 .setStyle(ButtonStyle.Primary)
111 .setCustomId("createtranscript")
112 .setEmoji(getEmojiByName("CONTROL.DOWNLOAD", "id"))
113 ]
Skyler Grey75ea9172022-08-06 10:22:23 +0100114 : []
115 )
116 )
117 ]
118 });
PineaFan0d06edc2023-01-17 22:10:31 +0000119 const data = {
120 meta: {
121 type: "ticketClosed",
122 displayName: "Ticket Archived",
123 calculateType: "ticketUpdate",
124 color: NucleusColors.yellow,
125 emoji: "GUILD.TICKET.ARCHIVED",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500126 timestamp: Date.now()
PineaFan0d06edc2023-01-17 22:10:31 +0000127 },
128 list: {
129 ticketFor: entry(
130 uID!,
131 renderUser((await interaction.guild.members.fetch(uID!)).user)
132 ),
133 archivedBy: entry(interaction.member!.user.id, renderUser(interaction.member!.user as Discord.User)),
TheCodedProf6ec331b2023-02-20 12:13:06 -0500134 archived: entry(Date.now(), renderDelta(Date.now())),
PineaFan0d06edc2023-01-17 22:10:31 +0000135 ticketChannel: entry(channel.id, renderChannel(channel))
136 },
137 hidden: {
138 guild: interaction.guild.id
139 }
140 };
141 log(data);
pineafan813bdf42022-07-24 10:39:10 +0100142 }
PineaFan0d06edc2023-01-17 22:10:31 +0000143 return;
pineafan813bdf42022-07-24 10:39:10 +0100144}
145
PineaFan0d06edc2023-01-17 22:10:31 +0000146
147async function purgeByUser(member: string, guild: string) {
PineaFan9b2ac4d2023-01-18 14:41:07 +0000148 const config = await client.database.guilds.read(guild);
PineaFan0d06edc2023-01-17 22:10:31 +0000149 const fetchedGuild = await client.guilds.fetch(guild);
pineafan813bdf42022-07-24 10:39:10 +0100150 if (!config.tickets.category) return;
PineaFan9b2ac4d2023-01-18 14:41:07 +0000151 const tickets: CategoryChannel | TextChannel | undefined = fetchedGuild.channels.cache.get(config.tickets.category) as CategoryChannel | TextChannel | undefined;
pineafan813bdf42022-07-24 10:39:10 +0100152 if (!tickets) return;
pineafan63fc5e22022-08-04 22:04:10 +0100153 let deleted = 0;
PineaFan9b2ac4d2023-01-18 14:41:07 +0000154 if (tickets.type === Discord.ChannelType.GuildCategory) {
155 // For channels, the topic is the user ID, then the word Active
156 const category = tickets as Discord.CategoryChannel;
157 category.children.cache.forEach((element) => {
158 if (!(element.type === Discord.ChannelType.GuildText)) return;
159 if (!(((element as Discord.TextChannel).topic ?? "").includes(member))) return;
pineafan63fc5e22022-08-04 22:04:10 +0100160 try {
161 element.delete();
PineaFan9b2ac4d2023-01-18 14:41:07 +0000162 deleted++;
163 } catch (e) {
164 console.error(e);
Skyler Grey75ea9172022-08-06 10:22:23 +0100165 }
PineaFan9b2ac4d2023-01-18 14:41:07 +0000166 });
167 } else {
168 // For threads, the name is the users name, id, then the word Active
169 const channel = tickets as Discord.TextChannel;
170 channel.threads.cache.forEach((element: Discord.ThreadChannel) => {
171 if (!element.name.includes(member)) return;
172 try {
173 element.delete();
174 deleted++;
175 } catch (e) {
176 console.error(e);
pineafan813bdf42022-07-24 10:39:10 +0100177 }
PineaFan9b2ac4d2023-01-18 14:41:07 +0000178 });
pineafan813bdf42022-07-24 10:39:10 +0100179 }
PineaFan9b2ac4d2023-01-18 14:41:07 +0000180 if (!deleted) return
181 const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
182 const data = {
183 meta: {
184 type: "ticketPurge",
185 displayName: "Tickets Purged",
186 calculateType: "ticketUpdate",
187 color: NucleusColors.red,
188 emoji: "GUILD.TICKET.DELETE",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500189 timestamp: Date.now()
PineaFan9b2ac4d2023-01-18 14:41:07 +0000190 },
191 list: {
192 ticketFor: entry(member, renderUser(member)),
193 deletedBy: entry(null, "Member left server"),
TheCodedProf6ec331b2023-02-20 12:13:06 -0500194 deleted: entry(Date.now(), renderDelta(Date.now())),
PineaFan9b2ac4d2023-01-18 14:41:07 +0000195 ticketsDeleted: deleted
196 },
197 hidden: {
198 guild: guild
199 }
200 };
201 log(data);
pineafan813bdf42022-07-24 10:39:10 +0100202}
203
TheCodedProf9c51a7e2023-02-27 17:11:13 -0500204export { purgeByUser };