summary refs log tree commit diff
diff options
context:
space:
mode:
authorCyber <cyber.hf18@gmail.com>2025-12-18 22:11:45 +0100
committerGitHub <noreply@github.com>2025-12-18 22:11:45 +0100
commita8375d75fbc53ac70a31d49679fc0ced01a3c6b8 (patch)
tree4bb51b8e016dd55ed24567566c9ea3eb77cbb14b
parentMore gateway trace (diff)
parentMerge branch 'master' into feat/forwards (diff)
downloadserver-ts-a8375d75fbc53ac70a31d49679fc0ced01a3c6b8.tar.xz
Merge pull request #1443 from CyberL1/feat/forwards
-rw-r--r--assets/openapi.json129
-rw-r--r--assets/schemas.json134
-rw-r--r--scripts/schemaExclusions.json14
-rw-r--r--src/api/util/handlers/Message.ts42
-rw-r--r--src/schemas/api/messages/Message.ts21
-rw-r--r--src/schemas/uncategorised/MessageCreateSchema.ts1
-rw-r--r--src/util/entities/Message.ts5
-rw-r--r--src/util/migration/postgres/1765185286988-message-snapshots.ts13
8 files changed, 345 insertions, 14 deletions
diff --git a/assets/openapi.json b/assets/openapi.json

