diff options
| author | Fuwn <[email protected]> | 2025-10-01 20:32:10 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2025-10-01 20:32:10 -0700 |
| commit | d5276c2368820bff20cbdda46abdd66d3041ae1a (patch) | |
| tree | 20836da068d04e44b8129668d7a47251cf007b94 /packages/interactions | |
| parent | refactor(listeners): Move clientReady listeners to clientReady module (diff) | |
| download | umabotdiscord-d5276c2368820bff20cbdda46abdd66d3041ae1a.tar.xz umabotdiscord-d5276c2368820bff20cbdda46abdd66d3041ae1a.zip | |
feat(interactions): Add age-verify command
Diffstat (limited to 'packages/interactions')
| -rw-r--r-- | packages/interactions/discord/commands/index.ts | 50 | ||||
| -rw-r--r-- | packages/interactions/register.ts | 2 | ||||
| -rw-r--r-- | packages/interactions/server.ts | 154 |
3 files changed, 206 insertions, 0 deletions
diff --git a/packages/interactions/discord/commands/index.ts b/packages/interactions/discord/commands/index.ts index b4c6721..a69e786 100644 --- a/packages/interactions/discord/commands/index.ts +++ b/packages/interactions/discord/commands/index.ts @@ -124,3 +124,53 @@ export const ROLEPLAY_VERIFY_COMMAND: DiscordCommand = { }, ], }; + +export const AGE_VERIFY_COMMAND: DiscordCommand = { + name: "age-verify", + description: + "Manage the verified age role (Staff only)", + options: [ + { + type: 3, + name: "action", + description: "Action to perform on the role", + required: true, + choices: [ + { + name: "Add Role", + value: "add", + }, + { + name: "Remove Role", + value: "remove", + }, + { + name: "Toggle Role", + value: "toggle", + }, + ], + }, + { + type: 6, + name: "user", + description: "User to perform the action on", + required: true, + }, + { + type: 3, + name: "access", + description: "Type of access to grant", + required: true, + choices: [ + { + name: "Art & Media", + value: "art_media", + }, + { + name: "Roleplay NSFW", + value: "roleplay_nsfw", + }, + ], + }, + ], +}; diff --git a/packages/interactions/register.ts b/packages/interactions/register.ts index 9ba9d90..00f4f9b 100644 --- a/packages/interactions/register.ts +++ b/packages/interactions/register.ts @@ -7,6 +7,7 @@ import { APPEAL_COMMAND, COLOURS_COMMAND, ROLEPLAY_VERIFY_COMMAND, + AGE_VERIFY_COMMAND, type DiscordCommand, } from "./discord/commands"; import dotenv from "dotenv"; @@ -36,6 +37,7 @@ const commands: DiscordCommand[] = [ APPEAL_COMMAND, COLOURS_COMMAND, ROLEPLAY_VERIFY_COMMAND, + AGE_VERIFY_COMMAND, ]; const response = await fetch(url, { diff --git a/packages/interactions/server.ts b/packages/interactions/server.ts index 8c8d3db..3a9651e 100644 --- a/packages/interactions/server.ts +++ b/packages/interactions/server.ts @@ -9,6 +9,7 @@ import { APPEAL_COMMAND, COLOURS_COMMAND, ROLEPLAY_VERIFY_COMMAND, + AGE_VERIFY_COMMAND, } from "./discord/commands"; import { getCutePost, @@ -33,6 +34,12 @@ const COMPLAINT_CHANNEL_ID = "1415868433714778204"; const APPEAL_CHANNEL_ID = "1420340807931531385"; const VERIFIED_ROLEPLAY_ROLE_ID = "1418311833303122021"; const ROLE_MANAGER_ROLE_ID = "1410993207608873070"; +const ART_MEDIA_ROLE_ID = "1410333831281643630"; +const ROLEPLAY_NSFW_ROLE_ID = "1418391675050528879"; +const OWNER_ROLE_ID = "1406422617765712095"; +const ADMINISTRATOR_ROLE_ID = "1406422617765712094"; +const MODERATOR_ROLE_ID = "1406422617765712093"; +const TRIAL_MODERATOR_ROLE_ID = "1406422617724026910"; const sendComplaintToChannel = async ( environment: Environment, @@ -692,6 +699,153 @@ router.post("/", async (request: Request, environment: Environment) => { } } + case AGE_VERIFY_COMMAND.name.toLowerCase(): { + try { + const member = interaction.member; + const hasAdminPermission = + member?.permissions && (parseInt(member.permissions) & 0x8) === 0x8; + const hasOwnerRole = member?.roles?.includes(OWNER_ROLE_ID); + const hasAdministratorRole = member?.roles?.includes(ADMINISTRATOR_ROLE_ID); + const hasModeratorRole = member?.roles?.includes(MODERATOR_ROLE_ID); + const hasTrialModeratorRole = member?.roles?.includes(TRIAL_MODERATOR_ROLE_ID); + + if (!hasAdminPermission && !hasOwnerRole && !hasAdministratorRole && !hasModeratorRole && !hasTrialModeratorRole) + return new JSONResponse({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: + "❌ You don't have permission to use this command. Only administrators and moderators can use this command.", + flags: 64, + }, + }); + + const action = interaction.data.options?.[0]?.value as string; + const targetUserID = interaction.data.options?.[1]?.value as string; + const access = interaction.data.options?.[2]?.value as string; + + if (!action || !targetUserID || !access) + return new JSONResponse({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: + "❌ Missing required parameters. Please provide action, user, and access type.", + flags: 64, + }, + }); + + const guild = await fetch( + `https://discord.com/api/v10/guilds/${GUILD_ID}/members/${targetUserID}`, + { + headers: { + Authorization: `Bot ${environment.DISCORD_TOKEN}`, + }, + }, + ); + + if (!guild.ok) + return new JSONResponse({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: + "❌ Unable to fetch user information. The user may not be in this server.", + flags: 64, + }, + }); + + const targetMember = await guild.json(); + const currentRoles = targetMember.roles || []; + const targetRoleId = access === "art_media" ? ART_MEDIA_ROLE_ID : ROLEPLAY_NSFW_ROLE_ID; + const hasRole = currentRoles.includes(targetRoleId); + let actionTaken = ""; + let newRoles = [...currentRoles]; + + if (action === "add") { + if (hasRole) + return new JSONResponse({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: `❌ <@${targetUserID}> already has the ${access === "art_media" ? "Art & Media" : "Roleplay NSFW"} role.`, + flags: 64, + }, + }); + + newRoles.push(targetRoleId); + + actionTaken = "added"; + } else if (action === "remove") { + if (!hasRole) + return new JSONResponse({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: `❌ <@${targetUserID}> doesn't have the ${access === "art_media" ? "Art & Media" : "Roleplay NSFW"} role.`, + flags: 64, + }, + }); + + newRoles = newRoles.filter((roleId) => roleId !== targetRoleId); + actionTaken = "removed"; + } else if (action === "toggle") { + if (hasRole) { + newRoles = newRoles.filter((roleId) => roleId !== targetRoleId); + actionTaken = "removed"; + } else { + newRoles.push(targetRoleId); + + actionTaken = "added"; + } + } + + const updateResponse = await fetch( + `https://discord.com/api/v10/guilds/${GUILD_ID}/members/${targetUserID}`, + { + method: "PATCH", + headers: { + Authorization: `Bot ${environment.DISCORD_TOKEN}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ + roles: newRoles, + }), + }, + ); + + if (!updateResponse.ok) { + console.error( + "Failed to update user roles:", + await updateResponse.text(), + ); + + return new JSONResponse({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: + "❌ Failed to update user roles. The bot may not have sufficient permissions.", + flags: 64, + }, + }); + } + + const accessTypeName = access === "art_media" ? "Art & Media" : "Roleplay NSFW"; + + return new JSONResponse({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: `✅ Successfully ${actionTaken} the ${accessTypeName} role for <@${targetUserID}>.`, + }, + }); + } catch (error) { + console.error("Error in age-verify command:", error); + + return new JSONResponse({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: "❌ An error occurred while managing the role.", + flags: 64, + }, + }); + } + } + default: return new JSONResponse({ error: "Unknown Type" }, { status: 400 }); } |