From 4f79da1cdbd67895984b7c23914800d73959ff50 Mon Sep 17 00:00:00 2001 From: TheCodedProf Date: Tue, 31 Jan 2023 16:50:37 -0500 Subject: [PATCH] worked on automod --- TODO.json | 5 -- src/commands/settings/filters.ts | 21 ----- src/commands/settings/filters/_meta.ts | 8 -- src/commands/settings/rolemenu.ts | 2 +- src/commands/settings/tracks.ts | 84 ++++++++++++------- src/config/default.json | 15 +++- src/config/emojis.json | 2 +- src/events/messageDelete.ts | 109 ++++++++++++------------- src/events/messageEdit.ts | 1 + src/index.ts | 2 +- src/premium/attachmentLogs.ts | 5 +- 11 files changed, 128 insertions(+), 126 deletions(-) delete mode 100644 src/commands/settings/filters.ts delete mode 100644 src/commands/settings/filters/_meta.ts diff --git a/TODO.json b/TODO.json index 4637953..90fe168 100644 --- a/TODO.json +++ b/TODO.json @@ -1,10 +1,5 @@ { "filters": { - "images": { - "NSFW": false, - "size": false - }, - "malware": false, "wordFilter": { "enabled": true, "words": { diff --git a/src/commands/settings/filters.ts b/src/commands/settings/filters.ts deleted file mode 100644 index 7636f91..0000000 --- a/src/commands/settings/filters.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type Discord from "discord.js"; -import type { CommandInteraction } from "discord.js"; -import type { SlashCommandSubcommandBuilder } from "discord.js"; - -const command = (builder: SlashCommandSubcommandBuilder) => - builder.setName("filter").setDescription("Setting for message filters"); - -const callback = async (_interaction: CommandInteraction): Promise => { - console.log("Filters"); -}; - -const check = (interaction: CommandInteraction, _partial: boolean = false) => { - const member = interaction.member as Discord.GuildMember; - if (!member.permissions.has("ManageMessages")) - return "You must have the *Manage Messages* permission to use this command"; - return true; -}; - -export { command }; -export { callback }; -export { check }; diff --git a/src/commands/settings/filters/_meta.ts b/src/commands/settings/filters/_meta.ts deleted file mode 100644 index d2aff53..0000000 --- a/src/commands/settings/filters/_meta.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { group } from "../../../utils/commandRegistration/slashCommandBuilder.js"; - -const name = "filters"; -const description = "Settings for filters"; - -const subcommand = await group(name, description, `settings/filters`) - -export { name, description, subcommand as command}; diff --git a/src/commands/settings/rolemenu.ts b/src/commands/settings/rolemenu.ts index 9528183..90b224d 100644 --- a/src/commands/settings/rolemenu.ts +++ b/src/commands/settings/rolemenu.ts @@ -364,7 +364,7 @@ const callback = async (interaction: CommandInteraction): Promise => { new ButtonBuilder() .setCustomId("reorder") .setLabel("Reorder Pages") - .setEmoji(getEmojiByName("ICONS.SHUFFLE", "id") as APIMessageComponentEmoji) + .setEmoji(getEmojiByName("ICONS.REORDER", "id") as APIMessageComponentEmoji) .setStyle(ButtonStyle.Secondary) .setDisabled(Object.keys(currentObject).length <= 1), new ButtonBuilder() diff --git a/src/commands/settings/tracks.ts b/src/commands/settings/tracks.ts index 782f52f..354a948 100644 --- a/src/commands/settings/tracks.ts +++ b/src/commands/settings/tracks.ts @@ -1,4 +1,4 @@ -import { ActionRowBuilder, APIMessageComponentEmoji, ButtonBuilder, ButtonInteraction, ButtonStyle, Collection, CommandInteraction, GuildMember, Message, ModalBuilder, ModalSubmitInteraction, Role, RoleSelectMenuBuilder, RoleSelectMenuInteraction, SlashCommandSubcommandBuilder, StringSelectMenuBuilder, StringSelectMenuInteraction, StringSelectMenuOptionBuilder, TextInputBuilder, TextInputStyle } from "discord.js"; +import { ActionRowBuilder, APIMessageComponentEmoji, ButtonBuilder, ButtonInteraction, ButtonStyle, Collection, CommandInteraction, GuildMember, Message, ModalBuilder, ModalSubmitInteraction, PermissionsBitField, Role, RoleSelectMenuBuilder, RoleSelectMenuInteraction, SlashCommandSubcommandBuilder, StringSelectMenuBuilder, StringSelectMenuInteraction, StringSelectMenuOptionBuilder, TextInputBuilder, TextInputStyle } from "discord.js"; import client from "../../utils/client.js"; import createPageIndicator, { createVerticalTrack } from "../../utils/createPageIndicator.js"; import { LoadingEmbed } from "../../utils/defaults.js"; @@ -7,6 +7,8 @@ import getEmojiByName from "../../utils/getEmojiByName.js"; import ellipsis from "../../utils/ellipsis.js"; import { modalInteractionCollector } from "../../utils/dualCollector.js"; +const { renderRole } = client.logger + const command = (builder: SlashCommandSubcommandBuilder) => builder .setName("tracks") @@ -20,6 +22,7 @@ interface ObjectSchema { manageableBy: string[]; } + const editName = async (i: ButtonInteraction, interaction: StringSelectMenuInteraction | ButtonInteraction, m: Message, current?: string) => { let name = current ?? ""; @@ -134,6 +137,7 @@ const reorderTracks = async (interaction: ButtonInteraction, m: Message, roles: } const editTrack = async (interaction: ButtonInteraction | StringSelectMenuInteraction, message: Message, roles: Collection, current?: ObjectSchema) => { + const isAdmin = (interaction.member!.permissions as PermissionsBitField).has("Administrator"); if(!current) { current = { name: "", @@ -143,40 +147,25 @@ const editTrack = async (interaction: ButtonInteraction | StringSelectMenuIntera manageableBy: [] } } - const buttons = new ActionRowBuilder() - .addComponents( - new ButtonBuilder() - .setCustomId("back") - .setLabel("Back") - .setStyle(ButtonStyle.Secondary) - .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji), - new ButtonBuilder() - .setCustomId("edit") - .setLabel("Edit Name") - .setStyle(ButtonStyle.Primary) - .setEmoji(getEmojiByName("ICONS.EDIT", "id") as APIMessageComponentEmoji), - new ButtonBuilder() - .setCustomId("reorder") - .setLabel("Reorder") - .setStyle(ButtonStyle.Primary) - .setEmoji(getEmojiByName("ICONS.REORDER", "id") as APIMessageComponentEmoji), - ); + const roleSelect = new ActionRowBuilder() .addComponents( new RoleSelectMenuBuilder() .setCustomId("addRole") .setPlaceholder("Select a role to add") + .setDisabled(!isAdmin) ); let closed = false; do { const editableRoles: string[] = current.track.map((r) => { - if(!(roles.get(r)!.position >= (interaction.member as GuildMember).roles.highest.position)) return r; + if(!(roles.get(r)!.position >= (interaction.member as GuildMember).roles.highest.position)) return roles.get(r)!.name; }).filter(v => v !== undefined) as string[]; const selectMenu = new ActionRowBuilder() .addComponents( new StringSelectMenuBuilder() .setCustomId("removeRole") .setPlaceholder("Select a role to remove") + .setDisabled(!isAdmin) .addOptions( editableRoles.map((r, i) => { return new StringSelectMenuOptionBuilder() @@ -185,23 +174,56 @@ const editTrack = async (interaction: ButtonInteraction | StringSelectMenuIntera ) ) ); + const buttons = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setCustomId("back") + .setLabel("Back") + .setStyle(ButtonStyle.Secondary) + .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji), + new ButtonBuilder() + .setCustomId("edit") + .setLabel("Edit Name") + .setStyle(ButtonStyle.Primary) + .setEmoji(getEmojiByName("ICONS.EDIT", "id") as APIMessageComponentEmoji), + new ButtonBuilder() + .setCustomId("reorder") + .setLabel("Reorder") + .setDisabled(!isAdmin) + .setStyle(ButtonStyle.Primary) + .setEmoji(getEmojiByName("ICONS.REORDER", "id") as APIMessageComponentEmoji), + new ButtonBuilder() + .setCustomId("retainPrevious") + .setLabel("Retain Previous") + .setStyle(current.retainPrevious ? ButtonStyle.Success : ButtonStyle.Danger) + .setEmoji(getEmojiByName("CONTROL." + (current.retainPrevious ? "TICK" : "CROSS"), "id") as APIMessageComponentEmoji), + new ButtonBuilder() + .setCustomId("nullable") + .setLabel(`Role ${current.nullable ? "Not " : ""}Required`) + .setStyle(current.nullable ? ButtonStyle.Success : ButtonStyle.Danger) + .setEmoji(getEmojiByName("CONTROL." + (current.nullable ? "TICK" : "CROSS"), "id") as APIMessageComponentEmoji) + ); + let allowed: boolean[] = []; for (const role of current.track) { const disabled: boolean = roles.get(role)!.position >= (interaction.member as GuildMember).roles.highest.position; allowed.push(disabled) } + const mapped = current.track.map(role => roles.find(aRole => aRole.id === role)!); const embed = new EmojiEmbed() .setTitle("Tracks") .setDescription( `**Currently Editing:** ${current.name}\n\n` + - `${getEmojiByName} Members ${current.nullable ? "don't " : ""}need a role in this track` + - `${getEmojiByName} Members ${current.retainPrevious ? "don't " : ""}keep all roles below their current highest` + - createVerticalTrack(current.track, new Array(current.track.length).fill(false), allowed) + `${getEmojiByName("CONTROL." + (current.nullable ? "CROSS" : "TICK"))} Members ${current.nullable ? "don't " : ""}need a role in this track\n` + + `${getEmojiByName("CONTROL." + (current.retainPrevious ? "TICK" : "CROSS"))} Members ${current.retainPrevious ? "" : "don't "}keep all roles below their current highest\n\n` + + createVerticalTrack( + mapped.map(role => renderRole(role)), new Array(current.track.length).fill(false), allowed) ) + .setStatus("Success") - interaction.editReply({embeds: [embed], components: [buttons, roleSelect, selectMenu]}); + interaction.editReply({embeds: [embed], components: [roleSelect, selectMenu, buttons]}); let out: ButtonInteraction | RoleSelectMenuInteraction | StringSelectMenuInteraction | null; @@ -227,6 +249,13 @@ const editTrack = async (interaction: ButtonInteraction | StringSelectMenuIntera break; case "reorder": current.track = (await reorderTracks(out, message, roles, current.track))!; + break; + case "retainPrevious": + current.retainPrevious = !current.retainPrevious; + break; + case "nullable": + current.nullable = !current.nullable; + break; } } else if (out.isStringSelectMenu()) { out.deferUpdate(); @@ -258,8 +287,6 @@ const callback = async (interaction: CommandInteraction) => { const config = await client.database.guilds.read(interaction.guild!.id); const tracks: ObjectSchema[] = config.tracks; const roles = await interaction.guild!.roles.fetch(); - const memberRoles = interaction.member!.roles; - const member = interaction.member as GuildMember; let page = 0; let closed = false; @@ -329,10 +356,11 @@ const callback = async (interaction: CommandInteraction) => { } else { page = Math.min(page, Object.keys(tracks).length - 1); current = tracks[page]!; + const mapped = current.track.map(role => roles.find(aRole => aRole.id === role)!); embed.setDescription(`**Currently Editing:** ${current.name}\n\n` + `${getEmojiByName("CONTROL." + (current.nullable ? "CROSS" : "TICK"))} Members ${current.nullable ? "don't " : ""}need a role in this track\n` + `${getEmojiByName("CONTROL." + (current.retainPrevious ? "TICK" : "CROSS"))} Members ${current.retainPrevious ? "" : "don't "}keep all roles below their current highest\n\n` + - createVerticalTrack(current.track, new Array(current.track.length).fill(false)) + + createVerticalTrack(mapped.map(role => renderRole(role)), new Array(current.track.length).fill(false)) + `\n${createPageIndicator(config.tracks.length, page)}` ); @@ -372,7 +400,7 @@ const callback = async (interaction: CommandInteraction) => { page = tracks.length - 1; break; case "save": - // client.database.guilds.write(interaction.guild!.id, {"roleMenu.options": tracks}); // TODO + client.database.guilds.write(interaction.guild!.id, {tracks: tracks}); modified = false; break; } diff --git a/src/config/default.json b/src/config/default.json index 8e4197c..9129765 100644 --- a/src/config/default.json +++ b/src/config/default.json @@ -15,12 +15,17 @@ "words": { "strict": [], "loose": [] + }, + "allowed": { + "user": [], + "roles": [], + "channels": [] } }, "invite": { "enabled": false, "allowed": { - "users": [], + "user": [], "roles": [], "channels": [] } @@ -28,7 +33,13 @@ "pings": { "mass": 5, "everyone": true, - "roles": true + "roles": true, + "allowed": { + "user": [], + "roles": [], + "channels": [], + "rolesToMention": [] + } } }, "welcome": { diff --git a/src/config/emojis.json b/src/config/emojis.json index abeb52a..9ccb9fa 100644 --- a/src/config/emojis.json +++ b/src/config/emojis.json @@ -25,7 +25,7 @@ "ATTACHMENT": "997570687193587812", "LOGGING": "999613304446144562", "SAVE": "1065722246322200586", - "SHUFFLE": "1069323453909454890", + "REORDER": "1069323453909454890", "NOTIFY": { "ON": "1000726394579464232", "OFF": "1000726363495477368" diff --git a/src/events/messageDelete.ts b/src/events/messageDelete.ts index f8433fc..9563a33 100644 --- a/src/events/messageDelete.ts +++ b/src/events/messageDelete.ts @@ -4,61 +4,58 @@ import Discord, { AuditLogEvent, GuildAuditLogsEntry, Message, User } from "disc export const event = "messageDelete"; export async function callback(client: NucleusClient, message: Message) { - try { - if (message.author.id === client.user!.id) return; - if (client.noLog.includes(`${message.id}/${message.channel.id}/${message.id}`)) return; - const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = client.logger; - const auditLog = (await getAuditLog(message.guild!, AuditLogEvent.MemberBanAdd)) - .filter((entry: GuildAuditLogsEntry) => (entry.target! as User).id === message.author.id)[0]; - if (auditLog) { - if (auditLog.createdTimestamp - 1000 < new Date().getTime()) return; - } - const replyTo = message.reference; - let content = message.cleanContent; - content.replace("`", "\\`"); - if (content.length > 256) content = content.substring(0, 253) + "..."; - const attachments = - message.attachments.size + ( - message.content.match( - /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/gi - ) ?? [] - ).length; - let attachmentJump = ""; - const config = (await client.database.guilds.read(message.guild!.id)).logging.attachments.saved[ - message.channel.id + message.id - ]; - if (config) { attachmentJump = ` [[View attachments]](${config})`; } - const data = { - meta: { - type: "messageDelete", - displayName: "Message Deleted", - calculateType: "messageDelete", - color: NucleusColors.red, - emoji: "MESSAGE.DELETE", - timestamp: new Date().getTime() - }, - separate: { - start: content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*" - }, - list: { - messageId: entry(message.id, `\`${message.id}\``), - sentBy: entry(message.author.id, renderUser(message.author)), - sentIn: entry(message.channel.id, renderChannel(message.channel as Discord.GuildChannel | Discord.ThreadChannel)), - deleted: entry(new Date().getTime(), renderDelta(new Date().getTime())), - mentions: message.mentions.users.size, - attachments: entry(attachments, attachments + attachmentJump), - repliedTo: entry( - replyTo ? replyTo.messageId! : null, - replyTo ? `[[Jump to message]](https://discord.com/channels/${message.guild!.id}/${message.channel.id}/${replyTo.messageId})` - : "None" - ) - }, - hidden: { - guild: message.guild!.id - } - }; - log(data); - } catch (e) { - console.log(e); + if (message.author.id === client.user!.id) return; + if (message.author.bot) return; + if (client.noLog.includes(`${message.id}/${message.channel.id}/${message.id}`)) return; + const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = client.logger; + const auditLog = (await getAuditLog(message.guild!, AuditLogEvent.MemberBanAdd)) + .filter((entry: GuildAuditLogsEntry) => (entry.target! as User).id === message.author.id)[0]; + if (auditLog) { + if (auditLog.createdTimestamp - 1000 < new Date().getTime()) return; } + const replyTo = message.reference; + let content = message.cleanContent; + content.replace("`", "\\`"); + if (content.length > 256) content = content.substring(0, 253) + "..."; + const attachments = + message.attachments.size + ( + message.content.match( + /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/gi + ) ?? [] + ).length; + let attachmentJump = ""; + const config = (await client.database.guilds.read(message.guild!.id)).logging.attachments.saved[ + message.channel.id + message.id + ]; + if (config) { attachmentJump = ` [[View attachments]](${config})`; } + const data = { + meta: { + type: "messageDelete", + displayName: "Message Deleted", + calculateType: "messageDelete", + color: NucleusColors.red, + emoji: "MESSAGE.DELETE", + timestamp: new Date().getTime() + }, + separate: { + start: content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*" + }, + list: { + messageId: entry(message.id, `\`${message.id}\``), + sentBy: entry(message.author.id, renderUser(message.author)), + sentIn: entry(message.channel.id, renderChannel(message.channel as Discord.GuildChannel | Discord.ThreadChannel)), + deleted: entry(new Date().getTime(), renderDelta(new Date().getTime())), + mentions: message.mentions.users.size, + attachments: entry(attachments, attachments + attachmentJump), + repliedTo: entry( + replyTo ? replyTo.messageId! : null, + replyTo ? `[[Jump to message]](https://discord.com/channels/${message.guild!.id}/${message.channel.id}/${replyTo.messageId})` + : "None" + ) + }, + hidden: { + guild: message.guild!.id + } + }; + log(data); } diff --git a/src/events/messageEdit.ts b/src/events/messageEdit.ts index caa00f6..d491641 100644 --- a/src/events/messageEdit.ts +++ b/src/events/messageEdit.ts @@ -6,6 +6,7 @@ export const event = "messageUpdate"; export async function callback(client: NucleusClient, oldMessage: Message, newMessage: Message) { if (newMessage.author.id === client.user!.id) return; + if (newMessage.author.bot) return; if (!newMessage.guild) return; const { log, NucleusColors, entry, renderUser, renderDelta, renderNumberDelta, renderChannel } = client.logger; const replyTo: MessageReference | null = newMessage.reference; diff --git a/src/index.ts b/src/index.ts index 306811e..a3a8d38 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,4 +19,4 @@ process.on("uncaughtException", (err) => { console.error(err) }); await client.login(config.enableDevelopment ? config.developmentToken : config.token) -await recordPerformance(); \ No newline at end of file +await recordPerformance(); diff --git a/src/premium/attachmentLogs.ts b/src/premium/attachmentLogs.ts index 628c2ec..078587e 100644 --- a/src/premium/attachmentLogs.ts +++ b/src/premium/attachmentLogs.ts @@ -13,7 +13,7 @@ export default async function logAttachment(message: Message): Promise file.local) }); - // await client.database.guilds.write(interaction.guild.id, {[`tags.${name}`]: value}); client.database.guilds.write(message.guild.id, { [`logging.attachments.saved.${message.channel.id}${message.id}`]: m.url });