diff --git "a/src/api/routes/channels/\043channel_id/greet.ts" "b/src/api/routes/channels/\043channel_id/greet.ts" index 8dbaacd..37fd558 100644 --- "a/src/api/routes/channels/\043channel_id/greet.ts" +++ "b/src/api/routes/channels/\043channel_id/greet.ts" @@ -90,11 +90,12 @@ channel.last_message_id = message.id; + await message.save(); + const publicMsg = message.toJSON(); await Promise.all([ - message.save(), emitEvent({ event: "MESSAGE_CREATE", - data: message, + data: publicMsg, channel_id, } satisfies MessageCreateEvent), channel.save(), diff --git "a/src/api/routes/channels/\043channel_id/messages/\043message_id/index.ts" "b/src/api/routes/channels/\043channel_id/messages/\043message_id/index.ts" index e69818b..32f51be 100644 --- "a/src/api/routes/channels/\043channel_id/messages/\043message_id/index.ts" +++ "b/src/api/routes/channels/\043channel_id/messages/\043message_id/index.ts" @@ -100,18 +100,15 @@ edited_timestamp: new Date(), }); - await Promise.all([ - new_message.save(), - await emitEvent({ - event: "MESSAGE_UPDATE", - channel_id, - data: { - ...new_message.toJSON(), - nonce: undefined, - member: new_message.member?.toPublicMember(), - }, - } satisfies MessageUpdateEvent), - ]); + await new_message.save(); + await emitEvent({ + event: "MESSAGE_UPDATE", + channel_id, + data: { + ...new_message.toJSON(), + nonce: undefined, + }, + } satisfies MessageUpdateEvent); postHandleMessage(new_message).catch((e) => console.error("[Message] post-message handler failed", e)); @@ -221,12 +218,13 @@ //Fix for the client bug delete message.member; + await message.save(); + const publicMsg = message.toJSON(); await Promise.all([ - message.save(), emitEvent({ event: "MESSAGE_CREATE", channel_id: channel_id, - data: message, + data: publicMsg, } satisfies MessageCreateEvent), channel.save(), ]); diff --git "a/src/api/routes/channels/\043channel_id/messages/index.ts" "b/src/api/routes/channels/\043channel_id/messages/index.ts" index c96715b..ca3db01 100644 --- "a/src/api/routes/channels/\043channel_id/messages/index.ts" +++ "b/src/api/routes/channels/\043channel_id/messages/index.ts" @@ -54,6 +54,8 @@ MessageCreateAttachment, MessageCreateCloudAttachment, MessageCreateSchema, + PartialUser, + PublicMessage, Reaction, ReadStateType, RelationshipType, @@ -178,8 +180,8 @@ await Message.fillReplies(messages); const endpoint = Config.get().cdn.endpointPublic; - const ret = messages.map((x: Message) => { - x = x.toJSON(); + const ret = messages.map((msg) => { + const x = msg.toJSON(); (x.reactions || []).forEach((y: Partial) => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -188,12 +190,13 @@ delete y.user_ids; }); if (!x.author) - x.author = User.create({ + x.author = { id: "4", discriminator: "0000", username: "Spacebar Ghost", public_flags: 0, - }); + avatar: null, + } as PartialUser; x.attachments?.forEach((y: Attachment) => { // dynamically set attachment proxy_url in case the endpoint changed const uri = y.proxy_url.startsWith("http") ? y.proxy_url : `https://example.org${y.proxy_url}`; @@ -243,11 +246,15 @@ }); //console.log(ret); + type MessageWithInteraction = PublicMessage & { + interaction_metadata?: { user?: User; user_id: string }; + interaction?: { user?: User }; + }; await Promise.all( - ret - .filter((x: MessageCreateSchema) => x.interaction_metadata && !x.interaction_metadata.user) - .map(async (x: MessageCreateSchema) => { - x.interaction_metadata!.user = x.interaction!.user = await User.findOneOrFail({ where: { id: (x as Message).interaction_metadata!.user_id } }); + (ret as MessageWithInteraction[]) + .filter((x) => x.interaction_metadata && !x.interaction_metadata.user) + .map(async (x) => { + x.interaction_metadata!.user = x.interaction!.user = await User.findOneOrFail({ where: { id: x.interaction_metadata!.user_id } }); }), ); diff --git "a/src/api/routes/channels/\043channel_id/messages/pins/index.ts" "b/src/api/routes/channels/\043channel_id/messages/pins/index.ts" index f9e4b69..e72352c 100644 --- "a/src/api/routes/channels/\043channel_id/messages/pins/index.ts" +++ "b/src/api/routes/channels/\043channel_id/messages/pins/index.ts" @@ -80,12 +80,14 @@ mention_everyone: false, }); + await message.save(); + const publicMsg = message.toJSON(); + const publicSystem = systemPinMessage.toJSON(); await Promise.all([ - message.save(), emitEvent({ event: "MESSAGE_UPDATE", channel_id, - data: message, + data: publicMsg, } satisfies MessageUpdateEvent), emitEvent({ event: "CHANNEL_PINS_UPDATE", @@ -100,7 +102,7 @@ emitEvent({ event: "MESSAGE_CREATE", channel_id: message.channel_id, - data: systemPinMessage, + data: publicSystem, } satisfies MessageCreateEvent), ]); @@ -133,12 +135,13 @@ message.pinned_at = null; + await message.save(); + const publicMsg2 = message.toJSON(); await Promise.all([ - message.save(), emitEvent({ event: "MESSAGE_UPDATE", channel_id, - data: message, + data: publicMsg2, } satisfies MessageUpdateEvent), emitEvent({ event: "CHANNEL_PINS_UPDATE", diff --git "a/src/api/routes/channels/\043channel_id/pins.ts" "b/src/api/routes/channels/\043channel_id/pins.ts" index 9b51559..5105421 100644 --- "a/src/api/routes/channels/\043channel_id/pins.ts" +++ "b/src/api/routes/channels/\043channel_id/pins.ts" @@ -81,12 +81,14 @@ mention_everyone: false, }); + await message.save(); + const publicMsg = message.toJSON(); + const publicSystem = systemPinMessage.toJSON(); await Promise.all([ - message.save(), emitEvent({ event: "MESSAGE_UPDATE", channel_id, - data: message, + data: publicMsg, } satisfies MessageUpdateEvent), emitEvent({ event: "CHANNEL_PINS_UPDATE", @@ -101,7 +103,7 @@ emitEvent({ event: "MESSAGE_CREATE", channel_id: message.channel_id, - data: systemPinMessage, + data: publicSystem, } satisfies MessageCreateEvent), ]); @@ -134,12 +136,13 @@ message.pinned_at = null; + await message.save(); + const publicMsg2 = message.toJSON(); await Promise.all([ - message.save(), emitEvent({ event: "MESSAGE_UPDATE", channel_id, - data: message, + data: publicMsg2, } satisfies MessageUpdateEvent), emitEvent({ event: "CHANNEL_PINS_UPDATE", diff --git "a/src/api/routes/channels/\043channel_id/post-data.ts" "b/src/api/routes/channels/\043channel_id/post-data.ts" index d37344a..79d0286 100644 --- "a/src/api/routes/channels/\043channel_id/post-data.ts" +++ "b/src/api/routes/channels/\043channel_id/post-data.ts" @@ -18,7 +18,7 @@ import { route } from "@spacebar/api"; import { Channel, Member, Message } from "@spacebar/util"; -import { PostDataSchema } from "@spacebar/schemas"; +import { PostDataSchema, PublicMessage } from "@spacebar/schemas"; import { Request, Response, Router } from "express"; import { messageUpload } from "./messages"; @@ -83,7 +83,7 @@ }), ]); await Message.fillReplies(messages); - const objRet: { threads: Record } = { threads: {} }; + const objRet: { threads: Record } = { threads: {} }; for (const thread of threads) { const owner = members.find(({ id }) => id === thread.owner_id)?.toJSON() || null; const first_message = messages.find(({ channel_id }) => channel_id === thread.id)?.toJSON() || null; diff --git "a/src/api/routes/channels/\043channel_id/threads.ts" "b/src/api/routes/channels/\043channel_id/threads.ts" index 26a1903..2af92f5 100644 --- "a/src/api/routes/channels/\043channel_id/threads.ts" +++ "b/src/api/routes/channels/\043channel_id/threads.ts" @@ -147,8 +147,17 @@ } } const embeds = body.message.embeds || []; - const message = await handleMessage({ + const bodyMsg = { ...body.message, + allowed_mentions: body.message.allowed_mentions + ? { + ...body.message.allowed_mentions, + parse: body.message.allowed_mentions.parse as ("users" | "roles" | "everyone")[], + } + : undefined, + } as Parameters[0]; + const message = await handleMessage({ + ...bodyMsg, id: thread.id, type: 0, pinned: false, @@ -189,7 +198,7 @@ emitEvent({ event: "MESSAGE_CREATE", channel_id: channel_id, - data: message, + data: message.toJSON(), } satisfies MessageCreateEvent), message.guild_id ? Member.update({ id: req.user_id, guild_id: message.guild_id }, { last_message_id: message.id }) : null, ]); diff --git a/src/api/routes/channels/preload-messages.ts b/src/api/routes/channels/preload-messages.ts index 09743cc..f14b387 100644 --- a/src/api/routes/channels/preload-messages.ts +++ b/src/api/routes/channels/preload-messages.ts @@ -58,11 +58,9 @@ const filteredMessages = messages.map((message) => { const x = message.toJSON(); // https://docs.discord.food/resources/message#preload-messages - reactions are not included in the response - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error x.reactions = undefined; return x; - }) as PreloadMessagesResponseSchema; + }) as unknown as PreloadMessagesResponseSchema; return res.status(200).send(filteredMessages); }, diff --git a/src/api/util/handlers/Message.ts b/src/api/util/handlers/Message.ts index a21149c..ed41341 100644 --- a/src/api/util/handlers/Message.ts +++ b/src/api/util/handlers/Message.ts @@ -69,6 +69,7 @@ UnfurledMediaItem, BaseMessageComponents, v1CompTypes, + PartialUser } from "@spacebar/schemas"; const allow_empty = false; // TODO: check webhook, application, system author, stickers @@ -830,12 +831,13 @@ if (data.embeds != undefined) { data.embeds = data.embeds?.filter((embed) => embed.type === "rich"); } + // author value is already included in message.toJSON() const event = { event: "MESSAGE_UPDATE", channel_id: message.channel_id, data: { - ...data, - author, + ...message.toJSON(), + embeds: data.embeds == undefined ? message.embeds || [] : data.embeds, }, } satisfies MessageUpdateEvent; const embeds = data.embeds == undefined ? [] : data.embeds; @@ -900,7 +902,7 @@ emitEvent({ event: "MESSAGE_UPDATE", channel_id: message.channel_id, - data, + data: message.toJSON(), } satisfies MessageUpdateEvent), Message.update({ id: message.id, channel_id: message.channel_id }, { embeds: embeds }), ...cachePromises, diff --git a/src/api/util/handlers/Webhook.ts b/src/api/util/handlers/Webhook.ts index b6a390a..deb0331 100644 --- a/src/api/util/handlers/Webhook.ts +++ b/src/api/util/handlers/Webhook.ts @@ -96,8 +96,17 @@ } const embeds = body.embeds || []; - const message = await handleMessage({ + const bodyMsg = { ...body, + allowed_mentions: body.allowed_mentions + ? { + ...body.allowed_mentions, + parse: body.allowed_mentions.parse as ("users" | "roles" | "everyone")[], + } + : undefined, + } as Parameters[0]; + const message = await handleMessage({ + ...bodyMsg, username: body.username || webhook.name, avatar_url: body.avatar_url || webhook.avatar, type: 0, @@ -123,7 +132,7 @@ emitEvent({ event: "MESSAGE_CREATE", channel_id: sendChannel.id, - data: message, + data: message.toJSON(), } satisfies MessageCreateEvent), ]); diff --git a/src/util/entities/Member.ts b/src/util/entities/Member.ts index f372277..00ac3a3 100644 --- a/src/util/entities/Member.ts +++ b/src/util/entities/Member.ts @@ -442,12 +442,13 @@ channel.last_message_id = message.id; + await message.save(); + const publicMsg = message.toJSON(); await Promise.all([ - message.save(), emitEvent({ event: "MESSAGE_CREATE", channel_id: message.channel_id, - data: message, + data: publicMsg, } satisfies MessageCreateEvent), channel.save(), ]); diff --git a/src/util/entities/Message.ts b/src/util/entities/Message.ts index 9649447..b343a0c 100644 --- a/src/util/entities/Message.ts +++ b/src/util/entities/Message.ts @@ -36,6 +36,7 @@ MessageComponentType, MessageSnapshot, MessageType, PartialMessage, Poll, PublicMessage, Reaction, UnfurledMediaItem, } from "@spacebar/schemas"; +import { PartialUser } from "@spacebar/schemas"; import { MessageFlags } from "@spacebar/util"; import { JsonRemoveEmpty } from "../util/Decorators"; @@ -251,15 +252,23 @@ ...this, channel_id: this.channel_id ?? this.channel.id, channel: undefined, + + timestamp: this.timestamp.toISOString(), + edited_timestamp: this.edited_timestamp ? this.edited_timestamp.toISOString() : null, + author_id: undefined, member_id: undefined, webhook_id: this.webhook_id ?? undefined, application_id: undefined, mentions: this.mentions?.map((user) => { if (user && !user.toPublicUser) console.trace("toPublic user missing!!!"); - return user?.toPublicUser?.() ?? user ?? undefined; + return (user?.toPublicUser?.() ?? user ?? undefined) as unknown as PartialUser; }), + mention_roles: this.mention_roles?.map((role) => role.id) ?? [], + mention_channels: this.mention_channels?.map((ch) => ch.toJSON()) ?? [], + attachments: this.attachments ?? [], + nonce: this.nonce ?? undefined, tts: this.tts ?? false, guild: this.guild ?? undefined, @@ -269,6 +278,7 @@ reactions: this.reactions ?? undefined, sticker_items: this.sticker_items ?? undefined, message_reference: this.message_reference ?? undefined, + mention_everyone: this.mention_everyone ?? false, author: { ...(this.author?.toPublicUser() ?? undefined), // Webhooks @@ -277,7 +287,7 @@ }, activity: this.activity ?? undefined, application: this.application ?? undefined, - components: this.components ?? undefined, + components: this.components ?? [], poll: this.poll ?? undefined, content: this.content ?? "", pinned: this.pinned,