From b4a823aba1b71dc9d8026ef7c8906ea5664dbf90 Mon Sep 17 00:00:00 2001 From: LTS20050703 Date: Mon, 12 Sep 2022 20:57:59 +0700 Subject: [PATCH] feat: Validation Plugin (#2451) * Plugins/Permissions: FIX PARITY ISSUES What is parity issues? Parity issues are files that exist but structured one way in the base/vanilla discordeno library, and structured another way in the permisison plugin. * deno fmt * plugins/permissions: nuke validations * plugins/permissions VALIDATIONS -> plugins/validations * plugins/validations: slash commands max 4000 chars * fix module not found --- plugins/mod.ts | 1 + plugins/permissions/mod.ts | 48 ++--- .../permissions/src/channels/createChannel.ts | 10 +- .../permissions/src/channels/deleteChannel.ts | 14 +- .../deleteChannelPermissionOverride.ts | 10 +- .../permissions/src/channels/editChannel.ts | 18 +- .../editChannelPermissionOverrides.ts | 10 +- .../src/channels/followAnnouncementChannel.ts | 10 +- .../src/channels/forums/createForumThread.ts | 10 +- .../permissions/src/channels/forums/mod.ts | 4 +- .../src/channels/getChannelWebhooks.ts | 10 +- plugins/permissions/src/channels/mod.ts | 31 +-- plugins/permissions/src/channels/stage.ts | 48 ----- .../channels/stages/createStageInstance.ts | 16 ++ .../channels/stages/deleteStageInstances.ts | 12 ++ .../src/channels/stages/editStageInstance.ts | 12 ++ .../permissions/src/channels/stages/mod.ts | 10 + .../permissions/src/channels/swapChannels.ts | 6 +- .../src/channels/threads/addThreadMember.ts | 14 +- .../threads/getPrivateArchivedThreads.ts | 10 +- .../getPrivateJoinedArchivedThreads.ts | 10 +- .../threads/getPublicArchivedThreads.ts | 8 +- .../src/channels/threads/getThreadMembers.ts | 16 -- .../src/channels/threads/joinThread.ts | 10 +- .../src/channels/threads/leaveThread.ts | 10 +- .../permissions/src/channels/threads/mod.ts | 12 +- .../channels/threads/removeThreadMember.ts | 14 +- plugins/permissions/src/editMember.ts | 64 ------ plugins/permissions/src/emojis.ts | 38 ---- plugins/permissions/src/emojis/createEmoji.ts | 12 ++ plugins/permissions/src/emojis/deleteEmoji.ts | 12 ++ plugins/permissions/src/emojis/editEmoji.ts | 12 ++ plugins/permissions/src/emojis/mod.ts | 10 + plugins/permissions/src/guilds/automod.ts | 92 -------- .../src/guilds/automod/createAutomodRule.ts | 28 +++ .../src/guilds/automod/deleteAutomodRule.ts | 12 ++ .../src/guilds/automod/editAutomodRule.ts | 28 +++ .../src/guilds/automod/getAutomodRule.ts | 12 ++ .../src/guilds/automod/getAutomodRules.ts | 12 ++ plugins/permissions/src/guilds/automod/mod.ts | 14 ++ plugins/permissions/src/guilds/createGuild.ts | 19 +- plugins/permissions/src/guilds/deleteGuild.ts | 10 +- plugins/permissions/src/guilds/editGuild.ts | 10 +- .../src/guilds/editGuildMfaLevel.ts | 6 +- .../src/guilds/editWelcomeScreen.ts | 12 ++ .../src/guilds/editWidgetSettings.ts | 16 -- plugins/permissions/src/guilds/events.ts | 141 ------------- .../src/guilds/events/createScheduledEvent.ts | 69 ++++++ .../src/guilds/events/editScheduledEvent.ts | 69 ++++++ plugins/permissions/src/guilds/events/mod.ts | 8 + plugins/permissions/src/guilds/getAuditLog.ts | 6 +- plugins/permissions/src/guilds/getBan.ts | 6 +- plugins/permissions/src/guilds/getBans.ts | 6 +- .../permissions/src/guilds/getPruneCount.ts | 6 +- .../permissions/src/guilds/getVanityUrl.ts | 6 +- .../src/guilds/getWelcomeScreen.ts | 13 ++ .../src/guilds/invites/createInvite.ts | 12 ++ .../src/guilds/invites/getChannelInvites.ts | 12 ++ .../src/guilds/invites/getInvites.ts | 12 ++ plugins/permissions/src/guilds/mod.ts | 39 ++-- .../voice}/connectToVoiceChannels.ts | 16 +- plugins/permissions/src/guilds/voice/mod.ts | 6 + .../permissions/src/guilds/welcomeScreen.ts | 30 --- .../src/guilds/widgets/editWidgetSettings.ts | 12 ++ plugins/permissions/src/guilds/widgets/mod.ts | 6 + plugins/permissions/src/integrations.ts | 27 --- .../src/integrations/deleteIntegrations.ts | 12 ++ .../src/integrations/getIntegrations.ts | 12 ++ plugins/permissions/src/integrations/mod.ts | 8 + .../permissions/src/interactions/commands.ts | 192 ----------------- plugins/permissions/src/interactions/mod.ts | 39 ---- plugins/permissions/src/invites.ts | 47 ----- plugins/permissions/src/members/ban.ts | 27 --- plugins/permissions/src/members/banMember.ts | 12 ++ .../permissions/src/members/editBotMember.ts | 6 +- plugins/permissions/src/members/editMember.ts | 43 ++-- plugins/permissions/src/members/kickMember.ts | 6 +- plugins/permissions/src/members/mod.ts | 16 +- .../permissions/src/members/pruneMembers.ts | 6 +- .../permissions/src/members/unbanMember.ts | 12 ++ plugins/permissions/src/messages/create.ts | 198 ------------------ plugins/permissions/src/messages/delete.ts | 80 ------- .../permissions/src/messages/deleteMessage.ts | 25 +++ .../src/messages/deleteMessages.ts | 21 ++ .../permissions/src/messages/editMessage.ts | 18 ++ plugins/permissions/src/messages/get.ts | 44 ---- .../permissions/src/messages/getMessage.ts | 13 ++ .../permissions/src/messages/getMessages.ts | 18 ++ plugins/permissions/src/messages/mod.ts | 28 ++- plugins/permissions/src/messages/pin.ts | 37 ---- .../permissions/src/messages/pinMessage.ts | 17 ++ .../src/messages/publishMessage.ts | 18 ++ plugins/permissions/src/messages/reactions.ts | 60 ------ .../src/messages/reactions/addReaction.ts | 12 ++ .../src/messages/reactions/addReactions.ts | 12 ++ .../messages/reactions/deleteReactionsAll.ts | 12 ++ .../reactions/deleteReactionsEmoji.ts | 12 ++ .../reactions/deleteUserReaction.ts.ts | 12 ++ .../permissions/src/messages/reactions/mod.ts | 14 ++ .../permissions/src/messages/sendMessage.ts | 26 +++ .../permissions/src/messages/unpinMessage.ts | 12 ++ plugins/permissions/src/permissions.ts | 24 +-- .../src/roles/{add.ts => addRole.ts} | 16 +- plugins/permissions/src/roles/create.ts | 16 -- plugins/permissions/src/roles/createRole.ts | 12 ++ plugins/permissions/src/roles/delete.ts | 15 -- plugins/permissions/src/roles/deleteRole.ts | 12 ++ .../src/roles/{edit.ts => editRole.ts} | 6 +- plugins/permissions/src/roles/mod.ts | 14 +- .../src/roles/modifyRolePositions.ts | 4 +- .../src/roles/{remove.ts => removeRole.ts} | 9 +- .../permissions/src/webhooks/createWebhook.ts | 21 +- .../permissions/src/webhooks/deleteWebhook.ts | 6 +- .../permissions/src/webhooks/editWebhook.ts | 18 +- plugins/permissions/src/webhooks/mod.ts | 10 +- .../permissions/src/webhooks/sendWebhook.ts | 67 ------ plugins/validations/README.md | 18 ++ plugins/validations/deps.ts | 1 + plugins/validations/mod.ts | 36 ++++ .../src/applicationCommandLength.ts | 51 +++++ .../src/applicationCommandOptions.ts | 54 +++++ .../src/attachments.ts | 0 plugins/validations/src/channels/mod.ts | 6 + .../src/channels/threads/addThreadMember.ts | 11 + .../src/channels/threads/getThreadMember.ts | 11 + .../validations/src/channels/threads/mod.ts | 10 + .../channels/threads/removeThreadMember.ts | 11 + .../src/components.ts | 17 +- plugins/validations/src/guilds/createGuild.ts | 16 ++ .../src/guilds/events/createScheduledEvent.ts | 27 +++ plugins/validations/src/guilds/events/mod.ts | 6 + plugins/validations/src/guilds/mod.ts | 8 + .../createGlobalApplicationCommand.ts | 58 +++++ .../commands/createGuildApplicationCommand.ts | 44 ++++ .../src/interaction/commands/mod.ts | 8 + plugins/validations/src/interaction/mod.ts | 8 + .../responses}/editFollowupMessage.ts | 16 +- .../editOriginalInteractionResponse.ts | 35 ++++ .../src/interaction/responses/mod.ts | 10 + .../responses/sendInteractionResponse.ts | 25 +++ .../validations/src/invites/createInvite.ts | 16 ++ plugins/validations/src/invites/mod.ts | 6 + plugins/validations/src/members/editMember.ts | 11 + plugins/validations/src/members/mod.ts | 6 + .../src/messages/deleteMessages.ts | 29 +++ .../validations/src/messages/editMessage.ts | 60 ++++++ plugins/validations/src/messages/mod.ts | 10 + .../validations/src/messages/sendMessage.ts | 59 ++++++ .../src/misc/editBotProfile.ts} | 16 +- plugins/validations/src/misc/mod.ts | 6 + .../validations/src/webhooks/createWebhook.ts | 19 ++ .../validations/src/webhooks/editWebhook.ts | 21 ++ .../src/webhooks/editWebhookMessage.ts} | 16 +- plugins/validations/src/webhooks/mod.ts | 12 ++ .../src/webhooks/sendWebhookMessage.ts | 42 ++++ 155 files changed, 1794 insertions(+), 1704 deletions(-) delete mode 100644 plugins/permissions/src/channels/stage.ts create mode 100644 plugins/permissions/src/channels/stages/createStageInstance.ts create mode 100644 plugins/permissions/src/channels/stages/deleteStageInstances.ts create mode 100644 plugins/permissions/src/channels/stages/editStageInstance.ts create mode 100644 plugins/permissions/src/channels/stages/mod.ts delete mode 100644 plugins/permissions/src/channels/threads/getThreadMembers.ts delete mode 100644 plugins/permissions/src/editMember.ts delete mode 100644 plugins/permissions/src/emojis.ts create mode 100644 plugins/permissions/src/emojis/createEmoji.ts create mode 100644 plugins/permissions/src/emojis/deleteEmoji.ts create mode 100644 plugins/permissions/src/emojis/editEmoji.ts create mode 100644 plugins/permissions/src/emojis/mod.ts delete mode 100644 plugins/permissions/src/guilds/automod.ts create mode 100644 plugins/permissions/src/guilds/automod/createAutomodRule.ts create mode 100644 plugins/permissions/src/guilds/automod/deleteAutomodRule.ts create mode 100644 plugins/permissions/src/guilds/automod/editAutomodRule.ts create mode 100644 plugins/permissions/src/guilds/automod/getAutomodRule.ts create mode 100644 plugins/permissions/src/guilds/automod/getAutomodRules.ts create mode 100644 plugins/permissions/src/guilds/automod/mod.ts create mode 100644 plugins/permissions/src/guilds/editWelcomeScreen.ts delete mode 100644 plugins/permissions/src/guilds/editWidgetSettings.ts delete mode 100644 plugins/permissions/src/guilds/events.ts create mode 100644 plugins/permissions/src/guilds/events/createScheduledEvent.ts create mode 100644 plugins/permissions/src/guilds/events/editScheduledEvent.ts create mode 100644 plugins/permissions/src/guilds/events/mod.ts create mode 100644 plugins/permissions/src/guilds/getWelcomeScreen.ts create mode 100644 plugins/permissions/src/guilds/invites/createInvite.ts create mode 100644 plugins/permissions/src/guilds/invites/getChannelInvites.ts create mode 100644 plugins/permissions/src/guilds/invites/getInvites.ts rename plugins/permissions/src/{ => guilds/voice}/connectToVoiceChannels.ts (73%) create mode 100644 plugins/permissions/src/guilds/voice/mod.ts delete mode 100644 plugins/permissions/src/guilds/welcomeScreen.ts create mode 100644 plugins/permissions/src/guilds/widgets/editWidgetSettings.ts create mode 100644 plugins/permissions/src/guilds/widgets/mod.ts delete mode 100644 plugins/permissions/src/integrations.ts create mode 100644 plugins/permissions/src/integrations/deleteIntegrations.ts create mode 100644 plugins/permissions/src/integrations/getIntegrations.ts create mode 100644 plugins/permissions/src/integrations/mod.ts delete mode 100644 plugins/permissions/src/interactions/commands.ts delete mode 100644 plugins/permissions/src/interactions/mod.ts delete mode 100644 plugins/permissions/src/invites.ts delete mode 100644 plugins/permissions/src/members/ban.ts create mode 100644 plugins/permissions/src/members/banMember.ts create mode 100644 plugins/permissions/src/members/unbanMember.ts delete mode 100644 plugins/permissions/src/messages/create.ts delete mode 100644 plugins/permissions/src/messages/delete.ts create mode 100644 plugins/permissions/src/messages/deleteMessage.ts create mode 100644 plugins/permissions/src/messages/deleteMessages.ts create mode 100644 plugins/permissions/src/messages/editMessage.ts delete mode 100644 plugins/permissions/src/messages/get.ts create mode 100644 plugins/permissions/src/messages/getMessage.ts create mode 100644 plugins/permissions/src/messages/getMessages.ts delete mode 100644 plugins/permissions/src/messages/pin.ts create mode 100644 plugins/permissions/src/messages/pinMessage.ts create mode 100644 plugins/permissions/src/messages/publishMessage.ts delete mode 100644 plugins/permissions/src/messages/reactions.ts create mode 100644 plugins/permissions/src/messages/reactions/addReaction.ts create mode 100644 plugins/permissions/src/messages/reactions/addReactions.ts create mode 100644 plugins/permissions/src/messages/reactions/deleteReactionsAll.ts create mode 100644 plugins/permissions/src/messages/reactions/deleteReactionsEmoji.ts create mode 100644 plugins/permissions/src/messages/reactions/deleteUserReaction.ts.ts create mode 100644 plugins/permissions/src/messages/reactions/mod.ts create mode 100644 plugins/permissions/src/messages/sendMessage.ts create mode 100644 plugins/permissions/src/messages/unpinMessage.ts rename plugins/permissions/src/roles/{add.ts => addRole.ts} (58%) delete mode 100644 plugins/permissions/src/roles/create.ts create mode 100644 plugins/permissions/src/roles/createRole.ts delete mode 100644 plugins/permissions/src/roles/delete.ts create mode 100644 plugins/permissions/src/roles/deleteRole.ts rename plugins/permissions/src/roles/{edit.ts => editRole.ts} (83%) rename plugins/permissions/src/roles/{remove.ts => removeRole.ts} (68%) delete mode 100644 plugins/permissions/src/webhooks/sendWebhook.ts create mode 100644 plugins/validations/README.md create mode 100644 plugins/validations/deps.ts create mode 100644 plugins/validations/mod.ts create mode 100644 plugins/validations/src/applicationCommandLength.ts create mode 100644 plugins/validations/src/applicationCommandOptions.ts rename plugins/{permissions => validations}/src/attachments.ts (100%) create mode 100644 plugins/validations/src/channels/mod.ts create mode 100644 plugins/validations/src/channels/threads/addThreadMember.ts create mode 100644 plugins/validations/src/channels/threads/getThreadMember.ts create mode 100644 plugins/validations/src/channels/threads/mod.ts create mode 100644 plugins/validations/src/channels/threads/removeThreadMember.ts rename plugins/{permissions => validations}/src/components.ts (92%) create mode 100644 plugins/validations/src/guilds/createGuild.ts create mode 100644 plugins/validations/src/guilds/events/createScheduledEvent.ts create mode 100644 plugins/validations/src/guilds/events/mod.ts create mode 100644 plugins/validations/src/guilds/mod.ts create mode 100644 plugins/validations/src/interaction/commands/createGlobalApplicationCommand.ts create mode 100644 plugins/validations/src/interaction/commands/createGuildApplicationCommand.ts create mode 100644 plugins/validations/src/interaction/commands/mod.ts create mode 100644 plugins/validations/src/interaction/mod.ts rename plugins/{permissions/src/interactions => validations/src/interaction/responses}/editFollowupMessage.ts (67%) create mode 100644 plugins/validations/src/interaction/responses/editOriginalInteractionResponse.ts create mode 100644 plugins/validations/src/interaction/responses/mod.ts create mode 100644 plugins/validations/src/interaction/responses/sendInteractionResponse.ts create mode 100644 plugins/validations/src/invites/createInvite.ts create mode 100644 plugins/validations/src/invites/mod.ts create mode 100644 plugins/validations/src/members/editMember.ts create mode 100644 plugins/validations/src/members/mod.ts create mode 100644 plugins/validations/src/messages/deleteMessages.ts create mode 100644 plugins/validations/src/messages/editMessage.ts create mode 100644 plugins/validations/src/messages/mod.ts create mode 100644 plugins/validations/src/messages/sendMessage.ts rename plugins/{permissions/src/misc/mod.ts => validations/src/misc/editBotProfile.ts} (73%) create mode 100644 plugins/validations/src/misc/mod.ts create mode 100644 plugins/validations/src/webhooks/createWebhook.ts create mode 100644 plugins/validations/src/webhooks/editWebhook.ts rename plugins/{permissions/src/webhooks/message.ts => validations/src/webhooks/editWebhookMessage.ts} (72%) create mode 100644 plugins/validations/src/webhooks/mod.ts create mode 100644 plugins/validations/src/webhooks/sendWebhookMessage.ts diff --git a/plugins/mod.ts b/plugins/mod.ts index 8053d1315..dabe63048 100644 --- a/plugins/mod.ts +++ b/plugins/mod.ts @@ -2,3 +2,4 @@ export * from "./cache/mod.ts"; export * from "./fileloader/mod.ts"; export * from "./helpers/mod.ts"; export * from "./permissions/mod.ts"; +export * from "./validations/mod.ts"; diff --git a/plugins/permissions/mod.ts b/plugins/permissions/mod.ts index b62a174ee..8c5f1e6d3 100644 --- a/plugins/permissions/mod.ts +++ b/plugins/permissions/mod.ts @@ -1,49 +1,37 @@ -import { Bot, BotWithCache } from "./deps.ts"; -import setupChannelPermChecks from "./src/channels/mod.ts"; +import { BotWithCache } from "./deps.ts"; +import { channels } from "./src/channels/mod.ts"; import setupDiscoveryPermChecks from "./src/discovery.ts"; -import setupEditMember from "./src/editMember.ts"; -import setupEmojiPermChecks from "./src/emojis.ts"; -import setupGuildPermChecks from "./src/guilds/mod.ts"; -import setupIntegrationPermChecks from "./src/integrations.ts"; -import setupInteractionPermChecks from "./src/interactions/mod.ts"; -import setupInvitesPermChecks from "./src/invites.ts"; -import setupMemberPermChecks from "./src/members/mod.ts"; -import setupMessagePermChecks from "./src/messages/mod.ts"; -import setupMiscPermChecks from "./src/misc/mod.ts"; -import setupRolePermChecks from "./src/roles/mod.ts"; -import setupWebhooksPermChecks from "./src/webhooks/mod.ts"; +import { emojis } from "./src/emojis/mod.ts"; +import { guilds } from "./src/guilds/mod.ts"; +import { integrations } from "./src/integrations/mod.ts"; +import { members } from "./src/members/mod.ts"; +import { messages } from "./src/messages/mod.ts"; +import { roles } from "./src/roles/mod.ts"; +import { webhooks } from "./src/webhooks/mod.ts"; // PLUGINS MUST TAKE A BOT ARGUMENT WHICH WILL BE MODIFIED export function enablePermissionsPlugin(bot: B): B { // PERM CHECKS REQUIRE CACHE DUH! - if (!bot.enabledPlugins?.has("CACHE")) { - throw new Error("The PERMISSIONS plugin requires the CACHE plugin first."); - } + if (!bot.enabledPlugins?.has("CACHE")) throw new Error("The PERMISSIONS plugin requires the CACHE plugin first."); // MARK THIS PLUGIN BEING USED bot.enabledPlugins.add("PERMISSIONS"); // BEGIN OVERRIDING HELPER FUNCTIONS - setupChannelPermChecks(bot); setupDiscoveryPermChecks(bot); - setupEmojiPermChecks(bot); - setupEditMember(bot); - setupGuildPermChecks(bot); - setupIntegrationPermChecks(bot); - setupInteractionPermChecks(bot); - setupInvitesPermChecks(bot); - setupMemberPermChecks(bot); - setupMessagePermChecks(bot); - setupMiscPermChecks(bot); - setupRolePermChecks(bot); - setupWebhooksPermChecks(bot); + channels(bot); + emojis(bot); + guilds(bot); + integrations(bot); + members(bot); + messages(bot); + roles(bot); + webhooks(bot); // PLUGINS MUST RETURN THE BOT return bot; } -// EXPORT ALL UTIL FUNCTIONS export * from "./src/permissions.ts"; -export * from "./src/components.ts"; // DEFAULT MAKES IT SLIGHTLY EASIER TO USE export default enablePermissionsPlugin; diff --git a/plugins/permissions/src/channels/createChannel.ts b/plugins/permissions/src/channels/createChannel.ts index 19390809c..36ee08efa 100644 --- a/plugins/permissions/src/channels/createChannel.ts +++ b/plugins/permissions/src/channels/createChannel.ts @@ -1,8 +1,8 @@ import { BotWithCache, ChannelTypes, PermissionStrings } from "../../deps.ts"; import { requireBotGuildPermissions } from "../permissions.ts"; -export default function createChannel(bot: BotWithCache) { - const createChannelOld = bot.helpers.createChannel; +export function createChannel(bot: BotWithCache) { + const createChannel = bot.helpers.createChannel; bot.helpers.createChannel = async function (guildId, options, reason) { const guild = bot.guilds.get(guildId); @@ -35,9 +35,7 @@ export default function createChannel(bot: BotWithCache) { throw new Error("The topic length must be between 1 and 1024 (4096 if forum)"); } - if (options?.userLimit && options.userLimit > 99) { - throw new Error("The user limit must be less than 99."); - } + if (options?.userLimit && options.userLimit > 99) throw new Error("The user limit must be less than 99."); if (options?.parentId) { const category = bot.channels.get(options.parentId); @@ -49,6 +47,6 @@ export default function createChannel(bot: BotWithCache) { requireBotGuildPermissions(bot, guild, requiredPerms); } - return await createChannelOld(guildId, options, reason); + return await createChannel(guildId, options, reason); }; } diff --git a/plugins/permissions/src/channels/deleteChannel.ts b/plugins/permissions/src/channels/deleteChannel.ts index 615057fd9..97381034b 100644 --- a/plugins/permissions/src/channels/deleteChannel.ts +++ b/plugins/permissions/src/channels/deleteChannel.ts @@ -1,8 +1,8 @@ import { BotWithCache, ChannelTypes } from "../../deps.ts"; import { requireBotGuildPermissions } from "../permissions.ts"; -export default function deleteChannel(bot: BotWithCache) { - const deleteChannelOld = bot.helpers.deleteChannel; +export function deleteChannel(bot: BotWithCache) { + const deleteChannel = bot.helpers.deleteChannel; bot.helpers.deleteChannel = async function (channelId, reason) { const channel = bot.channels.get(channelId); @@ -11,13 +11,9 @@ export default function deleteChannel(bot: BotWithCache) { const guild = bot.guilds.get(channel.guildId); if (!guild) throw new Error("GUILD_NOT_FOUND"); - if (guild.rulesChannelId === channelId) { - throw new Error("RULES_CHANNEL_CANNOT_BE_DELETED"); - } + if (guild.rulesChannelId === channelId) throw new Error("RULES_CHANNEL_CANNOT_BE_DELETED"); - if (guild.publicUpdatesChannelId === channelId) { - throw new Error("UPDATES_CHANNEL_CANNOT_BE_DELETED"); - } + if (guild.publicUpdatesChannelId === channelId) throw new Error("UPDATES_CHANNEL_CANNOT_BE_DELETED"); const isThread = [ChannelTypes.AnnouncementThread, ChannelTypes.PublicThread, ChannelTypes.PrivateThread] .includes(channel.type); @@ -25,6 +21,6 @@ export default function deleteChannel(bot: BotWithCache) { requireBotGuildPermissions(bot, guild, isThread ? ["MANAGE_THREADS"] : ["MANAGE_CHANNELS"]); } - return await deleteChannelOld(channelId, reason); + return await deleteChannel(channelId, reason); }; } diff --git a/plugins/permissions/src/channels/deleteChannelPermissionOverride.ts b/plugins/permissions/src/channels/deleteChannelPermissionOverride.ts index baab11c22..154e87211 100644 --- a/plugins/permissions/src/channels/deleteChannelPermissionOverride.ts +++ b/plugins/permissions/src/channels/deleteChannelPermissionOverride.ts @@ -1,16 +1,14 @@ import { BotWithCache } from "../../deps.ts"; import { requireBotChannelPermissions } from "../permissions.ts"; -export default function deleteChannelPermissionOverride(bot: BotWithCache) { - const deleteChannelPermissionOverrideOld = bot.helpers.deleteChannelPermissionOverride; +export function deleteChannelPermissionOverride(bot: BotWithCache) { + const deleteChannelPermissionOverride = bot.helpers.deleteChannelPermissionOverride; bot.helpers.deleteChannelPermissionOverride = async function (channelId, overwriteId) { const channel = bot.channels.get(channelId); - if (channel?.guildId) { - requireBotChannelPermissions(bot, channelId, ["MANAGE_ROLES"]); - } + if (channel?.guildId) requireBotChannelPermissions(bot, channelId, ["MANAGE_ROLES"]); - return await deleteChannelPermissionOverrideOld(channelId, overwriteId); + return await deleteChannelPermissionOverride(channelId, overwriteId); }; } diff --git a/plugins/permissions/src/channels/editChannel.ts b/plugins/permissions/src/channels/editChannel.ts index 6a06a465c..e3923f353 100644 --- a/plugins/permissions/src/channels/editChannel.ts +++ b/plugins/permissions/src/channels/editChannel.ts @@ -1,8 +1,8 @@ import { BotWithCache, ChannelTypes, PermissionStrings } from "../../deps.ts"; import { requireBotChannelPermissions } from "../permissions.ts"; -export default function editChannel(bot: BotWithCache) { - const editChannelOld = bot.helpers.editChannel; +export function editChannel(bot: BotWithCache) { + const editChannel = bot.helpers.editChannel; bot.helpers.editChannel = async function (channelId, options, reason) { const channel = bot.channels.get(channelId); @@ -33,18 +33,14 @@ export default function editChannel(bot: BotWithCache) { if (!channel.locked && options.archived === false) { requiredPerms.push("SEND_MESSAGES"); // MORE THAN ARCHIVE WAS MODIFIED - if (Object.keys(options).length > 1) { - requiredPerms.push("MANAGE_THREADS"); - } + if (Object.keys(options).length > 1) requiredPerms.push("MANAGE_THREADS"); } else { requiredPerms.push("MANAGE_THREADS"); } } else { requiredPerms.push("MANAGE_CHANNELS"); - if (options.permissionOverwrites) { - requiredPerms.push("MANAGE_ROLES"); - } + if (options.permissionOverwrites) requiredPerms.push("MANAGE_ROLES"); if (options.type) { if ([ChannelTypes.GuildAnnouncement, ChannelTypes.GuildText].includes(options.type)) { @@ -62,9 +58,7 @@ export default function editChannel(bot: BotWithCache) { } } - if (options.userLimit && options.userLimit > 99) { - throw new Error("The user limit must be less than 99."); - } + if (options.userLimit && options.userLimit > 99) throw new Error("The user limit must be less than 99."); if (options.parentId) { const category = bot.channels.get(options.parentId); @@ -77,6 +71,6 @@ export default function editChannel(bot: BotWithCache) { requireBotChannelPermissions(bot, channel, requiredPerms); } - return await editChannelOld(channelId, options, reason); + return await editChannel(channelId, options, reason); }; } diff --git a/plugins/permissions/src/channels/editChannelPermissionOverrides.ts b/plugins/permissions/src/channels/editChannelPermissionOverrides.ts index 715ba6c59..4b6c0e12c 100644 --- a/plugins/permissions/src/channels/editChannelPermissionOverrides.ts +++ b/plugins/permissions/src/channels/editChannelPermissionOverrides.ts @@ -1,15 +1,13 @@ import { BotWithCache } from "../../deps.ts"; import { requireBotChannelPermissions } from "../permissions.ts"; -export default function editChannelPermissionOverrides(bot: BotWithCache) { - const editChannelPermissionOverridesOld = bot.helpers.editChannelPermissionOverrides; +export function editChannelPermissionOverrides(bot: BotWithCache) { + const editChannelPermissionOverrides = bot.helpers.editChannelPermissionOverrides; bot.helpers.editChannelPermissionOverrides = async function (channelId, overwrite) { const channel = bot.channels.get(channelId); - if (channel?.guildId) { - requireBotChannelPermissions(bot, channelId, ["MANAGE_ROLES"]); - } + if (channel?.guildId) requireBotChannelPermissions(bot, channelId, ["MANAGE_ROLES"]); - return await editChannelPermissionOverridesOld(channelId, overwrite); + return await editChannelPermissionOverrides(channelId, overwrite); }; } diff --git a/plugins/permissions/src/channels/followAnnouncementChannel.ts b/plugins/permissions/src/channels/followAnnouncementChannel.ts index a92c75226..80a351e78 100644 --- a/plugins/permissions/src/channels/followAnnouncementChannel.ts +++ b/plugins/permissions/src/channels/followAnnouncementChannel.ts @@ -1,15 +1,13 @@ import { BotWithCache } from "../../deps.ts"; import { requireBotChannelPermissions } from "../permissions.ts"; -export default function followAnnouncementChannel(bot: BotWithCache) { - const followAnnouncementChannelOld = bot.helpers.followAnnouncementChannel; +export function followAnnouncementChannel(bot: BotWithCache) { + const followAnnouncementChannel = bot.helpers.followAnnouncementChannel; bot.helpers.followAnnouncementChannel = async function (sourceChannelId, targetChannelId) { const channel = bot.channels.get(targetChannelId); - if (channel?.guildId) { - requireBotChannelPermissions(bot, channel, ["MANAGE_WEBHOOKS"]); - } + if (channel?.guildId) requireBotChannelPermissions(bot, channel, ["MANAGE_WEBHOOKS"]); - return await followAnnouncementChannelOld(sourceChannelId, targetChannelId); + return await followAnnouncementChannel(sourceChannelId, targetChannelId); }; } diff --git a/plugins/permissions/src/channels/forums/createForumThread.ts b/plugins/permissions/src/channels/forums/createForumThread.ts index 40d38e5a9..35659ddca 100644 --- a/plugins/permissions/src/channels/forums/createForumThread.ts +++ b/plugins/permissions/src/channels/forums/createForumThread.ts @@ -1,16 +1,14 @@ import { BotWithCache } from "../../../deps.ts"; import { requireBotChannelPermissions } from "../../permissions.ts"; -export default function createForumThread(bot: BotWithCache) { - const createForumThreadOld = bot.helpers.createForumThread; +export function createForumThread(bot: BotWithCache) { + const createForumThread = bot.helpers.createForumThread; bot.helpers.createForumThread = async function (channelId, options) { const channel = bot.channels.get(channelId); - if (channel) { - requireBotChannelPermissions(bot, channel, ["SEND_MESSAGES"]); - } + if (channel) requireBotChannelPermissions(bot, channel, ["SEND_MESSAGES"]); - return await createForumThreadOld(channelId, options); + return await createForumThread(channelId, options); }; } diff --git a/plugins/permissions/src/channels/forums/mod.ts b/plugins/permissions/src/channels/forums/mod.ts index d8268c7ba..daac80082 100644 --- a/plugins/permissions/src/channels/forums/mod.ts +++ b/plugins/permissions/src/channels/forums/mod.ts @@ -1,6 +1,6 @@ import { BotWithCache } from "../../../deps.ts"; -import createForumThread from "./createForumThread.ts"; +import { createForumThread } from "./createForumThread.ts"; -export default function setupThreadPermChecks(bot: BotWithCache) { +export function forums(bot: BotWithCache) { createForumThread(bot); } diff --git a/plugins/permissions/src/channels/getChannelWebhooks.ts b/plugins/permissions/src/channels/getChannelWebhooks.ts index 15b911ea5..666b340a7 100644 --- a/plugins/permissions/src/channels/getChannelWebhooks.ts +++ b/plugins/permissions/src/channels/getChannelWebhooks.ts @@ -1,15 +1,13 @@ import { BotWithCache } from "../../deps.ts"; import { requireBotChannelPermissions } from "../permissions.ts"; -export default function getChannelWebhooks(bot: BotWithCache) { - const getChannelWebhooksOld = bot.helpers.getChannelWebhooks; +export function getChannelWebhooks(bot: BotWithCache) { + const getChannelWebhooks = bot.helpers.getChannelWebhooks; bot.helpers.getChannelWebhooks = async function (channelId) { const channel = bot.channels.get(channelId); - if (channel?.guildId) { - requireBotChannelPermissions(bot, channelId, ["MANAGE_WEBHOOKS"]); - } + if (channel?.guildId) requireBotChannelPermissions(bot, channelId, ["MANAGE_WEBHOOKS"]); - return await getChannelWebhooksOld(channelId); + return await getChannelWebhooks(channelId); }; } diff --git a/plugins/permissions/src/channels/mod.ts b/plugins/permissions/src/channels/mod.ts index 316abf59e..158b23562 100644 --- a/plugins/permissions/src/channels/mod.ts +++ b/plugins/permissions/src/channels/mod.ts @@ -1,21 +1,22 @@ import { BotWithCache } from "../../deps.ts"; -import createChannel from "./createChannel.ts"; -import deleteChannel from "./deleteChannel.ts"; -import deleteChannelPermissionOverride from "./deleteChannelPermissionOverride.ts"; -import editChannel from "./editChannel.ts"; -import editChannelPermissionOverrides from "./editChannelPermissionOverrides.ts"; -import followAnnouncementChannel from "./followAnnouncementChannel.ts"; -import setupForumPermChecks from "./forums/mod.ts"; -import getChannelWebhooks from "./getChannelWebhooks.ts"; -import setupStagePermChecks from "./stage.ts"; -import swapChannels from "./swapChannels.ts"; -import setupThreadPermChecks from "./threads/mod.ts"; +import { createChannel } from "./createChannel.ts"; +import { deleteChannel } from "./deleteChannel.ts"; +import { deleteChannelPermissionOverride } from "./deleteChannelPermissionOverride.ts"; +import { editChannel } from "./editChannel.ts"; +import { editChannelPermissionOverrides } from "./editChannelPermissionOverrides.ts"; +import { followAnnouncementChannel } from "./followAnnouncementChannel.ts"; +import { forums } from "./forums/mod.ts"; +import { getChannelWebhooks } from "./getChannelWebhooks.ts"; +import { stages } from "./stages/mod.ts"; +import { swapChannels } from "./swapChannels.ts"; +import { threads } from "./threads/mod.ts"; + +export function channels(bot: BotWithCache) { + forums(bot); + stages(bot); + threads(bot); -export default function setupChannelPermChecks(bot: BotWithCache) { createChannel(bot); - setupThreadPermChecks(bot); - setupForumPermChecks(bot); - setupStagePermChecks(bot); deleteChannel(bot); deleteChannelPermissionOverride(bot); editChannel(bot); diff --git a/plugins/permissions/src/channels/stage.ts b/plugins/permissions/src/channels/stage.ts deleted file mode 100644 index dff510951..000000000 --- a/plugins/permissions/src/channels/stage.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { BotWithCache, PermissionStrings } from "../../deps.ts"; -import { requireBotChannelPermissions } from "../permissions.ts"; - -export function createStageInstance(bot: BotWithCache) { - const createStageInstanceOld = bot.helpers.createStageInstance; - - bot.helpers.createStageInstance = async function (options) { - if (!bot.utils.validateLength(options.topic, { max: 120, min: 1 })) { - throw new Error("The topic length for creating a stage instance must be between 1-120."); - } - - const perms = new Set(["MANAGE_CHANNELS", "MUTE_MEMBERS", "MOVE_MEMBERS"]); - - if (options.sendStartNotification) { - perms.add("MENTION_EVERYONE"); - } - - requireBotChannelPermissions(bot, options.channelId, [...perms.values()]); - - return await createStageInstanceOld(options); - }; -} - -export function deleteStageInstance(bot: BotWithCache) { - const deleteStageInstanceOld = bot.helpers.deleteStageInstance; - - bot.helpers.deleteStageInstance = async function (channelId) { - requireBotChannelPermissions(bot, channelId, ["MANAGE_CHANNELS", "MUTE_MEMBERS", "MOVE_MEMBERS"]); - - return await deleteStageInstanceOld(channelId); - }; -} - -export function editStageInstance(bot: BotWithCache) { - const editStageInstanceOld = bot.helpers.editStageInstance; - - bot.helpers.editStageInstance = async function (channelId, data) { - requireBotChannelPermissions(bot, channelId, ["MANAGE_CHANNELS", "MUTE_MEMBERS", "MOVE_MEMBERS"]); - - return await editStageInstanceOld(channelId, data); - }; -} - -export default function setupStagePermChecks(bot: BotWithCache) { - createStageInstance(bot); - deleteStageInstance(bot); - editStageInstance(bot); -} diff --git a/plugins/permissions/src/channels/stages/createStageInstance.ts b/plugins/permissions/src/channels/stages/createStageInstance.ts new file mode 100644 index 000000000..234977ac5 --- /dev/null +++ b/plugins/permissions/src/channels/stages/createStageInstance.ts @@ -0,0 +1,16 @@ +import { BotWithCache, PermissionStrings } from "../../../deps.ts"; +import { requireBotChannelPermissions } from "../../permissions.ts"; + +export function createStageInstance(bot: BotWithCache) { + const createStageInstance = bot.helpers.createStageInstance; + + bot.helpers.createStageInstance = async function (options) { + const perms: PermissionStrings[] = ["MANAGE_CHANNELS", "MUTE_MEMBERS", "MOVE_MEMBERS"]; + + if (options.sendStartNotification) perms.push("MENTION_EVERYONE"); + + requireBotChannelPermissions(bot, options.channelId, perms); + + return await createStageInstance(options); + }; +} diff --git a/plugins/permissions/src/channels/stages/deleteStageInstances.ts b/plugins/permissions/src/channels/stages/deleteStageInstances.ts new file mode 100644 index 000000000..1692df2c7 --- /dev/null +++ b/plugins/permissions/src/channels/stages/deleteStageInstances.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../../deps.ts"; +import { requireBotChannelPermissions } from "../../permissions.ts"; + +export function deleteStageInstance(bot: BotWithCache) { + const deleteStageInstance = bot.helpers.deleteStageInstance; + + bot.helpers.deleteStageInstance = async function (channelId) { + requireBotChannelPermissions(bot, channelId, ["MANAGE_CHANNELS", "MUTE_MEMBERS", "MOVE_MEMBERS"]); + + return await deleteStageInstance(channelId); + }; +} diff --git a/plugins/permissions/src/channels/stages/editStageInstance.ts b/plugins/permissions/src/channels/stages/editStageInstance.ts new file mode 100644 index 000000000..8b15ad0ab --- /dev/null +++ b/plugins/permissions/src/channels/stages/editStageInstance.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../../deps.ts"; +import { requireBotChannelPermissions } from "../../permissions.ts"; + +export function editStageInstance(bot: BotWithCache) { + const editStageInstance = bot.helpers.editStageInstance; + + bot.helpers.editStageInstance = async function (channelId, data) { + requireBotChannelPermissions(bot, channelId, ["MANAGE_CHANNELS", "MUTE_MEMBERS", "MOVE_MEMBERS"]); + + return await editStageInstance(channelId, data); + }; +} diff --git a/plugins/permissions/src/channels/stages/mod.ts b/plugins/permissions/src/channels/stages/mod.ts new file mode 100644 index 000000000..45af3de5a --- /dev/null +++ b/plugins/permissions/src/channels/stages/mod.ts @@ -0,0 +1,10 @@ +import { BotWithCache } from "../../../deps.ts"; +import { createStageInstance } from "./createStageInstance.ts"; +import { deleteStageInstance } from "./deleteStageInstances.ts"; +import { editStageInstance } from "./editStageInstance.ts"; + +export function stages(bot: BotWithCache) { + createStageInstance(bot); + deleteStageInstance(bot); + editStageInstance(bot); +} diff --git a/plugins/permissions/src/channels/swapChannels.ts b/plugins/permissions/src/channels/swapChannels.ts index 61680d46b..1c1e0a7ee 100644 --- a/plugins/permissions/src/channels/swapChannels.ts +++ b/plugins/permissions/src/channels/swapChannels.ts @@ -1,12 +1,12 @@ import { BotWithCache } from "../../deps.ts"; import { requireBotGuildPermissions } from "../permissions.ts"; -export default function swapChannels(bot: BotWithCache) { - const swapChannelsOld = bot.helpers.swapChannels; +export function swapChannels(bot: BotWithCache) { + const swapChannels = bot.helpers.swapChannels; bot.helpers.swapChannels = async function (guildId, channelPositions) { requireBotGuildPermissions(bot, guildId, ["MANAGE_CHANNELS"]); - return await swapChannelsOld(guildId, channelPositions); + return await swapChannels(guildId, channelPositions); }; } diff --git a/plugins/permissions/src/channels/threads/addThreadMember.ts b/plugins/permissions/src/channels/threads/addThreadMember.ts index 599b11a96..c67526d11 100644 --- a/plugins/permissions/src/channels/threads/addThreadMember.ts +++ b/plugins/permissions/src/channels/threads/addThreadMember.ts @@ -1,24 +1,18 @@ import { BotWithCache } from "../../../deps.ts"; import { requireBotChannelPermissions } from "../../permissions.ts"; -export default function addThreadMember(bot: BotWithCache) { - const addThreadMemberOld = bot.helpers.addThreadMember; +export function addThreadMember(bot: BotWithCache) { + const addThreadMember = bot.helpers.addThreadMember; bot.helpers.addThreadMember = async function (threadId, userId) { - if (userId === bot.id) { - throw new Error("To add the bot to a thread, you must use bot.helpers.joinThread()"); - } - const channel = bot.channels.get(threadId); if (channel) { - if (channel.archived) { - throw new Error("Cannot add user to thread if thread is archived."); - } + if (channel.archived) throw new Error("Cannot add user to thread if thread is archived."); requireBotChannelPermissions(bot, channel, ["SEND_MESSAGES"]); } - return await addThreadMemberOld(threadId, userId); + return await addThreadMember(threadId, userId); }; } diff --git a/plugins/permissions/src/channels/threads/getPrivateArchivedThreads.ts b/plugins/permissions/src/channels/threads/getPrivateArchivedThreads.ts index 6d4343a87..69f119f94 100644 --- a/plugins/permissions/src/channels/threads/getPrivateArchivedThreads.ts +++ b/plugins/permissions/src/channels/threads/getPrivateArchivedThreads.ts @@ -2,12 +2,10 @@ import { BotWithCache } from "../../../deps.ts"; import { requireBotChannelPermissions } from "../../permissions.ts"; export function getPrivateArchivedThreads(bot: BotWithCache) { - const getPrivateArchivedThreadsOld = bot.helpers.getPrivateArchivedThreads; - bot.helpers.getPublicArchivedThreads = async function (channelId, options) { + const getPrivateArchivedThreads = bot.helpers.getPrivateArchivedThreads; + bot.helpers.getPrivateArchivedThreads = async function (channelId, options) { const channel = bot.channels.get(channelId); - if (channel) { - requireBotChannelPermissions(bot, channel, ["READ_MESSAGE_HISTORY", "MANAGE_MESSAGES"]); - } - return await getPrivateArchivedThreadsOld(channelId, options); + if (channel) requireBotChannelPermissions(bot, channel, ["READ_MESSAGE_HISTORY", "MANAGE_MESSAGES"]); + return await getPrivateArchivedThreads(channelId, options); }; } diff --git a/plugins/permissions/src/channels/threads/getPrivateJoinedArchivedThreads.ts b/plugins/permissions/src/channels/threads/getPrivateJoinedArchivedThreads.ts index 540001c8c..e16828479 100644 --- a/plugins/permissions/src/channels/threads/getPrivateJoinedArchivedThreads.ts +++ b/plugins/permissions/src/channels/threads/getPrivateJoinedArchivedThreads.ts @@ -2,12 +2,10 @@ import { BotWithCache } from "../../../deps.ts"; import { requireBotChannelPermissions } from "../../permissions.ts"; export function getPrivateJoinedArchivedThreads(bot: BotWithCache) { - const getPrivateJoinedArchivedThreadsOld = bot.helpers.getPrivateJoinedArchivedThreads; - bot.helpers.getPublicArchivedThreads = async function (channelId, options) { + const getPrivateJoinedArchivedThreads = bot.helpers.getPrivateJoinedArchivedThreads; + bot.helpers.getPrivateJoinedArchivedThreads = async function (channelId, options) { const channel = bot.channels.get(channelId); - if (channel) { - requireBotChannelPermissions(bot, channel, ["READ_MESSAGE_HISTORY"]); - } - return await getPrivateJoinedArchivedThreadsOld(channelId, options); + if (channel) requireBotChannelPermissions(bot, channel, ["READ_MESSAGE_HISTORY"]); + return await getPrivateJoinedArchivedThreads(channelId, options); }; } diff --git a/plugins/permissions/src/channels/threads/getPublicArchivedThreads.ts b/plugins/permissions/src/channels/threads/getPublicArchivedThreads.ts index 7fafa864a..81cd1abb9 100644 --- a/plugins/permissions/src/channels/threads/getPublicArchivedThreads.ts +++ b/plugins/permissions/src/channels/threads/getPublicArchivedThreads.ts @@ -2,12 +2,10 @@ import { BotWithCache } from "../../../deps.ts"; import { requireBotChannelPermissions } from "../../permissions.ts"; export function getPublicArchivedThreads(bot: BotWithCache) { - const getPublicArchivedThreadsOld = bot.helpers.getPublicArchivedThreads; + const getPublicArchivedThreads = bot.helpers.getPublicArchivedThreads; bot.helpers.getPublicArchivedThreads = async function (channelId, options) { const channel = bot.channels.get(channelId); - if (channel) { - requireBotChannelPermissions(bot, channel, ["READ_MESSAGE_HISTORY"]); - } - return await getPublicArchivedThreadsOld(channelId, options); + if (channel) requireBotChannelPermissions(bot, channel, ["READ_MESSAGE_HISTORY"]); + return await getPublicArchivedThreads(channelId, options); }; } diff --git a/plugins/permissions/src/channels/threads/getThreadMembers.ts b/plugins/permissions/src/channels/threads/getThreadMembers.ts deleted file mode 100644 index 3a5ff6096..000000000 --- a/plugins/permissions/src/channels/threads/getThreadMembers.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { BotWithCache, GatewayIntents } from "../../../deps.ts"; - -export default function getThreadMembers(bot: BotWithCache) { - const getThreadMembersOld = bot.helpers.getThreadMembers; - - bot.helpers.getThreadMembers = async function (threadId) { - const hasIntent = bot.intents & GatewayIntents.GuildMembers; - if (!hasIntent) { - throw new Error( - "The get thread members endpoint requires GuildMembers intent.", - ); - } - - return await getThreadMembersOld(threadId); - }; -} diff --git a/plugins/permissions/src/channels/threads/joinThread.ts b/plugins/permissions/src/channels/threads/joinThread.ts index c50a06d7e..013ad030c 100644 --- a/plugins/permissions/src/channels/threads/joinThread.ts +++ b/plugins/permissions/src/channels/threads/joinThread.ts @@ -1,15 +1,13 @@ import { BotWithCache } from "../../../deps.ts"; -export default function joinThread(bot: BotWithCache) { - const joinThreadOld = bot.helpers.joinThread; +export function joinThread(bot: BotWithCache) { + const joinThread = bot.helpers.joinThread; bot.helpers.joinThread = async function (threadId) { const channel = bot.channels.get(threadId); - if (channel && !channel.archived) { - throw new Error("You can not join an archived channel."); - } + if (channel && !channel.archived) throw new Error("You can not join an archived channel."); - return await joinThreadOld(threadId); + return await joinThread(threadId); }; } diff --git a/plugins/permissions/src/channels/threads/leaveThread.ts b/plugins/permissions/src/channels/threads/leaveThread.ts index 3ff3d455a..a2d7b3ffd 100644 --- a/plugins/permissions/src/channels/threads/leaveThread.ts +++ b/plugins/permissions/src/channels/threads/leaveThread.ts @@ -1,15 +1,13 @@ import { BotWithCache } from "../../../deps.ts"; -export default function leaveThread(bot: BotWithCache) { - const leaveThreadOld = bot.helpers.leaveThread; +export function leaveThread(bot: BotWithCache) { + const leaveThread = bot.helpers.leaveThread; bot.helpers.leaveThread = async function (threadId) { const channel = bot.channels.get(threadId); - if (channel && !channel.archived) { - throw new Error("You can not leave an archived channel."); - } + if (channel && !channel.archived) throw new Error("You can not leave an archived channel."); - return await leaveThreadOld(threadId); + return await leaveThread(threadId); }; } diff --git a/plugins/permissions/src/channels/threads/mod.ts b/plugins/permissions/src/channels/threads/mod.ts index e5d067b6d..830ef2551 100644 --- a/plugins/permissions/src/channels/threads/mod.ts +++ b/plugins/permissions/src/channels/threads/mod.ts @@ -1,19 +1,17 @@ import { BotWithCache } from "../../../deps.ts"; -import addThreadMember from "./addThreadMember.ts"; +import { addThreadMember } from "./addThreadMember.ts"; import { getPrivateArchivedThreads } from "./getPrivateArchivedThreads.ts"; import { getPrivateJoinedArchivedThreads } from "./getPrivateJoinedArchivedThreads.ts"; import { getPublicArchivedThreads } from "./getPublicArchivedThreads.ts"; -import getThreadMembers from "./getThreadMembers.ts"; -import joinThread from "./joinThread.ts"; -import leaveThread from "./leaveThread.ts"; -import removeThreadMember from "./removeThreadMember.ts"; +import { joinThread } from "./joinThread.ts"; +import { leaveThread } from "./leaveThread.ts"; +import { removeThreadMember } from "./removeThreadMember.ts"; -export default function setupThreadPermChecks(bot: BotWithCache) { +export function threads(bot: BotWithCache) { addThreadMember(bot); getPublicArchivedThreads(bot); getPrivateArchivedThreads(bot); getPrivateJoinedArchivedThreads(bot); - getThreadMembers(bot); joinThread(bot); leaveThread(bot); removeThreadMember(bot); diff --git a/plugins/permissions/src/channels/threads/removeThreadMember.ts b/plugins/permissions/src/channels/threads/removeThreadMember.ts index fad3860fe..2d47df58e 100644 --- a/plugins/permissions/src/channels/threads/removeThreadMember.ts +++ b/plugins/permissions/src/channels/threads/removeThreadMember.ts @@ -1,26 +1,20 @@ import { BotWithCache, ChannelTypes } from "../../../deps.ts"; import { requireBotChannelPermissions } from "../../permissions.ts"; -export default function removeThreadMember(bot: BotWithCache) { - const removeThreadMemberOld = bot.helpers.removeThreadMember; +export function removeThreadMember(bot: BotWithCache) { + const removeThreadMember = bot.helpers.removeThreadMember; bot.helpers.removeThreadMember = async function (threadId, userId) { - if (userId === bot.id) { - throw new Error("To remove the bot from a thread, you must use bot.helpers.leaveThread()"); - } - const channel = bot.channels.get(threadId); if (channel) { - if (channel.archived) { - throw new Error("Cannot remove user from thread if thread is archived."); - } + if (channel.archived) throw new Error("Cannot remove user from thread if thread is archived."); if (!(bot.id === channel.ownerId && channel.type === ChannelTypes.PrivateThread)) { requireBotChannelPermissions(bot, channel, ["MANAGE_MESSAGES"]); } } - return await removeThreadMemberOld(threadId, userId); + return await removeThreadMember(threadId, userId); }; } diff --git a/plugins/permissions/src/editMember.ts b/plugins/permissions/src/editMember.ts deleted file mode 100644 index 984b5bcdd..000000000 --- a/plugins/permissions/src/editMember.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { BotWithCache, PermissionStrings } from "../deps.ts"; -import { requireBotChannelPermissions, requireBotGuildPermissions } from "./permissions.ts"; - -export default function editMember(bot: BotWithCache) { - const editMemberOld = bot.helpers.editMember; - - bot.helpers.editMember = async function (guildId, memberId, options) { - const requiredPerms: Set = new Set(); - - if (options.nick) { - if (options.nick.length > 32) { - throw new Error("NICKNAMES_MAX_LENGTH"); - } - requiredPerms.add("MANAGE_NICKNAMES"); - } - - if (options.roles) requiredPerms.add("MANAGE_ROLES"); - - if ( - options.mute !== undefined || options.deaf !== undefined || - options.channelId !== undefined - ) { - const memberVoiceState = (await bot.guilds.get(guildId)) - ?.voiceStates.get(memberId); - - if (!memberVoiceState?.channelId) { - throw new Error("MEMBER_NOT_IN_VOICE_CHANNEL"); - } - - if (options.mute !== undefined) { - requiredPerms.add("MUTE_MEMBERS"); - } - - if (options.deaf !== undefined) { - requiredPerms.add("DEAFEN_MEMBERS"); - } - - if (options.channelId) { - const requiredVoicePerms: Set = new Set([ - "CONNECT", - "MOVE_MEMBERS", - ]); - if (memberVoiceState) { - await requireBotChannelPermissions( - bot, - memberVoiceState?.channelId, - [ - ...requiredVoicePerms, - ], - ); - } - await requireBotChannelPermissions(bot, options.channelId, [ - ...requiredVoicePerms, - ]); - } - } - - await requireBotGuildPermissions(bot, guildId, [ - ...requiredPerms, - ]); - - return await editMemberOld(guildId, memberId, options); - }; -} diff --git a/plugins/permissions/src/emojis.ts b/plugins/permissions/src/emojis.ts deleted file mode 100644 index 47d624790..000000000 --- a/plugins/permissions/src/emojis.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { BotWithCache } from "../deps.ts"; -import { requireBotGuildPermissions } from "./permissions.ts"; - -export function createEmoji(bot: BotWithCache) { - const createEmojiOld = bot.helpers.createEmoji; - - bot.helpers.createEmoji = async function (guildId, id) { - requireBotGuildPermissions(bot, guildId, ["MANAGE_EMOJIS"]); - - return await createEmojiOld(guildId, id); - }; -} - -export function deleteEmoji(bot: BotWithCache) { - const deleteEmojiOld = bot.helpers.deleteEmoji; - - bot.helpers.deleteEmoji = async function (guildId, id) { - requireBotGuildPermissions(bot, guildId, ["MANAGE_EMOJIS"]); - - return await deleteEmojiOld(guildId, id); - }; -} - -export function editEmoji(bot: BotWithCache) { - const editEmojiOld = bot.helpers.editEmoji; - - bot.helpers.editEmoji = async function (guildId, id, options) { - requireBotGuildPermissions(bot, guildId, ["MANAGE_EMOJIS"]); - - return await editEmojiOld(guildId, id, options); - }; -} - -export default function setupEmojiPermChecks(bot: BotWithCache) { - createEmoji(bot); - deleteEmoji(bot); - editEmoji(bot); -} diff --git a/plugins/permissions/src/emojis/createEmoji.ts b/plugins/permissions/src/emojis/createEmoji.ts new file mode 100644 index 000000000..f17e5456d --- /dev/null +++ b/plugins/permissions/src/emojis/createEmoji.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotGuildPermissions } from "../permissions.ts"; + +export function createEmoji(bot: BotWithCache) { + const createEmoji = bot.helpers.createEmoji; + + bot.helpers.createEmoji = async function (guildId, id) { + requireBotGuildPermissions(bot, guildId, ["MANAGE_EMOJIS"]); + + return await createEmoji(guildId, id); + }; +} diff --git a/plugins/permissions/src/emojis/deleteEmoji.ts b/plugins/permissions/src/emojis/deleteEmoji.ts new file mode 100644 index 000000000..8ea880efc --- /dev/null +++ b/plugins/permissions/src/emojis/deleteEmoji.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotGuildPermissions } from "../permissions.ts"; + +export function deleteEmoji(bot: BotWithCache) { + const deleteEmoji = bot.helpers.deleteEmoji; + + bot.helpers.deleteEmoji = async function (guildId, id) { + requireBotGuildPermissions(bot, guildId, ["MANAGE_EMOJIS"]); + + return await deleteEmoji(guildId, id); + }; +} diff --git a/plugins/permissions/src/emojis/editEmoji.ts b/plugins/permissions/src/emojis/editEmoji.ts new file mode 100644 index 000000000..122c87f6c --- /dev/null +++ b/plugins/permissions/src/emojis/editEmoji.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotGuildPermissions } from "../permissions.ts"; + +export function editEmoji(bot: BotWithCache) { + const editEmoji = bot.helpers.editEmoji; + + bot.helpers.editEmoji = async function (guildId, id, options) { + requireBotGuildPermissions(bot, guildId, ["MANAGE_EMOJIS"]); + + return await editEmoji(guildId, id, options); + }; +} diff --git a/plugins/permissions/src/emojis/mod.ts b/plugins/permissions/src/emojis/mod.ts new file mode 100644 index 000000000..cee2de541 --- /dev/null +++ b/plugins/permissions/src/emojis/mod.ts @@ -0,0 +1,10 @@ +import { BotWithCache } from "../../deps.ts"; +import { createEmoji } from "./createEmoji.ts"; +import { deleteEmoji } from "./deleteEmoji.ts"; +import { editEmoji } from "./editEmoji.ts"; + +export function emojis(bot: BotWithCache) { + createEmoji(bot); + deleteEmoji(bot); + editEmoji(bot); +} diff --git a/plugins/permissions/src/guilds/automod.ts b/plugins/permissions/src/guilds/automod.ts deleted file mode 100644 index af4de276a..000000000 --- a/plugins/permissions/src/guilds/automod.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { AutoModerationActionType, BotWithCache, PermissionStrings } from "../../deps.ts"; -import { requireBotGuildPermissions } from "../permissions.ts"; - -export function getAutomodRule(bot: BotWithCache) { - const getAutomodRuleOld = bot.helpers.getAutomodRule; - - bot.helpers.getAutomodRule = async function (guildId, ruleId) { - requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); - - return await getAutomodRuleOld(guildId, ruleId); - }; -} - -export function getAutomodRules(bot: BotWithCache) { - const getAutomodRulesOld = bot.helpers.getAutomodRules; - - bot.helpers.getAutomodRules = async function (guildId) { - requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); - - return await getAutomodRulesOld(guildId); - }; -} - -export function createAutomodRule(bot: BotWithCache) { - const createAutomodRuleOld = bot.helpers.createAutomodRule; - - bot.helpers.createAutomodRule = async function (guildId, options) { - requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); - - for (const action of options.actions) { - // Check for maximum duration seconds - if (action.metadata?.durationSeconds && action.metadata.durationSeconds > 2419200) { - console.log( - `[Warning] Automod action duration seconds is too high: ${action.metadata.durationSeconds}. Setting to Discord's allowed maximum.`, - ); - // Discords max is 4 weeks - action.metadata.durationSeconds = 2419200; - } - - // Timeout actions require perm check - if (action.type === AutoModerationActionType.Timeout) { - requireBotGuildPermissions(bot, guildId, ["MODERATE_MEMBERS"]); - } - } - - return await createAutomodRuleOld(guildId, options); - }; -} - -export function editAutomodRule(bot: BotWithCache) { - const editAutomodRuleOld = bot.helpers.editAutomodRule; - - bot.helpers.editAutomodRule = async function (guildId, options) { - requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); - - for (const action of options.actions ?? []) { - // Check for maximum duration seconds - if (action.metadata?.durationSeconds && action.metadata.durationSeconds > 2419200) { - console.log( - `[Warning] Automod action duration seconds is too high: ${action.metadata.durationSeconds}. Setting to Discord's allowed maximum.`, - ); - // Discords max is 4 weeks - action.metadata.durationSeconds = 2419200; - } - - // Timeout actions require perm check - if (action.type === AutoModerationActionType.Timeout) { - requireBotGuildPermissions(bot, guildId, ["MODERATE_MEMBERS"]); - } - } - - return await editAutomodRuleOld(guildId, options); - }; -} - -export function deleteAutomodRule(bot: BotWithCache) { - const deleteAutomodRuleOld = bot.helpers.deleteAutomodRule; - - bot.helpers.deleteAutomodRule = async function (guildId, options) { - requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); - - return await deleteAutomodRuleOld(guildId, options); - }; -} - -export default function setupAutoModerationPermChecks(bot: BotWithCache) { - getAutomodRule(bot); - getAutomodRules(bot); - createAutomodRule(bot); - editAutomodRule(bot); - deleteAutomodRule(bot); -} diff --git a/plugins/permissions/src/guilds/automod/createAutomodRule.ts b/plugins/permissions/src/guilds/automod/createAutomodRule.ts new file mode 100644 index 000000000..fd338f9e8 --- /dev/null +++ b/plugins/permissions/src/guilds/automod/createAutomodRule.ts @@ -0,0 +1,28 @@ +import { AutoModerationActionType, BotWithCache } from "../../../deps.ts"; +import { requireBotGuildPermissions } from "../../permissions.ts"; + +export function createAutomodRule(bot: BotWithCache) { + const createAutomodRule = bot.helpers.createAutomodRule; + + bot.helpers.createAutomodRule = async function (guildId, options) { + requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); + + for (const action of options.actions) { + // Check for maximum duration seconds + if (action.metadata?.durationSeconds && action.metadata.durationSeconds > 2419200) { + console.log( + `[Warning] Automod action duration seconds is too high: ${action.metadata.durationSeconds}. Setting to Discord's allowed maximum.`, + ); + // Discords max is 4 weeks + action.metadata.durationSeconds = 2419200; + } + + // Timeout actions require perm check + if (action.type === AutoModerationActionType.Timeout) { + requireBotGuildPermissions(bot, guildId, ["MODERATE_MEMBERS"]); + } + } + + return await createAutomodRule(guildId, options); + }; +} diff --git a/plugins/permissions/src/guilds/automod/deleteAutomodRule.ts b/plugins/permissions/src/guilds/automod/deleteAutomodRule.ts new file mode 100644 index 000000000..dcf54b041 --- /dev/null +++ b/plugins/permissions/src/guilds/automod/deleteAutomodRule.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../../deps.ts"; +import { requireBotGuildPermissions } from "../../permissions.ts"; + +export function deleteAutomodRule(bot: BotWithCache) { + const deleteAutomodRule = bot.helpers.deleteAutomodRule; + + bot.helpers.deleteAutomodRule = async function (guildId, options) { + requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); + + return await deleteAutomodRule(guildId, options); + }; +} diff --git a/plugins/permissions/src/guilds/automod/editAutomodRule.ts b/plugins/permissions/src/guilds/automod/editAutomodRule.ts new file mode 100644 index 000000000..0bc3c5ea5 --- /dev/null +++ b/plugins/permissions/src/guilds/automod/editAutomodRule.ts @@ -0,0 +1,28 @@ +import { AutoModerationActionType, BotWithCache } from "../../../deps.ts"; +import { requireBotGuildPermissions } from "../../permissions.ts"; + +export function editAutomodRule(bot: BotWithCache) { + const editAutomodRule = bot.helpers.editAutomodRule; + + bot.helpers.editAutomodRule = async function (guildId, ruleId, options) { + requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); + + for (const action of options.actions ?? []) { + // Check for maximum duration seconds + if (action.metadata?.durationSeconds && action.metadata.durationSeconds > 2419200) { + console.log( + `[Warning] Automod action duration seconds is too high: ${action.metadata.durationSeconds}. Setting to Discord's allowed maximum.`, + ); + // Discords max is 4 weeks + action.metadata.durationSeconds = 2419200; + } + + // Timeout actions require perm check + if (action.type === AutoModerationActionType.Timeout) { + requireBotGuildPermissions(bot, guildId, ["MODERATE_MEMBERS"]); + } + } + + return await editAutomodRule(guildId, ruleId, options); + }; +} diff --git a/plugins/permissions/src/guilds/automod/getAutomodRule.ts b/plugins/permissions/src/guilds/automod/getAutomodRule.ts new file mode 100644 index 000000000..805c53a0d --- /dev/null +++ b/plugins/permissions/src/guilds/automod/getAutomodRule.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../../deps.ts"; +import { requireBotGuildPermissions } from "../../permissions.ts"; + +export function getAutomodRule(bot: BotWithCache) { + const getAutomodRule = bot.helpers.getAutomodRule; + + bot.helpers.getAutomodRule = async function (guildId, ruleId) { + requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); + + return await getAutomodRule(guildId, ruleId); + }; +} diff --git a/plugins/permissions/src/guilds/automod/getAutomodRules.ts b/plugins/permissions/src/guilds/automod/getAutomodRules.ts new file mode 100644 index 000000000..35c4550d3 --- /dev/null +++ b/plugins/permissions/src/guilds/automod/getAutomodRules.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../../deps.ts"; +import { requireBotGuildPermissions } from "../../permissions.ts"; + +export function getAutomodRules(bot: BotWithCache) { + const getAutomodRules = bot.helpers.getAutomodRules; + + bot.helpers.getAutomodRules = async function (guildId) { + requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); + + return await getAutomodRules(guildId); + }; +} diff --git a/plugins/permissions/src/guilds/automod/mod.ts b/plugins/permissions/src/guilds/automod/mod.ts new file mode 100644 index 000000000..1a2c8c58e --- /dev/null +++ b/plugins/permissions/src/guilds/automod/mod.ts @@ -0,0 +1,14 @@ +import { BotWithCache } from "../../../deps.ts"; +import { createAutomodRule } from "./createAutomodRule.ts"; +import { deleteAutomodRule } from "./deleteAutomodRule.ts"; +import { editAutomodRule } from "./editAutomodRule.ts"; +import { getAutomodRule } from "./getAutomodRule.ts"; +import { getAutomodRules } from "./getAutomodRules.ts"; + +export function automod(bot: BotWithCache) { + createAutomodRule(bot); + deleteAutomodRule(bot); + editAutomodRule(bot); + getAutomodRule(bot); + getAutomodRules(bot); +} diff --git a/plugins/permissions/src/guilds/createGuild.ts b/plugins/permissions/src/guilds/createGuild.ts index 8524a0022..1bb527f5d 100644 --- a/plugins/permissions/src/guilds/createGuild.ts +++ b/plugins/permissions/src/guilds/createGuild.ts @@ -1,22 +1,11 @@ import { BotWithCache } from "../../deps.ts"; -export default function createGuild(bot: BotWithCache) { - const createGuildOld = bot.helpers.createGuild; +export function createGuild(bot: BotWithCache) { + const createGuild = bot.helpers.createGuild; bot.helpers.createGuild = async function (options) { - if (bot.guilds.size > 10) { - throw new Error( - "A bot can not create a guild if it is already in 10 guilds.", - ); - } + if (bot.guilds.size > 10) throw new Error("A bot can not create a guild if it is already in 10 guilds."); - if ( - options.name && - !bot.utils.validateLength(options.name, { min: 2, max: 100 }) - ) { - throw new Error("The guild name must be between 2 and 100 characters."); - } - - return await createGuildOld(options); + return await createGuild(options); }; } diff --git a/plugins/permissions/src/guilds/deleteGuild.ts b/plugins/permissions/src/guilds/deleteGuild.ts index 41cfda5e2..cd2a3b57e 100644 --- a/plugins/permissions/src/guilds/deleteGuild.ts +++ b/plugins/permissions/src/guilds/deleteGuild.ts @@ -1,14 +1,12 @@ import { BotWithCache } from "../../deps.ts"; -export default function deleteGuild(bot: BotWithCache) { - const deleteGuildOld = bot.helpers.deleteGuild; +export function deleteGuild(bot: BotWithCache) { + const deleteGuild = bot.helpers.deleteGuild; bot.helpers.deleteGuild = async function (guildId) { const guild = bot.guilds.get(guildId); - if (guild && guild.ownerId !== bot.id) { - throw new Error("A bot can only delete a guild it owns."); - } + if (guild && guild.ownerId !== bot.id) throw new Error("A bot can only delete a guild it owns."); - return await deleteGuildOld(guildId); + return await deleteGuild(guildId); }; } diff --git a/plugins/permissions/src/guilds/editGuild.ts b/plugins/permissions/src/guilds/editGuild.ts index 77badd444..f6037e464 100644 --- a/plugins/permissions/src/guilds/editGuild.ts +++ b/plugins/permissions/src/guilds/editGuild.ts @@ -1,16 +1,14 @@ import { BotWithCache, GuildFeatures } from "../../deps.ts"; import { requireBotGuildPermissions } from "../permissions.ts"; -export default function editGuild(bot: BotWithCache) { - const editGuildOld = bot.helpers.editGuild; +export function editGuild(bot: BotWithCache) { + const editGuild = bot.helpers.editGuild; bot.helpers.editGuild = async function (guildId, options, shardId) { if (options.features?.includes(GuildFeatures.Community)) { requireBotGuildPermissions(bot, guildId, ["ADMINISTRATOR"]); - } else { - requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); - } + } else requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); - return await editGuildOld(guildId, options, shardId); + return await editGuild(guildId, options, shardId); }; } diff --git a/plugins/permissions/src/guilds/editGuildMfaLevel.ts b/plugins/permissions/src/guilds/editGuildMfaLevel.ts index faed6e2ad..035c360a7 100644 --- a/plugins/permissions/src/guilds/editGuildMfaLevel.ts +++ b/plugins/permissions/src/guilds/editGuildMfaLevel.ts @@ -1,11 +1,11 @@ import { BotWithCache } from "../../deps.ts"; -export default function editGuildMfaLevel(bot: BotWithCache) { - const editGuildMfaLevelOld = bot.helpers.editGuildMfaLevel; +export function editGuildMfaLevel(bot: BotWithCache) { + const editGuildMfaLevel = bot.helpers.editGuildMfaLevel; bot.helpers.editGuildMfaLevel = async function (guildId, mfaLevel, reason) { const guild = bot.guilds.get(guildId); if (guild?.ownerId !== bot.id) throw new Error("The bot is not the owner of the guild"); - return await editGuildMfaLevelOld(guildId, mfaLevel, reason); + return await editGuildMfaLevel(guildId, mfaLevel, reason); }; } diff --git a/plugins/permissions/src/guilds/editWelcomeScreen.ts b/plugins/permissions/src/guilds/editWelcomeScreen.ts new file mode 100644 index 000000000..a6dfc637d --- /dev/null +++ b/plugins/permissions/src/guilds/editWelcomeScreen.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotGuildPermissions } from "../permissions.ts"; + +export function editWelcomeScreen(bot: BotWithCache) { + const editWelcomeScreen = bot.helpers.editWelcomeScreen; + + bot.helpers.editWelcomeScreen = async function (guildId, options) { + requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); + + return await editWelcomeScreen(guildId, options); + }; +} diff --git a/plugins/permissions/src/guilds/editWidgetSettings.ts b/plugins/permissions/src/guilds/editWidgetSettings.ts deleted file mode 100644 index 215791ce3..000000000 --- a/plugins/permissions/src/guilds/editWidgetSettings.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { BotWithCache } from "../../deps.ts"; -import { requireBotGuildPermissions } from "../permissions.ts"; - -export function editWidgetSettings(bot: BotWithCache) { - const editWidgetSettingsOld = bot.helpers.editWidgetSettings; - - bot.helpers.editWidgetSettings = async function (guildId, enabled, channelId) { - requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); - - return await editWidgetSettingsOld(guildId, enabled, channelId); - }; -} - -export default function (bot: BotWithCache) { - editWidgetSettings(bot); -} diff --git a/plugins/permissions/src/guilds/events.ts b/plugins/permissions/src/guilds/events.ts deleted file mode 100644 index eff9817c9..000000000 --- a/plugins/permissions/src/guilds/events.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { BotWithCache, ScheduledEventEntityType } from "../../deps.ts"; -import { requireBotChannelPermissions, requireBotGuildPermissions } from "../permissions.ts"; - -export function createScheduledEvent(bot: BotWithCache) { - const createScheduledEventOld = bot.helpers.createScheduledEvent; - - bot.helpers.createScheduledEvent = async function (guildId, options) { - if (options.entityType === ScheduledEventEntityType.StageInstance) { - if (!options.channelId) { - throw new Error( - "A channel id is required for creating a stage scheduled event.", - ); - } - - requireBotChannelPermissions(bot, options.channelId, [ - "MANAGE_CHANNELS", - "MUTE_MEMBERS", - "MOVE_MEMBERS", - ]); - - // MANAGE_EVENTS at the guild level or at least MANAGE_EVENTS for the channel_id associated with the event - try { - requireBotGuildPermissions(bot, guildId, [ - "MANAGE_EVENTS", - ]); - } catch { - requireBotChannelPermissions(bot, options.channelId, [ - "MANAGE_EVENTS", - ]); - } - - return createScheduledEventOld(guildId, options); - } - - if (options.entityType === ScheduledEventEntityType.Voice) { - if (!options.channelId) { - throw new Error( - "A channel id is required for creating a voice scheduled event.", - ); - } - - requireBotChannelPermissions(bot, options.channelId, [ - "VIEW_CHANNEL", - "CONNECT", - ]); - - // MANAGE_EVENTS at the guild level or at least MANAGE_EVENTS for the channel_id associated with the event - try { - requireBotGuildPermissions(bot, guildId, [ - "MANAGE_EVENTS", - ]); - } catch { - requireBotChannelPermissions(bot, options.channelId, [ - "MANAGE_EVENTS", - ]); - } - - return createScheduledEventOld(guildId, options); - } - - // EXTERNAL EVENTS - - requireBotGuildPermissions(bot, guildId, [ - "MANAGE_EVENTS", - ]); - - return await createScheduledEventOld(guildId, options); - }; -} - -export function editScheduledEvent(bot: BotWithCache) { - const editScheduledEventOld = bot.helpers.editScheduledEvent; - - bot.helpers.editScheduledEvent = async function (guildId, eventId, options) { - if (options.entityType === ScheduledEventEntityType.StageInstance) { - if (!options.channelId) { - throw new Error( - "A channel id is required for creating a stage scheduled event.", - ); - } - - requireBotChannelPermissions(bot, options.channelId, [ - "MANAGE_CHANNELS", - "MUTE_MEMBERS", - "MOVE_MEMBERS", - ]); - - // MANAGE_EVENTS at the guild level or at least MANAGE_EVENTS for the channel_id associated with the event - try { - requireBotGuildPermissions(bot, guildId, [ - "MANAGE_EVENTS", - ]); - } catch { - requireBotChannelPermissions(bot, options.channelId, [ - "MANAGE_EVENTS", - ]); - } - - return editScheduledEventOld(guildId, eventId, options); - } - - if (options.entityType === ScheduledEventEntityType.Voice) { - if (!options.channelId) { - throw new Error( - "A channel id is required for creating a voice scheduled event.", - ); - } - - requireBotChannelPermissions(bot, options.channelId, [ - "VIEW_CHANNEL", - "CONNECT", - ]); - - // MANAGE_EVENTS at the guild level or at least MANAGE_EVENTS for the channel_id associated with the event - try { - requireBotGuildPermissions(bot, guildId, [ - "MANAGE_EVENTS", - ]); - } catch { - requireBotChannelPermissions(bot, options.channelId, [ - "MANAGE_EVENTS", - ]); - } - - return editScheduledEventOld(guildId, eventId, options); - } - - // EXTERNAL EVENTS - - requireBotGuildPermissions(bot, guildId, [ - "MANAGE_EVENTS", - ]); - - return await editScheduledEventOld(guildId, eventId, options); - }; -} - -export default function setupEventsPermChecks(bot: BotWithCache) { - createScheduledEvent(bot); - editScheduledEvent(bot); -} diff --git a/plugins/permissions/src/guilds/events/createScheduledEvent.ts b/plugins/permissions/src/guilds/events/createScheduledEvent.ts new file mode 100644 index 000000000..c7968022e --- /dev/null +++ b/plugins/permissions/src/guilds/events/createScheduledEvent.ts @@ -0,0 +1,69 @@ +import { BotWithCache, ScheduledEventEntityType } from "../../../deps.ts"; +import { requireBotChannelPermissions, requireBotGuildPermissions } from "../../permissions.ts"; + +export function createScheduledEvent(bot: BotWithCache) { + const createScheduledEvent = bot.helpers.createScheduledEvent; + + bot.helpers.createScheduledEvent = async function (guildId, options) { + if (options.entityType === ScheduledEventEntityType.StageInstance) { + if (!options.channelId) { + throw new Error( + "A channel id is required for creating a stage scheduled event.", + ); + } + + requireBotChannelPermissions(bot, options.channelId, [ + "MANAGE_CHANNELS", + "MUTE_MEMBERS", + "MOVE_MEMBERS", + ]); + + // MANAGE_EVENTS at the guild level or at least MANAGE_EVENTS for the channel_id associated with the event + try { + requireBotGuildPermissions(bot, guildId, [ + "MANAGE_EVENTS", + ]); + } catch { + requireBotChannelPermissions(bot, options.channelId, [ + "MANAGE_EVENTS", + ]); + } + + return createScheduledEvent(guildId, options); + } + + if (options.entityType === ScheduledEventEntityType.Voice) { + if (!options.channelId) { + throw new Error( + "A channel id is required for creating a voice scheduled event.", + ); + } + + requireBotChannelPermissions(bot, options.channelId, [ + "VIEW_CHANNEL", + "CONNECT", + ]); + + // MANAGE_EVENTS at the guild level or at least MANAGE_EVENTS for the channel_id associated with the event + try { + requireBotGuildPermissions(bot, guildId, [ + "MANAGE_EVENTS", + ]); + } catch { + requireBotChannelPermissions(bot, options.channelId, [ + "MANAGE_EVENTS", + ]); + } + + return createScheduledEvent(guildId, options); + } + + // EXTERNAL EVENTS + + requireBotGuildPermissions(bot, guildId, [ + "MANAGE_EVENTS", + ]); + + return await createScheduledEvent(guildId, options); + }; +} diff --git a/plugins/permissions/src/guilds/events/editScheduledEvent.ts b/plugins/permissions/src/guilds/events/editScheduledEvent.ts new file mode 100644 index 000000000..ccce24183 --- /dev/null +++ b/plugins/permissions/src/guilds/events/editScheduledEvent.ts @@ -0,0 +1,69 @@ +import { BotWithCache, ScheduledEventEntityType } from "../../../deps.ts"; +import { requireBotChannelPermissions, requireBotGuildPermissions } from "../../permissions.ts"; + +export function editScheduledEvent(bot: BotWithCache) { + const editScheduledEvent = bot.helpers.editScheduledEvent; + + bot.helpers.editScheduledEvent = async function (guildId, eventId, options) { + if (options.entityType === ScheduledEventEntityType.StageInstance) { + if (!options.channelId) { + throw new Error( + "A channel id is required for creating a stage scheduled event.", + ); + } + + requireBotChannelPermissions(bot, options.channelId, [ + "MANAGE_CHANNELS", + "MUTE_MEMBERS", + "MOVE_MEMBERS", + ]); + + // MANAGE_EVENTS at the guild level or at least MANAGE_EVENTS for the channel_id associated with the event + try { + requireBotGuildPermissions(bot, guildId, [ + "MANAGE_EVENTS", + ]); + } catch { + requireBotChannelPermissions(bot, options.channelId, [ + "MANAGE_EVENTS", + ]); + } + + return editScheduledEvent(guildId, eventId, options); + } + + if (options.entityType === ScheduledEventEntityType.Voice) { + if (!options.channelId) { + throw new Error( + "A channel id is required for creating a voice scheduled event.", + ); + } + + requireBotChannelPermissions(bot, options.channelId, [ + "VIEW_CHANNEL", + "CONNECT", + ]); + + // MANAGE_EVENTS at the guild level or at least MANAGE_EVENTS for the channel_id associated with the event + try { + requireBotGuildPermissions(bot, guildId, [ + "MANAGE_EVENTS", + ]); + } catch { + requireBotChannelPermissions(bot, options.channelId, [ + "MANAGE_EVENTS", + ]); + } + + return editScheduledEvent(guildId, eventId, options); + } + + // EXTERNAL EVENTS + + requireBotGuildPermissions(bot, guildId, [ + "MANAGE_EVENTS", + ]); + + return await editScheduledEvent(guildId, eventId, options); + }; +} diff --git a/plugins/permissions/src/guilds/events/mod.ts b/plugins/permissions/src/guilds/events/mod.ts new file mode 100644 index 000000000..c152daf44 --- /dev/null +++ b/plugins/permissions/src/guilds/events/mod.ts @@ -0,0 +1,8 @@ +import { BotWithCache } from "../../../deps.ts"; +import { createScheduledEvent } from "./createScheduledEvent.ts"; +import { editScheduledEvent } from "./editScheduledEvent.ts"; + +export function events(bot: BotWithCache) { + createScheduledEvent(bot); + editScheduledEvent(bot); +} diff --git a/plugins/permissions/src/guilds/getAuditLog.ts b/plugins/permissions/src/guilds/getAuditLog.ts index 121731d7b..862514a88 100644 --- a/plugins/permissions/src/guilds/getAuditLog.ts +++ b/plugins/permissions/src/guilds/getAuditLog.ts @@ -1,12 +1,12 @@ import { BotWithCache } from "../../deps.ts"; import { requireBotGuildPermissions } from "../permissions.ts"; -export default function getAuditLog(bot: BotWithCache) { - const getAuditLogOld = bot.helpers.getAuditLog; +export function getAuditLog(bot: BotWithCache) { + const getAuditLog = bot.helpers.getAuditLog; bot.helpers.getAuditLog = async function (guildId, options) { requireBotGuildPermissions(bot, guildId, ["VIEW_AUDIT_LOG"]); - return await getAuditLogOld(guildId, options); + return await getAuditLog(guildId, options); }; } diff --git a/plugins/permissions/src/guilds/getBan.ts b/plugins/permissions/src/guilds/getBan.ts index 49736ac12..80b5d54ea 100644 --- a/plugins/permissions/src/guilds/getBan.ts +++ b/plugins/permissions/src/guilds/getBan.ts @@ -1,12 +1,12 @@ import { BotWithCache } from "../../deps.ts"; import { requireBotGuildPermissions } from "../permissions.ts"; -export default function getBan(bot: BotWithCache) { - const getBanOld = bot.helpers.getBan; +export function getBan(bot: BotWithCache) { + const getBan = bot.helpers.getBan; bot.helpers.getBan = async function (guildId, memberId) { requireBotGuildPermissions(bot, guildId, ["BAN_MEMBERS"]); - return await getBanOld(guildId, memberId); + return await getBan(guildId, memberId); }; } diff --git a/plugins/permissions/src/guilds/getBans.ts b/plugins/permissions/src/guilds/getBans.ts index f59c62ee4..059230292 100644 --- a/plugins/permissions/src/guilds/getBans.ts +++ b/plugins/permissions/src/guilds/getBans.ts @@ -1,12 +1,12 @@ import { BotWithCache } from "../../deps.ts"; import { requireBotGuildPermissions } from "../permissions.ts"; -export default function getBans(bot: BotWithCache) { - const getBansOld = bot.helpers.getBans; +export function getBans(bot: BotWithCache) { + const getBans = bot.helpers.getBans; bot.helpers.getBans = async function (guildId) { requireBotGuildPermissions(bot, guildId, ["BAN_MEMBERS"]); - return await getBansOld(guildId); + return await getBans(guildId); }; } diff --git a/plugins/permissions/src/guilds/getPruneCount.ts b/plugins/permissions/src/guilds/getPruneCount.ts index 2669b57c4..b7ffc00a4 100644 --- a/plugins/permissions/src/guilds/getPruneCount.ts +++ b/plugins/permissions/src/guilds/getPruneCount.ts @@ -1,12 +1,12 @@ import { BotWithCache } from "../../deps.ts"; import { requireBotGuildPermissions } from "../permissions.ts"; -export default function getPruneCount(bot: BotWithCache) { - const getPruneCountOld = bot.helpers.getPruneCount; +export function getPruneCount(bot: BotWithCache) { + const getPruneCount = bot.helpers.getPruneCount; bot.helpers.getPruneCount = async function (guildId, options) { requireBotGuildPermissions(bot, guildId, ["KICK_MEMBERS"]); - return await getPruneCountOld(guildId, options); + return await getPruneCount(guildId, options); }; } diff --git a/plugins/permissions/src/guilds/getVanityUrl.ts b/plugins/permissions/src/guilds/getVanityUrl.ts index a957f8ca2..7b82dd582 100644 --- a/plugins/permissions/src/guilds/getVanityUrl.ts +++ b/plugins/permissions/src/guilds/getVanityUrl.ts @@ -1,12 +1,12 @@ import { BotWithCache } from "../../deps.ts"; import { requireBotGuildPermissions } from "../permissions.ts"; -export default function getVanityUrl(bot: BotWithCache) { - const getVanityUrlOld = bot.helpers.getVanityUrl; +export function getVanityUrl(bot: BotWithCache) { + const getVanityUrl = bot.helpers.getVanityUrl; bot.helpers.getVanityUrl = async function (guildId) { requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); - return await getVanityUrlOld(guildId); + return await getVanityUrl(guildId); }; } diff --git a/plugins/permissions/src/guilds/getWelcomeScreen.ts b/plugins/permissions/src/guilds/getWelcomeScreen.ts new file mode 100644 index 000000000..84ff54318 --- /dev/null +++ b/plugins/permissions/src/guilds/getWelcomeScreen.ts @@ -0,0 +1,13 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotGuildPermissions } from "../permissions.ts"; + +export function getWelcomeScreen(bot: BotWithCache) { + const getWelcomeScreen = bot.helpers.getWelcomeScreen; + + bot.helpers.getWelcomeScreen = async function (guildId) { + const guild = bot.guilds.get(guildId); + if (!guild?.welcomeScreen) requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); + + return await getWelcomeScreen(guildId); + }; +} diff --git a/plugins/permissions/src/guilds/invites/createInvite.ts b/plugins/permissions/src/guilds/invites/createInvite.ts new file mode 100644 index 000000000..4a61827b3 --- /dev/null +++ b/plugins/permissions/src/guilds/invites/createInvite.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../../deps.ts"; +import { requireBotChannelPermissions } from "../../permissions.ts"; + +export function createInvite(bot: BotWithCache) { + const createInvite = bot.helpers.createInvite; + + bot.helpers.createInvite = async function (channelId, options = {}) { + requireBotChannelPermissions(bot, channelId, ["CREATE_INSTANT_INVITE"]); + + return await createInvite(channelId, options); + }; +} diff --git a/plugins/permissions/src/guilds/invites/getChannelInvites.ts b/plugins/permissions/src/guilds/invites/getChannelInvites.ts new file mode 100644 index 000000000..ac5fb4cea --- /dev/null +++ b/plugins/permissions/src/guilds/invites/getChannelInvites.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../../deps.ts"; +import { requireBotChannelPermissions } from "../../permissions.ts"; + +export function getChannelInvites(bot: BotWithCache) { + const getChannelInvites = bot.helpers.getChannelInvites; + + bot.helpers.getChannelInvites = async function (channelId) { + requireBotChannelPermissions(bot, channelId, ["MANAGE_CHANNELS"]); + + return await getChannelInvites(channelId); + }; +} diff --git a/plugins/permissions/src/guilds/invites/getInvites.ts b/plugins/permissions/src/guilds/invites/getInvites.ts new file mode 100644 index 000000000..b32c7031d --- /dev/null +++ b/plugins/permissions/src/guilds/invites/getInvites.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../../deps.ts"; +import { requireBotChannelPermissions } from "../../permissions.ts"; + +export function getInvites(bot: BotWithCache) { + const getInvites = bot.helpers.getInvites; + + bot.helpers.getInvites = async function (guildId) { + requireBotChannelPermissions(bot, guildId, ["MANAGE_GUILD"]); + + return await getInvites(guildId); + }; +} diff --git a/plugins/permissions/src/guilds/mod.ts b/plugins/permissions/src/guilds/mod.ts index 0cd1561e0..3d86266d4 100644 --- a/plugins/permissions/src/guilds/mod.ts +++ b/plugins/permissions/src/guilds/mod.ts @@ -1,26 +1,35 @@ import { BotWithCache } from "../../deps.ts"; -import createGuild from "./createGuild.ts"; -import deleteGuild from "./deleteGuild.ts"; -import editGuild from "./editGuild.ts"; -import editWidgetSettings from "./editWidgetSettings.ts"; -import setupEventsPermChecks from "./events.ts"; -import getAuditLog from "./getAuditLog.ts"; -import getBan from "./getBan.ts"; -import getBans from "./getBans.ts"; -import getPruneCount from "./getPruneCount.ts"; -import getVanityUrl from "./getVanityUrl.ts"; -import setupWelcomeScreenPermChecks from "./welcomeScreen.ts"; +import { automod } from "./automod/mod.ts"; +import { createGuild } from "./createGuild.ts"; +import { deleteGuild } from "./deleteGuild.ts"; +import { editGuild } from "./editGuild.ts"; +import { editGuildMfaLevel } from "./editGuildMfaLevel.ts"; +import { editWelcomeScreen } from "./editWelcomeScreen.ts"; +import { events } from "./events/mod.ts"; +import { getAuditLog } from "./getAuditLog.ts"; +import { getBan } from "./getBan.ts"; +import { getBans } from "./getBans.ts"; +import { getPruneCount } from "./getPruneCount.ts"; +import { getVanityUrl } from "./getVanityUrl.ts"; +import { getWelcomeScreen } from "./getWelcomeScreen.ts"; +import { voice } from "./voice/mod.ts"; +import { widgets } from "./widgets/mod.ts"; + +export function guilds(bot: BotWithCache) { + automod(bot); + events(bot); + voice(bot); + widgets(bot); -export default function setupGuildPermChecks(bot: BotWithCache) { createGuild(bot); deleteGuild(bot); editGuild(bot); - editWidgetSettings(bot); - setupEventsPermChecks(bot); + editGuildMfaLevel(bot); + editWelcomeScreen(bot); getAuditLog(bot); getBan(bot); getBans(bot); getPruneCount(bot); getVanityUrl(bot); - setupWelcomeScreenPermChecks(bot); + getWelcomeScreen(bot); } diff --git a/plugins/permissions/src/connectToVoiceChannels.ts b/plugins/permissions/src/guilds/voice/connectToVoiceChannels.ts similarity index 73% rename from plugins/permissions/src/connectToVoiceChannels.ts rename to plugins/permissions/src/guilds/voice/connectToVoiceChannels.ts index 96b42da8f..3180b552b 100644 --- a/plugins/permissions/src/connectToVoiceChannels.ts +++ b/plugins/permissions/src/guilds/voice/connectToVoiceChannels.ts @@ -1,14 +1,10 @@ -import { BotWithCache, ChannelTypes, PermissionStrings } from "../deps.ts"; -import { requireBotChannelPermissions } from "./permissions.ts"; +import { BotWithCache, ChannelTypes, PermissionStrings } from "../../../deps.ts"; +import { requireBotChannelPermissions } from "../../permissions.ts"; -export default function connectToVoiceChannel(bot: BotWithCache) { - const connectToVoiceChannelOld = bot.helpers.connectToVoiceChannel; +export function connectToVoiceChannel(bot: BotWithCache) { + const connectToVoiceChannel = bot.helpers.connectToVoiceChannel; - bot.helpers.connectToVoiceChannel = async function ( - guildId, - channelId, - options, - ) { + bot.helpers.connectToVoiceChannel = async function (guildId, channelId, options) { const channel = bot.channels.get(channelId); if (!channel) throw new Error("CHANNEL_NOT_FOUND"); @@ -40,6 +36,6 @@ export default function connectToVoiceChannel(bot: BotWithCache) { requireBotChannelPermissions(bot, channel, permsNeeded); - return await connectToVoiceChannelOld(guildId, channelId, options); + return await connectToVoiceChannel(guildId, channelId, options); }; } diff --git a/plugins/permissions/src/guilds/voice/mod.ts b/plugins/permissions/src/guilds/voice/mod.ts new file mode 100644 index 000000000..0e4ef4b6d --- /dev/null +++ b/plugins/permissions/src/guilds/voice/mod.ts @@ -0,0 +1,6 @@ +import { BotWithCache } from "../../../deps.ts"; +import { connectToVoiceChannel } from "./connectToVoiceChannels.ts"; + +export function voice(bot: BotWithCache) { + connectToVoiceChannel(bot); +} diff --git a/plugins/permissions/src/guilds/welcomeScreen.ts b/plugins/permissions/src/guilds/welcomeScreen.ts deleted file mode 100644 index e8ae7a073..000000000 --- a/plugins/permissions/src/guilds/welcomeScreen.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { BotWithCache } from "../../deps.ts"; -import { requireBotGuildPermissions } from "../permissions.ts"; - -export function getWelcomeScreen(bot: BotWithCache) { - const getWelcomeScreenOld = bot.helpers.getWelcomeScreen; - - bot.helpers.getWelcomeScreen = async function (guildId) { - const guild = bot.guilds.get(guildId); - if (!guild?.welcomeScreen) { - requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); - } - - return await getWelcomeScreenOld(guildId); - }; -} - -export function editWelcomeScreen(bot: BotWithCache) { - const editWelcomeScreenOld = bot.helpers.editWelcomeScreen; - - bot.helpers.editWelcomeScreen = async function (guildId, options) { - requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); - - return await editWelcomeScreenOld(guildId, options); - }; -} - -export default function setupWelcomeScreenPermChecks(bot: BotWithCache) { - getWelcomeScreen(bot); - editWelcomeScreen(bot); -} diff --git a/plugins/permissions/src/guilds/widgets/editWidgetSettings.ts b/plugins/permissions/src/guilds/widgets/editWidgetSettings.ts new file mode 100644 index 000000000..2790d1621 --- /dev/null +++ b/plugins/permissions/src/guilds/widgets/editWidgetSettings.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../../deps.ts"; +import { requireBotGuildPermissions } from "../../permissions.ts"; + +export function editWidgetSettings(bot: BotWithCache) { + const editWidgetSettings = bot.helpers.editWidgetSettings; + + bot.helpers.editWidgetSettings = async function (guildId, enabled, channelId) { + requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); + + return await editWidgetSettings(guildId, enabled, channelId); + }; +} diff --git a/plugins/permissions/src/guilds/widgets/mod.ts b/plugins/permissions/src/guilds/widgets/mod.ts new file mode 100644 index 000000000..ff2077013 --- /dev/null +++ b/plugins/permissions/src/guilds/widgets/mod.ts @@ -0,0 +1,6 @@ +import { BotWithCache } from "../../../deps.ts"; +import { editWidgetSettings } from "./editWidgetSettings.ts"; + +export function widgets(bot: BotWithCache) { + editWidgetSettings(bot); +} diff --git a/plugins/permissions/src/integrations.ts b/plugins/permissions/src/integrations.ts deleted file mode 100644 index c7fc1876f..000000000 --- a/plugins/permissions/src/integrations.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { BotWithCache } from "../deps.ts"; -import { requireBotGuildPermissions } from "./permissions.ts"; - -export function deleteIntegration(bot: BotWithCache) { - const deleteIntegrationOld = bot.helpers.deleteIntegration; - - bot.helpers.deleteIntegration = async function (guildId, id) { - requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); - - return await deleteIntegrationOld(guildId, id); - }; -} - -export function getIntegrations(bot: BotWithCache) { - const getIntegrationsOld = bot.helpers.getIntegrations; - - bot.helpers.getIntegrations = async function (guildId) { - requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); - - return await getIntegrationsOld(guildId); - }; -} - -export default function setupIntegrationPermChecks(bot: BotWithCache) { - deleteIntegration(bot); - getIntegrations(bot); -} diff --git a/plugins/permissions/src/integrations/deleteIntegrations.ts b/plugins/permissions/src/integrations/deleteIntegrations.ts new file mode 100644 index 000000000..852ae91ac --- /dev/null +++ b/plugins/permissions/src/integrations/deleteIntegrations.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotGuildPermissions } from "../permissions.ts"; + +export function deleteIntegration(bot: BotWithCache) { + const deleteIntegration = bot.helpers.deleteIntegration; + + bot.helpers.deleteIntegration = async function (guildId, id) { + requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); + + return await deleteIntegration(guildId, id); + }; +} diff --git a/plugins/permissions/src/integrations/getIntegrations.ts b/plugins/permissions/src/integrations/getIntegrations.ts new file mode 100644 index 000000000..f5d7480bf --- /dev/null +++ b/plugins/permissions/src/integrations/getIntegrations.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotGuildPermissions } from "../permissions.ts"; + +export function getIntegrations(bot: BotWithCache) { + const getIntegrations = bot.helpers.getIntegrations; + + bot.helpers.getIntegrations = async function (guildId) { + requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]); + + return await getIntegrations(guildId); + }; +} diff --git a/plugins/permissions/src/integrations/mod.ts b/plugins/permissions/src/integrations/mod.ts new file mode 100644 index 000000000..e05ff3520 --- /dev/null +++ b/plugins/permissions/src/integrations/mod.ts @@ -0,0 +1,8 @@ +import { BotWithCache } from "../../deps.ts"; +import { deleteIntegration } from "./deleteIntegrations.ts"; +import { getIntegrations } from "./getIntegrations.ts"; + +export function integrations(bot: BotWithCache) { + deleteIntegration(bot); + getIntegrations(bot); +} diff --git a/plugins/permissions/src/interactions/commands.ts b/plugins/permissions/src/interactions/commands.ts deleted file mode 100644 index 4021bd94d..000000000 --- a/plugins/permissions/src/interactions/commands.ts +++ /dev/null @@ -1,192 +0,0 @@ -import { - AllowedMentionsTypes, - ApplicationCommandOption, - ApplicationCommandOptionTypes, - ApplicationCommandTypes, - BotWithCache, - CONTEXT_MENU_COMMANDS_NAME_REGEX, - SLASH_COMMANDS_NAME_REGEX, -} from "../../deps.ts"; - -export function validateApplicationCommandOptions(bot: BotWithCache, options: ApplicationCommandOption[]) { - const requiredOptions: ApplicationCommandOption[] = []; - const optionalOptions: ApplicationCommandOption[] = []; - - for (const option of options) { - option.name = option.name.toLowerCase(); - - if (option.choices?.length) { - if (option.choices.length > 25) { - throw new Error("Too many application command options provided."); - } - - if ( - option.type !== ApplicationCommandOptionTypes.String && option.type !== ApplicationCommandOptionTypes.Integer - ) { - throw new Error("Only string or integer options can have choices."); - } - } - - if (!bot.utils.validateLength(option.name, { min: 1, max: 32 })) { - throw new Error("Invalid application command option name."); - } - - if (!bot.utils.validateLength(option.description, { min: 1, max: 100 })) { - throw new Error("Invalid application command description."); - } - - option.choices?.every((choice) => { - if (!bot.utils.validateLength(choice.name, { min: 1, max: 100 })) { - throw new Error("Invalid application command option choice name. Must be between 1-100 characters long."); - } - - if ( - option.type === ApplicationCommandOptionTypes.String && - (typeof choice.value !== "string" || choice.value.length < 1 || choice.value.length > 100) - ) { - throw new Error("Invalid slash options choice value type."); - } - - if (option.type === ApplicationCommandOptionTypes.Integer && typeof choice.value !== "number") { - throw new Error("A number must be set for Integer types."); - } - }); - - if (option.required) { - requiredOptions.push(option); - continue; - } - - optionalOptions.push(option); - } - - return [...requiredOptions, ...optionalOptions]; -} - -export function createGuildApplicationCommand(bot: BotWithCache) { - const createGuildApplicationCommandOld = bot.helpers.createGuildApplicationCommand; - - bot.helpers.createGuildApplicationCommand = async function (options, guildId) { - const isChatInput = !options.type || options.type === ApplicationCommandTypes.ChatInput; - - if (!options.name) { - throw new Error("A name is required to create a options."); - } - - if (isChatInput) { - if (!SLASH_COMMANDS_NAME_REGEX.test(options.name)) { - throw new Error("The name of the slash command did not match the required regex."); - } - - // Only slash need to be lowercase - options.name = options.name.toLowerCase(); - - // Slash commands require description - if (!options.description) { - throw new Error("Slash commands require some form of a description be provided."); - } else if (!bot.utils.validateLength(options.description, { min: 1, max: 100 })) { - throw new Error("Application command descriptions must be between 1 and 100 characters."); - } - - if (options.options?.length) { - if (options.options.length > 25) { - throw new Error("Only 25 options are allowed to be provided."); - } - - options.options = validateApplicationCommandOptions(bot, options.options); - } - } else { - if (!CONTEXT_MENU_COMMANDS_NAME_REGEX.test(options.name)) { - throw new Error("The name of the context menu did not match the required regex."); - } - } - - return await createGuildApplicationCommandOld(options, guildId); - }; -} - -export function createGlobalApplicationCommand(bot: BotWithCache) { - const createGlobalApplicationCommandOld = bot.helpers.createGlobalApplicationCommand; - - bot.helpers.createGlobalApplicationCommand = async function (options) { - const isChatInput = !options.type || options.type === ApplicationCommandTypes.ChatInput; - - if (!options.name) { - throw new Error("A name is required to create a options."); - } - - if (isChatInput) { - if (!SLASH_COMMANDS_NAME_REGEX.test(options.name)) { - throw new Error("The name of the slash command did not match the required regex."); - } - - // Only slash need to be lowercase - options.name = options.name.toLowerCase(); - - // Slash commands require description - if (!options.description) { - throw new Error("Slash commands require some form of a description be provided."); - } else if (!bot.utils.validateLength(options.description, { min: 1, max: 100 })) { - throw new Error("Application command descriptions must be between 1 and 100 characters."); - } - - if (options.options?.length) { - if (options.options.length > 25) { - throw new Error("Only 25 options are allowed to be provided."); - } - - options.options = validateApplicationCommandOptions(bot, options.options); - } - } else { - if (!CONTEXT_MENU_COMMANDS_NAME_REGEX.test(options.name)) { - throw new Error("The name of the context menu did not match the required regex."); - } - } - - return await createGlobalApplicationCommandOld(options); - }; -} - -export function editOriginalInteractionResponse(bot: BotWithCache) { - const editOriginalInteractionResponseOld = bot.helpers.editOriginalInteractionResponse; - - bot.helpers.editOriginalInteractionResponse = async function (token, options) { - if (options.content && options.content.length > 2000) { - throw Error(bot.constants.Errors.MESSAGE_MAX_LENGTH); - } - - if (options.embeds && options.embeds.length > 10) { - options.embeds.splice(10); - } - - if (options.allowedMentions) { - if (options.allowedMentions.users?.length) { - if (options.allowedMentions.parse?.includes(AllowedMentionsTypes.UserMentions)) { - options.allowedMentions.parse = options.allowedMentions.parse.filter((p) => p !== "users"); - } - - if (options.allowedMentions.users.length > 100) { - options.allowedMentions.users = options.allowedMentions.users.slice(0, 100); - } - } - - if (options.allowedMentions.roles?.length) { - if (options.allowedMentions.parse?.includes(AllowedMentionsTypes.RoleMentions)) { - options.allowedMentions.parse = options.allowedMentions.parse.filter((p) => p !== "roles"); - } - - if (options.allowedMentions.roles.length > 100) { - options.allowedMentions.roles = options.allowedMentions.roles.slice(0, 100); - } - } - } - - return await editOriginalInteractionResponseOld(token, options); - }; -} - -export default function setupInteractionCommandPermChecks(bot: BotWithCache) { - createGlobalApplicationCommand(bot); - createGuildApplicationCommand(bot); - editOriginalInteractionResponse(bot); -} diff --git a/plugins/permissions/src/interactions/mod.ts b/plugins/permissions/src/interactions/mod.ts deleted file mode 100644 index 55a7738ef..000000000 --- a/plugins/permissions/src/interactions/mod.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { BotWithCache } from "../../deps.ts"; -import setupInteractionCommandPermChecks from "./commands.ts"; -import editFollowupMessage from "./editFollowupMessage.ts"; - -export function sendInteractionResponse(bot: BotWithCache) { - const sendInteractionResponseOld = bot.helpers.sendInteractionResponse; - - bot.helpers.sendInteractionResponse = function (id, token, options) { - if (options.data?.title !== undefined) { - if (!bot.utils.validateLength(options.data.title, { min: 1, max: 45 })) { - throw new Error( - "Invalid modal title. Must be between 1-45 characters long.", - ); - } - } - - options.data?.choices?.every((choice) => { - if (!bot.utils.validateLength(choice.name, { min: 1, max: 100 })) { - throw new Error( - "Invalid application command option choice name. Must be between 1-100 characters long.", - ); - } - - if ( - typeof choice.value === "string" && (choice.value.length < 1 || - choice.value.length > 100) - ) { - throw new Error("Invalid slash options choice value type."); - } - }); - - return sendInteractionResponseOld(id, token, options); - }; -} - -export default function setupInteractionPermChecks(bot: BotWithCache) { - setupInteractionCommandPermChecks(bot); - editFollowupMessage(bot); -} diff --git a/plugins/permissions/src/invites.ts b/plugins/permissions/src/invites.ts deleted file mode 100644 index a10b02a6c..000000000 --- a/plugins/permissions/src/invites.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { BotWithCache } from "../deps.ts"; -import { requireBotChannelPermissions } from "./permissions.ts"; - -export function createInvite(bot: BotWithCache) { - const createInviteOld = bot.helpers.createInvite; - - bot.helpers.createInvite = async function (channelId, options = {}) { - if (options.maxAge && (options.maxAge < 0 || options.maxAge > 604800)) { - throw new Error( - "The max age for an invite must be between 0 and 604800.", - ); - } - if (options.maxUses && (options.maxUses < 0 || options.maxUses > 100)) { - throw new Error("The max uses for an invite must be between 0 and 100."); - } - - requireBotChannelPermissions(bot, channelId, ["CREATE_INSTANT_INVITE"]); - - return await createInviteOld(channelId, options); - }; -} - -export function getChannelInvites(bot: BotWithCache) { - const getChannelInvitesOld = bot.helpers.getChannelInvites; - - bot.helpers.getChannelInvites = async function (channelId) { - requireBotChannelPermissions(bot, channelId, ["MANAGE_CHANNELS"]); - - return await getChannelInvitesOld(channelId); - }; -} - -export function getInvites(bot: BotWithCache) { - const getInvitesOld = bot.helpers.getInvites; - - bot.helpers.getInvites = async function (guildId) { - requireBotChannelPermissions(bot, guildId, ["MANAGE_GUILD"]); - - return await getInvitesOld(guildId); - }; -} - -export default function setupInvitesPermChecks(bot: BotWithCache) { - createInvite(bot); - getChannelInvites(bot); - getInvites(bot); -} diff --git a/plugins/permissions/src/members/ban.ts b/plugins/permissions/src/members/ban.ts deleted file mode 100644 index 31031c59c..000000000 --- a/plugins/permissions/src/members/ban.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { BotWithCache } from "../../deps.ts"; -import { requireBotGuildPermissions } from "../permissions.ts"; - -export function banMember(bot: BotWithCache) { - const banMemberOld = bot.helpers.banMember; - - bot.helpers.banMember = async function (guildId, id, options) { - requireBotGuildPermissions(bot, guildId, ["BAN_MEMBERS"]); - - return await banMemberOld(guildId, id, options); - }; -} - -export function unbanMember(bot: BotWithCache) { - const unbanMemberOld = bot.helpers.unbanMember; - - bot.helpers.unbanMember = async function (guildId, id) { - requireBotGuildPermissions(bot, guildId, ["BAN_MEMBERS"]); - - return await unbanMemberOld(guildId, id); - }; -} - -export default function setupBanPermChecks(bot: BotWithCache) { - banMember(bot); - unbanMember(bot); -} diff --git a/plugins/permissions/src/members/banMember.ts b/plugins/permissions/src/members/banMember.ts new file mode 100644 index 000000000..dcea3e03a --- /dev/null +++ b/plugins/permissions/src/members/banMember.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotGuildPermissions } from "../permissions.ts"; + +export function banMember(bot: BotWithCache) { + const banMember = bot.helpers.banMember; + + bot.helpers.banMember = async function (guildId, id, options) { + requireBotGuildPermissions(bot, guildId, ["BAN_MEMBERS"]); + + return await banMember(guildId, id, options); + }; +} diff --git a/plugins/permissions/src/members/editBotMember.ts b/plugins/permissions/src/members/editBotMember.ts index 918d89937..78721acba 100644 --- a/plugins/permissions/src/members/editBotMember.ts +++ b/plugins/permissions/src/members/editBotMember.ts @@ -1,12 +1,12 @@ import { BotWithCache } from "../../deps.ts"; import { requireBotGuildPermissions } from "../permissions.ts"; -export default function editBotMember(bot: BotWithCache) { - const editBotMemberOld = bot.helpers.editBotMember; +export function editBotMember(bot: BotWithCache) { + const editBotMember = bot.helpers.editBotMember; bot.helpers.editBotMember = async function (guildId, options) { requireBotGuildPermissions(bot, guildId, ["CHANGE_NICKNAME"]); - return await editBotMemberOld(guildId, options); + return await editBotMember(guildId, options); }; } diff --git a/plugins/permissions/src/members/editMember.ts b/plugins/permissions/src/members/editMember.ts index 4de0e7aee..ecf285cc3 100644 --- a/plugins/permissions/src/members/editMember.ts +++ b/plugins/permissions/src/members/editMember.ts @@ -1,33 +1,38 @@ import { BotWithCache, PermissionStrings } from "../../deps.ts"; -import { hasGuildPermissions, requireBotGuildPermissions, requireGuildPermissions } from "../permissions.ts"; +import { requireBotChannelPermissions, requireBotGuildPermissions } from "../permissions.ts"; -export default function editMember(bot: BotWithCache) { - const editMemberOld = bot.helpers.editMember; +export function editMember(bot: BotWithCache) { + const editMember = bot.helpers.editMember; bot.helpers.editMember = async function (guildId, memberId, options) { const requiredPerms: PermissionStrings[] = []; + + if (options.nick) requiredPerms.push("MANAGE_NICKNAMES"); + if (options.roles) requiredPerms.push("MANAGE_ROLES"); - // NULL IS ALLOWED - if (options.nick !== undefined) requiredPerms.push("MANAGE_NICKNAMES"); - if (options.channelId !== undefined) requiredPerms.push("MOVE_MEMBERS"); - if (options.mute !== undefined) requiredPerms.push("MUTE_MEMBERS"); - if (options.deaf !== undefined) requiredPerms.push("DEAFEN_MEMBERS"); - if (options.communicationDisabledUntil) { - const guild = bot.guilds.get(guildId); - if (guild) { - if (guild.ownerId === memberId) throw new Error("You can not timeout the servers owner."); - } + if ( + options.mute !== undefined || options.deaf !== undefined || + options.channelId !== undefined + ) { + const memberVoiceState = (bot.guilds.get(guildId)) + ?.voiceStates.get(memberId); - if (hasGuildPermissions(bot, guildId, memberId, ["ADMINISTRATOR"])) { - throw new Error("You can not timeout a server administrator."); + if (!memberVoiceState?.channelId) throw new Error("MEMBER_NOT_IN_VOICE_CHANNEL"); + + if (options.mute !== undefined) requiredPerms.push("MUTE_MEMBERS"); + + if (options.deaf !== undefined) requiredPerms.push("DEAFEN_MEMBERS"); + + if (options.channelId) { + const requiredVoicePerms: PermissionStrings[] = ["CONNECT", "MOVE_MEMBERS"]; + if (memberVoiceState) requireBotChannelPermissions(bot, memberVoiceState?.channelId, requiredVoicePerms); + requireBotChannelPermissions(bot, options.channelId, requiredVoicePerms); } } - if (requiredPerms.length) { - requireBotGuildPermissions(bot, guildId, requiredPerms); - } + requireBotGuildPermissions(bot, guildId, requiredPerms); - return await editMemberOld(guildId, memberId, options); + return await editMember(guildId, memberId, options); }; } diff --git a/plugins/permissions/src/members/kickMember.ts b/plugins/permissions/src/members/kickMember.ts index a804cdc5e..fd6538365 100644 --- a/plugins/permissions/src/members/kickMember.ts +++ b/plugins/permissions/src/members/kickMember.ts @@ -1,12 +1,12 @@ import { BotWithCache } from "../../deps.ts"; import { requireBotGuildPermissions } from "../permissions.ts"; -export default function kickMember(bot: BotWithCache) { - const editMemberOld = bot.helpers.kickMember; +export function kickMember(bot: BotWithCache) { + const kickMember = bot.helpers.kickMember; bot.helpers.kickMember = async function (guildId, memberId, reason) { requireBotGuildPermissions(bot, guildId, ["KICK_MEMBERS"]); - return await editMemberOld(guildId, memberId, reason); + return await kickMember(guildId, memberId, reason); }; } diff --git a/plugins/permissions/src/members/mod.ts b/plugins/permissions/src/members/mod.ts index 2c4232489..6d1309bdc 100644 --- a/plugins/permissions/src/members/mod.ts +++ b/plugins/permissions/src/members/mod.ts @@ -1,14 +1,16 @@ import { BotWithCache } from "../../deps.ts"; -import setupBanPermChecks from "./ban.ts"; -import editBotMember from "./editBotMember.ts"; -import editMember from "./editMember.ts"; -import kickMember from "./kickMember.ts"; -import pruneMembers from "./pruneMembers.ts"; +import { banMember } from "./banMember.ts"; +import { editBotMember } from "./editBotMember.ts"; +import { editMember } from "./editMember.ts"; +import { kickMember } from "./kickMember.ts"; +import { pruneMembers } from "./pruneMembers.ts"; +import { unbanMember } from "./unbanMember.ts"; -export default function setupMemberPermChecks(bot: BotWithCache) { - setupBanPermChecks(bot); +export function members(bot: BotWithCache) { + banMember(bot); editBotMember(bot); editMember(bot); kickMember(bot); pruneMembers(bot); + unbanMember(bot); } diff --git a/plugins/permissions/src/members/pruneMembers.ts b/plugins/permissions/src/members/pruneMembers.ts index 870c41559..91d669b9e 100644 --- a/plugins/permissions/src/members/pruneMembers.ts +++ b/plugins/permissions/src/members/pruneMembers.ts @@ -1,12 +1,12 @@ import { BotWithCache } from "../../deps.ts"; import { requireBotGuildPermissions } from "../permissions.ts"; -export default function pruneMembers(bot: BotWithCache) { - const pruneMembersOld = bot.helpers.pruneMembers; +export function pruneMembers(bot: BotWithCache) { + const pruneMembers = bot.helpers.pruneMembers; bot.helpers.pruneMembers = async function (guildId, options) { requireBotGuildPermissions(bot, guildId, ["KICK_MEMBERS"]); - return await pruneMembersOld(guildId, options); + return await pruneMembers(guildId, options); }; } diff --git a/plugins/permissions/src/members/unbanMember.ts b/plugins/permissions/src/members/unbanMember.ts new file mode 100644 index 000000000..eeb0ff9b2 --- /dev/null +++ b/plugins/permissions/src/members/unbanMember.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotGuildPermissions } from "../permissions.ts"; + +export function unbanMember(bot: BotWithCache) { + const unbanMember = bot.helpers.unbanMember; + + bot.helpers.unbanMember = async function (guildId, id) { + requireBotGuildPermissions(bot, guildId, ["BAN_MEMBERS"]); + + return await unbanMember(guildId, id); + }; +} diff --git a/plugins/permissions/src/messages/create.ts b/plugins/permissions/src/messages/create.ts deleted file mode 100644 index 960b08b64..000000000 --- a/plugins/permissions/src/messages/create.ts +++ /dev/null @@ -1,198 +0,0 @@ -import { AllowedMentionsTypes, BotWithCache, ChannelTypes, PermissionStrings } from "../../deps.ts"; -import { validateAttachments } from "../attachments.ts"; -import { validateComponents } from "../components.ts"; -import { requireBotChannelPermissions } from "../permissions.ts"; - -export function sendMessage(bot: BotWithCache) { - const sendMessageOld = bot.helpers.sendMessage; - - bot.helpers.sendMessage = async function ( - channelId, - content, - ) { - if (typeof content === "string") { - throw new Error("TODO"); - } - - const channel = bot.channels.get(channelId); - if ( - channel && - [ - ChannelTypes.GuildCategory, - ChannelTypes.GuildStageVoice, - ChannelTypes.GuildForum, - ].includes(channel.type) - ) { - throw new Error( - `Can not send message to a channel of this type. Channel ID: ${channelId}`, - ); - } - - if ( - content.content && - !bot.utils.validateLength(content.content, { max: 2000 }) - ) { - throw new Error("The content should not exceed 2000 characters."); - } - - if (content.allowedMentions) { - if (content.allowedMentions.users?.length) { - if ( - content.allowedMentions.parse?.includes( - AllowedMentionsTypes.UserMentions, - ) - ) { - content.allowedMentions.parse = content.allowedMentions.parse.filter(( - p, - ) => p !== "users"); - } - - if (content.allowedMentions.users.length > 100) { - content.allowedMentions.users = content.allowedMentions.users.slice( - 0, - 100, - ); - } - } - - if (content.allowedMentions.roles?.length) { - if ( - content.allowedMentions.parse?.includes( - AllowedMentionsTypes.RoleMentions, - ) - ) { - content.allowedMentions.parse = content.allowedMentions.parse.filter(( - p, - ) => p !== "roles"); - } - - if (content.allowedMentions.roles.length > 100) { - content.allowedMentions.roles = content.allowedMentions.roles.slice( - 0, - 100, - ); - } - } - } - - if (content.components) { - validateComponents(bot, content.components); - } - - if (channel) { - const requiredPerms: PermissionStrings[] = []; - if (channel.guildId) { - requiredPerms.push("SEND_MESSAGES"); - } - if (content.tts) requiredPerms.push("SEND_TTS_MESSAGES"); - if (content.messageReference) requiredPerms.push("READ_MESSAGE_HISTORY"); - if (requiredPerms.length) { - requireBotChannelPermissions(bot, channel, requiredPerms); - } - } - - return await sendMessageOld(channelId, content); - }; -} - -export function editMessage(bot: BotWithCache) { - const editMessageOld = bot.helpers.editMessage; - - bot.helpers.editMessage = function ( - channelId, - messageId, - content, - ) { - if (typeof content === "string") { - throw new Error("TODO"); - } - - const message = bot.messages.get(messageId); - if (message) { - if (message.authorId !== bot.id) { - content = { flags: content.flags }; - requireBotChannelPermissions(bot, channelId, ["MANAGE_MESSAGES"]); - } - } - - if (content.allowedMentions) { - if (content.allowedMentions.users?.length) { - if ( - content.allowedMentions.parse?.includes( - AllowedMentionsTypes.UserMentions, - ) - ) { - content.allowedMentions.parse = content.allowedMentions.parse.filter(( - p, - ) => p !== "users"); - } - - if (content.allowedMentions.users.length > 100) { - content.allowedMentions.users = content.allowedMentions.users.slice( - 0, - 100, - ); - } - } - - if (content.allowedMentions.roles?.length) { - if ( - content.allowedMentions.parse?.includes( - AllowedMentionsTypes.RoleMentions, - ) - ) { - content.allowedMentions.parse = content.allowedMentions.parse.filter(( - p, - ) => p !== "roles"); - } - - if (content.allowedMentions.roles.length > 100) { - content.allowedMentions.roles = content.allowedMentions.roles.slice( - 0, - 100, - ); - } - } - } - - content.embeds?.splice(10); - - if ( - content.content && - !bot.utils.validateLength(content.content, { max: 2000 }) - ) { - throw new Error( - "A message content can not contain more than 2000 characters.", - ); - } - - if (content.attachments) validateAttachments(bot, content.attachments); - - return editMessageOld(channelId, messageId, content); - }; -} - -export function publishMessage(bot: BotWithCache) { - const publishMessageOld = bot.helpers.publishMessage; - - bot.helpers.publishMessage = function ( - channelId, - messageId, - ) { - const message = bot.messages.get(messageId); - - requireBotChannelPermissions( - bot, - channelId, - message?.authorId === bot.id ? ["SEND_MESSAGES"] : ["MANAGE_MESSAGES"], - ); - - return publishMessageOld(channelId, messageId); - }; -} - -export default function setupCreateMessagePermChecks(bot: BotWithCache) { - sendMessage(bot); - editMessage(bot); - publishMessage(bot); -} diff --git a/plugins/permissions/src/messages/delete.ts b/plugins/permissions/src/messages/delete.ts deleted file mode 100644 index 57c9ec1e2..000000000 --- a/plugins/permissions/src/messages/delete.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { BotWithCache } from "../../deps.ts"; -import { requireBotChannelPermissions } from "../permissions.ts"; - -export function deleteMessage(bot: BotWithCache) { - const deleteMessageOld = bot.helpers.deleteMessage; - - bot.helpers.deleteMessage = async function ( - channelId, - messageId, - reason, - milliseconds, - ) { - const message = bot.messages.get(messageId); - // DELETING SELF MESSAGES IS ALWAYS ALLOWED - if (message?.authorId === bot.id) { - return deleteMessageOld(channelId, messageId, reason, milliseconds); - } - - const channel = bot.channels.get(channelId); - if (channel?.guildId) { - requireBotChannelPermissions(bot, channel, [ - "MANAGE_MESSAGES", - ]); - } else { - throw new Error( - `You can only delete messages in a channel which has a guild id. Channel ID: ${channelId} Message Id: ${messageId}`, - ); - } - - return await deleteMessageOld(channelId, messageId, reason, milliseconds); - }; -} - -export function deleteMessages(bot: BotWithCache) { - const deleteMessagesOld = bot.helpers.deleteMessages; - - bot.helpers.deleteMessages = async function ( - channelId, - ids, - reason, - ) { - const channel = bot.channels.get(channelId); - if (!channel?.guildId) { - throw new Error( - `Bulk deleting messages is only allowed in channels which has a guild id. Channel ID: ${channelId} IDS: ${ - ids.join(" ") - }`, - ); - } - - // 2 WEEKS - const oldestAllowed = Date.now() - 1209600000; - - ids = ids.filter((id) => { - const createdAt = Number(id / 4194304n + 1420070400000n); - // IF MESSAGE IS OLDER THAN 2 WEEKS - if (createdAt > oldestAllowed) return true; - - console.log( - `[Permission Plugin] Skipping bulk message delete of ID ${id} because it is older than 2 weeks.`, - ); - return false; - }); - - if (ids.length < 2) { - throw new Error("Bulk message delete requires at least 2 messages."); - } - - requireBotChannelPermissions(bot, channel, [ - "MANAGE_MESSAGES", - ]); - - return await deleteMessagesOld(channelId, ids, reason); - }; -} - -export default function setupDeleteMessagePermChecks(bot: BotWithCache) { - deleteMessage(bot); - deleteMessages(bot); -} diff --git a/plugins/permissions/src/messages/deleteMessage.ts b/plugins/permissions/src/messages/deleteMessage.ts new file mode 100644 index 000000000..d35a43dfe --- /dev/null +++ b/plugins/permissions/src/messages/deleteMessage.ts @@ -0,0 +1,25 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotChannelPermissions } from "../permissions.ts"; + +export function deleteMessage(bot: BotWithCache) { + const deleteMessage = bot.helpers.deleteMessage; + + bot.helpers.deleteMessage = async function (channelId, messageId, reason, milliseconds) { + const message = bot.messages.get(messageId); + // DELETING SELF MESSAGES IS ALWAYS ALLOWED + if (message?.authorId === bot.id) return deleteMessage(channelId, messageId, reason, milliseconds); + + const channel = bot.channels.get(channelId); + if (channel?.guildId) { + requireBotChannelPermissions(bot, channel, [ + "MANAGE_MESSAGES", + ]); + } else { + throw new Error( + `You can only delete messages in a channel which has a guild id. Channel ID: ${channelId} Message Id: ${messageId}`, + ); + } + + return await deleteMessage(channelId, messageId, reason, milliseconds); + }; +} diff --git a/plugins/permissions/src/messages/deleteMessages.ts b/plugins/permissions/src/messages/deleteMessages.ts new file mode 100644 index 000000000..3649e7c15 --- /dev/null +++ b/plugins/permissions/src/messages/deleteMessages.ts @@ -0,0 +1,21 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotChannelPermissions } from "../permissions.ts"; + +export function deleteMessages(bot: BotWithCache) { + const deleteMessages = bot.helpers.deleteMessages; + + bot.helpers.deleteMessages = async function (channelId, ids, reason) { + const channel = bot.channels.get(channelId); + if (!channel?.guildId) { + throw new Error( + `Bulk deleting messages is only allowed in channels which has a guild id. Channel ID: ${channelId} IDS: ${ + ids.join(" ") + }`, + ); + } + + requireBotChannelPermissions(bot, channel, ["MANAGE_MESSAGES"]); + + return await deleteMessages(channelId, ids, reason); + }; +} diff --git a/plugins/permissions/src/messages/editMessage.ts b/plugins/permissions/src/messages/editMessage.ts new file mode 100644 index 000000000..fed0d8c4d --- /dev/null +++ b/plugins/permissions/src/messages/editMessage.ts @@ -0,0 +1,18 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotChannelPermissions } from "../permissions.ts"; + +export function editMessage(bot: BotWithCache) { + const editMessage = bot.helpers.editMessage; + + bot.helpers.editMessage = function (channelId, messageId, content) { + const message = bot.messages.get(messageId); + if (message) { + if (message.authorId !== bot.id) { + content = { flags: content.flags }; + requireBotChannelPermissions(bot, channelId, ["MANAGE_MESSAGES"]); + } + } + + return editMessage(channelId, messageId, content); + }; +} diff --git a/plugins/permissions/src/messages/get.ts b/plugins/permissions/src/messages/get.ts deleted file mode 100644 index 129f446a0..000000000 --- a/plugins/permissions/src/messages/get.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { BotWithCache } from "../../deps.ts"; -import { requireBotChannelPermissions } from "../permissions.ts"; - -export function getMessage(bot: BotWithCache) { - const getMessageOld = bot.helpers.getMessage; - - bot.helpers.getMessage = async function ( - channelId, - messageId, - ) { - const channel = bot.channels.get(channelId); - if (channel?.guildId) { - requireBotChannelPermissions(bot, channel, [ - "READ_MESSAGE_HISTORY", - ]); - } - - return await getMessageOld(channelId, messageId); - }; -} - -export function getMessages(bot: BotWithCache) { - const getMessagesOld = bot.helpers.getMessages; - - bot.helpers.getMessages = async function ( - channelId, - options, - ) { - const channel = bot.channels.get(channelId); - if (channel?.guildId) { - requireBotChannelPermissions(bot, channel, [ - "READ_MESSAGE_HISTORY", - "VIEW_CHANNEL", - ]); - } - - return await getMessagesOld(channelId, options); - }; -} - -export default function setupGetMessagePermChecks(bot: BotWithCache) { - getMessage(bot); - getMessages(bot); -} diff --git a/plugins/permissions/src/messages/getMessage.ts b/plugins/permissions/src/messages/getMessage.ts new file mode 100644 index 000000000..18ebc4cf0 --- /dev/null +++ b/plugins/permissions/src/messages/getMessage.ts @@ -0,0 +1,13 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotChannelPermissions } from "../permissions.ts"; + +export function getMessage(bot: BotWithCache) { + const getMessage = bot.helpers.getMessage; + + bot.helpers.getMessage = async function (channelId, messageId) { + const channel = bot.channels.get(channelId); + if (channel?.guildId) requireBotChannelPermissions(bot, channel, ["READ_MESSAGE_HISTORY"]); + + return await getMessage(channelId, messageId); + }; +} diff --git a/plugins/permissions/src/messages/getMessages.ts b/plugins/permissions/src/messages/getMessages.ts new file mode 100644 index 000000000..43beb1fd8 --- /dev/null +++ b/plugins/permissions/src/messages/getMessages.ts @@ -0,0 +1,18 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotChannelPermissions } from "../permissions.ts"; + +export function getMessages(bot: BotWithCache) { + const getMessages = bot.helpers.getMessages; + + bot.helpers.getMessages = async function (channelId, options) { + const channel = bot.channels.get(channelId); + if (channel?.guildId) { + requireBotChannelPermissions(bot, channel, [ + "READ_MESSAGE_HISTORY", + "VIEW_CHANNEL", + ]); + } + + return await getMessages(channelId, options); + }; +} diff --git a/plugins/permissions/src/messages/mod.ts b/plugins/permissions/src/messages/mod.ts index dff8cd30a..38b699db1 100644 --- a/plugins/permissions/src/messages/mod.ts +++ b/plugins/permissions/src/messages/mod.ts @@ -1,14 +1,20 @@ import { BotWithCache } from "../../deps.ts"; -import setupCreateMessagePermChecks from "./create.ts"; -import setupDeleteMessagePermChecks from "./delete.ts"; -import setupGetMessagePermChecks from "./get.ts"; -import setupPinMessagePermChecks from "./pin.ts"; -import setupReactionsPermChecks from "./reactions.ts"; +import { deleteMessage } from "./deleteMessage.ts"; +import { deleteMessages } from "./deleteMessages.ts"; +import { getMessage } from "./getMessage.ts"; +import { getMessages } from "./getMessages.ts"; +import { pinMessage } from "./pinMessage.ts"; +import { reactions } from "./reactions/mod.ts"; +import { sendMessage } from "./sendMessage.ts"; +import { unpinMessage } from "./unpinMessage.ts"; -export default function setupMessagesPermChecks(bot: BotWithCache) { - setupReactionsPermChecks(bot); - setupDeleteMessagePermChecks(bot); - setupGetMessagePermChecks(bot); - setupPinMessagePermChecks(bot); - setupCreateMessagePermChecks(bot); +export function messages(bot: BotWithCache) { + reactions(bot); + deleteMessage(bot); + deleteMessages(bot); + getMessage(bot); + getMessages(bot); + pinMessage(bot); + sendMessage(bot); + unpinMessage(bot); } diff --git a/plugins/permissions/src/messages/pin.ts b/plugins/permissions/src/messages/pin.ts deleted file mode 100644 index 9be081529..000000000 --- a/plugins/permissions/src/messages/pin.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { BotWithCache } from "../../deps.ts"; -import { requireBotChannelPermissions } from "../permissions.ts"; - -export function pinMessage(bot: BotWithCache) { - const pinMessageOld = bot.helpers.pinMessage; - - bot.helpers.pinMessage = async function ( - channelId, - messageId, - ) { - requireBotChannelPermissions(bot, channelId, [ - "MANAGE_MESSAGES", - ]); - - return await pinMessageOld(channelId, messageId); - }; -} - -export function unpinMessage(bot: BotWithCache) { - const unpinMessageOld = bot.helpers.unpinMessage; - - bot.helpers.unpinMessage = async function ( - channelId, - messageId, - ) { - requireBotChannelPermissions(bot, channelId, [ - "MANAGE_MESSAGES", - ]); - - return await unpinMessageOld(channelId, messageId); - }; -} - -export default function setupPinMessagePermChecks(bot: BotWithCache) { - pinMessage(bot); - unpinMessage(bot); -} diff --git a/plugins/permissions/src/messages/pinMessage.ts b/plugins/permissions/src/messages/pinMessage.ts new file mode 100644 index 000000000..9cef9e96d --- /dev/null +++ b/plugins/permissions/src/messages/pinMessage.ts @@ -0,0 +1,17 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotChannelPermissions } from "../permissions.ts"; + +export function pinMessage(bot: BotWithCache) { + const pinMessage = bot.helpers.pinMessage; + + bot.helpers.pinMessage = async function ( + channelId, + messageId, + ) { + requireBotChannelPermissions(bot, channelId, [ + "MANAGE_MESSAGES", + ]); + + return await pinMessage(channelId, messageId); + }; +} diff --git a/plugins/permissions/src/messages/publishMessage.ts b/plugins/permissions/src/messages/publishMessage.ts new file mode 100644 index 000000000..8b73efb30 --- /dev/null +++ b/plugins/permissions/src/messages/publishMessage.ts @@ -0,0 +1,18 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotChannelPermissions } from "../permissions.ts"; + +export function publishMessage(bot: BotWithCache) { + const publishMessage = bot.helpers.publishMessage; + + bot.helpers.publishMessage = function (channelId, messageId) { + const message = bot.messages.get(messageId); + + requireBotChannelPermissions( + bot, + channelId, + message?.authorId === bot.id ? ["SEND_MESSAGES"] : ["MANAGE_MESSAGES"], + ); + + return publishMessage(channelId, messageId); + }; +} diff --git a/plugins/permissions/src/messages/reactions.ts b/plugins/permissions/src/messages/reactions.ts deleted file mode 100644 index 42f2c89d1..000000000 --- a/plugins/permissions/src/messages/reactions.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { BotWithCache } from "../../deps.ts"; -import { requireBotChannelPermissions } from "../permissions.ts"; - -export function addReaction(bot: BotWithCache) { - const addReactionOld = bot.helpers.addReaction; - - bot.helpers.addReaction = async function (channelId, messageId, reaction) { - requireBotChannelPermissions(bot, channelId, ["READ_MESSAGE_HISTORY", "ADD_REACTIONS"]); - - return await addReactionOld(channelId, messageId, reaction); - }; -} - -export function addReactions(bot: BotWithCache) { - const addReactionsOld = bot.helpers.addReactions; - - bot.helpers.addReactions = async function (channelId, messageId, reactions, ordered) { - requireBotChannelPermissions(bot, channelId, ["READ_MESSAGE_HISTORY", "ADD_REACTIONS"]); - - return await addReactionsOld(channelId, messageId, reactions, ordered); - }; -} - -export function deleteUserReaction(bot: BotWithCache) { - const deleteUserReactionOld = bot.helpers.deleteUserReaction; - - bot.helpers.deleteUserReaction = async function (channelId, messageId, userId, reaction) { - requireBotChannelPermissions(bot, channelId, ["MANAGE_MESSAGES"]); - - return await deleteUserReactionOld(channelId, messageId, userId, reaction); - }; -} - -export function deleteReactionsAll(bot: BotWithCache) { - const DeleteReactionsAllOld = bot.helpers.deleteReactionsAll; - - bot.helpers.deleteReactionsAll = async function (channelId, messageId) { - requireBotChannelPermissions(bot, channelId, ["MANAGE_MESSAGES"]); - - return await DeleteReactionsAllOld(channelId, messageId); - }; -} - -export function deleteReactionsEmoji(bot: BotWithCache) { - const deleteReactionsEmojiOld = bot.helpers.deleteReactionsEmoji; - - bot.helpers.deleteReactionsEmoji = async function (channelId, messageId, reaction) { - requireBotChannelPermissions(bot, channelId, ["MANAGE_MESSAGES"]); - - return await deleteReactionsEmojiOld(channelId, messageId, reaction); - }; -} - -export default function setupReactionsPermChecks(bot: BotWithCache) { - addReaction(bot); - addReactions(bot); - deleteUserReaction(bot); - deleteReactionsAll(bot); - deleteReactionsEmoji(bot); -} diff --git a/plugins/permissions/src/messages/reactions/addReaction.ts b/plugins/permissions/src/messages/reactions/addReaction.ts new file mode 100644 index 000000000..ba48be219 --- /dev/null +++ b/plugins/permissions/src/messages/reactions/addReaction.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../../deps.ts"; +import { requireBotChannelPermissions } from "../../permissions.ts"; + +export function addReaction(bot: BotWithCache) { + const addReaction = bot.helpers.addReaction; + + bot.helpers.addReaction = async function (channelId, messageId, reaction) { + requireBotChannelPermissions(bot, channelId, ["READ_MESSAGE_HISTORY", "ADD_REACTIONS"]); + + return await addReaction(channelId, messageId, reaction); + }; +} diff --git a/plugins/permissions/src/messages/reactions/addReactions.ts b/plugins/permissions/src/messages/reactions/addReactions.ts new file mode 100644 index 000000000..43c34afb6 --- /dev/null +++ b/plugins/permissions/src/messages/reactions/addReactions.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../../deps.ts"; +import { requireBotChannelPermissions } from "../../permissions.ts"; + +export function addReactions(bot: BotWithCache) { + const addReactions = bot.helpers.addReactions; + + bot.helpers.addReactions = async function (channelId, messageId, reactions, ordered) { + requireBotChannelPermissions(bot, channelId, ["READ_MESSAGE_HISTORY", "ADD_REACTIONS"]); + + return await addReactions(channelId, messageId, reactions, ordered); + }; +} diff --git a/plugins/permissions/src/messages/reactions/deleteReactionsAll.ts b/plugins/permissions/src/messages/reactions/deleteReactionsAll.ts new file mode 100644 index 000000000..e6f5b3cd2 --- /dev/null +++ b/plugins/permissions/src/messages/reactions/deleteReactionsAll.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../../deps.ts"; +import { requireBotChannelPermissions } from "../../permissions.ts"; + +export function deleteReactionsAll(bot: BotWithCache) { + const deleteReactionsAll = bot.helpers.deleteReactionsAll; + + bot.helpers.deleteReactionsAll = async function (channelId, messageId) { + requireBotChannelPermissions(bot, channelId, ["MANAGE_MESSAGES"]); + + return await deleteReactionsAll(channelId, messageId); + }; +} diff --git a/plugins/permissions/src/messages/reactions/deleteReactionsEmoji.ts b/plugins/permissions/src/messages/reactions/deleteReactionsEmoji.ts new file mode 100644 index 000000000..9c6b58fc8 --- /dev/null +++ b/plugins/permissions/src/messages/reactions/deleteReactionsEmoji.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../../deps.ts"; +import { requireBotChannelPermissions } from "../../permissions.ts"; + +export function deleteReactionsEmoji(bot: BotWithCache) { + const deleteReactionsEmoji = bot.helpers.deleteReactionsEmoji; + + bot.helpers.deleteReactionsEmoji = async function (channelId, messageId, reaction) { + requireBotChannelPermissions(bot, channelId, ["MANAGE_MESSAGES"]); + + return await deleteReactionsEmoji(channelId, messageId, reaction); + }; +} diff --git a/plugins/permissions/src/messages/reactions/deleteUserReaction.ts.ts b/plugins/permissions/src/messages/reactions/deleteUserReaction.ts.ts new file mode 100644 index 000000000..8412aa91a --- /dev/null +++ b/plugins/permissions/src/messages/reactions/deleteUserReaction.ts.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../../deps.ts"; +import { requireBotChannelPermissions } from "../../permissions.ts"; + +export function deleteUserReaction(bot: BotWithCache) { + const deleteUserReaction = bot.helpers.deleteUserReaction; + + bot.helpers.deleteUserReaction = async function (channelId, messageId, userId, reaction) { + requireBotChannelPermissions(bot, channelId, ["MANAGE_MESSAGES"]); + + return await deleteUserReaction(channelId, messageId, userId, reaction); + }; +} diff --git a/plugins/permissions/src/messages/reactions/mod.ts b/plugins/permissions/src/messages/reactions/mod.ts new file mode 100644 index 000000000..4ffb6617f --- /dev/null +++ b/plugins/permissions/src/messages/reactions/mod.ts @@ -0,0 +1,14 @@ +import { BotWithCache } from "../../../deps.ts"; +import { addReaction } from "./addReaction.ts"; +import { addReactions } from "./addReactions.ts"; +import { deleteReactionsAll } from "./deleteReactionsAll.ts"; +import { deleteReactionsEmoji } from "./deleteReactionsEmoji.ts"; +import { deleteUserReaction } from "./deleteUserReaction.ts.ts"; + +export function reactions(bot: BotWithCache) { + addReaction(bot); + addReactions(bot); + deleteReactionsAll(bot); + deleteReactionsEmoji(bot); + deleteUserReaction(bot); +} diff --git a/plugins/permissions/src/messages/sendMessage.ts b/plugins/permissions/src/messages/sendMessage.ts new file mode 100644 index 000000000..149ee6a16 --- /dev/null +++ b/plugins/permissions/src/messages/sendMessage.ts @@ -0,0 +1,26 @@ +import { BotWithCache, ChannelTypes, PermissionStrings } from "../../deps.ts"; +import { requireBotChannelPermissions } from "../permissions.ts"; + +export function sendMessage(bot: BotWithCache) { + const sendMessage = bot.helpers.sendMessage; + + bot.helpers.sendMessage = async function (channelId, content) { + const channel = bot.channels.get(channelId); + if ( + channel && + [ChannelTypes.GuildCategory, ChannelTypes.GuildStageVoice, ChannelTypes.GuildForum].includes(channel.type) + ) { + throw new Error(`Can not send message to a channel of this type. Channel ID: ${channelId}`); + } + + if (channel) { + const requiredPerms: PermissionStrings[] = []; + if (channel.guildId) requiredPerms.push("SEND_MESSAGES"); + if (content.tts) requiredPerms.push("SEND_TTS_MESSAGES"); + if (content.messageReference) requiredPerms.push("READ_MESSAGE_HISTORY"); + if (requiredPerms.length) requireBotChannelPermissions(bot, channel, requiredPerms); + } + + return await sendMessage(channelId, content); + }; +} diff --git a/plugins/permissions/src/messages/unpinMessage.ts b/plugins/permissions/src/messages/unpinMessage.ts new file mode 100644 index 000000000..b908ae9a6 --- /dev/null +++ b/plugins/permissions/src/messages/unpinMessage.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotChannelPermissions } from "../permissions.ts"; + +export function unpinMessage(bot: BotWithCache) { + const unpinMessage = bot.helpers.unpinMessage; + + bot.helpers.unpinMessage = async function (channelId, messageId) { + requireBotChannelPermissions(bot, channelId, ["MANAGE_MESSAGES"]); + + return await unpinMessage(channelId, messageId); + }; +} diff --git a/plugins/permissions/src/permissions.ts b/plugins/permissions/src/permissions.ts index 32614a37c..98d25b4f2 100644 --- a/plugins/permissions/src/permissions.ts +++ b/plugins/permissions/src/permissions.ts @@ -309,18 +309,12 @@ export function requireOverwritePermissions( let requiredPerms: Set = new Set(["MANAGE_CHANNELS"]); overwrites?.forEach((overwrite) => { - if (overwrite.allow) { - overwrite.allow.forEach(requiredPerms.add, requiredPerms); - } - if (overwrite.deny) { - overwrite.deny.forEach(requiredPerms.add, requiredPerms); - } + if (overwrite.allow) overwrite.allow.forEach(requiredPerms.add, requiredPerms); + if (overwrite.deny) overwrite.deny.forEach(requiredPerms.add, requiredPerms); }); // MANAGE_ROLES permission can only be set by administrators - if (requiredPerms.has("MANAGE_ROLES")) { - requiredPerms = new Set(["ADMINISTRATOR"]); - } + if (requiredPerms.has("MANAGE_ROLES")) requiredPerms = new Set(["ADMINISTRATOR"]); requireGuildPermissions(bot, guildOrId, bot.id, [ ...requiredPerms, @@ -382,9 +376,7 @@ export function higherRolePosition( if (!role || !otherRole) throw new Error(Errors.ROLE_NOT_FOUND); // Rare edge case handling - if (role.position === otherRole.position) { - return role.id < otherRole.id; - } + if (role.position === otherRole.position) return role.id < otherRole.id; return role.position > otherRole.position; } @@ -429,11 +421,7 @@ export function channelOverwriteHasPermission( return permissions.every((perm) => { const [_type, _id, allowBits, denyBits] = separateOverwrites(overwrite); - if (BigInt(denyBits) & BigInt(BitwisePermissionFlags[perm])) { - return false; - } - if (BigInt(allowBits) & BigInt(BitwisePermissionFlags[perm])) { - return true; - } + if (BigInt(denyBits) & BigInt(BitwisePermissionFlags[perm])) return false; + if (BigInt(allowBits) & BigInt(BitwisePermissionFlags[perm])) return true; }); } diff --git a/plugins/permissions/src/roles/add.ts b/plugins/permissions/src/roles/addRole.ts similarity index 58% rename from plugins/permissions/src/roles/add.ts rename to plugins/permissions/src/roles/addRole.ts index 2fb55848f..dcf6e8445 100644 --- a/plugins/permissions/src/roles/add.ts +++ b/plugins/permissions/src/roles/addRole.ts @@ -1,16 +1,10 @@ import { BotWithCache } from "../../deps.ts"; -import { higherRolePosition } from "../permissions.ts"; -import { highestRole, requireBotGuildPermissions } from "../permissions.ts"; +import { higherRolePosition, highestRole, requireBotGuildPermissions } from "../permissions.ts"; -export default function addRole(bot: BotWithCache) { - const addRoleOld = bot.helpers.addRole; +export function addRole(bot: BotWithCache) { + const addRole = bot.helpers.addRole; - bot.helpers.addRole = async function ( - guildId, - memberId, - roleId, - reason, - ) { + bot.helpers.addRole = async function (guildId, memberId, roleId, reason) { const guild = bot.guilds.get(guildId); if (guild) { const role = guild.roles.get(roleId); @@ -27,6 +21,6 @@ export default function addRole(bot: BotWithCache) { requireBotGuildPermissions(bot, guild, ["MANAGE_ROLES"]); } - return await addRoleOld(guildId, memberId, roleId, reason); + return await addRole(guildId, memberId, roleId, reason); }; } diff --git a/plugins/permissions/src/roles/create.ts b/plugins/permissions/src/roles/create.ts deleted file mode 100644 index 19fefc83f..000000000 --- a/plugins/permissions/src/roles/create.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { BotWithCache } from "../../deps.ts"; -import { requireBotGuildPermissions } from "../permissions.ts"; - -export default function createRole(bot: BotWithCache) { - const createRoleOld = bot.helpers.createRole; - - bot.helpers.createRole = async function ( - guildId, - options, - reason, - ) { - requireBotGuildPermissions(bot, guildId, ["MANAGE_ROLES"]); - - return await createRoleOld(guildId, options, reason); - }; -} diff --git a/plugins/permissions/src/roles/createRole.ts b/plugins/permissions/src/roles/createRole.ts new file mode 100644 index 000000000..48e5f73d5 --- /dev/null +++ b/plugins/permissions/src/roles/createRole.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotGuildPermissions } from "../permissions.ts"; + +export function createRole(bot: BotWithCache) { + const createRole = bot.helpers.createRole; + + bot.helpers.createRole = async function (guildId, options, reason) { + requireBotGuildPermissions(bot, guildId, ["MANAGE_ROLES"]); + + return await createRole(guildId, options, reason); + }; +} diff --git a/plugins/permissions/src/roles/delete.ts b/plugins/permissions/src/roles/delete.ts deleted file mode 100644 index 16a6eda21..000000000 --- a/plugins/permissions/src/roles/delete.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { BotWithCache } from "../../deps.ts"; -import { requireBotGuildPermissions } from "../permissions.ts"; - -export default function deleteRole(bot: BotWithCache) { - const deleteRoleOld = bot.helpers.deleteRole; - - bot.helpers.deleteRole = async function ( - guildId, - id, - ) { - requireBotGuildPermissions(bot, guildId, ["MANAGE_ROLES"]); - - return await deleteRoleOld(guildId, id); - }; -} diff --git a/plugins/permissions/src/roles/deleteRole.ts b/plugins/permissions/src/roles/deleteRole.ts new file mode 100644 index 000000000..dc3722d9b --- /dev/null +++ b/plugins/permissions/src/roles/deleteRole.ts @@ -0,0 +1,12 @@ +import { BotWithCache } from "../../deps.ts"; +import { requireBotGuildPermissions } from "../permissions.ts"; + +export function deleteRole(bot: BotWithCache) { + const deleteRole = bot.helpers.deleteRole; + + bot.helpers.deleteRole = async function (guildId, id) { + requireBotGuildPermissions(bot, guildId, ["MANAGE_ROLES"]); + + return await deleteRole(guildId, id); + }; +} diff --git a/plugins/permissions/src/roles/edit.ts b/plugins/permissions/src/roles/editRole.ts similarity index 83% rename from plugins/permissions/src/roles/edit.ts rename to plugins/permissions/src/roles/editRole.ts index ff14a4d4a..e587e3774 100644 --- a/plugins/permissions/src/roles/edit.ts +++ b/plugins/permissions/src/roles/editRole.ts @@ -2,8 +2,8 @@ import { BotWithCache } from "../../deps.ts"; import { higherRolePosition } from "../permissions.ts"; import { highestRole, requireBotGuildPermissions } from "../permissions.ts"; -export default function editRole(bot: BotWithCache) { - const editRoleOld = bot.helpers.editRole; +export function editRole(bot: BotWithCache) { + const editRole = bot.helpers.editRole; bot.helpers.editRole = async function ( guildId, @@ -26,6 +26,6 @@ export default function editRole(bot: BotWithCache) { requireBotGuildPermissions(bot, guild, ["MANAGE_ROLES"]); } - return await editRoleOld(guildId, id, options); + return await editRole(guildId, id, options); }; } diff --git a/plugins/permissions/src/roles/mod.ts b/plugins/permissions/src/roles/mod.ts index a279d5e48..5b5f5a56e 100644 --- a/plugins/permissions/src/roles/mod.ts +++ b/plugins/permissions/src/roles/mod.ts @@ -1,14 +1,16 @@ import { BotWithCache } from "../../deps.ts"; -import addRole from "./add.ts"; -import createRole from "./create.ts"; -import deleteRole from "./delete.ts"; -import editRole from "./edit.ts"; -import removeRole from "./remove.ts"; +import { addRole } from "./addRole.ts"; +import { createRole } from "./createRole.ts"; +import { deleteRole } from "./deleteRole.ts"; +import { editRole } from "./editRole.ts"; +import { modifyRolePositions } from "./modifyRolePositions.ts"; +import { removeRole } from "./removeRole.ts"; -export default function setupRolePermChecks(bot: BotWithCache) { +export function roles(bot: BotWithCache) { addRole(bot); createRole(bot); deleteRole(bot); editRole(bot); + modifyRolePositions(bot); removeRole(bot); } diff --git a/plugins/permissions/src/roles/modifyRolePositions.ts b/plugins/permissions/src/roles/modifyRolePositions.ts index 71dd7b3c6..e50285f26 100644 --- a/plugins/permissions/src/roles/modifyRolePositions.ts +++ b/plugins/permissions/src/roles/modifyRolePositions.ts @@ -2,11 +2,11 @@ import { BotWithCache } from "../../deps.ts"; import { requireBotGuildPermissions } from "../permissions.ts"; export function modifyRolePositions(bot: BotWithCache) { - const modifyRolePositionsOld = bot.helpers.modifyRolePositions; + const modifyRolePositions = bot.helpers.modifyRolePositions; bot.helpers.modifyRolePositions = async function (guildId, categoryId) { requireBotGuildPermissions(bot, guildId, ["MANAGE_ROLES"]); - return await modifyRolePositionsOld(guildId, categoryId); + return await modifyRolePositions(guildId, categoryId); }; } diff --git a/plugins/permissions/src/roles/remove.ts b/plugins/permissions/src/roles/removeRole.ts similarity index 68% rename from plugins/permissions/src/roles/remove.ts rename to plugins/permissions/src/roles/removeRole.ts index 215397f47..650195917 100644 --- a/plugins/permissions/src/roles/remove.ts +++ b/plugins/permissions/src/roles/removeRole.ts @@ -1,9 +1,8 @@ import { BotWithCache } from "../../deps.ts"; -import { higherRolePosition } from "../permissions.ts"; -import { highestRole, requireBotGuildPermissions } from "../permissions.ts"; +import { higherRolePosition, highestRole, requireBotGuildPermissions } from "../permissions.ts"; -export default function removeRole(bot: BotWithCache) { - const removeRoleOld = bot.helpers.removeRole; +export function removeRole(bot: BotWithCache) { + const removeRole = bot.helpers.removeRole; bot.helpers.removeRole = async function ( guildId, @@ -27,6 +26,6 @@ export default function removeRole(bot: BotWithCache) { requireBotGuildPermissions(bot, guild, ["MANAGE_ROLES"]); } - return await removeRoleOld(guildId, memberId, roleId, reason); + return await removeRole(guildId, memberId, roleId, reason); }; } diff --git a/plugins/permissions/src/webhooks/createWebhook.ts b/plugins/permissions/src/webhooks/createWebhook.ts index 878534ac6..7d08e39ed 100644 --- a/plugins/permissions/src/webhooks/createWebhook.ts +++ b/plugins/permissions/src/webhooks/createWebhook.ts @@ -1,27 +1,12 @@ import { BotWithCache } from "../../deps.ts"; import { requireBotChannelPermissions } from "../permissions.ts"; -export default function createWebhook(bot: BotWithCache) { - const createWebhookOld = bot.helpers.createWebhook; +export function createWebhook(bot: BotWithCache) { + const createWebhook = bot.helpers.createWebhook; bot.helpers.createWebhook = async function (channelId, options) { requireBotChannelPermissions(bot, channelId, ["MANAGE_WEBHOOKS", "VIEW_CHANNEL"]); - if ( - // Specific usernames that discord does not allow - ["clyde", "everyone", "here"].includes(options.name) || - options.name.includes("discord") || - options.name.includes("@") || - options.name.includes("#") || - options.name.includes(":") || - options.name.includes("\/") || - !bot.utils.validateLength(options.name, { min: 2, max: 32 }) - ) { - throw new Error( - "The webhook name can not be clyde, everyone, here or include 'discord, @, #, :, ' and it must be between 2 and 32 characters long.", - ); - } - - return await createWebhookOld(channelId, options); + return await createWebhook(channelId, options); }; } diff --git a/plugins/permissions/src/webhooks/deleteWebhook.ts b/plugins/permissions/src/webhooks/deleteWebhook.ts index 1dc0c5694..ea556a09f 100644 --- a/plugins/permissions/src/webhooks/deleteWebhook.ts +++ b/plugins/permissions/src/webhooks/deleteWebhook.ts @@ -1,12 +1,12 @@ import { BotWithCache } from "../../deps.ts"; import { requireBotChannelPermissions } from "../permissions.ts"; -export default function deleteWebhook(bot: BotWithCache) { - const deleteWebhookOld = bot.helpers.deleteWebhook; +export function deleteWebhook(bot: BotWithCache) { + const deleteWebhook = bot.helpers.deleteWebhook; bot.helpers.deleteWebhook = async function (channelId, options) { requireBotChannelPermissions(bot, channelId, ["MANAGE_WEBHOOKS", "VIEW_CHANNEL"]); - return await deleteWebhookOld(channelId, options); + return await deleteWebhook(channelId, options); }; } diff --git a/plugins/permissions/src/webhooks/editWebhook.ts b/plugins/permissions/src/webhooks/editWebhook.ts index fc2f879e3..a18ccfa4a 100644 --- a/plugins/permissions/src/webhooks/editWebhook.ts +++ b/plugins/permissions/src/webhooks/editWebhook.ts @@ -1,25 +1,13 @@ import { BotWithCache } from "../../deps.ts"; import { requireBotChannelPermissions } from "../permissions.ts"; -export default function editWebhook(bot: BotWithCache) { - const editWebhookOld = bot.helpers.editWebhook; +export function editWebhook(bot: BotWithCache) { + const editWebhook = bot.helpers.editWebhook; bot.helpers.editWebhook = async function (webhookId, options, fromChannelId) { if (options.channelId) requireBotChannelPermissions(bot, options.channelId, ["MANAGE_WEBHOOKS", "VIEW_CHANNEL"]); if (fromChannelId) requireBotChannelPermissions(bot, fromChannelId, ["MANAGE_WEBHOOKS", "VIEW_CHANNEL"]); - if (options.name) { - if ( - // Specific usernames that discord does not allow - options.name === "clyde" || - !bot.utils.validateLength(options.name, { min: 2, max: 32 }) - ) { - throw new Error( - "The webhook name can not be clyde and it must be between 2 and 32 characters long.", - ); - } - } - - return await editWebhookOld(webhookId, options); + return await editWebhook(webhookId, options); }; } diff --git a/plugins/permissions/src/webhooks/mod.ts b/plugins/permissions/src/webhooks/mod.ts index 35ba01bc0..2237e2227 100644 --- a/plugins/permissions/src/webhooks/mod.ts +++ b/plugins/permissions/src/webhooks/mod.ts @@ -1,12 +1,10 @@ import { BotWithCache } from "../../deps.ts"; -import createWebhook from "./createWebhook.ts"; -import deleteWebhook from "./deleteWebhook.ts"; -import editWebhook from "./editWebhook.ts"; -import setupMessageWebhookPermChecks from "./message.ts"; +import { createWebhook } from "./createWebhook.ts"; +import { deleteWebhook } from "./deleteWebhook.ts"; +import { editWebhook } from "./editWebhook.ts"; -export default function setupWebhooksPermChecks(bot: BotWithCache) { +export function webhooks(bot: BotWithCache) { createWebhook(bot); deleteWebhook(bot); editWebhook(bot); - setupMessageWebhookPermChecks(bot); } diff --git a/plugins/permissions/src/webhooks/sendWebhook.ts b/plugins/permissions/src/webhooks/sendWebhook.ts deleted file mode 100644 index 9ab776cb2..000000000 --- a/plugins/permissions/src/webhooks/sendWebhook.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { AllowedMentionsTypes, BotWithCache } from "../../deps.ts"; -import { validateComponents } from "../components.ts"; - -export default function sendWebhook(bot: BotWithCache) { - const sendWebhookOld = bot.helpers.sendWebhook; - - bot.helpers.sendWebhook = async function (webhookId, webhookToken, options) { - if ( - options.content && - !bot.utils.validateLength(options.content, { max: 2000 }) - ) { - throw new Error("The content should not exceed 2000 characters."); - } - - if (options.allowedMentions) { - if (options.allowedMentions.users?.length) { - if ( - options.allowedMentions.parse?.includes( - AllowedMentionsTypes.UserMentions, - ) - ) { - options.allowedMentions.parse = options.allowedMentions.parse.filter(( - p, - ) => p !== "users"); - } - - if (options.allowedMentions.users.length > 100) { - options.allowedMentions.users = options.allowedMentions.users.slice( - 0, - 100, - ); - } - } - - if (options.allowedMentions.roles?.length) { - if ( - options.allowedMentions.parse?.includes( - AllowedMentionsTypes.RoleMentions, - ) - ) { - options.allowedMentions.parse = options.allowedMentions.parse.filter(( - p, - ) => p !== "roles"); - } - - if (options.allowedMentions.roles.length > 100) { - options.allowedMentions.roles = options.allowedMentions.roles.slice( - 0, - 100, - ); - } - } - } - - if (options.components) { - validateComponents(bot, options.components); - } - - if (!options.content && !options.file && !options.embeds) { - throw new Error( - "You must provide a value for at least one of content, embeds, or file.", - ); - } - - return await sendWebhookOld(webhookId, webhookToken, options); - }; -} diff --git a/plugins/validations/README.md b/plugins/validations/README.md new file mode 100644 index 000000000..319c124ca --- /dev/null +++ b/plugins/validations/README.md @@ -0,0 +1,18 @@ +# validations-plugin + +This is an official plugin maintained by Discordeno. This plugin provides automatic request checking and useful +validation utility functions. Highly recommended to install this plugin for all users as you can use the utility +functions. + +## Usage + +```ts +// MOVE TO DEPS.TS AND USE SPECIFIC VERSION +import { enableValidationsPlugin } from "./deps.ts"; +// Create the bot object, THIS WILL NEED YOUR OPTIONS. +const bot = createBot({}); +// Enables the plugin on this bot +enableValidationsPlugin(bot); +// Start your bot +await startBot(bot); +``` diff --git a/plugins/validations/deps.ts b/plugins/validations/deps.ts new file mode 100644 index 000000000..ac326e73f --- /dev/null +++ b/plugins/validations/deps.ts @@ -0,0 +1 @@ +export * from "../../mod.ts"; diff --git a/plugins/validations/mod.ts b/plugins/validations/mod.ts new file mode 100644 index 000000000..a02705bd4 --- /dev/null +++ b/plugins/validations/mod.ts @@ -0,0 +1,36 @@ +import { Bot } from "./deps.ts"; +import { channels } from "./src/channels/mod.ts"; +import { guilds } from "./src/guilds/mod.ts"; +import { interactions } from "./src/interaction/mod.ts"; +import { invites } from "./src/invites/mod.ts"; +import { members } from "./src/members/mod.ts"; +import { messages } from "./src/messages/mod.ts"; +import { misc } from "./src/misc/mod.ts"; +import { webhooks } from "./src/webhooks/mod.ts"; + +// PLUGINS MUST TAKE A BOT ARGUMENT WHICH WILL BE MODIFIED +export function enableValidationsPlugin(bot: Bot) { + // MARK THIS PLUGIN BEING USED + bot.enabledPlugins.add("VALIDATIONS"); + + // BEGIN OVERRIDING HELPER FUNCTIONS + channels(bot); + guilds(bot); + interactions(bot); + invites(bot); + members(bot); + messages(bot); + misc(bot); + webhooks(bot); + + // PLUGINS MUST RETURN THE BOT + return bot; +} + +// EXPORT ALL UTIL FUNCTIONS +export * from "./src/applicationCommandOptions.ts"; +export * from "./src/attachments.ts"; +export * from "./src/components.ts"; + +// DEFAULT MAKES IT SLIGHTLY EASIER TO USE +export default enableValidationsPlugin; diff --git a/plugins/validations/src/applicationCommandLength.ts b/plugins/validations/src/applicationCommandLength.ts new file mode 100644 index 000000000..c3d137432 --- /dev/null +++ b/plugins/validations/src/applicationCommandLength.ts @@ -0,0 +1,51 @@ +import { ApplicationCommandOption, Bot, CreateSlashApplicationCommand } from "../deps.ts"; +export function validateApplicationCommandLength(bot: Bot, options: CreateSlashApplicationCommand) { + let length = 0; + if (options.nameLocalizations) { + length += Math.max(options.name.length, ...Object.values(options.nameLocalizations).map((name) => name.length)); + } else length += options.name.length; + if (options.descriptionLocalizations) { + length += Math.max( + options.description.length, + ...Object.values(options.descriptionLocalizations).map((name) => name.length), + ); + } else { + length += options.description.length; + } + if (options.options) length += validateApplicationCommandOptionLength(bot, options.options); + + if (length > 4000) { + throw new Error( + "Slash commands can have a maximum of 4000 characters for combined name, description, and value properties for each command, its options (including subcommands and groups), and choices. When localization fields are present, only the longest localization for each field (including the default value) is counted towards the size limit.", + ); + } +} + +function validateApplicationCommandOptionLength(bot: Bot, options: ApplicationCommandOption[]) { + let length = 0; + for (const option of options) { + if (option.nameLocalizations) { + length += Math.max(option.name.length, ...Object.values(option.nameLocalizations).map((name) => name.length)); + } else length += option.name.length; + if (option.descriptionLocalizations) { + length += Math.max( + option.description.length, + ...Object.values(option.descriptionLocalizations).map((name) => name.length), + ); + } else { + length += option.description.length; + } + + if (option.choices) { + for (const choice of option.choices) { + length += choice.value.toString().length; + if (choice.nameLocalizations) { + length += Math.max(option.name.length, ...Object.values(choice.nameLocalizations).map((name) => name.length)); + } else length += choice.name.length; + } + } + + if (option.options) length += validateApplicationCommandOptionLength(bot, option.options); + } + return length; +} diff --git a/plugins/validations/src/applicationCommandOptions.ts b/plugins/validations/src/applicationCommandOptions.ts new file mode 100644 index 000000000..5b991db25 --- /dev/null +++ b/plugins/validations/src/applicationCommandOptions.ts @@ -0,0 +1,54 @@ +import { ApplicationCommandOption, ApplicationCommandOptionTypes, Bot } from "../deps.ts"; + +export function validateApplicationCommandOptions(bot: Bot, options: ApplicationCommandOption[]) { + const requiredOptions: ApplicationCommandOption[] = []; + const optionalOptions: ApplicationCommandOption[] = []; + + for (const option of options) { + option.name = option.name.toLowerCase(); + + if (option.choices?.length) { + if (option.choices.length > 25) throw new Error("Too many application command options provided."); + + if ( + option.type !== ApplicationCommandOptionTypes.String && option.type !== ApplicationCommandOptionTypes.Integer + ) { + throw new Error("Only string or integer options can have choices."); + } + } + + if (!bot.utils.validateLength(option.name, { min: 1, max: 32 })) { + throw new Error("Invalid application command option name."); + } + + if (!bot.utils.validateLength(option.description, { min: 1, max: 100 })) { + throw new Error("Invalid application command description."); + } + + option.choices?.every((choice) => { + if (!bot.utils.validateLength(choice.name, { min: 1, max: 100 })) { + throw new Error("Invalid application command option choice name. Must be between 1-100 characters long."); + } + + if ( + option.type === ApplicationCommandOptionTypes.String && + (typeof choice.value !== "string" || choice.value.length < 1 || choice.value.length > 100) + ) { + throw new Error("Invalid slash options choice value type."); + } + + if (option.type === ApplicationCommandOptionTypes.Integer && typeof choice.value !== "number") { + throw new Error("A number must be set for Integer types."); + } + }); + + if (option.required) { + requiredOptions.push(option); + continue; + } + + optionalOptions.push(option); + } + + return [...requiredOptions, ...optionalOptions]; +} diff --git a/plugins/permissions/src/attachments.ts b/plugins/validations/src/attachments.ts similarity index 100% rename from plugins/permissions/src/attachments.ts rename to plugins/validations/src/attachments.ts diff --git a/plugins/validations/src/channels/mod.ts b/plugins/validations/src/channels/mod.ts new file mode 100644 index 000000000..5b5ed0e15 --- /dev/null +++ b/plugins/validations/src/channels/mod.ts @@ -0,0 +1,6 @@ +import { Bot } from "../../deps.ts"; +import { threads } from "./threads/mod.ts"; + +export function channels(bot: Bot) { + threads(bot); +} diff --git a/plugins/validations/src/channels/threads/addThreadMember.ts b/plugins/validations/src/channels/threads/addThreadMember.ts new file mode 100644 index 000000000..59126bd61 --- /dev/null +++ b/plugins/validations/src/channels/threads/addThreadMember.ts @@ -0,0 +1,11 @@ +import { Bot } from "../../../deps.ts"; + +export function addThreadMember(bot: Bot) { + const addThreadMember = bot.helpers.addThreadMember; + + bot.helpers.addThreadMember = async function (threadId, userId) { + if (userId === bot.id) throw new Error("To add the bot to a thread, you must use bot.helpers.joinThread()"); + + return addThreadMember(threadId, userId); + }; +} diff --git a/plugins/validations/src/channels/threads/getThreadMember.ts b/plugins/validations/src/channels/threads/getThreadMember.ts new file mode 100644 index 000000000..e4ffc8b86 --- /dev/null +++ b/plugins/validations/src/channels/threads/getThreadMember.ts @@ -0,0 +1,11 @@ +import { Bot, GatewayIntents } from "../../../deps.ts"; + +export function getThreadMembers(bot: Bot) { + const getThreadMembers = bot.helpers.getThreadMembers; + + bot.helpers.getThreadMembers = function (threadId) { + const hasIntent = bot.intents & GatewayIntents.GuildMembers; + if (!hasIntent) throw new Error("The get thread members endpoint requires GuildMembers intent."); + return getThreadMembers(threadId); + }; +} diff --git a/plugins/validations/src/channels/threads/mod.ts b/plugins/validations/src/channels/threads/mod.ts new file mode 100644 index 000000000..e1a602053 --- /dev/null +++ b/plugins/validations/src/channels/threads/mod.ts @@ -0,0 +1,10 @@ +import { Bot } from "../../../deps.ts"; +import { addThreadMember } from "./addThreadMember.ts"; +import { getThreadMembers } from "./getThreadMember.ts"; +import { removeThreadMember } from "./removeThreadMember.ts"; + +export function threads(bot: Bot) { + addThreadMember(bot); + getThreadMembers(bot); + removeThreadMember(bot); +} diff --git a/plugins/validations/src/channels/threads/removeThreadMember.ts b/plugins/validations/src/channels/threads/removeThreadMember.ts new file mode 100644 index 000000000..32b0d0a4f --- /dev/null +++ b/plugins/validations/src/channels/threads/removeThreadMember.ts @@ -0,0 +1,11 @@ +import { Bot } from "../../../deps.ts"; + +export function removeThreadMember(bot: Bot) { + const removeThreadMember = bot.helpers.removeThreadMember; + + bot.helpers.removeThreadMember = async function (threadId, userId) { + if (userId === bot.id) throw new Error("To remove the bot from a thread, you must use bot.helpers.leaveThread()"); + + return removeThreadMember(threadId, userId); + }; +} diff --git a/plugins/permissions/src/components.ts b/plugins/validations/src/components.ts similarity index 92% rename from plugins/permissions/src/components.ts rename to plugins/validations/src/components.ts index cd250d9b4..6c33846da 100644 --- a/plugins/permissions/src/components.ts +++ b/plugins/validations/src/components.ts @@ -11,9 +11,8 @@ export function validateComponents(bot: Bot, components: MessageComponents) { if (actionRowCounter > 5) throw new Error("Too many action rows."); // Max of 5 Buttons (or any component type) within an ActionRow - if (component.components?.length > 5) { - throw new Error("Too many components."); - } else if ( + if (component.components?.length > 5) throw new Error("Too many components."); + else if ( component.components?.length > 1 && component.components.some((subComponent) => subComponent.type === MessageComponentTypes.SelectMenu) ) { @@ -72,9 +71,7 @@ export function validateComponents(bot: Bot, components: MessageComponents) { ); } - if (!subComponent.maxValues) { - subComponent.maxValues = subComponent.minValues; - } + if (!subComponent.maxValues) subComponent.maxValues = subComponent.minValues; if (subComponent.minValues > subComponent.maxValues) { throw new Error( "The select component can not have a min values higher than a max values.", @@ -96,9 +93,7 @@ export function validateComponents(bot: Bot, components: MessageComponents) { } } - if (subComponent.options.length < 1) { - throw new Error("You need at least 1 option in the select component."); - } + if (subComponent.options.length < 1) throw new Error("You need at least 1 option in the select component."); if (subComponent.options.length > 25) { throw new Error( @@ -111,9 +106,7 @@ export function validateComponents(bot: Bot, components: MessageComponents) { for (const option of subComponent.options) { if (option.default) { defaults++; - if (defaults > (subComponent.maxValues || 25)) { - throw new Error("You chose too many default options."); - } + if (defaults > (subComponent.maxValues || 25)) throw new Error("You chose too many default options."); } if (!bot.utils.validateLength(option.label, { max: 25 })) { diff --git a/plugins/validations/src/guilds/createGuild.ts b/plugins/validations/src/guilds/createGuild.ts new file mode 100644 index 000000000..6e137128d --- /dev/null +++ b/plugins/validations/src/guilds/createGuild.ts @@ -0,0 +1,16 @@ +import { Bot } from "../../deps.ts"; + +export function createGuild(bot: Bot) { + const createGuild = bot.helpers.createGuild; + + bot.helpers.createGuild = function (options) { + if ( + options.name && + !bot.utils.validateLength(options.name, { min: 2, max: 100 }) + ) { + throw new Error("The guild name must be between 2 and 100 characters."); + } + + return createGuild(options); + }; +} diff --git a/plugins/validations/src/guilds/events/createScheduledEvent.ts b/plugins/validations/src/guilds/events/createScheduledEvent.ts new file mode 100644 index 000000000..2210dfc85 --- /dev/null +++ b/plugins/validations/src/guilds/events/createScheduledEvent.ts @@ -0,0 +1,27 @@ +import { Bot, ScheduledEventEntityType } from "../../../deps.ts"; + +export function createScheduledEvent(bot: Bot) { + const createScheduledEvent = bot.helpers.createScheduledEvent; + + bot.helpers.createScheduledEvent = function (guildId, options) { + if (options.entityType === ScheduledEventEntityType.StageInstance) { + if (!options.channelId) { + throw new Error( + "A channel id is required for creating a stage scheduled event.", + ); + } + + return createScheduledEvent(guildId, options); + } + + if (options.entityType === ScheduledEventEntityType.Voice) { + if (!options.channelId) { + throw new Error( + "A channel id is required for creating a voice scheduled event.", + ); + } + } + + return createScheduledEvent(guildId, options); + }; +} diff --git a/plugins/validations/src/guilds/events/mod.ts b/plugins/validations/src/guilds/events/mod.ts new file mode 100644 index 000000000..abded0eba --- /dev/null +++ b/plugins/validations/src/guilds/events/mod.ts @@ -0,0 +1,6 @@ +import { Bot } from "../../../deps.ts"; +import { createScheduledEvent } from "./createScheduledEvent.ts"; + +export function events(bot: Bot) { + createScheduledEvent(bot); +} diff --git a/plugins/validations/src/guilds/mod.ts b/plugins/validations/src/guilds/mod.ts new file mode 100644 index 000000000..5aa3675c8 --- /dev/null +++ b/plugins/validations/src/guilds/mod.ts @@ -0,0 +1,8 @@ +import { Bot } from "../../deps.ts"; +import { createGuild } from "./createGuild.ts"; +import { events } from "./events/mod.ts"; + +export function guilds(bot: Bot) { + events(bot); + createGuild(bot); +} diff --git a/plugins/validations/src/interaction/commands/createGlobalApplicationCommand.ts b/plugins/validations/src/interaction/commands/createGlobalApplicationCommand.ts new file mode 100644 index 000000000..b1b2a4aa0 --- /dev/null +++ b/plugins/validations/src/interaction/commands/createGlobalApplicationCommand.ts @@ -0,0 +1,58 @@ +import { + ApplicationCommandTypes, + Bot, + CONTEXT_MENU_COMMANDS_NAME_REGEX, + SLASH_COMMANDS_NAME_REGEX, +} from "../../../deps.ts"; +import { validateApplicationCommandLength } from "../../applicationCommandLength.ts"; +import { validateApplicationCommandOptions } from "../../applicationCommandOptions.ts"; + +export function createGlobalApplicationCommand(bot: Bot) { + const createGlobalApplicationCommand = bot.helpers.createGlobalApplicationCommand; + + bot.helpers.createGlobalApplicationCommand = async function (options) { + const isChatInput = !options.type || options.type === ApplicationCommandTypes.ChatInput; + + if (!options.name) throw new Error("A name is required to create a options."); + + if (isChatInput) { + if (!SLASH_COMMANDS_NAME_REGEX.test(options.name)) { + throw new Error("The name of the slash command did not match the required regex."); + } + + // Only slash need to be lowercase + options.name = options.name.toLowerCase(); + + // Slash commands require description + if (!options.description) throw new Error("Slash commands require some form of a description be provided."); + else if (!bot.utils.validateLength(options.description, { min: 1, max: 100 })) { + throw new Error("Application command descriptions must be between 1 and 100 characters."); + } + + if (options.options?.length) { + if (options.options.length > 25) throw new Error("Only 25 options are allowed to be provided."); + + options.options = validateApplicationCommandOptions(bot, options.options); + } + + validateApplicationCommandLength(bot, options); + } else { + if (!CONTEXT_MENU_COMMANDS_NAME_REGEX.test(options.name)) { + throw new Error("The name of the context menu did not match the required regex."); + } + + let length = 0; + if (options.nameLocalizations) { + length += Math.max(options.name.length, ...Object.values(options.nameLocalizations).map((name) => name.length)); + } else length += options.name.length; + + if (length > 4000) { + throw new Error( + "Slash commands can have a maximum of 4000 characters for combined name, description, and value properties for each command, its options (including subcommands and groups), and choices. When localization fields are present, only the longest localization for each field (including the default value) is counted towards the size limit.", + ); + } + } + + return await createGlobalApplicationCommand(options); + }; +} diff --git a/plugins/validations/src/interaction/commands/createGuildApplicationCommand.ts b/plugins/validations/src/interaction/commands/createGuildApplicationCommand.ts new file mode 100644 index 000000000..1799ef8a2 --- /dev/null +++ b/plugins/validations/src/interaction/commands/createGuildApplicationCommand.ts @@ -0,0 +1,44 @@ +import { + ApplicationCommandTypes, + Bot, + CONTEXT_MENU_COMMANDS_NAME_REGEX, + SLASH_COMMANDS_NAME_REGEX, +} from "../../../deps.ts"; +import { validateApplicationCommandOptions } from "../../applicationCommandOptions.ts"; + +export function createGuildApplicationCommand(bot: Bot) { + const createGuildApplicationCommand = bot.helpers.createGuildApplicationCommand; + + bot.helpers.createGuildApplicationCommand = async function (options, guildId) { + const isChatInput = !options.type || options.type === ApplicationCommandTypes.ChatInput; + + if (!options.name) throw new Error("A name is required to create a options."); + + if (isChatInput) { + if (!SLASH_COMMANDS_NAME_REGEX.test(options.name)) { + throw new Error("The name of the slash command did not match the required regex."); + } + + // Only slash need to be lowercase + options.name = options.name.toLowerCase(); + + // Slash commands require description + if (!options.description) throw new Error("Slash commands require some form of a description be provided."); + else if (!bot.utils.validateLength(options.description, { min: 1, max: 100 })) { + throw new Error("Application command descriptions must be between 1 and 100 characters."); + } + + if (options.options?.length) { + if (options.options.length > 25) throw new Error("Only 25 options are allowed to be provided."); + + options.options = validateApplicationCommandOptions(bot, options.options); + } + } else { + if (!CONTEXT_MENU_COMMANDS_NAME_REGEX.test(options.name)) { + throw new Error("The name of the context menu did not match the required regex."); + } + } + + return await createGuildApplicationCommand(options, guildId); + }; +} diff --git a/plugins/validations/src/interaction/commands/mod.ts b/plugins/validations/src/interaction/commands/mod.ts new file mode 100644 index 000000000..ee9d3ed1d --- /dev/null +++ b/plugins/validations/src/interaction/commands/mod.ts @@ -0,0 +1,8 @@ +import { Bot } from "../../../deps.ts"; +import { createGlobalApplicationCommand } from "./createGlobalApplicationCommand.ts"; +import { createGuildApplicationCommand } from "./createGuildApplicationCommand.ts"; + +export function commands(bot: Bot) { + createGlobalApplicationCommand(bot); + createGuildApplicationCommand(bot); +} diff --git a/plugins/validations/src/interaction/mod.ts b/plugins/validations/src/interaction/mod.ts new file mode 100644 index 000000000..8530871a9 --- /dev/null +++ b/plugins/validations/src/interaction/mod.ts @@ -0,0 +1,8 @@ +import { Bot } from "../../deps.ts"; +import { commands } from "./commands/mod.ts"; +import { responses } from "./responses/mod.ts"; + +export function interactions(bot: Bot) { + commands(bot); + responses(bot); +} diff --git a/plugins/permissions/src/interactions/editFollowupMessage.ts b/plugins/validations/src/interaction/responses/editFollowupMessage.ts similarity index 67% rename from plugins/permissions/src/interactions/editFollowupMessage.ts rename to plugins/validations/src/interaction/responses/editFollowupMessage.ts index d1c103f9e..2be1e696c 100644 --- a/plugins/permissions/src/interactions/editFollowupMessage.ts +++ b/plugins/validations/src/interaction/responses/editFollowupMessage.ts @@ -1,16 +1,12 @@ -import { AllowedMentionsTypes, BotWithCache } from "../../deps.ts"; +import { AllowedMentionsTypes, Bot } from "../../../deps.ts"; -export default function editFollowupMessage(bot: BotWithCache) { - const editFollowupMessageOld = bot.helpers.editFollowupMessage; +export function editFollowupMessage(bot: Bot) { + const editFollowupMessage = bot.helpers.editFollowupMessage; bot.helpers.editFollowupMessage = async function (token, messageId, options) { - if (options.content && options.content.length > 2000) { - throw Error("MESSAGE_MAX_LENGTH"); - } + if (options.content && options.content.length > 2000) throw Error("MESSAGE_MAX_LENGTH"); - if (options.embeds && options.embeds.length > 10) { - options.embeds.splice(10); - } + if (options.embeds && options.embeds.length > 10) options.embeds.splice(10); if (options.allowedMentions) { if (options.allowedMentions.users?.length) { @@ -34,6 +30,6 @@ export default function editFollowupMessage(bot: BotWithCache) { } } - return await editFollowupMessageOld(token, messageId, options); + return await editFollowupMessage(token, messageId, options); }; } diff --git a/plugins/validations/src/interaction/responses/editOriginalInteractionResponse.ts b/plugins/validations/src/interaction/responses/editOriginalInteractionResponse.ts new file mode 100644 index 000000000..e7d16d853 --- /dev/null +++ b/plugins/validations/src/interaction/responses/editOriginalInteractionResponse.ts @@ -0,0 +1,35 @@ +import { AllowedMentionsTypes, Bot } from "../../../deps.ts"; + +export function editOriginalInteractionResponse(bot: Bot) { + const editOriginalInteractionResponse = bot.helpers.editOriginalInteractionResponse; + + bot.helpers.editOriginalInteractionResponse = async function (token, options) { + if (options.content && options.content.length > 2000) throw Error(bot.constants.Errors.MESSAGE_MAX_LENGTH); + + if (options.embeds && options.embeds.length > 10) options.embeds.splice(10); + + if (options.allowedMentions) { + if (options.allowedMentions.users?.length) { + if (options.allowedMentions.parse?.includes(AllowedMentionsTypes.UserMentions)) { + options.allowedMentions.parse = options.allowedMentions.parse.filter((p) => p !== "users"); + } + + if (options.allowedMentions.users.length > 100) { + options.allowedMentions.users = options.allowedMentions.users.slice(0, 100); + } + } + + if (options.allowedMentions.roles?.length) { + if (options.allowedMentions.parse?.includes(AllowedMentionsTypes.RoleMentions)) { + options.allowedMentions.parse = options.allowedMentions.parse.filter((p) => p !== "roles"); + } + + if (options.allowedMentions.roles.length > 100) { + options.allowedMentions.roles = options.allowedMentions.roles.slice(0, 100); + } + } + } + + return await editOriginalInteractionResponse(token, options); + }; +} diff --git a/plugins/validations/src/interaction/responses/mod.ts b/plugins/validations/src/interaction/responses/mod.ts new file mode 100644 index 000000000..0db13bc8e --- /dev/null +++ b/plugins/validations/src/interaction/responses/mod.ts @@ -0,0 +1,10 @@ +import { Bot } from "../../../deps.ts"; +import { editFollowupMessage } from "./editFollowupMessage.ts"; +import { editOriginalInteractionResponse } from "./editOriginalInteractionResponse.ts"; +import { sendInteractionResponse } from "./sendInteractionResponse.ts"; + +export function responses(bot: Bot) { + editFollowupMessage(bot); + editOriginalInteractionResponse(bot); + sendInteractionResponse(bot); +} diff --git a/plugins/validations/src/interaction/responses/sendInteractionResponse.ts b/plugins/validations/src/interaction/responses/sendInteractionResponse.ts new file mode 100644 index 000000000..a882d07c8 --- /dev/null +++ b/plugins/validations/src/interaction/responses/sendInteractionResponse.ts @@ -0,0 +1,25 @@ +import { Bot } from "../../../deps.ts"; + +export function sendInteractionResponse(bot: Bot) { + const sendInteractionResponse = bot.helpers.sendInteractionResponse; + + bot.helpers.sendInteractionResponse = function (id, token, options) { + if (options.data?.title !== undefined) { + if (!bot.utils.validateLength(options.data.title, { min: 1, max: 45 })) { + throw new Error("Invalid modal title. Must be between 1-45 characters long."); + } + } + + options.data?.choices?.every((choice) => { + if (!bot.utils.validateLength(choice.name, { min: 1, max: 100 })) { + throw new Error("Invalid application command option choice name. Must be between 1-100 characters long."); + } + + if (typeof choice.value === "string" && (choice.value.length < 1 || choice.value.length > 100)) { + throw new Error("Invalid slash options choice value type."); + } + }); + + return sendInteractionResponse(id, token, options); + }; +} diff --git a/plugins/validations/src/invites/createInvite.ts b/plugins/validations/src/invites/createInvite.ts new file mode 100644 index 000000000..293b5a6c0 --- /dev/null +++ b/plugins/validations/src/invites/createInvite.ts @@ -0,0 +1,16 @@ +import { Bot } from "../../deps.ts"; + +export function createInvite(bot: Bot) { + const createInvite = bot.helpers.createInvite; + + bot.helpers.createInvite = function (channelId, options = {}) { + if (options.maxAge && (options.maxAge < 0 || options.maxAge > 604800)) { + throw new Error("The max age for an invite must be between 0 and 604800."); + } + if (options.maxUses && (options.maxUses < 0 || options.maxUses > 100)) { + throw new Error("The max uses for an invite must be between 0 and 100."); + } + + return createInvite(channelId, options); + }; +} diff --git a/plugins/validations/src/invites/mod.ts b/plugins/validations/src/invites/mod.ts new file mode 100644 index 000000000..6a004df09 --- /dev/null +++ b/plugins/validations/src/invites/mod.ts @@ -0,0 +1,6 @@ +import { Bot } from "../../deps.ts"; +import { createInvite } from "./createInvite.ts"; + +export function invites(bot: Bot) { + createInvite(bot); +} diff --git a/plugins/validations/src/members/editMember.ts b/plugins/validations/src/members/editMember.ts new file mode 100644 index 000000000..0f6e97b56 --- /dev/null +++ b/plugins/validations/src/members/editMember.ts @@ -0,0 +1,11 @@ +import { Bot } from "../../deps.ts"; + +export function editMember(bot: Bot) { + const editMember = bot.helpers.editMember; + + bot.helpers.editMember = async function (guildId, memberId, options) { + if (options.nick && options.nick.length > 32) throw new Error("NICKNAMES_MAX_LENGTH"); + + return editMember(guildId, memberId, options); + }; +} diff --git a/plugins/validations/src/members/mod.ts b/plugins/validations/src/members/mod.ts new file mode 100644 index 000000000..b5eaf59b4 --- /dev/null +++ b/plugins/validations/src/members/mod.ts @@ -0,0 +1,6 @@ +import { Bot } from "../../deps.ts"; +import { editMember } from "./editMember.ts"; + +export function members(bot: Bot) { + editMember(bot); +} diff --git a/plugins/validations/src/messages/deleteMessages.ts b/plugins/validations/src/messages/deleteMessages.ts new file mode 100644 index 000000000..4dcbe260c --- /dev/null +++ b/plugins/validations/src/messages/deleteMessages.ts @@ -0,0 +1,29 @@ +import { Bot } from "../../deps.ts"; + +export function deleteMessages(bot: Bot) { + const deleteMessages = bot.helpers.deleteMessages; + + bot.helpers.deleteMessages = function ( + channelId, + ids, + reason, + ) { + // 2 WEEKS + const oldestAllowed = Date.now() - 1209600000; + + ids = ids.filter((id) => { + const createdAt = Number(id / 4194304n + 1420070400000n); + // IF MESSAGE IS OLDER THAN 2 WEEKS + if (createdAt > oldestAllowed) return true; + + console.log( + `[Validation Plugin] Skipping bulk message delete of ID ${id} because it is older than 2 weeks.`, + ); + return false; + }); + + if (ids.length < 2) throw new Error("Bulk message delete requires at least 2 messages."); + + return deleteMessages(channelId, ids, reason); + }; +} diff --git a/plugins/validations/src/messages/editMessage.ts b/plugins/validations/src/messages/editMessage.ts new file mode 100644 index 000000000..d723ef64b --- /dev/null +++ b/plugins/validations/src/messages/editMessage.ts @@ -0,0 +1,60 @@ +import { AllowedMentionsTypes, Bot } from "../../deps.ts"; + +export function editMessage(bot: Bot) { + const editMessage = bot.helpers.editMessage; + + bot.helpers.editMessage = function (channelId, messageId, content) { + if (content.allowedMentions) { + if (content.allowedMentions.users?.length) { + if ( + content.allowedMentions.parse?.includes( + AllowedMentionsTypes.UserMentions, + ) + ) { + content.allowedMentions.parse = content.allowedMentions.parse.filter(( + p, + ) => p !== "users"); + } + + if (content.allowedMentions.users.length > 100) { + content.allowedMentions.users = content.allowedMentions.users.slice( + 0, + 100, + ); + } + } + + if (content.allowedMentions.roles?.length) { + if ( + content.allowedMentions.parse?.includes( + AllowedMentionsTypes.RoleMentions, + ) + ) { + content.allowedMentions.parse = content.allowedMentions.parse.filter(( + p, + ) => p !== "roles"); + } + + if (content.allowedMentions.roles.length > 100) { + content.allowedMentions.roles = content.allowedMentions.roles.slice( + 0, + 100, + ); + } + } + } + + content.embeds?.splice(10); + + if ( + content.content && + !bot.utils.validateLength(content.content, { max: 2000 }) + ) { + throw new Error( + "A message content can not contain more than 2000 characters.", + ); + } + + return editMessage(channelId, messageId, content); + }; +} diff --git a/plugins/validations/src/messages/mod.ts b/plugins/validations/src/messages/mod.ts new file mode 100644 index 000000000..dcf7a9545 --- /dev/null +++ b/plugins/validations/src/messages/mod.ts @@ -0,0 +1,10 @@ +import { Bot } from "../../deps.ts"; +import { deleteMessages } from "./deleteMessages.ts"; +import { editMessage } from "./editMessage.ts"; +import { sendMessage } from "./sendMessage.ts"; + +export function messages(bot: Bot) { + deleteMessages(bot); + editMessage(bot); + sendMessage(bot); +} diff --git a/plugins/validations/src/messages/sendMessage.ts b/plugins/validations/src/messages/sendMessage.ts new file mode 100644 index 000000000..bfc73c543 --- /dev/null +++ b/plugins/validations/src/messages/sendMessage.ts @@ -0,0 +1,59 @@ +import { AllowedMentionsTypes, Bot } from "../../deps.ts"; +import { validateComponents } from "../components.ts"; + +export function sendMessage(bot: Bot) { + const sendMessage = bot.helpers.sendMessage; + + bot.helpers.sendMessage = function (channelId, content) { + if ( + content.content && + !bot.utils.validateLength(content.content, { max: 2000 }) + ) { + throw new Error("The content should not exceed 2000 characters."); + } + + if (content.allowedMentions) { + if (content.allowedMentions.users?.length) { + if ( + content.allowedMentions.parse?.includes( + AllowedMentionsTypes.UserMentions, + ) + ) { + content.allowedMentions.parse = content.allowedMentions.parse.filter(( + p, + ) => p !== "users"); + } + + if (content.allowedMentions.users.length > 100) { + content.allowedMentions.users = content.allowedMentions.users.slice( + 0, + 100, + ); + } + } + + if (content.allowedMentions.roles?.length) { + if ( + content.allowedMentions.parse?.includes( + AllowedMentionsTypes.RoleMentions, + ) + ) { + content.allowedMentions.parse = content.allowedMentions.parse.filter(( + p, + ) => p !== "roles"); + } + + if (content.allowedMentions.roles.length > 100) { + content.allowedMentions.roles = content.allowedMentions.roles.slice( + 0, + 100, + ); + } + } + } + + if (content.components) validateComponents(bot, content.components); + + return sendMessage(channelId, content); + }; +} diff --git a/plugins/permissions/src/misc/mod.ts b/plugins/validations/src/misc/editBotProfile.ts similarity index 73% rename from plugins/permissions/src/misc/mod.ts rename to plugins/validations/src/misc/editBotProfile.ts index c6d7a4b41..365fe818e 100644 --- a/plugins/permissions/src/misc/mod.ts +++ b/plugins/validations/src/misc/editBotProfile.ts @@ -1,11 +1,9 @@ -import { BotWithCache } from "../../deps.ts"; +import { Bot } from "../../deps.ts"; -export function editBotProfile(bot: BotWithCache) { - const editBotProfileOld = bot.helpers.editBotProfile; +export function editBotProfile(bot: Bot) { + const editBotProfile = bot.helpers.editBotProfile; - bot.helpers.editBotProfile = async function ( - options, - ) { + bot.helpers.editBotProfile = async function (options) { // Nothing was edited if (!options.username && options.botAvatarURL === undefined) { throw new Error( @@ -36,10 +34,6 @@ export function editBotProfile(bot: BotWithCache) { } } - return await editBotProfileOld(options); + return await editBotProfile(options); }; } - -export default function setupMiscPermChecks(bot: BotWithCache) { - editBotProfile(bot); -} diff --git a/plugins/validations/src/misc/mod.ts b/plugins/validations/src/misc/mod.ts new file mode 100644 index 000000000..944fc8947 --- /dev/null +++ b/plugins/validations/src/misc/mod.ts @@ -0,0 +1,6 @@ +import { Bot } from "../../deps.ts"; +import { editBotProfile } from "./editBotProfile.ts"; + +export function misc(bot: Bot) { + editBotProfile(bot); +} diff --git a/plugins/validations/src/webhooks/createWebhook.ts b/plugins/validations/src/webhooks/createWebhook.ts new file mode 100644 index 000000000..0efe34139 --- /dev/null +++ b/plugins/validations/src/webhooks/createWebhook.ts @@ -0,0 +1,19 @@ +import { Bot } from "../../deps.ts"; + +export function createWebhook(bot: Bot) { + const createWebhook = bot.helpers.createWebhook; + + bot.helpers.createWebhook = function (channelId, options) { + if ( + // Specific usernames that discord does not allow + options.name === "clyde" || + !bot.utils.validateLength(options.name, { min: 2, max: 32 }) + ) { + throw new Error( + "The webhook name can not be clyde and it must be between 2 and 32 characters long.", + ); + } + + return createWebhook(channelId, options); + }; +} diff --git a/plugins/validations/src/webhooks/editWebhook.ts b/plugins/validations/src/webhooks/editWebhook.ts new file mode 100644 index 000000000..aefc5b231 --- /dev/null +++ b/plugins/validations/src/webhooks/editWebhook.ts @@ -0,0 +1,21 @@ +import { Bot } from "../../deps.ts"; + +export function editWebhook(bot: Bot) { + const editWebhook = bot.helpers.editWebhook; + + bot.helpers.editWebhook = function (webhookId, options) { + if (options.name) { + if ( + // Specific usernames that discord does not allow + options.name === "clyde" || + !bot.utils.validateLength(options.name, { min: 2, max: 32 }) + ) { + throw new Error( + "The webhook name can not be clyde and it must be between 2 and 32 characters long.", + ); + } + } + + return editWebhook(webhookId, options); + }; +} diff --git a/plugins/permissions/src/webhooks/message.ts b/plugins/validations/src/webhooks/editWebhookMessage.ts similarity index 72% rename from plugins/permissions/src/webhooks/message.ts rename to plugins/validations/src/webhooks/editWebhookMessage.ts index 30a0ac59d..25cc1f293 100644 --- a/plugins/permissions/src/webhooks/message.ts +++ b/plugins/validations/src/webhooks/editWebhookMessage.ts @@ -1,17 +1,15 @@ -import { AllowedMentionsTypes, BotWithCache } from "../../deps.ts"; +import { AllowedMentionsTypes, Bot } from "../../deps.ts"; import { validateComponents } from "../components.ts"; -export function editWebhookMessage(bot: BotWithCache) { - const editWebhookMessageOld = bot.helpers.editWebhookMessage; +export function editWebhookMessage(bot: Bot) { + const editWebhookMessage = bot.helpers.editWebhookMessage; bot.helpers.editWebhookMessage = async function (webhookId, webhookToken, messageId, options) { if (options.content && !bot.utils.validateLength(options.content, { max: 2000 })) { throw Error("The content can not exceed 2000 characters."); } - if (options.embeds && options.embeds.length > 10) { - options.embeds.splice(10); - } + if (options.embeds && options.embeds.length > 10) options.embeds.splice(10); if (options.allowedMentions) { if (options.allowedMentions.users?.length) { @@ -37,10 +35,6 @@ export function editWebhookMessage(bot: BotWithCache) { if (options.components) validateComponents(bot, options.components); - return await editWebhookMessageOld(webhookId, webhookToken, messageId, options); + return await editWebhookMessage(webhookId, webhookToken, messageId, options); }; } - -export default function setupMessageWebhookPermChecks(bot: BotWithCache) { - editWebhookMessage(bot); -} diff --git a/plugins/validations/src/webhooks/mod.ts b/plugins/validations/src/webhooks/mod.ts new file mode 100644 index 000000000..838a2b04f --- /dev/null +++ b/plugins/validations/src/webhooks/mod.ts @@ -0,0 +1,12 @@ +import { Bot } from "../../deps.ts"; +import { createWebhook } from "./createWebhook.ts"; +import { editWebhook } from "./editWebhook.ts"; +import { editWebhookMessage } from "./editWebhookMessage.ts"; +import { sendWebhookMessage } from "./sendWebhookMessage.ts"; + +export function webhooks(bot: Bot) { + createWebhook(bot); + editWebhookMessage(bot); + editWebhook(bot); + sendWebhookMessage(bot); +} diff --git a/plugins/validations/src/webhooks/sendWebhookMessage.ts b/plugins/validations/src/webhooks/sendWebhookMessage.ts new file mode 100644 index 000000000..123733535 --- /dev/null +++ b/plugins/validations/src/webhooks/sendWebhookMessage.ts @@ -0,0 +1,42 @@ +import { AllowedMentionsTypes, Bot } from "../../deps.ts"; +import { validateComponents } from "../components.ts"; + +export function sendWebhookMessage(bot: Bot) { + const sendWebhookMessage = bot.helpers.sendWebhookMessage; + + bot.helpers.sendWebhookMessage = async function (webhookId, webhookToken, options) { + if (options.content && !bot.utils.validateLength(options.content, { max: 2000 })) { + throw new Error("The content should not exceed 2000 characters."); + } + + if (options.allowedMentions) { + if (options.allowedMentions.users?.length) { + if (options.allowedMentions.parse?.includes(AllowedMentionsTypes.UserMentions)) { + options.allowedMentions.parse = options.allowedMentions.parse.filter((p) => p !== "users"); + } + + if (options.allowedMentions.users.length > 100) { + options.allowedMentions.users = options.allowedMentions.users.slice(0, 100); + } + } + + if (options.allowedMentions.roles?.length) { + if (options.allowedMentions.parse?.includes(AllowedMentionsTypes.RoleMentions)) { + options.allowedMentions.parse = options.allowedMentions.parse.filter((p) => p !== "roles"); + } + + if (options.allowedMentions.roles.length > 100) { + options.allowedMentions.roles = options.allowedMentions.roles.slice(0, 100); + } + } + } + + if (options.components) validateComponents(bot, options.components); + + if (!options.content && !options.file && !options.embeds) { + throw new Error("You must provide a value for at least one of content, embeds, or file."); + } + + return await sendWebhookMessage(webhookId, webhookToken, options); + }; +}