fix: interaction callback
This commit is contained in:
parent
d0ae4d06bc
commit
bbd0617d53
@ -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",
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { MessageCreateSchema } from "@spacebar/schemas";
|
||||
import { Message } from "@spacebar/util";
|
||||
import { InteractionCallbackType } from "./InteractionCallbackType";
|
||||
|
||||
export interface InteractionCallbackSchema {
|
||||
type: InteractionCallbackType;
|
||||
data: MessageCreateSchema;
|
||||
data: Message;
|
||||
}
|
||||
|
||||
32
src/schemas/api/bots/InteractionCreateSchema.ts
Normal file
32
src/schemas/api/bots/InteractionCreateSchema.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { PublicMember, PublicUser, Snowflake } from "@spacebar/schemas";
|
||||
import { Channel, InteractionType, Message } from "@spacebar/util";
|
||||
|
||||
export interface InteractionCreateSchema {
|
||||
version: number; // TODO: types?
|
||||
id: Snowflake;
|
||||
application_id: Snowflake;
|
||||
type: InteractionType;
|
||||
token: string;
|
||||
data?: object; // TODO: types?
|
||||
guild?: InteractionGuild;
|
||||
guild_id?: Snowflake;
|
||||
guild_locale?: string;
|
||||
channel?: Channel; // TODO: is this right?
|
||||
channel_id?: Snowflake;
|
||||
member?: PublicMember; // TODO: is this right?
|
||||
user?: PublicUser; // TODO: is this right?
|
||||
locale?: string;
|
||||
message?: Message; // TODO: is this right?
|
||||
app_permissions: string;
|
||||
entitlements?: object[]; // TODO: types?
|
||||
entitlement_sku_ids?: Snowflake[]; // DEPRECATED
|
||||
authorizing_integration_owners?: Record<number, Snowflake>; // TODO: types?
|
||||
context?: number;
|
||||
attachment_size_limit: number;
|
||||
}
|
||||
|
||||
interface InteractionGuild {
|
||||
id: Snowflake;
|
||||
features: string[];
|
||||
locale: string;
|
||||
}
|
||||
@ -20,6 +20,7 @@ export * from "./ApplicationCommandSchema";
|
||||
export * from "./InteractionSchema";
|
||||
export * from "./InteractionCallbackSchema";
|
||||
export * from "./InteractionCallbackType";
|
||||
export * from "./InteractionCreateSchema";
|
||||
export * from "./SendableApplicationCommandDataSchema";
|
||||
export * from "./SendableMessageComponentDataSchema";
|
||||
export * from "./SendableModalSubmitDataSchema";
|
||||
|
||||
@ -21,6 +21,7 @@ import { InteractionType, Snowflake } from "@spacebar/util";
|
||||
|
||||
interface PendingInteraction {
|
||||
timeout: NodeJS.Timeout;
|
||||
applicationId: string;
|
||||
userId: string;
|
||||
channelId?: string;
|
||||
guildId?: string;
|
||||
|
||||
@ -30,9 +30,11 @@ export interface Interaction {
|
||||
}
|
||||
|
||||
export enum InteractionType {
|
||||
SelfCommand = 0,
|
||||
Ping = 1,
|
||||
ApplicationCommand = 2,
|
||||
MessageComponent = 3,
|
||||
ApplicationCommandAutocomplete = 4,
|
||||
ModalSubmit = 5,
|
||||
}
|
||||
|
||||
export enum InteractionResponseType {
|
||||
|
||||
Reference in New Issue
Block a user