summary refs log tree commit diff
path: root/src/api
diff options
context:
space:
mode:
authorCyberL1 <cyber.hf18@gmail.com>2025-10-19 16:31:35 +0200
committerRory& <root@rory.gay>2025-10-19 20:15:47 +0200
commitbbd0617d53b262ccb642b9fff6d0eb9ea0c9936e (patch)
tree88ec7ee7196166f443d1b9fadaf4a27196a64b22 /src/api
parentMake reconicle migration not suck (diff)
downloadserver-ts-bbd0617d53b262ccb642b9fff6d0eb9ea0c9936e.tar.xz
fix: interaction callback
Diffstat (limited to 'src/api')
-rw-r--r--src/api/middlewares/Authentication.ts2
-rw-r--r--src/api/routes/interactions/#interaction_id/#interaction_token/callback.ts14
-rw-r--r--src/api/routes/interactions/index.ts62
3 files changed, 59 insertions, 19 deletions
diff --git a/src/api/middlewares/Authentication.ts b/src/api/middlewares/Authentication.ts

index 83b989255..0821f811b 100644 --- a/src/api/middlewares/Authentication.ts +++ b/src/api/middlewares/Authentication.ts
@@ -32,7 +32,7 @@ export const NO_AUTHORIZATION_ROUTES = [ "GET /invites/", // Routes with a seperate auth system /^(POST|HEAD|GET|PATCH|DELETE) \/webhooks\/\d+\/\w+\/?/, // no token requires auth - // /^POST \/interactions\/\d+\/\w+\/callback/, // This is marked as Unauthoricated route on https://discord.food. But when it is then not all requests have req.user_id? + /^POST \/interactions\/\d+\/[A-Za-z0-9_-]+\/callback/, // Public information endpoints "GET /ping", "GET /gateway", diff --git a/src/api/routes/interactions/#interaction_id/#interaction_token/callback.ts b/src/api/routes/interactions/#interaction_id/#interaction_token/callback.ts
index 1860e0b3d..77f0112f8 100644 --- a/src/api/routes/interactions/#interaction_id/#interaction_token/callback.ts +++ b/src/api/routes/interactions/#interaction_id/#interaction_token/callback.ts
@@ -55,13 +55,13 @@ router.post("/", route({}), async (req: Request, res: Response) => { // TODO break; case InteractionCallbackType.CHANNEL_MESSAGE_WITH_SOURCE: { - const message = Message.create({ + const message = await Message.createWithDefaults({ type: MessageType.APPLICATION_COMMAND, timestamp: new Date(), - application_id: req.user_id, + application_id: interaction.applicationId, guild_id: interaction.guildId, channel_id: interaction.channelId, - author_id: req.user_id, + author_id: interaction.applicationId, content: body.data.content, tts: body.data.tts, embeds: body.data.embeds || [], @@ -69,7 +69,7 @@ router.post("/", route({}), async (req: Request, res: Response) => { poll: body.data.poll, flags: body.data.flags, reactions: [], - // webhook_id: req.user_id, // This one requires a webhook to be created first + // webhook_id: interaction.applicationId, // This one requires a webhook to be created first interaction: { id: interactionId, name: interaction.commandName, @@ -98,9 +98,9 @@ router.post("/", route({}), async (req: Request, res: Response) => { event: "MESSAGE_CREATE", channel_id: interaction.channelId, data: { - application_id: message.application_id, + application_id: interaction.applicationId, attachments: message.attachments, - author: (await User.findOneOrFail({ where: { id: message.author_id } })).toPublicUser(), + author: message.author?.toPublicUser(), channel_id: message.channel_id, channel_type: 0, components: message.components, @@ -131,7 +131,7 @@ router.post("/", route({}), async (req: Request, res: Response) => { timestamp: message.timestamp, tss: message.tts, type: message.type, - webhook_id: req.user_id, + webhook_id: interaction.applicationId, } as MessageCreateSchema, } as MessageCreateEvent); break; diff --git a/src/api/routes/interactions/index.ts b/src/api/routes/interactions/index.ts
index 8789b2910..05571ace6 100644 --- a/src/api/routes/interactions/index.ts +++ b/src/api/routes/interactions/index.ts
@@ -20,8 +20,9 @@ import { randomBytes } from "crypto"; import { InteractionSchema } from "@spacebar/schemas"; import { route } from "@spacebar/api"; import { Request, Response, Router } from "express"; -import { emitEvent, InteractionCreateEvent, InteractionFailureEvent, Snowflake } from "@spacebar/util"; -import { pendingInteractions } from "../../../util/imports/Interactions"; +import { emitEvent, Guild, InteractionCreateEvent, InteractionFailureEvent, InteractionType, Member, Message, Snowflake, User } from "@spacebar/util"; +import { pendingInteractions } from "@spacebar/util/imports/Interactions"; +import { InteractionCreateSchema } from "@spacebar/schemas/api/bots/InteractionCreateSchema"; const router = Router({ mergeParams: true }); @@ -40,18 +41,56 @@ router.post("/", route({}), async (req: Request, res: Response) => { }, } as InteractionCreateEvent); + const user = await User.findOneOrFail({ where: { id: req.user_id } }); + + const interactionData: Partial<InteractionCreateSchema> = { + id: interactionId, + application_id: body.application_id, + channel_id: body.channel_id, + type: body.type, + token: interactionToken, + version: 1, + app_permissions: "0", // TODO: add this later + entitlements: [], + authorizing_integration_owners: { "0": req.user_id }, + context: 0, // TODO: add this later + attachment_size_limit: 0, // TODO: add this later + }; + + if (body.type === InteractionType.ApplicationCommand || body.data.type === InteractionType.MessageComponent || body.data.type === InteractionType.ModalSubmit) { + interactionData.data = body.data; + } + + if (body.type != InteractionType.Ping) { + interactionData.locale = user?.settings?.locale; + } + + if (body.guild_id) { + interactionData.guild_id = body.guild_id; + + const guild = await Guild.findOneOrFail({ where: { id: body.guild_id } }); + const member = await Member.findOneOrFail({ where: { guild_id: body.guild_id, id: req.user_id }, relations: ["user"] }); + + interactionData.guild = { + id: guild.id, + features: guild.features, + locale: guild.preferred_locale!, + }; + + interactionData.guild_locale = guild.preferred_locale; + interactionData.member = member.toPublicMember(); + } else { + interactionData.user = user.toPublicUser(); + } + + if (body.type === InteractionType.MessageComponent || body.data.type === InteractionType.ModalSubmit) { + interactionData.message = await Message.findOneOrFail({ where: { id: body.message_id } }); + } + emitEvent({ event: "INTERACTION_CREATE", user_id: body.application_id, - data: { - channel_id: body.channel_id, - guild_id: body.guild_id, - id: interactionId, - member_id: req.user_id, - token: interactionToken, - type: body.type, - nonce: body.nonce, - }, + data: interactionData, } as InteractionCreateEvent); const interactionTimeout = setTimeout(() => { @@ -69,6 +108,7 @@ router.post("/", route({}), async (req: Request, res: Response) => { pendingInteractions.set(interactionId, { timeout: interactionTimeout, nonce: body.nonce, + applicationId: body.application_id, userId: req.user_id, guildId: body.guild_id, channelId: body.channel_id,