summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuwn <[email protected]>2025-11-23 19:12:43 -0800
committerFuwn <[email protected]>2025-11-23 19:12:43 -0800
commita846ff2547f807a68522b36e447df6990e024aa2 (patch)
tree568112ab71d5c2965c18022a9ccc83a4862065cf
parentfeat(gateway:reactionRoles): Add additional handler (diff)
downloadumabotdiscord-a846ff2547f807a68522b36e447df6990e024aa2.tar.xz
umabotdiscord-a846ff2547f807a68522b36e447df6990e024aa2.zip
feat(interactions): Add role slash command
-rw-r--r--packages/interactions/discord/commands/index.ts19
-rw-r--r--packages/interactions/register.ts2
-rw-r--r--packages/interactions/server.ts153
3 files changed, 174 insertions, 0 deletions
diff --git a/packages/interactions/discord/commands/index.ts b/packages/interactions/discord/commands/index.ts
index b3d0d84..f5fda7a 100644
--- a/packages/interactions/discord/commands/index.ts
+++ b/packages/interactions/discord/commands/index.ts
@@ -147,3 +147,22 @@ export const TOGGLE_PRIVILEGED_ACCESS_COMMAND: DiscordCommand = {
},
],
};
+
+export const ROLE_COMMAND: DiscordCommand = {
+ name: "role",
+ description: "Toggle a role for a user",
+ options: [
+ {
+ type: DISCORD_APPLICATION_COMMAND_OPTION_TYPES.USER,
+ name: "user",
+ description: "User to toggle the role for",
+ required: true,
+ },
+ {
+ type: DISCORD_APPLICATION_COMMAND_OPTION_TYPES.ROLE,
+ name: "role",
+ description: "Role to toggle for the user",
+ required: true,
+ },
+ ],
+};
diff --git a/packages/interactions/register.ts b/packages/interactions/register.ts
index d5b0eb6..c864577 100644
--- a/packages/interactions/register.ts
+++ b/packages/interactions/register.ts
@@ -8,6 +8,7 @@ import {
COLOURS_COMMAND,
ROLEPLAY_VERIFY_COMMAND,
TOGGLE_PRIVILEGED_ACCESS_COMMAND,
+ ROLE_COMMAND,
type DiscordCommand,
} from "./discord/commands";
import dotenv from "dotenv";
@@ -38,6 +39,7 @@ const commands: DiscordCommand[] = [
COLOURS_COMMAND,
ROLEPLAY_VERIFY_COMMAND,
TOGGLE_PRIVILEGED_ACCESS_COMMAND,
+ ROLE_COMMAND,
];
const response = await fetch(url, {
diff --git a/packages/interactions/server.ts b/packages/interactions/server.ts
index a6cef92..c840bc1 100644
--- a/packages/interactions/server.ts
+++ b/packages/interactions/server.ts
@@ -12,6 +12,7 @@ import {
COLOURS_COMMAND,
ROLEPLAY_VERIFY_COMMAND,
TOGGLE_PRIVILEGED_ACCESS_COMMAND,
+ ROLE_COMMAND,
} from "./discord/commands";
import {
getCutePost,
@@ -49,6 +50,25 @@ const ADMINISTRATOR_ROLE_ID = "1406422617765712094";
const MODERATOR_ROLE_ID = "1406422617765712093";
const TRIAL_MODERATOR_ROLE_ID = "1406422617724026910";
+const ALLOWED_ROLE_IDS: readonly string[] = [
+ // MODERATOR_ROLE_ID,
+ // TRIAL_MODERATOR_ROLE_ID,
+ // "1436486313770483812", // Probationary Staff
+ // "1411116123302400010", // Reddit Moderator
+ "1410993207608873070", // Minecraft Server Staff
+ "1416917764546756618", // Quote Curator
+ "1419243376938582057", // Event Planner
+ "1423510107685261354", // Moderation Team Staging
+ "1428143899712426084", // Tracen Academy Joint Staff
+ "1417624486345179187", // Top Buddy of the Month
+ // "1435764652591022144", // Staff
+ "1425706904478289928", // Removed from Privileged Access
+ "1435760220805660713", // Removed from Vent Access
+ "1423213971422580736", // Privileged Access
+ "1410333831281643630", // Art & Media NSFW
+ "1418391675050528879", // Roleplay NSFW
+];
+
const sendComplaintToChannel = async (
environment: Environment,
embed: DiscordEmbed,
@@ -823,6 +843,139 @@ router.post("/", async (request: Request, environment: Environment) => {
}
}
+ case ROLE_COMMAND.name.toLowerCase(): {
+ try {
+ const member = interaction.member;
+ const hasAdminPermission =
+ member?.permissions && (parseInt(member.permissions) & 0x8) === 0x8;
+
+ if (!hasAdminPermission)
+ return new JSONResponse({
+ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
+ data: {
+ content:
+ "❌ You don't have permission to use this command. Only server administrators can use this command.",
+ flags: 64,
+ },
+ });
+
+ if (!interaction.guild_id)
+ return new JSONResponse({
+ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
+ data: {
+ content: "❌ This command can only be used in server channels.",
+ flags: 64,
+ },
+ });
+
+ const targetUserID = interaction.data.options?.find(
+ (opt) => opt.name === "user",
+ )?.value as string;
+ const targetRoleID = interaction.data.options?.find(
+ (opt) => opt.name === "role",
+ )?.value as string;
+
+ if (!targetUserID || !targetRoleID)
+ return new JSONResponse({
+ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
+ data: {
+ content:
+ "❌ Missing required parameters. Please provide both user and role.",
+ flags: 64,
+ },
+ });
+
+ if (!ALLOWED_ROLE_IDS.includes(targetRoleID))
+ return new JSONResponse({
+ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
+ data: {
+ content:
+ "❌ This role is not allowed to be added via this command.",
+ flags: 64,
+ },
+ });
+
+ const guild = await fetch(
+ `https://discord.com/api/v10/guilds/${interaction.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 || []) as string[];
+ const hasRole = currentRoles.includes(targetRoleID);
+ const newRoles = hasRole
+ ? currentRoles.filter((roleId: string) => roleId !== targetRoleID)
+ : [...currentRoles, targetRoleID];
+
+ const updateResponse = await fetch(
+ `https://discord.com/api/v10/guilds/${interaction.guild_id}/members/${targetUserID}`,
+ {
+ method: "PATCH",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bot ${environment.DISCORD_TOKEN}`,
+ },
+ body: JSON.stringify({
+ roles: newRoles,
+ }),
+ },
+ );
+
+ if (!updateResponse.ok) {
+ const errorText = await updateResponse.text();
+
+ console.error(
+ "Error updating member roles:",
+ updateResponse.status,
+ errorText,
+ );
+
+ 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 action = hasRole ? "removed" : "added";
+
+ return new JSONResponse({
+ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
+ data: {
+ content: `✅ Successfully ${action} <@&${targetRoleID}> for <@${targetUserID}>.`,
+ flags: 64,
+ },
+ });
+ } catch (error) {
+ console.error("Error in role 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 });
}