blob: 507e50643b96269b130d126208380277988b6f02 [file] [log] [blame]
pineafan63fc5e22022-08-04 22:04:10 +01001import { LoadingEmbed } from "./../../utils/defaultEmbeds.js";
Skyler Grey75ea9172022-08-06 10:22:23 +01002import Discord, {
3 CommandInteraction,
4 Message,
5 MessageActionRow,
6 MessageSelectMenu
7} from "discord.js";
pineafan0bc04162022-07-25 17:22:26 +01008import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
9import confirmationMessage from "../../utils/confirmationMessage.js";
pineafanc1c18792022-08-03 21:41:36 +010010import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
pineafan708692b2022-07-24 22:16:22 +010011import { WrappedCheck } from "jshaiku";
pineafan0bc04162022-07-25 17:22:26 +010012import client from "../../utils/client.js";
pineafan63fc5e22022-08-04 22:04:10 +010013import convertCurlyBracketString from "../../utils/convertCurlyBracketString.js";
Skyler Grey75ea9172022-08-06 10:22:23 +010014import { callback as statsChannelAddCallback } from "../../reflex/statsChannelUpdate.js";
pineafan63fc5e22022-08-04 22:04:10 +010015import singleNotify from "../../utils/singleNotify.js";
pineafan708692b2022-07-24 22:16:22 +010016
17const command = (builder: SlashCommandSubcommandBuilder) =>
18 builder
pineafan63fc5e22022-08-04 22:04:10 +010019 .setName("stats")
Skyler Grey75ea9172022-08-06 10:22:23 +010020 .setDescription(
21 "Controls channels which update when someone joins or leaves the server"
22 )
23 .addChannelOption((option) =>
24 option.setName("channel").setDescription("The channel to modify")
25 )
26 .addStringOption((option) =>
27 option
28 .setName("name")
29 .setDescription(
30 "The new channel name | Enter any text or use the extra variables like {memberCount}"
31 )
32 .setAutocomplete(true)
33 );
pineafan708692b2022-07-24 22:16:22 +010034
Skyler Grey75ea9172022-08-06 10:22:23 +010035const callback = async (
36 interaction: CommandInteraction
37): Promise<void | unknown> => {
pineafan63fc5e22022-08-04 22:04:10 +010038 singleNotify("statsChannelDeleted", interaction.guild.id, true);
Skyler Grey75ea9172022-08-06 10:22:23 +010039 const m = (await interaction.reply({
40 embeds: LoadingEmbed,
41 ephemeral: true,
42 fetchReply: true
43 })) as Message;
pineafane23c4ec2022-07-27 21:56:27 +010044 let config = await client.database.guilds.read(interaction.guild.id);
pineafan0bc04162022-07-25 17:22:26 +010045 if (interaction.options.getString("name")) {
pineafane23c4ec2022-07-27 21:56:27 +010046 let channel;
47 if (Object.keys(config.getKey("stats")).length >= 25) {
Skyler Grey75ea9172022-08-06 10:22:23 +010048 return await interaction.editReply({
49 embeds: [
50 new EmojiEmbed()
51 .setEmoji("CHANNEL.TEXT.DELETE")
52 .setTitle("Stats Channel")
53 .setDescription(
54 "You can only have 25 stats channels in a server"
55 )
56 .setStatus("Danger")
57 ]
58 });
pineafane23c4ec2022-07-27 21:56:27 +010059 }
pineafan708692b2022-07-24 22:16:22 +010060 try {
pineafan63fc5e22022-08-04 22:04:10 +010061 channel = interaction.options.getChannel("channel");
pineafan708692b2022-07-24 22:16:22 +010062 } catch {
Skyler Grey75ea9172022-08-06 10:22:23 +010063 return await interaction.editReply({
64 embeds: [
65 new EmojiEmbed()
66 .setEmoji("CHANNEL.TEXT.DELETE")
67 .setTitle("Stats Channel")
68 .setDescription(
69 "The channel you provided is not a valid channel"
70 )
71 .setStatus("Danger")
72 ]
73 });
pineafan708692b2022-07-24 22:16:22 +010074 }
pineafan63fc5e22022-08-04 22:04:10 +010075 channel = channel as Discord.TextChannel;
pineafane23c4ec2022-07-27 21:56:27 +010076 if (channel.guild.id !== interaction.guild.id) {
Skyler Grey75ea9172022-08-06 10:22:23 +010077 return interaction.editReply({
78 embeds: [
79 new EmojiEmbed()
80 .setTitle("Stats Channel")
81 .setDescription(
82 "You must choose a channel in this server"
83 )
84 .setStatus("Danger")
85 .setEmoji("CHANNEL.TEXT.DELETE")
86 ]
87 });
pineafan708692b2022-07-24 22:16:22 +010088 }
Skyler Grey75ea9172022-08-06 10:22:23 +010089 let newName = await convertCurlyBracketString(
90 interaction.options.getString("name"),
91 null,
92 null,
93 interaction.guild.name,
94 interaction.guild.members
95 );
pineafan708692b2022-07-24 22:16:22 +010096 if (interaction.options.getChannel("channel").type === "GUILD_TEXT") {
pineafan63fc5e22022-08-04 22:04:10 +010097 newName = newName.toLowerCase().replace(/[\s]/g, "-");
pineafan708692b2022-07-24 22:16:22 +010098 }
pineafan63fc5e22022-08-04 22:04:10 +010099 const confirmation = await new confirmationMessage(interaction)
pineafan708692b2022-07-24 22:16:22 +0100100 .setEmoji("CHANNEL.TEXT.EDIT")
101 .setTitle("Stats Channel")
Skyler Grey75ea9172022-08-06 10:22:23 +0100102 .setDescription(
103 `Are you sure you want to set <#${
104 channel.id
105 }> to a stats channel?\n\n*Preview: ${newName.replace(
106 /^ +| $/g,
107 ""
108 )}*`
109 )
pineafan708692b2022-07-24 22:16:22 +0100110 .setColor("Warning")
111 .setInverted(true)
pineafan63fc5e22022-08-04 22:04:10 +0100112 .send(true);
113 if (confirmation.cancelled) return;
pineafan708692b2022-07-24 22:16:22 +0100114 if (confirmation.success) {
115 try {
pineafan63fc5e22022-08-04 22:04:10 +0100116 const name = interaction.options.getString("name");
117 const channel = interaction.options.getChannel("channel");
Skyler Grey75ea9172022-08-06 10:22:23 +0100118 await client.database.guilds.write(interaction.guild.id, {
119 [`stats.${channel.id}`]: { name: name, enabled: true }
120 });
121 const { log, NucleusColors, entry, renderUser, renderChannel } =
122 client.logger;
pineafan63fc5e22022-08-04 22:04:10 +0100123 const data = {
Skyler Grey75ea9172022-08-06 10:22:23 +0100124 meta: {
pineafan63fc5e22022-08-04 22:04:10 +0100125 type: "statsChannelUpdate",
126 displayName: "Stats Channel Updated",
127 calculateType: "nucleusSettingsUpdated",
128 color: NucleusColors.yellow,
129 emoji: "CHANNEL.TEXT.EDIT",
130 timestamp: new Date().getTime()
131 },
132 list: {
Skyler Grey75ea9172022-08-06 10:22:23 +0100133 memberId: entry(
134 interaction.user.id,
135 `\`${interaction.user.id}\``
136 ),
137 changedBy: entry(
138 interaction.user.id,
139 renderUser(interaction.user)
140 ),
pineafan63fc5e22022-08-04 22:04:10 +0100141 channel: entry(channel.id, renderChannel(channel)),
Skyler Grey75ea9172022-08-06 10:22:23 +0100142 name: entry(
143 interaction.options.getString("name"),
144 `\`${interaction.options.getString("name")}\``
145 )
pineafan63fc5e22022-08-04 22:04:10 +0100146 },
147 hidden: {
148 guild: interaction.guild.id
pineafan708692b2022-07-24 22:16:22 +0100149 }
pineafan63fc5e22022-08-04 22:04:10 +0100150 };
151 log(data);
pineafan708692b2022-07-24 22:16:22 +0100152 } catch (e) {
pineafan63fc5e22022-08-04 22:04:10 +0100153 console.log(e);
Skyler Grey75ea9172022-08-06 10:22:23 +0100154 return interaction.editReply({
155 embeds: [
156 new EmojiEmbed()
157 .setTitle("Stats Channel")
158 .setDescription(
159 "Something went wrong and the stats channel could not be set"
160 )
161 .setStatus("Danger")
162 .setEmoji("CHANNEL.TEXT.DELETE")
163 ],
164 components: []
165 });
pineafan708692b2022-07-24 22:16:22 +0100166 }
167 } else {
Skyler Grey75ea9172022-08-06 10:22:23 +0100168 return interaction.editReply({
169 embeds: [
170 new EmojiEmbed()
171 .setTitle("Stats Channel")
172 .setDescription("No changes were made")
173 .setStatus("Success")
174 .setEmoji("CHANNEL.TEXT.CREATE")
175 ],
176 components: []
177 });
pineafan708692b2022-07-24 22:16:22 +0100178 }
179 await statsChannelAddCallback(client, interaction.member);
pineafan0bc04162022-07-25 17:22:26 +0100180 }
181 while (true) {
pineafane23c4ec2022-07-27 21:56:27 +0100182 config = await client.database.guilds.read(interaction.guild.id);
pineafan63fc5e22022-08-04 22:04:10 +0100183 const stats = config.getKey("stats");
184 const selectMenu = new MessageSelectMenu()
pineafan0bc04162022-07-25 17:22:26 +0100185 .setCustomId("remove")
186 .setMinValues(1)
pineafan63fc5e22022-08-04 22:04:10 +0100187 .setMaxValues(Math.max(1, Object.keys(stats).length));
Skyler Grey75ea9172022-08-06 10:22:23 +0100188 await interaction.editReply({
189 embeds: [
190 new EmojiEmbed()
191 .setTitle("Stats Channel")
192 .setDescription(
193 "The following channels update when someone joins or leaves the server. You can select a channel to remove it from the list."
194 )
195 .setStatus("Success")
196 .setEmoji("CHANNEL.TEXT.CREATE")
197 ],
198 components: [
199 new MessageActionRow().addComponents(
200 Object.keys(stats).length
201 ? [
202 selectMenu
203 .setPlaceholder(
204 "Select a stats channel to remove, stopping it updating"
205 )
206 .addOptions(
207 Object.keys(stats).map((key) => ({
208 label: interaction.guild.channels.cache.get(
209 key
210 ).name,
211 value: key,
212 description: `${stats[key].name}`
213 }))
214 )
215 ]
216 : [
217 selectMenu
218 .setPlaceholder(
219 "The server has no stats channels"
220 )
221 .setDisabled(true)
222 .setOptions([
223 {
224 label: "*Placeholder*",
225 value: "placeholder",
226 description: "No stats channels"
227 }
228 ])
229 ]
230 )
231 ]
232 });
pineafan0bc04162022-07-25 17:22:26 +0100233 let i;
234 try {
235 i = await m.awaitMessageComponent({ time: 300000 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100236 } catch (e) {
237 break;
238 }
pineafan63fc5e22022-08-04 22:04:10 +0100239 i.deferUpdate();
pineafan0bc04162022-07-25 17:22:26 +0100240 if (i.customId === "remove") {
pineafan63fc5e22022-08-04 22:04:10 +0100241 const toRemove = i.values;
Skyler Grey75ea9172022-08-06 10:22:23 +0100242 await client.database.guilds.write(
243 interaction.guild.id,
244 null,
245 toRemove.map((k) => `stats.${k}`)
246 );
pineafan0bc04162022-07-25 17:22:26 +0100247 }
pineafan708692b2022-07-24 22:16:22 +0100248 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100249 await interaction.editReply({
250 embeds: [m.embeds[0]!.setFooter({ text: "Message closed" })],
251 components: []
252 });
pineafan63fc5e22022-08-04 22:04:10 +0100253};
pineafan708692b2022-07-24 22:16:22 +0100254
Skyler Grey75ea9172022-08-06 10:22:23 +0100255const check = (
256 interaction: CommandInteraction,
257 _defaultCheck: WrappedCheck
258) => {
259 const member = interaction.member as Discord.GuildMember;
260 if (!member.permissions.has("MANAGE_CHANNELS"))
261 throw "You must have the *Manage Channels* permission to use this command";
pineafan708692b2022-07-24 22:16:22 +0100262 return true;
pineafan63fc5e22022-08-04 22:04:10 +0100263};
pineafan708692b2022-07-24 22:16:22 +0100264
265export { command };
266export { callback };
Skyler Grey75ea9172022-08-06 10:22:23 +0100267export { check };