blob: 3159e2d32dc9f9a0b2f6c37f39d57d1c4f456622 [file] [log] [blame]
pineafan708692b2022-07-24 22:16:22 +01001import { ChannelType } from 'discord-api-types';
pineafan0bc04162022-07-25 17:22:26 +01002import Discord, { AutocompleteInteraction, CommandInteraction, Message, MessageActionRow, MessageButton, MessageSelectMenu } from "discord.js";
3import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
4import confirmationMessage from "../../utils/confirmationMessage.js";
5import getEmojiByName from "../../utils/getEmojiByName.js";
6import { SelectMenuOption, SlashCommandSubcommandBuilder } from "@discordjs/builders";
pineafan708692b2022-07-24 22:16:22 +01007import { WrappedCheck } from "jshaiku";
pineafan0bc04162022-07-25 17:22:26 +01008import client from "../../utils/client.js";
9import convertCurlyBracketString from '../../utils/convertCurlyBracketString.js';
10import {callback as statsChannelAddCallback} from "../../reflex/statsChannelUpdate.js";
pineafan708692b2022-07-24 22:16:22 +010011
12const command = (builder: SlashCommandSubcommandBuilder) =>
13 builder
pineafan0bc04162022-07-25 17:22:26 +010014 .setName("stats")
15 .setDescription("Controls channels which update when someone joins or leaves the server")
16 .addChannelOption(option => option.setName("channel").setDescription("The channel to modify"))
17 .addStringOption(option => option.setName("name").setDescription("The new channel name | Enter any text or use the extra variables like {memberCount}").setAutocomplete(true))
pineafan708692b2022-07-24 22:16:22 +010018
19const callback = async (interaction: CommandInteraction): Promise<any> => {
pineafan708692b2022-07-24 22:16:22 +010020 let m;
21 m = await interaction.reply({embeds: [new EmojiEmbed()
22 .setTitle("Loading")
23 .setStatus("Danger")
24 .setEmoji("NUCLEUS.LOADING")
25 ], ephemeral: true, fetchReply: true});
pineafan0bc04162022-07-25 17:22:26 +010026 if (interaction.options.getString("name")) {
pineafan708692b2022-07-24 22:16:22 +010027 let channel
28 try {
29 channel = interaction.options.getChannel("channel")
30 } catch {
31 return await interaction.editReply({embeds: [new EmojiEmbed()
32 .setEmoji("CHANNEL.TEXT.DELETE")
33 .setTitle("Stats Channel")
34 .setDescription("The channel you provided is not a valid channel")
35 .setStatus("Danger")
36 ]})
37 }
38 channel = channel as Discord.TextChannel
39 if (channel.guild.id != interaction.guild.id) {
40 return interaction.editReply({embeds: [new EmojiEmbed()
41 .setTitle("Stats Channel")
42 .setDescription(`You must choose a channel in this server`)
43 .setStatus("Danger")
44 .setEmoji("CHANNEL.TEXT.DELETE")
45 ]});
46 }
47 let newName = await convertCurlyBracketString(interaction.options.getString("name"), null, null, interaction.guild.name, interaction.guild.members)
48 if (interaction.options.getChannel("channel").type === "GUILD_TEXT") {
49 newName = newName.toLowerCase().replace(/[\s]/g, "-")
50 }
51 let confirmation = await new confirmationMessage(interaction)
52 .setEmoji("CHANNEL.TEXT.EDIT")
53 .setTitle("Stats Channel")
54 .setDescription(`Are you sure you want to set <#${channel.id}> to a stats channel?\n\n*Preview: ${newName}*`)
55 .setColor("Warning")
56 .setInverted(true)
57 .send(true)
58 if (confirmation.cancelled) return
59 if (confirmation.success) {
60 try {
61 let name = interaction.options.getString("name")
62 let channel = interaction.options.getChannel("channel")
63 await client.database.guilds.write(interaction.guild.id, {[`stats.${channel.id}`]: {name: name, enabled: true}});
64 const { log, NucleusColors, entry, renderUser, renderChannel } = client.logger
65 try {
66 let data = {
67 meta:{
68 type: 'statsChannelUpdate',
69 displayName: 'Stats Channel Updated',
70 calculateType: 'nucleusSettingsUpdated',
71 color: NucleusColors.yellow,
72 emoji: "CHANNEL.TEXT.EDIT",
73 timestamp: new Date().getTime()
74 },
75 list: {
76 memberId: entry(interaction.user.id, `\`${interaction.user.id}\``),
77 changedBy: entry(interaction.user.id, renderUser(interaction.user)),
78 channel: entry(channel.id, renderChannel(channel)),
79 name: entry(interaction.options.getString("name"), `\`${interaction.options.getString("name")}\``)
80 },
81 hidden: {
82 guild: interaction.guild.id
83 }
84 }
85 log(data);
86 } catch {}
87 } catch (e) {
88 console.log(e)
89 return interaction.editReply({embeds: [new EmojiEmbed()
90 .setTitle("Stats Channel")
91 .setDescription(`Something went wrong and the stats channel could not be set`)
92 .setStatus("Danger")
93 .setEmoji("CHANNEL.TEXT.DELETE")
94 ], components: []});
95 }
96 } else {
97 return interaction.editReply({embeds: [new EmojiEmbed()
98 .setTitle("Stats Channel")
99 .setDescription(`No changes were made`)
100 .setStatus("Success")
101 .setEmoji("CHANNEL.TEXT.CREATE")
102 ], components: []});
103 }
104 await statsChannelAddCallback(client, interaction.member);
pineafan0bc04162022-07-25 17:22:26 +0100105 }
106 while (true) {
107 let config = await client.database.guilds.read(interaction.guild.id);
108 let stats = config.getKey("stats")
109 let selectMenu = new MessageSelectMenu()
110 .setCustomId("remove")
111 .setMinValues(1)
112 .setMaxValues(Math.max(1, Object.keys(stats).length))
113 await interaction.editReply({embeds: [new EmojiEmbed()
pineafan708692b2022-07-24 22:16:22 +0100114 .setTitle("Stats Channel")
pineafan0bc04162022-07-25 17:22:26 +0100115 .setDescription("The following channels update when someone joins or leaves the server. You can select a channel to remove it from the list.")
pineafan708692b2022-07-24 22:16:22 +0100116 .setStatus("Success")
117 .setEmoji("CHANNEL.TEXT.CREATE")
pineafan0bc04162022-07-25 17:22:26 +0100118 ], components: [
119 new MessageActionRow().addComponents(Object.keys(stats).length ? [
120 selectMenu.setPlaceholder("Select a stats channel to remove, stopping it updating").addOptions(Object.keys(stats).map(key => ({
121 label: interaction.guild.channels.cache.get(key).name,
122 value: key,
123 description: `${stats[key].name}`,
124 })))
125 ] : [selectMenu.setPlaceholder("The server has no stats channels").setDisabled(true).setOptions([
126 {label: "*Placeholder*", value: "placeholder", description: "No stats channels"}
127 ])])
128 ]})
129 let i;
130 try {
131 i = await m.awaitMessageComponent({ time: 300000 });
132 } catch (e) { break }
133 i.deferUpdate()
134 if (i.customId === "remove") {
135 let toRemove = i.values;
136 console.log(toRemove.map(k => `stats.${k}`))
137 await client.database.guilds.write(interaction.guild.id, {}, toRemove.map(k => `stats.${k}`));
138 }
pineafan708692b2022-07-24 22:16:22 +0100139 }
pineafan0bc04162022-07-25 17:22:26 +0100140 await interaction.editReply({embeds: [new EmojiEmbed()
141 .setTitle("Stats Channel")
142 .setDescription("The following channels update when someone joins or leaves the server. You can select a channel to remove it from the list.")
143 .setStatus("Danger")
144 .setEmoji("CHANNEL.TEXT.DELETE")
145 ], components: []})
pineafan708692b2022-07-24 22:16:22 +0100146}
147
148const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
149 let member = (interaction.member as Discord.GuildMember)
150 if (!member.permissions.has("MANAGE_GUILD")) throw "You must have the Manage Server permission to use this command"
151 return true;
152}
153
154export { command };
155export { callback };
pineafan0bc04162022-07-25 17:22:26 +0100156export { check };