borogove

created pr with borogove/multi-dm.1 on 2026-11-09T19:47:55Z · by 9e834e0d
added borogove/multi-dm.2 on 2026-11-10T19:08:22Z · by 9e834e0d
1: 0ef2769 = 1: 41e89c8 Use to for chatId if not in recipients
2: 90e5a6a = 2: c323e3d clone should clone attributes
3: d86ea28 = 3: a1199ae Actually send to all recipients
4: 1c1061f ! 4: 94bf87d Never add self as counterpart
5: 9c8aa41 = 5: 32b9fad Extended addressing for sent messages specifies all recipients
6: 2da9124 = 6: ce4d9e1 Always add all recipients to outbound message
7: e7db006 = 7: 350343e Use a shared helper for adding extended addressing
8: 4530ece = 8: 40f662a Add startMultiChat to create multiDMs
9: 6810ba9 = 9: 8043c53 Never include ourselves in incoming chat ids
-: ------- > 10: 68e7246 Cannot MAM or bookmark a multiDM
cmds
checkout latest patchset:
ssh pr.pico.sh pull borogove:multi-dm | git am -3
checkout specific patchset revision:
ssh pr.pico.sh pull borogove:multi-dm [rev] | git am -3
add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh borogove:multi-dm
add comment to patch request:
ssh pr.pico.sh comment borogove:multi-dm "lgtm!"
+5 -2 borogove/Message.hx #
......@@ -192,8 +192,11 @@ class Message {
192192 trace("No support for addressing to non-jid", address);
193193 return new Message(msg.chatId(), msg.senderId, msg.threadId, UnknownMessageStanza(stanza), encryptionInfo);
194194 } else if (address.attr.get("type") == "to" || address.attr.get("type") == "cc") {
195- recipients[JID.parse(jid).asBare().asString()] = true;
196- if (!anyExtendedReplyTo) replyTo[JID.parse(jid).asString()] = true; // reply all
195+ final addressJid = JID.parse(jid);
196+ recipients[addressJid.asBare().asString()] = true;
197+ if (!anyExtendedReplyTo && !(msg.direction == MessageReceived && addressJid.asBare().equals(localJidBare))) {
198+ replyTo[addressJid.asString()] = true; // reply all
199+ }
197200 } else if (address.attr.get("type") == "replyto" || address.attr.get("type") == "replyroom") {
198201 if (!anyExtendedReplyTo) {
199202 replyTo.clear();
+25 -0 test/TestChatMessage.hx #
......@@ -259,7 +259,9 @@ class TestChatMessage extends utest.Test {
259259 final msg = Message.fromStanza(stanza, JID.parse("me@example.com"));
260260 switch (msg.parsed) {
261261 case ChatMessageStanza(m):
262+ Assert.equals("alice@example.com", m.chatId());
262263 Assert.same(["alice@example.com", "me@example.com"], m.recipients.map(r -> r.asBare().asString()));
264+ Assert.same(["alice@example.com"], m.replyTo.map(r -> r.asBare().asString()));
263265 default:
264266 Assert.fail("Expected ChatMessageStanza");
265267 }
......@@ -363,6 +365,29 @@ class TestChatMessage extends utest.Test {
363365 }
364366 }
365367
368+ public function testExtendedMultiDMChatIdNeverIncludesSelf() {
369+ final builder = new borogove.ChatMessageBuilder();
370+ builder.localId = "extended-multi-1";
371+ builder.direction = MessageSent;
372+ builder.from = JID.parse("alice@example.com");
373+ builder.senderId = "alice@example.com";
374+ builder.to = JID.parse("bob@example.com");
375+ builder.recipients = [JID.parse("bob@example.com"), JID.parse("carol@example.com")];
376+ builder.replyTo = [JID.parse("alice@example.com")];
377+ builder.setBody(borogove.Html.text("hi"));
378+
379+ final stanza = builder.build().asStanza();
380+ Assert.equals("bob@example.com\ncarol@example.com", Message.fromStanza(stanza, JID.parse("alice@example.com")).chatId);
381+
382+ final toBob = stanza.clone();
383+ toBob.attr.set("to", "bob@example.com");
384+ Assert.equals("alice@example.com\ncarol@example.com", Message.fromStanza(toBob, JID.parse("bob@example.com")).chatId);
385+
386+ final toCarol = stanza.clone();
387+ toCarol.attr.set("to", "carol@example.com");
388+ Assert.equals("alice@example.com\nbob@example.com", Message.fromStanza(toCarol, JID.parse("carol@example.com")).chatId);
389+ }
390+
366391 public function testReactionFallbackSkipsNestedQuotes() {
367392 // Build a parent message that itself contains a quote and regular text
368393 final parentBuilder = new borogove.ChatMessageBuilder();
Back to top