From 40742cd9c6c9104a7a7e50c70b4c86b5995a0612 Mon Sep 17 00:00:00 2001 From: Pankaj Sha Date: Wed, 18 Dec 2024 02:14:04 +0530 Subject: [PATCH] feat: added command and handler --- src/constants/commands.ts | 31 ++++++++++ src/controllers/baseHandler.ts | 17 ++++++ src/controllers/onboardingExtensionCommand.ts | 45 ++++++++++++++ src/register.ts | 2 + src/utils/onboardingExtension.ts | 59 +++++++++++++++++++ src/utils/sendReplyInDiscordChannel.ts | 18 ++++++ 6 files changed, 172 insertions(+) create mode 100644 src/controllers/onboardingExtensionCommand.ts create mode 100644 src/utils/onboardingExtension.ts create mode 100644 src/utils/sendReplyInDiscordChannel.ts diff --git a/src/constants/commands.ts b/src/constants/commands.ts index 5d7d9e31..6de43906 100644 --- a/src/constants/commands.ts +++ b/src/constants/commands.ts @@ -217,3 +217,34 @@ export const NOTIFY_ONBOARDING = { }, ], }; + +export const ONBOARDING_EXTENSION = { + name: "onboarding-extension", + description: "This command helps to create an onboarding extension request.", + options: [ + { + name: "username", + description: "Username of onboarding user", + type: 6, + required: true, + }, + { + name: "number-of-days", + description: "Number of days required for the extension request", + type: 4, + required: true, + }, + { + name: "reason", + description: "Reason for the extension request", + type: 3, + required: true, + }, + { + name: "dev", + description: "Feature flag", + type: 5, + required: true, + }, + ], +}; diff --git a/src/controllers/baseHandler.ts b/src/controllers/baseHandler.ts index 0593f3a3..58776b87 100644 --- a/src/controllers/baseHandler.ts +++ b/src/controllers/baseHandler.ts @@ -30,6 +30,7 @@ import { REMOVE, GROUP_INVITE, GRANT_AWS_ACCESS, + ONBOARDING_EXTENSION, } from "../constants/commands"; import { updateNickName } from "../utils/updateNickname"; import { discordEphemeralResponse } from "../utils/discordEphemeralResponse"; @@ -46,6 +47,7 @@ import { DevFlag } from "../typeDefinitions/filterUsersByRole"; import { kickEachUser } from "./kickEachUser"; import { groupInvite } from "./groupInvite"; import { grantAWSAccessCommand } from "./grantAWSAccessCommand"; +import { onboardingExtensionCommand } from "./onboardingExtensionCommand"; export async function baseHandler( message: discordMessageRequest, @@ -187,6 +189,21 @@ export async function baseHandler( return await groupInvite(data[0].value, data[1].value, env); } + + case getCommandName(ONBOARDING_EXTENSION): { + const data = message.data?.options as Array; + const transformedArgument = { + userId: data[0], + numberOfDays: data[1], + reason: data[2], + channelId: message.channel_id, + member: message.member, + dev: data.find((item) => item.name === "dev") as unknown as DevFlag, + }; + + return await onboardingExtensionCommand(transformedArgument, env, ctx); + } + default: { return commandNotFound(); } diff --git a/src/controllers/onboardingExtensionCommand.ts b/src/controllers/onboardingExtensionCommand.ts new file mode 100644 index 00000000..689df6ed --- /dev/null +++ b/src/controllers/onboardingExtensionCommand.ts @@ -0,0 +1,45 @@ +import { env } from "../typeDefinitions/default.types"; +import { + messageRequestDataOptions, + messageRequestMember, +} from "../typeDefinitions/discordMessage.types"; +import { DevFlag } from "../typeDefinitions/filterUsersByRole"; +import { discordTextResponse } from "../utils/discordResponse"; +import { + createOnboardingExtension, + CreateOnboardingExtensionArgs, +} from "../utils/onboardingExtension"; + +export async function onboardingExtensionCommand( + transformedArgument: { + member: messageRequestMember; + userId: messageRequestDataOptions; + numberOfDays: messageRequestDataOptions; + reason: messageRequestDataOptions; + channelId: number; + dev?: DevFlag; + }, + env: env, + ctx: ExecutionContext +) { + const dev = transformedArgument.dev?.value || false; + const discordId = transformedArgument.member.user.id.toString(); + + if (!dev) { + return discordTextResponse(`<@${discordId}> Feature not implemented`); + } + + const args: CreateOnboardingExtensionArgs = { + channelId: transformedArgument.channelId, + userId: transformedArgument.userId.value, + numberOfDays: Number(transformedArgument.numberOfDays.value), + reason: transformedArgument.reason.value, + discordId: discordId, + }; + + const initialResponse = `<@${discordId}> Processing your request for onboarding extension`; + + ctx.waitUntil(createOnboardingExtension(args, env)); + + return discordTextResponse(initialResponse); +} diff --git a/src/register.ts b/src/register.ts index 76786999..cba90029 100644 --- a/src/register.ts +++ b/src/register.ts @@ -11,6 +11,7 @@ import { REMOVE, GROUP_INVITE, GRANT_AWS_ACCESS, + ONBOARDING_EXTENSION, } from "./constants/commands"; import { config } from "dotenv"; import { DISCORD_BASE_URL } from "./constants/urls"; @@ -44,6 +45,7 @@ async function registerGuildCommands( REMOVE, GROUP_INVITE, GRANT_AWS_ACCESS, + ONBOARDING_EXTENSION, ]; try { diff --git a/src/utils/onboardingExtension.ts b/src/utils/onboardingExtension.ts new file mode 100644 index 00000000..80244a0b --- /dev/null +++ b/src/utils/onboardingExtension.ts @@ -0,0 +1,59 @@ +import config from "../../config/config"; +import { DISCORD_BASE_URL } from "../constants/urls"; +import { env } from "../typeDefinitions/default.types"; +import { generateDiscordAuthToken } from "./authTokenGenerator"; +import { sendReplyInDiscordChannel } from "./sendReplyInDiscordChannel"; + +export type CreateOnboardingExtensionArgs = { + userId: string; + channelId: number; + reason: string; + numberOfDays: number; + discordId: string; +}; + +export const createOnboardingExtension = async ( + args: CreateOnboardingExtensionArgs, + env: env +) => { + const { channelId } = args; + + const authToken = await generateDiscordAuthToken( + "Cloudflare Worker", + Math.floor(Date.now() / 1000) + 2, + env.BOT_PRIVATE_KEY, + "RS256" + ); + + const discordReplyUrl = `${DISCORD_BASE_URL}/channels/${channelId}/messages`; + const base_url = config(env).RDS_BASE_API_URL; + const createOnboardingExtensionUrl = `${base_url}/requests?dev=true`; + const requestBody = { + userId: args.userId, + type: "ONBOARDING", + numberOfDays: args.numberOfDays, + requestedBy: args.discordId, + reason: args.reason, + }; + + let content: string; + + try { + const response = await fetch(createOnboardingExtensionUrl, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${authToken}`, + }, + body: JSON.stringify(requestBody), + }); + const jsonResponse = (await response.json()) as unknown as { + message: string; + }; + content = `<@${args.discordId}> ${jsonResponse.message}`; + await sendReplyInDiscordChannel(discordReplyUrl, content, env); + } catch (err) { + content = `<@${args.discordId}> Error occurred while creating onboarding extension request.`; + await sendReplyInDiscordChannel(discordReplyUrl, content, env); + } +}; diff --git a/src/utils/sendReplyInDiscordChannel.ts b/src/utils/sendReplyInDiscordChannel.ts new file mode 100644 index 00000000..20e0e473 --- /dev/null +++ b/src/utils/sendReplyInDiscordChannel.ts @@ -0,0 +1,18 @@ +import { env } from "../typeDefinitions/default.types"; + +export const sendReplyInDiscordChannel = async ( + discordReplyUrl: string, + body: any, + env: env +) => { + await fetch(discordReplyUrl, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bot ${env.DISCORD_TOKEN}`, + }, + body: JSON.stringify({ + content: body, + }), + }); +};