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),