From 85fefac15b5f76cc792b91bb2731d14ab3df71a7 Mon Sep 17 00:00:00 2001 From: Jiralite <33201955+Jiralite@users.noreply.github.com> Date: Fri, 10 Jul 2026 22:58:37 +0100 Subject: [PATCH] fix(MessagePersistenceService): preserve embeds if not passed (#1363) --- .../message/MessagePersistenceService.ts | 2 +- .../channel/tests/MessageEditEmbeds.test.ts | 58 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 fluxer_api/src/api/channel/tests/MessageEditEmbeds.test.ts diff --git a/fluxer_api/src/api/channel/services/message/MessagePersistenceService.ts b/fluxer_api/src/api/channel/services/message/MessagePersistenceService.ts index 38408da79..d17946833 100644 --- a/fluxer_api/src/api/channel/services/message/MessagePersistenceService.ts +++ b/fluxer_api/src/api/channel/services/message/MessagePersistenceService.ts @@ -513,7 +513,7 @@ export class MessagePersistenceService { } hasChanges = true; } - if (allowEmbeds && (data.content !== undefined || data.embeds !== undefined)) { + if (allowEmbeds && (data.embeds !== undefined || (data.content !== undefined && message.embeds.length === 0))) { const attachmentsForResolution = updatedRowData.attachments || []; const resolvedEmbeds = this.embedAttachmentResolver.resolveEmbedAttachmentUrls({ embeds: data.embeds, diff --git a/fluxer_api/src/api/channel/tests/MessageEditEmbeds.test.ts b/fluxer_api/src/api/channel/tests/MessageEditEmbeds.test.ts new file mode 100644 index 000000000..178926321 --- /dev/null +++ b/fluxer_api/src/api/channel/tests/MessageEditEmbeds.test.ts @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later + +import type {MessageResponse} from '@fluxer/schema/src/domains/message/MessageResponseSchemas'; +import {afterAll, beforeAll, beforeEach, describe, expect, it} from 'vitest'; +import {createTestAccount} from '../../auth/tests/AuthTestUtils'; +import {ensureSessionStarted} from '../../message/tests/MessageTestUtils'; +import {type ApiTestHarness, createApiTestHarness} from '../../test/ApiTestHarness'; +import {createBuilder} from '../../test/TestRequestBuilder'; +import {createGuild} from './ChannelTestUtils'; + +describe('Message embed edits', () => { + let harness: ApiTestHarness; + + beforeAll(async () => { + harness = await createApiTestHarness(); + }); + + beforeEach(async () => { + await harness.reset(); + }); + + afterAll(async () => { + await harness?.shutdown(); + }); + + it('preserves embeds when omitted from an edit and removes them when explicitly empty', async () => { + const account = await createTestAccount(harness); + const guild = await createGuild(harness, account.token, 'Message embed edit'); + const channelId = guild.system_channel_id!; + await ensureSessionStarted(harness, account.token); + + const createdMessage = await createBuilder(harness, account.token) + .post(`/channels/${channelId}/messages`) + .body({ + content: "I swear if someone steals my embed I'm gonna", + embeds: [{title: 'My saucy embed', description: 'Keep me close. Hold me. Never let me go.'}], + }) + .execute(); + + const contentEditedMessage = await createBuilder(harness, account.token) + .patch(`/channels/${channelId}/messages/${createdMessage.id}`) + .body({content: 'MY EMBED IS STILL HERE OMG'}) + .execute(); + + expect(contentEditedMessage.content).toBe('MY EMBED IS STILL HERE OMG'); + expect(contentEditedMessage.embeds).toHaveLength(1); + expect(contentEditedMessage.embeds?.[0]?.title).toBe('My saucy embed'); + expect(contentEditedMessage.embeds?.[0]?.description).toBe('Keep me close. Hold me. Never let me go.'); + + const embedsRemovedMessage = await createBuilder(harness, account.token) + .patch(`/channels/${channelId}/messages/${createdMessage.id}`) + .body({content: 'I got nothing left', embeds: []}) + .execute(); + + expect(embedsRemovedMessage.content).toBe('I got nothing left'); + expect(embedsRemovedMessage.embeds ?? []).toHaveLength(0); + }); +});