index 0b326c88..ad4bd98a 100644 --- a/assets/openapi.json +++ b/assets/openapi.json
@@ -5460,6 +5460,9 @@ }, "fail_if_not_exists": { "type": "boolean" + }, + "type": { + "type": "integer" } }, "additionalProperties": false, @@ -5750,6 +5753,9 @@ }, "fail_if_not_exists": { "type": "boolean" + }, + "type": { + "type": "integer" } }, "additionalProperties": false, @@ -7615,6 +7621,12 @@ "avatar": { "type": "string" }, + "message_snapshots": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MessageSnapshot" + } + }, "id": { "type": "string" } @@ -7627,6 +7639,7 @@ "mention_channels", "mention_roles", "mentions", + "message_snapshots", "pinned", "reactions", "timestamp", @@ -10835,6 +10848,122 @@ "me_voted" ] }, + "MessageSnapshot": { + "type": "object", + "properties": { + "message": { + "type": "object", + "properties": { + "content": { + "type": "string" + }, + "timestamp": { + "type": "string", + "format": "date-time" + }, + "edited_timestamp": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ] + }, + "mentions": { + "type": "array", + "items": { + "type": "string" + } + }, + "mention_roles": { + "type": "array", + "items": { + "type": "string" + } + }, + "attachments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Attachment" + } + }, + "embeds": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Embed" + } + }, + "type": { + "$ref": "#/components/schemas/MessageType" + }, + "flags": { + "type": "integer" + }, + "components": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MessageComponent" + } + }, + "resolved": { + "type": "array", + "items": { + "type": "object", + "properties": {}, + "additionalProperties": true + } + }, + "sticker_items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Sticker" + } + } + }, + "additionalProperties": false, + "required": [ + "content", + "embeds", + "flags", + "mention_roles", + "mentions", + "timestamp", + "type" + ] + } + }, + "required": [ + "message" + ] + }, + "MessageComponent": { + "type": "object", + "properties": { + "type": { + "$ref": "#/components/schemas/MessageComponentType" + } + }, + "required": [ + "type" + ] + }, + "MessageComponentType": { + "type": "number", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 + ] + }, "InteractionGuild": { "type": "object", "properties": { diff --git a/assets/schemas.json b/assets/schemas.json
index 3d734edf..08eea064 100644 --- a/assets/schemas.json +++ b/assets/schemas.json
@@ -5807,6 +5807,9 @@ }, "fail_if_not_exists": { "type": "boolean" + }, + "type": { + "type": "integer" } }, "additionalProperties": false, @@ -6103,6 +6106,9 @@ }, "fail_if_not_exists": { "type": "boolean" + }, + "type": { + "type": "integer" } }, "additionalProperties": false, @@ -8092,6 +8098,12 @@ "avatar": { "type": "string" }, + "message_snapshots": { + "type": "array", + "items": { + "$ref": "#/definitions/MessageSnapshot" + } + }, "id": { "type": "string" } @@ -8105,6 +8117,7 @@ "mention_channels", "mention_roles", "mentions", + "message_snapshots", "pinned", "reactions", "timestamp", @@ -11460,6 +11473,127 @@ ], "$schema": "http://json-schema.org/draft-07/schema#" }, + "MessageSnapshot": { + "type": "object", + "properties": { + "message": { + "type": "object", + "properties": { + "content": { + "type": "string" + }, + "timestamp": { + "type": "string", + "format": "date-time" + }, + "edited_timestamp": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ] + }, + "mentions": { + "type": "array", + "items": { + "type": "string" + } + }, + "mention_roles": { + "type": "array", + "items": { + "type": "string" + } + }, + "attachments": { + "type": "array", + "items": { + "$ref": "#/definitions/Attachment" + } + }, + "embeds": { + "type": "array", + "items": { + "$ref": "#/definitions/Embed" + } + }, + "type": { + "$ref": "#/definitions/MessageType" + }, + "flags": { + "type": "integer" + }, + "components": { + "type": "array", + "items": { + "$ref": "#/definitions/MessageComponent" + } + }, + "resolved": { + "type": "array", + "items": { + "type": "object", + "properties": {}, + "additionalProperties": true + } + }, + "sticker_items": { + "type": "array", + "items": { + "$ref": "#/definitions/Sticker" + } + } + }, + "additionalProperties": false, + "required": [ + "content", + "embeds", + "flags", + "mention_roles", + "mentions", + "timestamp", + "type" + ] + } + }, + "additionalProperties": false, + "required": [ + "message" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "MessageComponent": { + "type": "object", + "properties": { + "type": { + "$ref": "#/definitions/MessageComponentType" + } + }, + "additionalProperties": false, + "required": [ + "type" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "MessageComponentType": { + "type": "number", + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, "InteractionGuild": { "type": "object", "properties": { diff --git a/scripts/schemaExclusions.json b/scripts/schemaExclusions.json
index 64e2bbf0..b2847670 100644 --- a/scripts/schemaExclusions.json +++ b/scripts/schemaExclusions.json
@@ -1,10 +1,6 @@ { - "include": [ - "MessageInteractionSchema" - ], - "includeRe": [ - "^MessageComponentType\\..*" - ], + "include": ["MessageInteractionSchema"], + "includeRe": ["^MessageComponentType\\..*"], "manual": [ "DefaultSchema", "Schema", @@ -87,9 +83,7 @@ "^Job" ], "manualWarn": [], - "manualWarnRe": [ - ".*<.*>$" - ], + "manualWarnRe": [".*<.*>$"], "auto": [ { "value": "StringSchema", @@ -412,4 +406,4 @@ "reason": "Schema with only uppercase properties" } ] -} \ No newline at end of file +} diff --git a/src/api/util/handlers/Message.ts b/src/api/util/handlers/Message.ts
index 915fe292..618f02f0 100644 --- a/src/api/util/handlers/Message.ts +++ b/src/api/util/handlers/Message.ts
@@ -232,7 +232,7 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> { if (!opts.message_reference.guild_id) opts.message_reference.guild_id = channel.guild_id; if (!opts.message_reference.channel_id) opts.message_reference.channel_id = opts.channel_id; - if (!guild.features.includes("CROSS_CHANNEL_REPLIES")) { + if (opts.message_reference.type != 1) { if (opts.message_reference.guild_id !== channel.guild_id) throw new HTTPError("You can only reference messages from this guild"); if (opts.message_reference.channel_id !== opts.channel_id) throw new HTTPError("You can only reference messages from this channel"); } @@ -257,7 +257,16 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> { } // TODO: stickers/activity - if (!allow_empty && !opts.content && !opts.embeds?.length && !opts.attachments?.length && !opts.sticker_ids?.length && !opts.poll && !opts.components?.length) { + if ( + !allow_empty && + !opts.content && + !opts.embeds?.length && + !opts.attachments?.length && + !opts.sticker_ids?.length && + !opts.poll && + !opts.components?.length && + opts.message_reference?.type != 1 + ) { console.log("[Message] Rejecting empty message:", opts, message); throw new HTTPError("Empty messages are not allowed", 50006); } @@ -314,6 +323,35 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> { }), ); } + + // FORWARD + if (message.message_reference.type === 1) { + message.type = MessageType.DEFAULT; + + if (message.referenced_message) { + const mention_roles: string[] = []; + const mentions: string[] = []; + + // TODO: mention_roles and mentions arrays - not needed it seems, but discord still returns that + + message.message_snapshots = [ + { + message: { + attachments: message.referenced_message.attachments, + components: message.referenced_message.components, + content: message.referenced_message.content!, + edited_timestamp: message.referenced_message.edited_timestamp, + embeds: message.referenced_message.embeds, + flags: message.referenced_message.flags, + mention_roles, + mentions, + timestamp: message.referenced_message.timestamp, + type: message.referenced_message.type, + }, + }, + ]; + } + } } // root@Rory - 20/02/2023 - This breaks channel mentions in test client. We're not sure this was used in older clients. diff --git a/src/schemas/api/messages/Message.ts b/src/schemas/api/messages/Message.ts
index 69984e2a..a46c8f10 100644 --- a/src/schemas/api/messages/Message.ts +++ b/src/schemas/api/messages/Message.ts
@@ -16,7 +16,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { PartialUser, Snowflake } from "@spacebar/schemas"; +import { Attachment, Sticker } from "@spacebar/util"; +import { Embed, MessageComponent, PartialUser, Snowflake } from "@spacebar/schemas"; export enum MessageType { DEFAULT = 0, @@ -94,3 +95,21 @@ export interface AllowedMentions { users?: Snowflake[]; replied_user?: boolean; } + +export interface MessageSnapshot { + message: { + content: string; + timestamp: Date; + edited_timestamp?: Date | null; + mentions: Snowflake[]; + mention_roles: Snowflake[]; + attachments?: Attachment[]; + embeds: Embed[]; + type: MessageType; + flags: number; + components?: MessageComponent[]; + resolved?: object[]; + sticker_items?: Sticker[]; + // soundboard_sounds?: object[]; // TODO: when soundboard is done + }; +} diff --git a/src/schemas/uncategorised/MessageCreateSchema.ts b/src/schemas/uncategorised/MessageCreateSchema.ts
index bdf2ab22..345be32c 100644 --- a/src/schemas/uncategorised/MessageCreateSchema.ts +++ b/src/schemas/uncategorised/MessageCreateSchema.ts
@@ -53,6 +53,7 @@ export interface MessageCreateSchema { channel_id?: string; guild_id?: string; fail_if_not_exists?: boolean; + type?: number; }; payload_json?: string; file?: { filename: string }; diff --git a/src/util/entities/Message.ts b/src/util/entities/Message.ts
index 9935ae04..508ffd8c 100644 --- a/src/util/entities/Message.ts +++ b/src/util/entities/Message.ts
@@ -29,7 +29,7 @@ import { Webhook } from "./Webhook"; import { Sticker } from "./Sticker"; import { Attachment } from "./Attachment"; import { NewUrlUserSignatureData } from "../Signing"; -import { ActionRowComponent, ApplicationCommandType, Embed, MessageType, PartialMessage, Poll, Reaction } from "@spacebar/schemas"; +import { ActionRowComponent, ApplicationCommandType, Embed, MessageSnapshot, MessageType, PartialMessage, Poll, Reaction } from "@spacebar/schemas"; import { MessageFlags } from "@spacebar/util"; @Entity({ @@ -202,6 +202,9 @@ export class Message extends BaseClass { @Column({ nullable: true }) avatar?: string; + @Column({ default: "[]", type: "simple-json" }) + message_snapshots: MessageSnapshot[]; + toJSON(): Message { return { ...this, diff --git a/src/util/migration/postgres/1765185286988-message-snapshots.ts b/src/util/migration/postgres/1765185286988-message-snapshots.ts new file mode 100644
index 00000000..ca0c33ee --- /dev/null +++ b/src/util/migration/postgres/1765185286988-message-snapshots.ts
@@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class MessageSnapshots1765185286988 implements MigrationInterface { + name = "MessageSnapshots1765185286988"; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(`ALTER TABLE "messages" ADD "message_snapshots" text NOT NULL DEFAULT '[]'`); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(`ALTER TABLE "messages" DROP COLUMN "message_snapshots"`); + } +}