Add XEP-0359 IDs

This commit is contained in:
Bohdan Horbeshko 2025-05-17 01:17:08 -04:00
parent dd00abe977
commit 538b9bca8b
5 changed files with 78 additions and 20 deletions

View file

@ -11,6 +11,7 @@ import (
"dev.narayana.im/narayana/telegabber/telegram/formatter" "dev.narayana.im/narayana/telegabber/telegram/formatter"
"dev.narayana.im/narayana/telegabber/xmpp/gateway" "dev.narayana.im/narayana/telegabber/xmpp/gateway"
"github.com/google/uuid"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/zelenin/go-tdlib/client" "github.com/zelenin/go-tdlib/client"
) )
@ -393,8 +394,13 @@ func (c *Client) updateMessageContent(update *client.UpdateMessageContent) {
} else { } else {
from = gateway.CHATNODE(update.ChatId) from = gateway.CHATNODE(update.ChatId)
} }
id := "e"+sId
uuid, err := uuid.NewRandom()
if err == nil {
id = id+":"+uuid.String()
}
for _, jid := range jids { for _, jid := range jids {
gateway.SendMessage(jid, from, text.String(), "e"+sId, c.xmpp, nil, 0, replaceId, isCarbon, isMUC, false, originalFrom) gateway.SendMessage(jid, from, text.String(), id, c.xmpp, nil, 0, replaceId, isCarbon, isMUC, false, originalFrom, "")
} }
} }
} }

View file

@ -1644,10 +1644,14 @@ func (c *Client) SendMessageToGateway(chatId int64, message *client.Message, id
// forward message to XMPP // forward message to XMPP
var sId string var sId string
var stanzaId string
strId := strconv.FormatInt(message.Id, 10)
if id == "" { if id == "" {
sId = strconv.FormatInt(message.Id, 10) sId = strId
stanzaId = strId
} else { } else {
sId = id sId = id
stanzaId = strId
} }
var from string var from string
@ -1663,9 +1667,9 @@ func (c *Client) SendMessageToGateway(chatId int64, message *client.Message, id
} }
for _, jid := range jids { for _, jid := range jids {
gateway.SendMessageWithOOB(jid, from, text, sId, c.xmpp, reply, timestamp, oob, "", isCarbon, isGroupchat, c.Session.Receipts, originalFrom) gateway.SendMessageWithOOB(jid, from, text, sId, c.xmpp, reply, timestamp, oob, "", isCarbon, isGroupchat, c.Session.Receipts, originalFrom, stanzaId)
if auxText != "" { if auxText != "" {
gateway.SendMessage(jid, from, auxText, sId, c.xmpp, reply, timestamp, "", isCarbon, isGroupchat, c.Session.Receipts, originalFrom) gateway.SendMessage(jid, from, auxText, sId, c.xmpp, reply, timestamp, "", isCarbon, isGroupchat, c.Session.Receipts, originalFrom, stanzaId)
} }
} }
c.UpdateLastChatMessageId(chatId, sId) c.UpdateLastChatMessageId(chatId, sId)
@ -2353,11 +2357,12 @@ func (c *Client) sendMessagesReverse(chatID int64, messages []*client.Message, p
if plain { if plain {
reply, _ := c.getMessageReply(message, false, true) reply, _ := c.getMessageReply(message, false, true)
sId := strconv.FormatInt(message.Id, 10)
gateway.SendMessage( gateway.SendMessage(
c.jid, c.jid,
sChatId, sChatId,
c.formatMessage(0, 0, false, message), c.formatMessage(0, 0, false, message),
strconv.FormatInt(message.Id, 10), sId,
c.xmpp, c.xmpp,
reply, reply,
0, 0,
@ -2366,12 +2371,14 @@ func (c *Client) sendMessagesReverse(chatID int64, messages []*client.Message, p
false, false,
false, false,
"", "",
"",
) )
} else { } else {
msgId, _ := gateway.IdsDB.GetByTgIds(c.Session.Login, c.jid, chatID, message.Id)
c.SendMessageToGateway( c.SendMessageToGateway(
chatID, chatID,
message, message,
"", msgId,
true, true,
mucJid + "/" + c.GetMUCNickname(c.getMessageSenderId(message)), mucJid + "/" + c.GetMUCNickname(c.getMessageSenderId(message)),
[]string{toJid}, []string{toJid},

View file

@ -289,6 +289,19 @@ type MessageAddress struct {
Jid string `xml:"jid,attr"` Jid string `xml:"jid,attr"`
} }
// MessageStanzaId is from XEP-0359
type MessageStanzaId struct {
XMLName xml.Name `xml:"urn:xmpp:sid:0 stanza-id"`
Id string `xml:"id,attr"`
By string `xml:"by,attr"`
}
// MessageOriginId is from XEP-0359
type MessageOriginId struct {
XMLName xml.Name `xml:"urn:xmpp:sid:0 origin-id"`
Id string `xml:"id,attr"`
}
// EmptySubject is a dummy for MUCs to circumvent omitempty. Not registered as it would conflict with Subject field // EmptySubject is a dummy for MUCs to circumvent omitempty. Not registered as it would conflict with Subject field
type EmptySubject struct { type EmptySubject struct {
XMLName xml.Name `xml:"subject"` XMLName xml.Name `xml:"subject"`
@ -488,4 +501,16 @@ func init() {
"http://jabber.org/protocol/address", "http://jabber.org/protocol/address",
"addresses", "addresses",
}, MessageAddresses{}) }, MessageAddresses{})
// stable stanza id
stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{
"urn:xmpp:sid:0",
"stanza-id",
}, MessageStanzaId{})
// message addresses
stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{
"urn:xmpp:sid:0",
"origin-id",
}, MessageOriginId{})
} }

