| author | Stephen Paul Weber
<singpolyma@singpolyma.net> 2026-04-21 02:24:59 UTC |
| committer | Stephen Paul Weber
<singpolyma@singpolyma.net> 2026-04-21 02:24:59 UTC |
| parent | 78aaef98cd175d38886b430369392229bc9c74e4 |
| borogove/ChatMessage.hx | +8 | -0 |
| test/TestClient.hx | +74 | -0 |
diff --git a/borogove/ChatMessage.hx b/borogove/ChatMessage.hx index 5b6454e..8564975 100644 --- a/borogove/ChatMessage.hx +++ b/borogove/ChatMessage.hx @@ -453,6 +453,14 @@ class ChatMessage { return threadId == null ? null : Identicon.svg(threadId); } + /** + If message is moderated, the reason + **/ + public function moderationReason(): Null<String> { + final retracted = payloads.find((el) -> el.attr.get("xmlns") == "urn:xmpp:message-retract:1"); + return retracted == null ? null : retracted.getChildText("reason") ?? "moderated"; + } + /** The last status of the call if this message is related to a call **/ diff --git a/test/TestClient.hx b/test/TestClient.hx index ba6fae8..0b48b24 100644 --- a/test/TestClient.hx +++ b/test/TestClient.hx @@ -10,6 +10,7 @@ import borogove.ChatMessageBuilder; import borogove.Client; import borogove.JID; import borogove.Message; +import borogove.ModerationAction; import borogove.Stanza; import borogove.persistence.Dummy; @@ -23,6 +24,58 @@ class TestClient extends utest.Test { Assert.equals("test@example.com", client.accountId()); } + public function testModerateMessage(async: Async) { + final persistence = new MessageMockPersistence(); + final client = new Client("test@example.com", persistence); + final chatId = "chat@example.com"; + final serverId = "msg123"; + + // Pre-populate persistence with a message + final builder = new ChatMessageBuilder(); + builder.serverId = serverId; + builder.from = JID.parse("other@example.com"); + builder.to = JID.parse("test@example.com"); + builder.senderId = "other@example.com"; + builder.text = "to be moderated"; + final originalMessage = builder.build(); + + persistence.storeMessages(client.accountId(), [originalMessage]).then((_) -> { + final action = new ModerationAction(chatId, serverId, "2023-01-01T00:00:00Z", "mod@example.com", "Spam"); + + client.moderateMessage(action).then((moderatedMessage) -> { + Assert.notNull(moderatedMessage); + Assert.equals("Spam", moderatedMessage.moderationReason()); + async.done(); + }); + }); + } + + public function testModerateMessageNoReason(async: Async) { + final persistence = new MessageMockPersistence(); + final client = new Client("test@example.com", persistence); + final chatId = "chat@example.com"; + final serverId = "msg124"; + + // Pre-populate persistence with a message + final builder = new ChatMessageBuilder(); + builder.serverId = serverId; + builder.from = JID.parse("other@example.com"); + builder.to = JID.parse("test@example.com"); + builder.senderId = "other@example.com"; + builder.text = "to be moderated"; + final originalMessage = builder.build(); + + persistence.storeMessages(client.accountId(), [originalMessage]).then((_) -> { + final action = new ModerationAction(chatId, serverId, "2023-01-01T00:00:00Z", "mod@example.com", null); + + client.moderateMessage(action).then((moderatedMessage) -> { + Assert.notNull(moderatedMessage); + Assert.equals("moderated", moderatedMessage.moderationReason()); + async.done(); + }); + }); + } + public function testDefaultDisplayName() { final persistence = new Dummy(); final client = new Client("test@example.com", persistence); @@ -413,3 +466,24 @@ class MockPersistence extends Dummy { return Promise.resolve(builder.build()); } } + +@:access(borogove) +class MessageMockPersistence extends Dummy { + public var messages: Map<String, ChatMessage> = []; + public function new() { super(); } + + override public function storeMessages(accountId: String, messages: Array<ChatMessage>): Promise<Array<ChatMessage>> { + for (m in messages) { + if (m.serverId != null) this.messages.set(m.serverId, m); + } + return Promise.resolve(messages); + } + + override public function getMessage(accountId: String, chatId: String, serverId: Null<String>, localId: Null<String>): Promise<Null<ChatMessage>> { + return Promise.resolve(serverId != null ? messages.get(serverId) : null); + } + + override public function updateMessage(accountId: String, message: ChatMessage) { + if (message.serverId != null) this.messages.set(message.serverId, message); + } +}