From e6ef9150b9542278e0a385f2881a90bd38d5c251 Mon Sep 17 00:00:00 2001 From: hampus-fluxer Date: Tue, 6 Jan 2026 06:22:18 +0100 Subject: [PATCH] fix(api): enforce correct message type for replies in personal notes (#58) --- .../services/message/MessageSendService.ts | 2 +- .../personal_notes_reply_type_test.go | 80 +++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 tests/integration/personal_notes_reply_type_test.go diff --git a/fluxer_api/src/channel/services/message/MessageSendService.ts b/fluxer_api/src/channel/services/message/MessageSendService.ts index 3896af9b..6c15091c 100644 --- a/fluxer_api/src/channel/services/message/MessageSendService.ts +++ b/fluxer_api/src/channel/services/message/MessageSendService.ts @@ -907,7 +907,7 @@ export class MessageSendService { messageId, channelId, user, - type: MessageTypes.DEFAULT, + type: this.getMessageTypeForRequest(data), content: data.content, flags: data.flags ? data.flags & SENDABLE_MESSAGE_FLAGS : 0, embeds: data.embeds, diff --git a/tests/integration/personal_notes_reply_type_test.go b/tests/integration/personal_notes_reply_type_test.go new file mode 100644 index 00000000..e4ed7b97 --- /dev/null +++ b/tests/integration/personal_notes_reply_type_test.go @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2026 Fluxer Contributors + * + * This file is part of Fluxer. + * + * Fluxer is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Fluxer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Fluxer. If not, see . + */ + +package integration + +import ( + "fmt" + "net/http" + "testing" +) + +const personalNotesMessageTypeReply = 19 + +// TestPersonalNotesReplyType ensures replies sent from the Personal Notes channel +// are serialized with the REPLY message type. +func TestPersonalNotesReplyType(t *testing.T) { + client := newTestClient(t) + account := createTestAccount(t, client) + ensureSessionStarted(t, client, account.Token) + + channelID := parseSnowflake(t, account.UserID) + originalMessage := sendChannelMessage(t, client, account.Token, channelID, "Original personal note") + + replyPayload := map[string]any{ + "content": "Replying in personal notes", + "message_reference": map[string]any{ + "message_id": originalMessage.ID, + "channel_id": account.UserID, + "type": 0, + }, + } + + resp, err := client.postJSONWithAuth( + fmt.Sprintf("/channels/%d/messages", channelID), + replyPayload, + account.Token, + ) + if err != nil { + t.Fatalf("failed to post personal notes reply: %v", err) + } + assertStatus(t, resp, http.StatusOK) + + var reply struct { + ID string `json:"id"` + Type int `json:"type"` + MessageReference *struct { + MessageID string `json:"message_id"` + ChannelID string `json:"channel_id"` + } `json:"message_reference"` + } + decodeJSONResponse(t, resp, &reply) + + if reply.Type != personalNotesMessageTypeReply { + t.Fatalf("expected personal notes reply type %d but got %d", personalNotesMessageTypeReply, reply.Type) + } + + if reply.MessageReference == nil { + t.Fatalf("expected message_reference to be present in personal notes reply") + } + + if reply.MessageReference.MessageID != originalMessage.ID { + t.Fatalf("personal notes reply referenced wrong message: expected %s, got %s", originalMessage.ID, reply.MessageReference.MessageID) + } +}