View file

@ -88,8 +88,8 @@ func MUCJID(chatId int64) string {
} }
// SendMessage creates and sends a message stanza // SendMessage creates and sends a message stanza
func SendMessage(to, from, body, id string, component *xmpp.Component, reply *Reply, timestamp int64, replaceId string, isCarbon, isGroupchat, requestReceipt bool, originalFrom string) { func SendMessage(to, from, body, id string, component *xmpp.Component, reply *Reply, timestamp int64, replaceId string, isCarbon, isGroupchat, requestReceipt bool, originalFrom, stanzaId string) {
sendMessageWrapper(to, from, body, "", "", id, component, reply, nil, timestamp, "", replaceId, isCarbon, isGroupchat, false, requestReceipt, originalFrom, 0, "") sendMessageWrapper(to, from, body, "", "", id, component, reply, nil, timestamp, "", replaceId, isCarbon, isGroupchat, false, requestReceipt, originalFrom, 0, "", stanzaId)
} }
// SendServiceMessage creates and sends a simple message stanza from transport // SendServiceMessage creates and sends a simple message stanza from transport
@ -98,7 +98,7 @@ func SendServiceMessage(to, body string, component *xmpp.Component) {
if uuid, err := uuid.NewRandom(); err == nil { if uuid, err := uuid.NewRandom(); err == nil {
id = uuid.String() id = uuid.String()
} }
sendMessageWrapper(to, "", body, "", "", id, component, nil, nil, 0, "", "", false, false, false, false, "", 0, "") sendMessageWrapper(to, "", body, "", "", id, component, nil, nil, 0, "", "", false, false, false, false, "", 0, "", "")
} }
// SendTextMessage creates and sends a simple message stanza // SendTextMessage creates and sends a simple message stanza
@ -107,27 +107,27 @@ func SendTextMessage(to, from, body string, component *xmpp.Component, isGroupch
if uuid, err := uuid.NewRandom(); err == nil { if uuid, err := uuid.NewRandom(); err == nil {
id = uuid.String() id = uuid.String()
} }
sendMessageWrapper(to, from, body, "", "", id, component, nil, nil, 0, "", "", false, isGroupchat, false, false, "", 0, "") sendMessageWrapper(to, from, body, "", "", id, component, nil, nil, 0, "", "", false, isGroupchat, false, false, "", 0, "", "")
} }
// SendErrorMessage creates and sends an error message stanza // SendErrorMessage creates and sends an error message stanza
func SendErrorMessage(to, from, text string, code int, isGroupchat bool, component *xmpp.Component) { func SendErrorMessage(to, from, text string, code int, isGroupchat bool, component *xmpp.Component) {
sendMessageWrapper(to, from, "", "", text, "", component, nil, nil, 0, "", "", false, isGroupchat, false, false, "", code, "") sendMessageWrapper(to, from, "", "", text, "", component, nil, nil, 0, "", "", false, isGroupchat, false, false, "", code, "", "")
} }
// SendErrorMessageWithBody creates and sends an error message stanza with body payload // SendErrorMessageWithBody creates and sends an error message stanza with body payload
func SendErrorMessageWithBody(to, from, body, errorText, id string, code int, isGroupchat bool, component *xmpp.Component) { func SendErrorMessageWithBody(to, from, body, errorText, id string, code int, isGroupchat bool, component *xmpp.Component) {
sendMessageWrapper(to, from, body, "", errorText, id, component, nil, nil, 0, "", "", false, isGroupchat, false, false, "", code, "") sendMessageWrapper(to, from, body, "", errorText, id, component, nil, nil, 0, "", "", false, isGroupchat, false, false, "", code, "", "")
} }
// SendMessageWithOOB creates and sends a message stanza with OOB URL // SendMessageWithOOB creates and sends a message stanza with OOB URL
func SendMessageWithOOB(to, from, body, id string, component *xmpp.Component, reply *Reply, timestamp int64, oob, replaceId string, isCarbon, isGroupchat, requestReceipt bool, originalFrom string) { func SendMessageWithOOB(to, from, body, id string, component *xmpp.Component, reply *Reply, timestamp int64, oob, replaceId string, isCarbon, isGroupchat, requestReceipt bool, originalFrom, stanzaId string) {
sendMessageWrapper(to, from, body, "", "", id, component, reply, nil, timestamp, oob, replaceId, isCarbon, isGroupchat, false, requestReceipt, originalFrom, 0, "") sendMessageWrapper(to, from, body, "", "", id, component, reply, nil, timestamp, oob, replaceId, isCarbon, isGroupchat, false, requestReceipt, originalFrom, 0, "", stanzaId)
} }
// SendSubjectMessage creates and sends a MUC subject // SendSubjectMessage creates and sends a MUC subject
func SendSubjectMessage(to, from, subject, id string, component *xmpp.Component, timestamp int64) { func SendSubjectMessage(to, from, subject, id string, component *xmpp.Component, timestamp int64) {
sendMessageWrapper(to, from, "", subject, "", id, component, nil, nil, timestamp, "", "", false, true, true, false, "", 0, "") sendMessageWrapper(to, from, "", subject, "", id, component, nil, nil, timestamp, "", "", false, true, true, false, "", 0, "", "")
} }
// SendMessageMarker creates and sends a message stanza with a XEP-0333 marker // SendMessageMarker creates and sends a message stanza with a XEP-0333 marker
@ -135,15 +135,15 @@ func SendMessageMarker(to string, from string, component *xmpp.Component, marker
sendMessageWrapper(to, from, "", "", "", "", component, nil, &marker{ sendMessageWrapper(to, from, "", "", "", "", component, nil, &marker{
Type: markerType, Type: markerType,
Id: markerId, Id: markerId,
}, 0, "", "", false, false, false, false, "", 0, "") }, 0, "", "", false, false, false, false, "", 0, "", "")
} }
// SendMUCInvite creates and send a MUC invitation message // SendMUCInvite creates and send a MUC invitation message
func SendMUCInvite(to string, from string, component *xmpp.Component, inviteFrom string) { func SendMUCInvite(to string, from string, component *xmpp.Component, inviteFrom string) {
sendMessageWrapper(to, from, "", "", "", "", component, nil, nil, 0, "", "", false, false, false, false, "", 0, inviteFrom) sendMessageWrapper(to, from, "", "", "", "", component, nil, nil, 0, "", "", false, false, false, false, "", 0, inviteFrom, "")
} }
func sendMessageWrapper(to, from, body, subject, errorText, id string, component *xmpp.Component, reply *Reply, marker *marker, timestamp int64, oob, replaceId string, isCarbon, isGroupchat, forceSubject, requestReceipt bool, originalFrom string, errorCode int, inviteFrom string) { func sendMessageWrapper(to, from, body, subject, errorText, id string, component *xmpp.Component, reply *Reply, marker *marker, timestamp int64, oob, replaceId string, isCarbon, isGroupchat, forceSubject, requestReceipt bool, originalFrom string, errorCode int, inviteFrom, stanzaId string) {
toJid, err := stanza.NewJid(to) toJid, err := stanza.NewJid(to)
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
@ -158,19 +158,24 @@ func sendMessageWrapper(to, from, body, subject, errorText, id string, component
var logFrom string var logFrom string
var messageFrom string var messageFrom string
var messageTo string var messageTo string
var bareFrom string
if isGroupchat { if isGroupchat {
logFrom = from logFrom = from
messageFrom = from messageFrom = from
bareFrom, _, _ = SplitJID(from)
} else { } else {
if from == "" { if from == "" {
logFrom = componentJid logFrom = componentJid
messageFrom = componentJid messageFrom = componentJid
bareFrom = componentJid
} else if inviteFrom != "" { } else if inviteFrom != "" {
logFrom = from logFrom = from
messageFrom = from + "@" + Jid.Bare() messageFrom = from + "@" + Jid.Bare()
bareFrom = messageFrom
} else { } else {
logFrom = from logFrom = from
messageFrom = from + "@" + componentJid messageFrom = from + "@" + componentJid
bareFrom = from + "@" + Jid.Bare()
} }
} }
if isCarbon { if isCarbon {
@ -254,7 +259,7 @@ func sendMessageWrapper(to, from, body, subject, errorText, id string, component
if timestamp != 0 { if timestamp != 0 {
var delayFrom string var delayFrom string
if isGroupchat { if isGroupchat {
delayFrom, _, _ = SplitJID(from) delayFrom = bareFrom
} }
message.Extensions = append(message.Extensions, extensions.MessageDelay{ message.Extensions = append(message.Extensions, extensions.MessageDelay{
From: delayFrom, From: delayFrom,
@ -301,6 +306,17 @@ func sendMessageWrapper(to, from, body, subject, errorText, id string, component
Jid: messageFrom, Jid: messageFrom,
}) })
} }
if stanzaId != "" {
message.Extensions = append(message.Extensions, extensions.MessageStanzaId{
Id: stanzaId,
By: bareFrom,
})
if stanzaId != id {
message.Extensions = append(message.Extensions, extensions.MessageOriginId{
Id: id,
})
}
}
if isCarbon { if isCarbon {
carbonMessage := extensions.ClientMessage{ carbonMessage := extensions.ClientMessage{

View file

@ -181,7 +181,10 @@ func HandleMessage(s xmpp.Sender, p stanza.Packet) {
} else { } else {
id := reply.Id id := reply.Id
if id[0] == 'e' { if id[0] == 'e' {
id = id[1:] idParts := strings.Split(id[1:], ":")
if len(idParts) >= 1 {
id = idParts[0]
}
} }
replyId, err = strconv.ParseInt(id, 10, 64) replyId, err = strconv.ParseInt(id, 10, 64)
if err != nil { if err != nil {
@ -848,6 +851,7 @@ func handleGetDiscoInfo(s xmpp.Sender, iq *stanza.IQ, di *stanza.DiscoInfo) {
"muc_unsecured", "muc_unsecured",
"http://jabber.org/protocol/muc#stable_id", "http://jabber.org/protocol/muc#stable_id",
"jabber:iq:register", "jabber:iq:register",
"urn:xmpp:sid:0",
) )
fields := []*stanza.Field{ fields := []*stanza.Field{
&stanza.Field{ &stanza.Field{