diff options
| -rw-r--r-- | src/discord/commands.ts | 33 | ||||
| -rw-r--r-- | src/discord/interfaces.ts | 2 | ||||
| -rw-r--r-- | src/register.ts | 2 | ||||
| -rw-r--r-- | src/server.ts | 168 |
4 files changed, 205 insertions, 0 deletions
diff --git a/src/discord/commands.ts b/src/discord/commands.ts index 85ff7c0..652a20a 100644 --- a/src/discord/commands.ts +++ b/src/discord/commands.ts @@ -75,3 +75,36 @@ export const COLOURS_COMMAND: DiscordCommand = { name: "colours", description: "Show the distribution of colour roles in the server", }; + +export const ROLEPLAY_SERIOUS_COMMAND: DiscordCommand = { + name: "roleplay-serious", + description: "Manage the serious roleplay role (Admin/Roleplay Curator 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, + }, + ], +}; diff --git a/src/discord/interfaces.ts b/src/discord/interfaces.ts index 6b26876..63b8e82 100644 --- a/src/discord/interfaces.ts +++ b/src/discord/interfaces.ts @@ -29,6 +29,8 @@ export interface DiscordInteraction { username: string; avatar?: string; }; + roles?: string[]; + permissions?: string; }; } diff --git a/src/register.ts b/src/register.ts index c7bd8f5..4b5567d 100644 --- a/src/register.ts +++ b/src/register.ts @@ -5,6 +5,7 @@ import { TOP_COMMAND, COMPLAIN_COMMAND, COLOURS_COMMAND, + ROLEPLAY_SERIOUS_COMMAND, type DiscordCommand, } from "./discord/commands.ts"; import dotenv from "dotenv"; @@ -32,6 +33,7 @@ const commands: DiscordCommand[] = [ TOP_COMMAND, COMPLAIN_COMMAND, COLOURS_COMMAND, + ROLEPLAY_SERIOUS_COMMAND, ]; const response = await fetch(url, { diff --git a/src/server.ts b/src/server.ts index c8968a5..afc4743 100644 --- a/src/server.ts +++ b/src/server.ts @@ -7,6 +7,7 @@ import { TOP_COMMAND, COMPLAIN_COMMAND, COLOURS_COMMAND, + ROLEPLAY_SERIOUS_COMMAND, } from "./discord/commands.ts"; import { getCutePost, @@ -26,6 +27,8 @@ import { verifyDiscordRequest } from "./discord/verification.ts"; const router = AutoRouter(); const COMPLAINT_CHANNEL_ID = "1415868433714778204"; +const SERIOUS_ROLEPLAY_ROLE_ID = "1418311833303122021"; +const ROLE_MANAGER_ROLE_ID = "1410993207608873070"; const GUILD_ID = "1406422617724026901"; const COLOR_ROLE_IDS = [ "1407075059830624406", // Nice Nature Red @@ -457,6 +460,171 @@ router.post("/", async (request: Request, environment: Environment) => { } } + case ROLEPLAY_SERIOUS_COMMAND.name.toLowerCase(): { + try { + const member = interaction.member; + const hasAdminPermission = + member?.permissions && (parseInt(member.permissions) & 0x8) === 0x8; + const hasManagerRole = member?.roles?.includes(ROLE_MANAGER_ROLE_ID); + + if (!hasAdminPermission && !hasManagerRole) + return new JSONResponse({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: + "❌ You don't have permission to use this command. Only administrators and role managers can use this command.", + flags: 64, + }, + }); + + const action = interaction.data.options?.[0]?.value as string; + const targetUserID = interaction.data.options?.[1]?.value as string; + + if (!action || !targetUserID) + return new JSONResponse({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: + "❌ Missing required parameters. Please provide both action and user.", + 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 hasRole = currentRoles.includes(SERIOUS_ROLEPLAY_ROLE_ID); + let newRoles = [...currentRoles]; + let actionTaken = ""; + + switch (action) { + case "add": + if (hasRole) + return new JSONResponse({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: + "❌ The user already has the serious roleplay role.", + flags: 64, + }, + }); + + newRoles.push(SERIOUS_ROLEPLAY_ROLE_ID); + + actionTaken = "added"; + + break; + + case "remove": + if (!hasRole) + return new JSONResponse({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: + "❌ The user doesn't have the serious roleplay role.", + flags: 64, + }, + }); + + newRoles = newRoles.filter( + (roleId) => roleId !== SERIOUS_ROLEPLAY_ROLE_ID, + ); + actionTaken = "removed"; + + break; + + case "toggle": + if (hasRole) { + newRoles = newRoles.filter( + (roleId) => roleId !== SERIOUS_ROLEPLAY_ROLE_ID, + ); + actionTaken = "removed"; + } else { + newRoles.push(SERIOUS_ROLEPLAY_ROLE_ID); + + actionTaken = "added"; + } + + break; + + default: + return new JSONResponse({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: + "❌ Invalid action. Please use 'add', 'remove', or 'toggle'.", + flags: 64, + }, + }); + } + + 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, + }, + }); + } + + return new JSONResponse({ + type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, + data: { + content: `✅ Successfully ${actionTaken} the serious roleplay role for <@${targetUserID}>.`, + }, + }); + } catch (error) { + console.error("Error in roleplay-serious 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 }); } |