diff --git a/src/api/routes/channels/#channel_id/messages/index.ts b/src/api/routes/channels/#channel_id/messages/index.ts index e391b2ab1..2446da63d 100644 --- a/src/api/routes/channels/#channel_id/messages/index.ts +++ b/src/api/routes/channels/#channel_id/messages/index.ts @@ -121,6 +121,7 @@ router.get( const query: FindManyOptions & { where: { id?: FindOperator | FindOperator[] }; } = { + relationLoadStrategy: "query", order: { timestamp: "DESC" }, take: limit, where: { channel_id }, @@ -133,16 +134,6 @@ router.get( mention_channels: true, sticker_items: true, attachments: true, - referenced_message: { - author: true, - webhook: true, - application: true, - mentions: true, - mention_roles: true, - mention_channels: true, - sticker_items: true, - attachments: true, - }, thread: { recipients: { user: true, @@ -156,6 +147,7 @@ router.get( if (around) { query.take = Math.floor(limit / 2); if (query.take != 0) { + console.time("Query"); const [right, left] = await Promise.all([ Message.find({ ...query, @@ -167,6 +159,7 @@ router.get( order: { timestamp: "ASC" }, }), ]); + console.timeEnd("Query"); left.push(...right); messages = left.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime()); } else { @@ -192,6 +185,7 @@ router.get( messages = await Message.find(query); } + await Message.fillReplies(messages); const endpoint = Config.get().cdn.endpointPublic; const ret = messages.map((x: Message) => { @@ -267,24 +261,6 @@ router.get( }), ); - // polyfill message references for old messages - await Promise.all( - ret - .filter((msg) => msg.message_reference && !msg.referenced_message?.id && msg.message_reference.message_id) - .map(async (msg) => { - const whereOptions: { id: string; guild_id?: string; channel_id?: string } = { - id: msg.message_reference!.message_id as string, - }; - if (msg.message_reference!.guild_id) whereOptions.guild_id = msg.message_reference!.guild_id; - if (msg.message_reference!.channel_id) whereOptions.channel_id = msg.message_reference!.channel_id; - - msg.referenced_message = await Message.findOne({ - where: whereOptions, - relations: { author: true, mentions: true, mention_roles: true, mention_channels: true }, - }); - }), - ); - return res.json(ret); }, ); diff --git a/src/util/entities/Message.ts b/src/util/entities/Message.ts index 37170fe44..2f0ec673f 100644 --- a/src/util/entities/Message.ts +++ b/src/util/entities/Message.ts @@ -22,7 +22,7 @@ import { Role } from "./Role"; import { Channel } from "./Channel"; import { InteractionType } from "../interfaces/Interaction"; import { Application } from "./Application"; -import { Column, CreateDateColumn, Entity, Index, JoinColumn, JoinTable, ManyToMany, ManyToOne, OneToMany, RelationId, FindOneOptions, Raw, Not, BaseEntity } from "typeorm"; +import { Column, CreateDateColumn, Entity, Index, JoinColumn, JoinTable, ManyToMany, ManyToOne, OneToMany, RelationId, FindOneOptions, Raw, Not, BaseEntity, In } from "typeorm"; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; import { Webhook } from "./Webhook"; @@ -215,7 +215,28 @@ export class Message extends BaseClass { @Column({ default: "[]", type: "simple-json" }) message_snapshots: MessageSnapshot[]; - toJSON(): Message { + static async fillReplies(messages: Message[]) { + const ms = messages + .filter((msg) => msg.message_reference && !msg.referenced_message?.id && msg.message_reference.message_id) + .filter((msg) => [MessageType.REPLY, MessageType.THREAD_STARTER_MESSAGE, MessageType.CONTEXT_MENU_COMMAND].includes(msg.type)); + if (!ms.length) return; + const curMs = new Map(messages.map((m) => [m.id, m] as const)); + const neededIds = new Set(ms.map((m) => m.message_reference!.message_id as string)).difference(curMs); + if (neededIds.size) { + const newMessages = await Message.find({ + where: { + id: In([...neededIds]), + }, + relations: { author: true, mentions: true, mention_roles: true, mention_channels: true }, + }); + newMessages.forEach((msg) => curMs.set(msg.id, msg)); + } + for (const message of ms) { + message.referenced_message = curMs.get(message.message_reference!.message_id as string) || null; + } + } + + toJSON(shallow = false): Message { return { ...this, author_id: undefined, @@ -246,6 +267,7 @@ export class Message extends BaseClass { content: this.content ?? "", pinned: this.pinned, thread: this.thread ? this.thread.toJSON() : this.thread, + referenced_message: this.referenced_message && !shallow ? this.referenced_message.toJSON(true) : undefined, }; }