From d540e7de522164ff65b1c8869f8e2f2f8cc3d704 Mon Sep 17 00:00:00 2001 From: Sunny Hashmi <6833405+sh4sh@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:39:16 -0500 Subject: [PATCH 1/3] Add XEP-0461 Message Replies support --- xmpp.go | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/xmpp.go b/xmpp.go index 6998f732..98a0fd7d 100644 --- a/xmpp.go +++ b/xmpp.go @@ -1466,6 +1466,10 @@ type Chat struct { OriginID string // Only for incoming messages, ID for outgoing messages will be generated. StanzaID StanzaID + // XEP-0461: id of the message being replied to (use StanzaID for groupchat) + ReplyID string + // XEP-0461: JID of the author of the message being replied to + ReplyTo string Roster Roster Other []string OtherElem []XMLElement @@ -1561,6 +1565,8 @@ func (c *Client) Recv() (stanza interface{}, err error) { Lang: v.Lang, OriginID: v.OriginID.ID, StanzaID: v.StanzaID, + ReplyID: v.Reply.ID, + ReplyTo: v.Reply.To, Oob: v.Oob, } return chat, nil @@ -1852,10 +1858,19 @@ func (c *Client) Send(chat Chat) (n int, err error) { oobtext += `` } + var replytext string + if chat.replyID != `` { + replytext = `` + } + chat.Text = validUTF8(chat.Text) id := getUUID() - stanza := fmt.Sprintf("%s%s"+ - "%s%s\n", + stanza := fmt.Sprintf("%s%s" + + replytext + "%s%s\n", xmlEscape(chat.Remote), xmlEscape(chat.Type), id, subtext, xmlEscape(chat.Text), XMPPNS_SID_0, id, oobtext, thdtext) if c.LimitMaxBytes != 0 && len(stanza) > c.LimitMaxBytes { @@ -2166,6 +2181,13 @@ type StanzaID struct { By string `xml:"by,attr"` } +// XEP-0461 Message Replies +type clientReply struct { + XMLName xml.Name `xml:"urn:xmpp:reply:0 reply"` + ID string `xml:"id,attr"` + To string `xml:"to,attr"` +} + // RFC 3921 B.1 jabber:client type clientMessage struct { XMLName xml.Name `xml:"jabber:client message"` @@ -2184,6 +2206,9 @@ type clientMessage struct { OriginID originID `xml:"origin-id"` StanzaID StanzaID `xml:"stanza-id"` + // XEP-0461 + Reply clientReply `xml:"reply"` + // Pubsub Event clientPubsubEvent `xml:"event"` From da5f0ff8bc58ff4b9ce0cec40dd00d4c2786838c Mon Sep 17 00:00:00 2001 From: Sunny Hashmi <6833405+sh4sh@users.noreply.github.com> Date: Mon, 16 Feb 2026 12:57:34 -0500 Subject: [PATCH 2/3] fix some typos --- xmpp.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/xmpp.go b/xmpp.go index 98a0fd7d..62994b85 100644 --- a/xmpp.go +++ b/xmpp.go @@ -1465,9 +1465,9 @@ type Chat struct { // Only for incoming messages, ID for outgoing messages will be generated. OriginID string // Only for incoming messages, ID for outgoing messages will be generated. - StanzaID StanzaID + StanzaID StanzaID // XEP-0461: id of the message being replied to (use StanzaID for groupchat) - ReplyID string + ReplyID string // XEP-0461: JID of the author of the message being replied to ReplyTo string Roster Roster @@ -1859,8 +1859,8 @@ func (c *Client) Send(chat Chat) (n int, err error) { } var replytext string - if chat.replyID != `` { - replytext = `%s%s" - + replytext + "%s%s\n", + stanza := fmt.Sprintf("%s%s"+ + replytext+"%s%s\n", xmlEscape(chat.Remote), xmlEscape(chat.Type), id, subtext, xmlEscape(chat.Text), XMPPNS_SID_0, id, oobtext, thdtext) if c.LimitMaxBytes != 0 && len(stanza) > c.LimitMaxBytes { @@ -2206,8 +2206,8 @@ type clientMessage struct { OriginID originID `xml:"origin-id"` StanzaID StanzaID `xml:"stanza-id"` - // XEP-0461 - Reply clientReply `xml:"reply"` + // XEP-0461 + Reply clientReply `xml:"reply"` // Pubsub Event clientPubsubEvent `xml:"event"` From 3148e36f12ce48628b18c5fef58db490aa8a06e2 Mon Sep 17 00:00:00 2001 From: Sunny Hashmi <6833405+sh4sh@users.noreply.github.com> Date: Mon, 16 Feb 2026 13:22:05 -0500 Subject: [PATCH 3/3] add support for chat.ID --- xmpp.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/xmpp.go b/xmpp.go index 62994b85..0afdd7e8 100644 --- a/xmpp.go +++ b/xmpp.go @@ -1451,6 +1451,7 @@ func (c *Client) IsEncrypted() bool { // Chat is an incoming or outgoing XMPP chat message. type Chat struct { + ID string Remote string Type string Text string @@ -1554,6 +1555,7 @@ func (c *Client) Recv() (stanza interface{}, err error) { v.Delay.Stamp, ) chat := Chat{ + ID: v.ID, Remote: v.From, Type: v.Type, Text: v.Body, @@ -1868,7 +1870,10 @@ func (c *Client) Send(chat Chat) (n int, err error) { } chat.Text = validUTF8(chat.Text) - id := getUUID() + id := chat.ID + if id == "" { + id = getUUID() + } stanza := fmt.Sprintf("%s%s"+ replytext+"%s%s\n", xmlEscape(chat.Remote), xmlEscape(chat.Type), id, subtext, xmlEscape(chat.Text),