From 0bc0416355647918dfa3eb7715236c4f86ab323b Mon Sep 17 00:00:00 2001 From: pineafan Date: Mon, 25 Jul 2022 17:22:26 +0100 Subject: [PATCH] Added options for stats channels, moderation command buttons and fixed the updating of stats channels --- TODO.json | 57 +------ src/commands/settings/commands.ts | 144 ++++++++++++++++++ src/commands/settings/logs/ignore.ts | 144 ------------------ .../settings/{stats/set.ts => stats.ts} | 72 ++++++--- src/commands/settings/stats/_meta.ts | 4 - src/commands/settings/stats/remove.ts | 120 --------------- src/commands/tags/delete.ts | 3 +- src/config/default.json | 29 +--- src/config/emojis.json | 20 +-- src/events/interactionCreate.ts | 2 +- src/events/memberJoin.ts | 2 +- src/reflex/statsChannelUpdate.ts | 1 - src/utils/database.ts | 16 +- 13 files changed, 225 insertions(+), 389 deletions(-) create mode 100644 src/commands/settings/commands.ts delete mode 100644 src/commands/settings/logs/ignore.ts rename src/commands/settings/{stats/set.ts => stats.ts} (62%) delete mode 100644 src/commands/settings/stats/_meta.ts delete mode 100644 src/commands/settings/stats/remove.ts diff --git a/TODO.json b/TODO.json index d95afcb..44bb7e6 100644 --- a/TODO.json +++ b/TODO.json @@ -2,12 +2,7 @@ "logging": { "logs": { "enabled": true, - "toLog": "3fffff", - "ignore": { - "users": [], - "roles": [], - "channels": [] - } + "toLog": "3fffff" } }, "filters": { @@ -19,16 +14,8 @@ "wordFilter": { "enabled": true, "words": { - "strict": [ - "meat", - "noon" - ], + "strict": [], "loose": [] - }, - "allowed": { - "users": [], - "roles": [], - "channels": [] } }, "invite": { @@ -42,51 +29,13 @@ "pings": { "mass": 5, "everyone": true, - "roles": true, - "allowed": { - "roles": [], - "rolesToMention": [], - "users": [], - "channels": [] - } - } - }, - "moderation": { - "mute": { - "timeout": true, - "role": "934941408849186856", - "text": null, - "link": null - }, - "kick": { - "text": null, - "link": null - }, - "ban": { - "text": null, - "link": null - }, - "softban": { - "text": null, - "link": null - }, - "warn": { - "text": "Test", - "link": "https://google.com" - }, - "role": { - "role": null + "roles": true } }, "roleMenu": [], - "stats": [], "tracks": [], "welcome": { "enabled": false, - "verificationRequired": { - "message": null, - "role": null - }, "welcomeRole": null, "channel": null, "message": null diff --git a/src/commands/settings/commands.ts b/src/commands/settings/commands.ts new file mode 100644 index 0000000..df2cdb4 --- /dev/null +++ b/src/commands/settings/commands.ts @@ -0,0 +1,144 @@ +import Discord, { CommandInteraction, MessageActionRow, MessageButton, TextInputComponent } from "discord.js"; +import EmojiEmbed from "../../utils/generateEmojiEmbed.js"; +import getEmojiByName from "../../utils/getEmojiByName.js"; +import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; +import { WrappedCheck } from "jshaiku"; +import client from "../../utils/client.js"; +import { modalInteractionCollector } from "../../utils/dualCollector.js"; +import confirmationMessage from "../../utils/confirmationMessage.js"; +import keyValueList from "../../utils/generateKeyValueList.js"; + +const command = (builder: SlashCommandSubcommandBuilder) => + builder + .setName("commands") + .setDescription("Links and text shown to a user after a moderator action is performed") + .addRoleOption(o => o.setName("role").setDescription("The role given when a member is muted")) + +const callback = async (interaction: CommandInteraction): Promise => { + await interaction.reply({embeds: [new EmojiEmbed() + .setTitle("Loading") + .setStatus("Danger") + .setEmoji("NUCLEUS.LOADING") + ], ephemeral: true, fetchReply: true}); + let m; + let clicked = ""; + if (interaction.options.getRole("role")) { + let confirmation = await new confirmationMessage(interaction) + .setEmoji("GUILD.ROLES.DELETE") + .setTitle("Moderation Commands") + .setDescription(keyValueList({ + role: `<@&${interaction.options.getRole("role").id}>`, + })) + .setColor("Danger") + .send(true) + if (confirmation.cancelled) return await interaction.editReply({embeds: [new EmojiEmbed() + .setTitle("Moderation Commands") + .setDescription("No changes were made") + .setStatus("Success") + .setEmoji("GUILD.ROLES.CREATE") + ]}) + if (confirmation.success) { + await client.database.guilds.write(interaction.guild.id, {["moderation.mute.role"]: interaction.options.getRole("role").id}); + } + } + while (true) { + let config = await client.database.guilds.read(interaction.guild.id); + let moderation = config.getKey("moderation"); + m = await interaction.editReply({embeds: [new EmojiEmbed() + .setTitle("Moderation Commands") + .setEmoji("PUNISH.BAN.GREEN") + .setStatus("Success") + .setDescription( + "These links are shown below the message sent in a user's DM when they are warned, banned, etc.\n\n" + + `**Mute Role:** ` + (moderation.mute.role ? `<@&${moderation.mute.role}>` : "*None set*") + ) + ], components: [new MessageActionRow().addComponents([ + new MessageButton().setLabel("Warn").setEmoji(getEmojiByName("PUNISH.WARN.YELLOW", "id")).setCustomId("warn").setStyle("SECONDARY"), + new MessageButton().setLabel("Mute").setEmoji(getEmojiByName("PUNISH.MUTE.YELLOW", "id")).setCustomId("mute").setStyle("SECONDARY"), + new MessageButton().setLabel("Nickname").setEmoji(getEmojiByName("PUNISH.NICKNAME.GREEN", "id")).setCustomId("nickname").setStyle("SECONDARY") + ]), new MessageActionRow().addComponents([ + new MessageButton().setLabel("Kick").setEmoji(getEmojiByName("PUNISH.KICK.RED", "id")).setCustomId("kick").setStyle("SECONDARY"), + new MessageButton().setLabel("Softban").setEmoji(getEmojiByName("PUNISH.BAN.YELLOW", "id")).setCustomId("softban").setStyle("SECONDARY"), + new MessageButton().setLabel("Ban").setEmoji(getEmojiByName("PUNISH.BAN.RED", "id")).setCustomId("ban").setStyle("SECONDARY") + ]), new MessageActionRow().addComponents([ + new MessageButton().setLabel( + clicked === "clearMuteRole" ? "Click again to confirm" : "Clear mute role" + ).setEmoji(getEmojiByName("CONTROL.CROSS", "id")).setCustomId("clearMuteRole").setStyle("DANGER").setDisabled(!moderation.mute.role), + new MessageButton() + .setCustomId("timeout") + .setLabel("Mute timeout " + (moderation.mute.timeout ? "Enabled" : "Disabled")) + .setStyle(moderation.mute.timeout ? "SUCCESS" : "DANGER") + .setEmoji(getEmojiByName("CONTROL." + (moderation.mute.timeout ? "TICK" : "CROSS"), "id")) + ])]}); + let i; + try { + i = await m.awaitMessageComponent({ time: 300000 }); + } catch (e) { return } + let chosen = moderation[i.customId] ?? {text: null, url: null}; + if (i.component.customId === "clearMuteRole") { + if (clicked === "clearMuteRole") { + await client.database.guilds.write(interaction.guild.id, { moderation: { mute: { role: null } } }); + } else { clicked = "clearMuteRole" } + } else { clicked = "" } + if (i.component.customId === "timeout") { + await i.deferUpdate() + await client.database.guilds.write(interaction.guild.id, { moderation: { mute: { timeout: !moderation.mute.timeout } } }); + } else if (i.customId) { + await i.showModal(new Discord.Modal().setCustomId("modal").setTitle(`Options for ${i.customId}`).addComponents( + new MessageActionRow().addComponents(new TextInputComponent() + .setCustomId("name") + .setLabel("Button text") + .setMaxLength(100) + .setRequired(false) + .setStyle("SHORT") + .setValue(chosen.text ?? "") + ), + new MessageActionRow().addComponents(new TextInputComponent() + .setCustomId("url") + .setLabel("URL - Type {id} to insert the user's ID") + .setMaxLength(2000) + .setRequired(false) + .setStyle("SHORT") + .setValue(chosen.link ?? "") + ) + )) + await interaction.editReply({ + embeds: [new EmojiEmbed() + .setTitle("Moderation Links") + .setDescription("Modal opened. If you can't see it, click back and try again.") + .setStatus("Success") + .setEmoji("GUILD.TICKET.OPEN") + ], components: [new MessageActionRow().addComponents([new MessageButton() + .setLabel("Back") + .setEmoji(getEmojiByName("CONTROL.LEFT", "id")) + .setStyle("PRIMARY") + .setCustomId("back") + ])] + }); + let out; + try { + out = await modalInteractionCollector(m, (m) => m.channel.id == interaction.channel.id, (m) => true) + } catch (e) { continue } + if (out.fields) { + let buttonText = out.fields.getTextInputValue("name"); + let buttonLink = out.fields.getTextInputValue("url").replace(/{id}/gi, "{id}"); + let current = chosen; + if (current.text !== buttonText || current.link !== buttonLink) { + chosen = { text: buttonText, link: buttonLink }; + await client.database.guilds.write(interaction.guild.id, { ["moderation" + i.customId]: { text: buttonText, link: buttonLink }}); + } + } else { continue } + } + } +} + + +const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => { + let member = (interaction.member as Discord.GuildMember) + if (!member.permissions.has("MANAGE_GUILD")) throw "You must have the Manage server permission to use this command" + return true; +} + +export { command }; +export { callback }; +export { check }; \ No newline at end of file diff --git a/src/commands/settings/logs/ignore.ts b/src/commands/settings/logs/ignore.ts deleted file mode 100644 index 59f6621..0000000 --- a/src/commands/settings/logs/ignore.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { ChannelType } from 'discord-api-types'; -import Discord, { CommandInteraction } from "discord.js"; -import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; -import EmojiEmbed from "../../../utils/generateEmojiEmbed.js"; -import { WrappedCheck } from "jshaiku"; -import confirmationMessage from '../../../utils/confirmationMessage.js'; -import keyValueList from '../../../utils/generateKeyValueList.js'; -import client from '../../../utils/client.js'; - -const command = (builder: SlashCommandSubcommandBuilder) => - builder - .setName("ignore") - .setDescription("Sets which users, channels and roles should be ignored") - .addStringOption(o => o.setName("action").setDescription("Add or remove from the list").addChoices([ - ["Add", "add"], ["Remove", "remove"] - ]).setRequired(true)) - .addChannelOption(o => o.setName("addchannel").setDescription("Add a channel that should be ignored").addChannelTypes([ - ChannelType.GuildText, ChannelType.GuildVoice, ChannelType.GuildNews, ChannelType.GuildPublicThread, ChannelType.GuildPrivateThread, ChannelType.GuildNewsThread - ])) - .addUserOption(o => o.setName("adduser").setDescription("Add a user that should be ignored")) - .addRoleOption(o => o.setName("addrole").setDescription("Add a role that should be ignored")) - -const callback = async (interaction: CommandInteraction): Promise => { - let channel = interaction.options.getChannel("addchannel") - let user = interaction.options.getUser("adduser") - let role = interaction.options.getRole("addrole") - await interaction.reply({embeds: [new EmojiEmbed() - .setTitle("Loading") - .setStatus("Danger") - .setEmoji("NUCLEUS.LOADING") - ], ephemeral: true, fetchReply: true}); - if (channel || user || role) { - if (channel) { - try { - channel = interaction.guild.channels.cache.get(channel.id) - } catch { - return await interaction.editReply({embeds: [new EmojiEmbed() - .setEmoji("CHANNEL.TEXT.DELETE") - .setTitle("Logs > Ignore") - .setDescription("The channel you provided is not a valid channel") - .setStatus("Danger") - ]}) - } - channel = channel as Discord.TextChannel - if (channel.guild.id != interaction.guild.id) { - return interaction.editReply({embeds: [new EmojiEmbed() - .setTitle("Logs > Ignore") - .setDescription(`You must choose a channel in this server`) - .setStatus("Danger") - .setEmoji("CHANNEL.TEXT.DELETE") - ]}); - } - } - if (user) { - try { - user = interaction.guild.members.cache.get(user.id).user - } catch { - return await interaction.editReply({embeds: [new EmojiEmbed() - .setEmoji("USER.DELETE") - .setTitle("Logs > Ignore") - .setDescription("The user you provided is not a valid user") - .setStatus("Danger") - ]}) - } - user = user as Discord.User - } - if (role) { - try { - role = interaction.guild.roles.cache.get(role.id) - } catch { - return await interaction.editReply({embeds: [new EmojiEmbed() - .setEmoji("ROLE.DELETE") - .setTitle("Logs > Ignore") - .setDescription("The role you provided is not a valid role") - .setStatus("Danger") - ]}) - } - role = role as Discord.Role - if (role.guild.id != interaction.guild.id) { - return interaction.editReply({embeds: [new EmojiEmbed() - .setTitle("Logs > Ignore") - .setDescription(`You must choose a role in this server`) - .setStatus("Danger") - .setEmoji("ROLE.DELETE") - ]}); - } - } - let changes = {} - if (channel) changes["channel"] = channel.id - if (user) changes["user"] = user.id - if (role) changes["role"] = role.id - let confirmation = await new confirmationMessage(interaction) - .setEmoji("NUCLEUS.COMMANDS.IGNORE") - .setTitle("Logs > Ignore") - .setDescription(keyValueList(changes) - + `Are you sure you want to **${interaction.options.getString("action") == "add" ? "add" : "remove"}** these to the ignore list?`) - .setColor("Warning") - .send(true) - if (confirmation.cancelled) return - if (confirmation.success) { - let data = client.database.guilds.read(interaction.guild.id) - if (channel) data.logging.logs.ignore.channels.concat([channel.id]) - if (user) data.logging.logs.ignore.users.concat([user.id]) - if (role) data.logging.logs.ignore.roles.concat([role.id]) - if (interaction.options.getString("action") == "add") { - await client.database.guilds.append(interaction.guild.id, data) - } else { - await client.database.guilds.remove(interaction.guild.id, data) - } - const { log, NucleusColors, entry, renderUser, renderChannel } = client.logger - try { - let data = { - meta:{ - type: 'logIgnoreUpdated', - displayName: 'Ignored Groups Changed', - calculateType: 'nucleusSettingsUpdated', - color: NucleusColors.yellow, - emoji: "CHANNEL.TEXT.EDIT", - timestamp: new Date().getTime() - }, - list: { - memberId: entry(interaction.user.id, `\`${interaction.user.id}\``), - changedBy: entry(interaction.user.id, renderUser(interaction.user)), - channel: entry(channel.id, renderChannel(channel)), - }, - hidden: { - guild: interaction.guild.id - } - } - log(data); - } catch {} - } - } -} - -const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => { - let member = (interaction.member as Discord.GuildMember) - if (!member.permissions.has("MANAGE_GUILD")) throw "You must have the Manage Server permission to use this command" - return true; -} - -export { command }; -export { callback }; -export { check }; \ No newline at end of file diff --git a/src/commands/settings/stats/set.ts b/src/commands/settings/stats.ts similarity index 62% rename from src/commands/settings/stats/set.ts rename to src/commands/settings/stats.ts index 10c3011..3159e2d 100644 --- a/src/commands/settings/stats/set.ts +++ b/src/commands/settings/stats.ts @@ -1,33 +1,29 @@ import { ChannelType } from 'discord-api-types'; -import Discord, { CommandInteraction, MessageActionRow, MessageButton } from "discord.js"; -import EmojiEmbed from "../../../utils/generateEmojiEmbed.js"; -import confirmationMessage from "../../../utils/confirmationMessage.js"; -import getEmojiByName from "../../../utils/getEmojiByName.js"; -import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; +import Discord, { AutocompleteInteraction, CommandInteraction, Message, MessageActionRow, MessageButton, MessageSelectMenu } from "discord.js"; +import EmojiEmbed from "../../utils/generateEmojiEmbed.js"; +import confirmationMessage from "../../utils/confirmationMessage.js"; +import getEmojiByName from "../../utils/getEmojiByName.js"; +import { SelectMenuOption, SlashCommandSubcommandBuilder } from "@discordjs/builders"; import { WrappedCheck } from "jshaiku"; -import client from "../../../utils/client.js"; -import convertCurlyBracketString from '../../../utils/convertCurlyBracketString.js'; -import {callback as statsChannelAddCallback} from "../../../reflex/statsChannelUpdate.js"; +import client from "../../utils/client.js"; +import convertCurlyBracketString from '../../utils/convertCurlyBracketString.js'; +import {callback as statsChannelAddCallback} from "../../reflex/statsChannelUpdate.js"; const command = (builder: SlashCommandSubcommandBuilder) => builder - .setName("set") - .setDescription("Adds or edits a channel which will update when members join or leave") - .addChannelOption(option => option.setName("channel").setDescription("The channel to modify").addChannelTypes([ - ChannelType.GuildNews, ChannelType.GuildText - ]).setRequired(true)) - .addStringOption(option => option.setName("name").setDescription("The channel name").setRequired(true).setAutocomplete(true)) + .setName("stats") + .setDescription("Controls channels which update when someone joins or leaves the server") + .addChannelOption(option => option.setName("channel").setDescription("The channel to modify")) + .addStringOption(option => option.setName("name").setDescription("The new channel name | Enter any text or use the extra variables like {memberCount}").setAutocomplete(true)) const callback = async (interaction: CommandInteraction): Promise => { - console.log(interaction.options.getString("name")) let m; m = await interaction.reply({embeds: [new EmojiEmbed() .setTitle("Loading") .setStatus("Danger") .setEmoji("NUCLEUS.LOADING") ], ephemeral: true, fetchReply: true}); - if (interaction.options.getChannel("channel")) { - let config = client.database.guilds.read(interaction.guild.id); + if (interaction.options.getString("name")) { let channel try { channel = interaction.options.getChannel("channel") @@ -106,13 +102,47 @@ const callback = async (interaction: CommandInteraction): Promise => { ], components: []}); } await statsChannelAddCallback(client, interaction.member); - return interaction.editReply({embeds: [new EmojiEmbed() + } + while (true) { + let config = await client.database.guilds.read(interaction.guild.id); + let stats = config.getKey("stats") + let selectMenu = new MessageSelectMenu() + .setCustomId("remove") + .setMinValues(1) + .setMaxValues(Math.max(1, Object.keys(stats).length)) + await interaction.editReply({embeds: [new EmojiEmbed() .setTitle("Stats Channel") - .setDescription(`The stats channel has been set to <#${channel.id}>`) + .setDescription("The following channels update when someone joins or leaves the server. You can select a channel to remove it from the list.") .setStatus("Success") .setEmoji("CHANNEL.TEXT.CREATE") - ], components: []}); + ], components: [ + new MessageActionRow().addComponents(Object.keys(stats).length ? [ + selectMenu.setPlaceholder("Select a stats channel to remove, stopping it updating").addOptions(Object.keys(stats).map(key => ({ + label: interaction.guild.channels.cache.get(key).name, + value: key, + description: `${stats[key].name}`, + }))) + ] : [selectMenu.setPlaceholder("The server has no stats channels").setDisabled(true).setOptions([ + {label: "*Placeholder*", value: "placeholder", description: "No stats channels"} + ])]) + ]}) + let i; + try { + i = await m.awaitMessageComponent({ time: 300000 }); + } catch (e) { break } + i.deferUpdate() + if (i.customId === "remove") { + let toRemove = i.values; + console.log(toRemove.map(k => `stats.${k}`)) + await client.database.guilds.write(interaction.guild.id, {}, toRemove.map(k => `stats.${k}`)); + } } + await interaction.editReply({embeds: [new EmojiEmbed() + .setTitle("Stats Channel") + .setDescription("The following channels update when someone joins or leaves the server. You can select a channel to remove it from the list.") + .setStatus("Danger") + .setEmoji("CHANNEL.TEXT.DELETE") + ], components: []}) } const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => { @@ -123,4 +153,4 @@ const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => { export { command }; export { callback }; -export { check }; +export { check }; \ No newline at end of file diff --git a/src/commands/settings/stats/_meta.ts b/src/commands/settings/stats/_meta.ts deleted file mode 100644 index 7443a9e..0000000 --- a/src/commands/settings/stats/_meta.ts +++ /dev/null @@ -1,4 +0,0 @@ -const name = "stats"; -const description = "Settings for stats channels"; - -export { name, description }; \ No newline at end of file diff --git a/src/commands/settings/stats/remove.ts b/src/commands/settings/stats/remove.ts deleted file mode 100644 index 8e3a64a..0000000 --- a/src/commands/settings/stats/remove.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { ChannelType } from 'discord-api-types'; -import Discord, { CommandInteraction, MessageActionRow, MessageButton } from "discord.js"; -import EmojiEmbed from "../../../utils/generateEmojiEmbed.js"; -import confirmationMessage from "../../../utils/confirmationMessage.js"; -import getEmojiByName from "../../../utils/getEmojiByName.js"; -import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; -import { WrappedCheck } from "jshaiku"; -import client from "../../../utils/client.js"; - -const command = (builder: SlashCommandSubcommandBuilder) => - builder - .setName("remove") - .setDescription("Stops updating channels when a member joins or leaves") - .addChannelOption(option => option.setName("channel").setDescription("The channel to stop updating").addChannelTypes([ - ChannelType.GuildNews, ChannelType.GuildText - ]).setRequired(true)) - -const callback = async (interaction: CommandInteraction): Promise => { - let m; - m = await interaction.reply({embeds: [new EmojiEmbed() - .setTitle("Loading") - .setStatus("Danger") - .setEmoji("NUCLEUS.LOADING") - ], ephemeral: true, fetchReply: true}); - if (interaction.options.getChannel("channel")) { - let config = client.database.guilds.read(interaction.guild.id); - let channel - try { - channel = interaction.options.getChannel("channel") - } catch { - return await interaction.editReply({embeds: [new EmojiEmbed() - .setEmoji("CHANNEL.TEXT.DELETE") - .setTitle("Stats Channel") - .setDescription("The channel you provided is not a valid channel") - .setStatus("Danger") - ]}) - } - channel = channel as Discord.TextChannel - if (channel.guild.id != interaction.guild.id) { - return interaction.editReply({embeds: [new EmojiEmbed() - .setTitle("Stats Channel") - .setDescription(`You must choose a channel in this server`) - .setStatus("Danger") - .setEmoji("CHANNEL.TEXT.DELETE") - ]}); - } - // check if the channel is not in the list - let allow = false; - for (let c of config.stats) { if (c.channel == channel.id) allow = true; } - if (!allow) { - return interaction.editReply({embeds: [new EmojiEmbed() - .setTitle("Stats Channel") - .setDescription(`That channel is not a stats channel`) - .setStatus("Danger") - .setEmoji("CHANNEL.TEXT.DELETE") - ]}); - } - let confirmation = await new confirmationMessage(interaction) - .setEmoji("CHANNEL.TEXT.EDIT") - .setTitle("Stats Channel") - .setDescription(`Are you sure you want to stop <#${channel.id}> updating?`) - .setColor("Warning") - .setInverted(true) - .send(true) - if (confirmation.cancelled) return - if (confirmation.success) { - try { - let channel = interaction.options.getChannel("channel") - await client.database.guilds.write(interaction.guild.id, {}, [`stats.${channel.id}`]); - const { log, NucleusColors, entry, renderUser, renderChannel } = client.logger - try { - let data = { - meta:{ - type: 'statsChannelUpdate', - displayName: 'Stats Channel Removed', - calculateType: 'nucleusSettingsUpdated', - color: NucleusColors.red, - emoji: "CHANNEL.TEXT.EDIT", - timestamp: new Date().getTime() - }, - list: { - memberId: entry(interaction.user.id, `\`${interaction.user.id}\``), - changedBy: entry(interaction.user.id, renderUser(interaction.user)), - channel: entry(channel.id, renderChannel(channel)), - }, - hidden: { - guild: interaction.guild.id - } - } - log(data); - } catch {} - } catch (e) { - console.log(e) - return interaction.editReply({embeds: [new EmojiEmbed() - .setTitle("Stats Channel") - .setDescription(`Something went wrong and the stats channel could not be reset`) - .setStatus("Danger") - .setEmoji("CHANNEL.TEXT.DELETE") - ], components: []}); - } - } else { - return interaction.editReply({embeds: [new EmojiEmbed() - .setTitle("Stats Channel") - .setDescription(`No changes were made`) - .setStatus("Success") - .setEmoji("CHANNEL.TEXT.CREATE") - ], components: []}); - } - } -} - -const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => { - let member = (interaction.member as Discord.GuildMember) - if (!member.permissions.has("MANAGE_GUILD")) throw "You must have the Manage Server permission to use this command" - return true; -} - -export { command }; -export { callback }; -export { check }; diff --git a/src/commands/tags/delete.ts b/src/commands/tags/delete.ts index 74ebb25..f531e93 100644 --- a/src/commands/tags/delete.ts +++ b/src/commands/tags/delete.ts @@ -40,8 +40,9 @@ const callback = async (interaction: CommandInteraction): Promise => { .setEmoji("PUNISH.NICKNAME.GREEN") ]}); try { - await client.database.guilds.write(interaction.guild.id, null, [`tags.${name}`]); + await client.database.guilds.write(interaction.guild.id, null, ["tags." + name]); } catch (e) { + console.log(e) return await interaction.editReply({embeds: [new EmojiEmbed() .setTitle("Tag Delete") .setDescription("Something went wrong and the tag was not deleted") diff --git a/src/config/default.json b/src/config/default.json index 2f95e94..93b571f 100644 --- a/src/config/default.json +++ b/src/config/default.json @@ -15,11 +15,6 @@ "words": { "strict": [], "loose": [] - }, - "allowed": { - "users": [], - "roles": [], - "channels": [] } }, "invite": { @@ -33,21 +28,11 @@ "pings": { "mass": 5, "everyone": true, - "roles": true, - "allowed": { - "roles": [], - "rolesToMention": [], - "users": [], - "channels": [] - } + "roles": true } }, "welcome": { "enabled": false, - "verificationRequired": { - "message": null, - "role": null - }, "welcomeRole": null, "channel": null, "message": null @@ -57,12 +42,7 @@ "logs": { "enabled": true, "channel": null, - "toLog": "3fffff", - "ignore": { - "users": [], - "roles": [], - "channels": [] - } + "toLog": "3fffff" }, "staff": { "channel": null @@ -107,8 +87,9 @@ "text": null, "link": null }, - "role": { - "role": null + "nickname": { + "text": null, + "link": null } }, "tracks": [], diff --git a/src/config/emojis.json b/src/config/emojis.json index 7024a73..49c2b27 100644 --- a/src/config/emojis.json +++ b/src/config/emojis.json @@ -144,28 +144,28 @@ "PUNISH": { "WARN": { "RED": "947433493384806430", - "GREEN": "947433504076091424", - "YELLOW": "729764054897524768" + "YELLOW": "729764054897524768", + "GREEN": "947433504076091424" }, "KICK": { "RED": "729764053794422896", - "GREEN": "947428786692042764", - "YELLOW": "947429333289562132" + "YELLOW": "947429333289562132", + "GREEN": "947428786692042764" }, "BAN": { "RED": "729764053861400637", - "GREEN": "947421674364629022", - "YELLOW": "729764053941223476" + "YELLOW": "729764053941223476", + "GREEN": "947421674364629022" }, "UNBAN": { - "GREEN": "729263536840114216", + "RED": "972511610885255259", "YELLOW": "972511620343414794", - "RED": "972511610885255259" + "GREEN": "729263536840114216" }, "MUTE": { "RED": "947555098974883910", - "GREEN": "947555107980066866", - "YELLOW": "729764053865463840" + "YELLOW": "729764053865463840", + "GREEN": "947555107980066866" }, "SOFTBAN": "729764053941223476", "VOICEMUTE": "729764054855450697", diff --git a/src/events/interactionCreate.ts b/src/events/interactionCreate.ts index 900c774..eaf4fea 100644 --- a/src/events/interactionCreate.ts +++ b/src/events/interactionCreate.ts @@ -38,7 +38,7 @@ async function interactionCreate(interaction) { } else if (interaction.type === "APPLICATION_COMMAND_AUTOCOMPLETE") { switch (`${interaction.commandName} ${interaction.options.getSubcommandGroup(false)} ${interaction.options.getSubcommand(false)}`) { case `tag null null`: { return interaction.respond(getAutocomplete(interaction.options.getString("tag"), (await tagAutocomplete(interaction)))) } - case `settings stats set`: { return interaction.respond(generateStatsChannelAutocomplete(interaction.options.getString("name"))) } + case `settings null stats`: { return interaction.respond(generateStatsChannelAutocomplete(interaction.options.getString("name"))) } } } } diff --git a/src/events/memberJoin.ts b/src/events/memberJoin.ts index 7bee084..109f226 100644 --- a/src/events/memberJoin.ts +++ b/src/events/memberJoin.ts @@ -7,6 +7,7 @@ export const event = 'guildMemberAdd' export async function callback(_, member) { try { welcome(_, member); } catch {} + try { statsChannelAdd(_, member, ); } catch {} try { const { log, NucleusColors, entry, renderUser, renderDelta } = member.client.logger try { await client.database.history.create("join", member.guild.id, member.user, null, null) } catch {} @@ -32,5 +33,4 @@ export async function callback(_, member) { } log(data); } catch {} - try { statsChannelAdd(_, member, ); } catch {} } diff --git a/src/reflex/statsChannelUpdate.ts b/src/reflex/statsChannelUpdate.ts index 51d4329..7d04c8f 100644 --- a/src/reflex/statsChannelUpdate.ts +++ b/src/reflex/statsChannelUpdate.ts @@ -5,7 +5,6 @@ import client from '../utils/client.js'; interface PropSchema { enabled: boolean, name: string } export async function callback(_, member) { - console.log("UPDATING STATS CHANNEL") let guild = await client.guilds.fetch(member.guild.id) let config = await client.database.guilds.read(guild.id); Object.entries(config.getKey("stats")).forEach(async ([channel, props]) => { diff --git a/src/utils/database.ts b/src/utils/database.ts index 5b1d6d9..d24c7bf 100644 --- a/src/utils/database.ts +++ b/src/utils/database.ts @@ -43,12 +43,12 @@ export class Guilds { async write(guild: string, set: object = {}, unset: string[] = []) { let uo = {} for (let key of unset) { - uo[key] = ""; + uo[key] = null; } - await this.guilds.updateOne({ id: guild }, { - $unset: uo, - $set: set - }, { upsert: true }); + let out = {} + if (set) out["$set"] = set; + if (unset.length) out["$unset"] = uo; + await this.guilds.updateOne({ id: guild }, out, { upsert: true }); } async append(guild: string, key: string, value: any) { @@ -63,13 +63,13 @@ export class Guilds { } } - async remove(guild: string, key: string, value: any, innerKey?: string) { + async remove(guild: string, key: string, value: any, innerKey?: string | null) { + console.log(Array.isArray(value)) if (innerKey) { await this.guilds.updateOne({ id: guild }, { $pull: { [key]: { [innerKey]: { $eq: value } } } }, { upsert: true }); - } - else if (Array.isArray(value)) { + } else if (Array.isArray(value)) { await this.guilds.updateOne({ id: guild }, { $pullAll: { [key]: value } }, { upsert: true });