mirror of
https://dev.narayana.im/narayana/telegabber.git
synced 2026-10-07 16:51:47 +00:00
Implement occupant IDs (XEP-0421) and shorten visible occupant nicknames
This commit is contained in:
parent
4566297817
commit
22cb5b3d4c
7 changed files with 311 additions and 97 deletions
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
|
@ -215,9 +216,17 @@ func (c *Client) updateUser(update *client.UpdateUser) {
|
|||
// check if MUC nicknames should be updated
|
||||
oldCacheUser, ok := c.cache.GetUser(update.User.Id)
|
||||
c.cache.SetUser(update.User.Id, update.User)
|
||||
if ok && (oldCacheUser.FirstName != update.User.FirstName || oldCacheUser.LastName != update.User.LastName) {
|
||||
newNickname := c.GetMUCNickname(update.User.Id)
|
||||
c.updateMUCsNickname(update.User.Id, newNickname)
|
||||
if ok {
|
||||
var oldUsernames, newUsernames []string
|
||||
if oldCacheUser.Usernames != nil {
|
||||
oldUsernames = oldCacheUser.Usernames.ActiveUsernames
|
||||
}
|
||||
if update.User.Usernames != nil {
|
||||
newUsernames = update.User.Usernames.ActiveUsernames
|
||||
}
|
||||
if oldCacheUser.FirstName != update.User.FirstName || oldCacheUser.LastName != update.User.LastName || !slices.Equal(oldUsernames, newUsernames) {
|
||||
c.updateMUCsNickname(update.User.Id)
|
||||
}
|
||||
}
|
||||
|
||||
show, status, presenceType := c.userStatusToText(update.User.Status, update.User.Id)
|
||||
|
|
@ -425,10 +434,11 @@ func (c *Client) updateMessageContent(update *client.UpdateMessageContent) {
|
|||
var from string
|
||||
var originalFrom string
|
||||
var nickname string
|
||||
var senderId int64
|
||||
if isMUC {
|
||||
if messageErr == nil {
|
||||
senderId := c.getMessageSenderId(message)
|
||||
nickname = c.GetMUCNickname(senderId)
|
||||
senderId = c.getMessageSenderId(message)
|
||||
nickname = c.GetMUCNickname(update.ChatId, senderId)
|
||||
originalFrom = gateway.CHATJID(senderId, true)
|
||||
|
||||
safeToSend = c.assureMUCOccupant(update.ChatId, senderId, message.SenderId, chat)
|
||||
|
|
@ -461,7 +471,7 @@ func (c *Client) updateMessageContent(update *client.UpdateMessageContent) {
|
|||
textContent.Text.Text,
|
||||
textContent.Text.Entities,
|
||||
markupFunction,
|
||||
c,
|
||||
mucMentionRetriever{c, update.ChatId},
|
||||
))
|
||||
|
||||
id := "e"+sId
|
||||
|
|
@ -510,10 +520,14 @@ func (c *Client) updateMessageContent(update *client.UpdateMessageContent) {
|
|||
|
||||
for _, jid := range jids {
|
||||
if safeToSend {
|
||||
var occupantId string
|
||||
if isMUC && senderId != 0 {
|
||||
occupantId = gateway.CHATNODE(senderId)
|
||||
}
|
||||
gateway.SendMessage(jid, from, c.xmpp,
|
||||
gateway.SMBody(body), gateway.SMId(id), gateway.SMReplaceId(replaceId),
|
||||
gateway.SMIsCarbon(isCarbon), gateway.SMIsGroupchat(isMUC), gateway.SMOriginalFrom(originalFrom),
|
||||
gateway.SMOMEMOEnvelope(envelope),
|
||||
gateway.SMOMEMOEnvelope(envelope), gateway.SMOccupantId(occupantId),
|
||||
)
|
||||
} else {
|
||||
gateway.SendMUCAnnouncement(jid, from, body, nickname, id, c.xmpp)
|
||||
|
|
@ -713,6 +727,7 @@ func (c *Client) updateChatPermissions(update *client.UpdateChatPermissions) {
|
|||
gateway.SPResource(occupant.Nickname),
|
||||
gateway.SPImmed(true),
|
||||
gateway.SPMUCJid(gateway.CHATJID(occupant.id, true)),
|
||||
gateway.SPOccupantId(gateway.CHATNODE(occupant.id)),
|
||||
gateway.SPMUCAffiliation(affiliation),
|
||||
gateway.SPMUCRole(role),
|
||||
gateway.SPToJids(toJids),
|
||||
|
|
|
|||
|
|
@ -114,8 +114,8 @@ func (lru *MUCOccupantsLRU) Set(id int64, occupant *MUCOccupant) (deleted *MUCOc
|
|||
lru.cutOut(oldOccupant)
|
||||
|
||||
delete(lru.rev, oldOccupant.Nickname)
|
||||
lru.rev[occupant.Nickname] = id
|
||||
}
|
||||
lru.rev[occupant.Nickname] = id
|
||||
|
||||
if (lru.oldest == nil) != (lru.newest == nil) {
|
||||
log.Fatal("MRD MUDAQ")
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ func (c *Client) updateMessageInteractionInfo(update *client.UpdateMessageIntera
|
|||
if jids := c.GetReactionCapableFullJids(); len(jids) > 0 && c.peerReactionsChanged(update.ChatId, update.MessageId, 0, peerEmojis) {
|
||||
from := gateway.CHATNODE(update.ChatId)
|
||||
for _, jid := range jids {
|
||||
gateway.SendReactionMessage(jid, from, c.xmpp, xmppId, peerEmojis, false)
|
||||
gateway.SendReactionMessage(jid, from, c.xmpp, xmppId, peerEmojis)
|
||||
}
|
||||
}
|
||||
return
|
||||
|
|
@ -231,9 +231,9 @@ func (c *Client) updateMessageInteractionInfo(update *client.UpdateMessageIntera
|
|||
if !c.assureMUCOccupant(update.ChatId, senderId, &client.MessageSenderUser{UserId: senderId}, chat) {
|
||||
continue
|
||||
}
|
||||
from := mucJid + "/" + c.GetMUCNickname(senderId)
|
||||
from := mucJid + "/" + c.GetMUCNickname(update.ChatId, senderId)
|
||||
for _, jid := range jids {
|
||||
gateway.SendReactionMessage(jid, from, c.xmpp, xmppId, senderEmojis, true)
|
||||
gateway.SendReactionMessage(jid, from, c.xmpp, xmppId, senderEmojis, gateway.SMIsGroupchat(true), gateway.SMOccupantId(gateway.CHATNODE(senderId)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -245,9 +245,9 @@ func (c *Client) updateMessageInteractionInfo(update *client.UpdateMessageIntera
|
|||
if c.peerReactionsChanged(update.ChatId, update.MessageId, update.ChatId, anonymousEmojis) {
|
||||
anonymousSender := &client.MessageSenderChat{ChatId: update.ChatId}
|
||||
if c.assureMUCOccupant(update.ChatId, update.ChatId, anonymousSender, chat) {
|
||||
from := mucJid + "/" + c.GetMUCNickname(update.ChatId)
|
||||
from := mucJid + "/" + c.GetMUCNickname(update.ChatId, update.ChatId)
|
||||
for _, jid := range jids {
|
||||
gateway.SendReactionMessage(jid, from, c.xmpp, xmppId, anonymousEmojis, true)
|
||||
gateway.SendReactionMessage(jid, from, c.xmpp, xmppId, anonymousEmojis, gateway.SMIsGroupchat(true), gateway.SMOccupantId(gateway.CHATNODE(update.ChatId)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -306,13 +306,21 @@ func (c *Client) SendDelayedMUCReactions(chatId int64, message *client.Message,
|
|||
timestamp := int64(message.Date)
|
||||
|
||||
for senderId, senderEmojis := range perOccupant {
|
||||
from := mucJid + "/" + c.GetMUCNickname(senderId)
|
||||
from := mucJid + "/" + c.GetMUCNickname(chatId, senderId)
|
||||
entryId := "r" + strId + "-" + strconv.FormatInt(senderId, 10)
|
||||
gateway.SendMAMReactionMessage(toJid, from, c.xmpp, xmppId, senderEmojis, entryId, timestamp, mucJid, mamQueryId)
|
||||
gateway.SendReactionMessage(toJid, from, c.xmpp, xmppId, senderEmojis,
|
||||
gateway.SMId(entryId), gateway.SMStanzaId(entryId), gateway.SMTimestamp(timestamp),
|
||||
gateway.SMMamQueryId(mamQueryId), gateway.SMMucJID(mucJid), gateway.SMIsGroupchat(true),
|
||||
gateway.SMOccupantId(gateway.CHATNODE(senderId)),
|
||||
)
|
||||
}
|
||||
if len(anonymousEmojis) > 0 {
|
||||
from := mucJid + "/" + c.GetMUCNickname(chatId)
|
||||
gateway.SendMAMReactionMessage(toJid, from, c.xmpp, xmppId, anonymousEmojis, "r"+strId+"-a", timestamp, mucJid, mamQueryId)
|
||||
from := mucJid + "/" + c.GetMUCNickname(chatId, chatId)
|
||||
gateway.SendReactionMessage(toJid, from, c.xmpp, xmppId, anonymousEmojis,
|
||||
gateway.SMId("r"+strId+"-a"), gateway.SMStanzaId("r"+strId+"-a"), gateway.SMTimestamp(timestamp),
|
||||
gateway.SMMamQueryId(mamQueryId), gateway.SMMucJID(mucJid), gateway.SMIsGroupchat(true),
|
||||
gateway.SMOccupantId(gateway.CHATNODE(chatId)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -431,7 +439,24 @@ func (c *Client) ownReactions(chatId, messageId int64) (map[string]bool, error)
|
|||
MessageId: messageId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// messageId may be a since-superseded provisional id for a message
|
||||
// we ourselves just sent - TDlib assigns a temporary id
|
||||
// immediately and reassigns the real one shortly after via
|
||||
// UpdateMessageSendSucceeded (see updateMessageSendSucceeded's
|
||||
// MessageIdChanges bookkeeping). Retry with the current id if the
|
||||
// reassignment has already landed.
|
||||
c.MessageIdChangesLock.Lock()
|
||||
newId, newIdOk := c.MessageIdChanges[chatId][messageId]
|
||||
c.MessageIdChangesLock.Unlock()
|
||||
if newIdOk && newId.Id != 0 {
|
||||
message, err = c.client.GetMessage(&client.GetMessageRequest{
|
||||
ChatId: chatId,
|
||||
MessageId: newId.Id,
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
current := make(map[string]bool)
|
||||
|
|
|
|||
|
|
@ -596,6 +596,7 @@ func (c *Client) ProcessStatusUpdate(chatID int64, status string, show string, o
|
|||
gateway.SPMUCAffiliation(occupant.Affiliation),
|
||||
gateway.SPMUCRole(occupant.Role),
|
||||
gateway.SPMUCJid(chatJid),
|
||||
gateway.SPOccupantId(gateway.CHATNODE(chatID)),
|
||||
gateway.SPToJids(toJids),
|
||||
)
|
||||
err := c.sendPresence(newMucArgs...)
|
||||
|
|
@ -723,10 +724,11 @@ func (c *Client) sendMUCStatuses(chatID int64) {
|
|||
func (c *Client) updateMUCOccupants(mucState *MUCState, chatID int64, members []*client.ChatMember) {
|
||||
sChatId := gateway.MUCNODE(chatID)
|
||||
myNickname := "me"
|
||||
var myJid string
|
||||
var myJid, myOccupantId string
|
||||
if c.me != nil {
|
||||
myNickname = c.GetMUCNickname(c.me.Id)
|
||||
myNickname = c.getMUCNicknameLocked(c.me.Id, mucState)
|
||||
myJid = gateway.CHATJID(c.me.Id, true)
|
||||
myOccupantId = gateway.CHATNODE(c.me.Id)
|
||||
}
|
||||
myAffiliation := "member"
|
||||
myRole := "participant"
|
||||
|
|
@ -736,7 +738,7 @@ func (c *Client) updateMUCOccupants(mucState *MUCState, chatID int64, members []
|
|||
_, toJids := c.getMUCJoinedJIDs(chatID, mucState, false)
|
||||
|
||||
for _, member := range members {
|
||||
senderId, nickname, affiliation, role := c.TgMemberToMUCOccupant(member, chat)
|
||||
senderId, nickname, affiliation, role := c.tgMemberToMUCOccupantLocked(member, chat, mucState)
|
||||
mucState.Occupants.Set(senderId, &MUCOccupant{
|
||||
Nickname: nickname,
|
||||
Affiliation: affiliation,
|
||||
|
|
@ -758,6 +760,7 @@ func (c *Client) updateMUCOccupants(mucState *MUCState, chatID int64, members []
|
|||
gateway.SPMUCAffiliation(affiliation),
|
||||
gateway.SPMUCRole(role),
|
||||
gateway.SPMUCJid(gateway.CHATJID(senderId, true)),
|
||||
gateway.SPOccupantId(gateway.CHATNODE(senderId)),
|
||||
gateway.SPToJids(toJids),
|
||||
)
|
||||
}
|
||||
|
|
@ -774,6 +777,7 @@ func (c *Client) updateMUCOccupants(mucState *MUCState, chatID int64, members []
|
|||
gateway.SPMUCAffiliation(myAffiliation),
|
||||
gateway.SPMUCRole(myRole),
|
||||
gateway.SPMUCJid(myJid),
|
||||
gateway.SPOccupantId(myOccupantId),
|
||||
gateway.SPMUCStatusCodes(selfStatusCodes),
|
||||
gateway.SPToJids(toJids),
|
||||
)
|
||||
|
|
@ -819,7 +823,7 @@ func (c *Client) addMUCOccupant(mucID int64, memberID int64, affiliation, role s
|
|||
return false
|
||||
}
|
||||
|
||||
nickname := c.GetMUCNickname(memberID)
|
||||
nickname := c.getMUCNicknameLocked(memberID, mucState)
|
||||
|
||||
_, toJids := c.getMUCJoinedJIDs(mucID, mucState, false)
|
||||
|
||||
|
|
@ -830,6 +834,7 @@ func (c *Client) addMUCOccupant(mucID int64, memberID int64, affiliation, role s
|
|||
gateway.SPMUCAffiliation(affiliation),
|
||||
gateway.SPMUCRole(role),
|
||||
gateway.SPMUCJid(gateway.CHATJID(memberID, true)),
|
||||
gateway.SPOccupantId(gateway.CHATNODE(memberID)),
|
||||
gateway.SPToJids(toJids),
|
||||
)
|
||||
|
||||
|
|
@ -857,7 +862,7 @@ func (c *Client) sendMUCSubject(chatID int64, resource string) {
|
|||
if err == nil {
|
||||
gateway.SendSubjectMessage(
|
||||
toJid,
|
||||
mucJid + "/" + c.GetMUCNickname(c.getMessageSenderId(pin)),
|
||||
mucJid + "/" + c.GetMUCNickname(chatID, c.getMessageSenderId(pin)),
|
||||
c.messageToText(pin, false),
|
||||
strconv.FormatInt(pin.Id, 10),
|
||||
c.xmpp,
|
||||
|
|
@ -868,8 +873,37 @@ func (c *Client) sendMUCSubject(chatID int64, resource string) {
|
|||
}
|
||||
}
|
||||
|
||||
// GetMUCNickname generates a unique nickname for a MUC occupant
|
||||
func (c *Client) GetMUCNickname(chatID int64) string {
|
||||
// MyId returns the bridged Telegram account's own user id, or 0 if the
|
||||
// account info isn't loaded yet.
|
||||
func (c *Client) MyId() int64 {
|
||||
if c.me == nil {
|
||||
return 0
|
||||
}
|
||||
return c.me.Id
|
||||
}
|
||||
|
||||
// resourcePrepBMP runs XMPP resourceprep and additionally rejects non-BMP
|
||||
// characters, returning ok=false if either check fails.
|
||||
func resourcePrepBMP(s string) (string, bool) {
|
||||
rp, err := gateway.ResourcePrep(s)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
for _, r := range rp {
|
||||
if r > bmpCeil {
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
return rp, true
|
||||
}
|
||||
|
||||
// buildMUCNickname formats chatID (a Telegram user or chat id) for display
|
||||
// as a MUC nickname. Normally a username-less user's nickname is always
|
||||
// disambiguated with a trailing "(id)" so nicknames can never collide.
|
||||
// When collides is non-nil (see GetMUCNickname), that disambiguator is
|
||||
// dropped in favor of the bare name, unless collides reports that the
|
||||
// bare name is already claimed by a different member.
|
||||
func (c *Client) buildMUCNickname(chatID int64, collides func(name string) bool) string {
|
||||
if chatID == 0 {
|
||||
if c.me != nil {
|
||||
chatID = c.me.Id
|
||||
|
|
@ -877,22 +911,49 @@ func (c *Client) GetMUCNickname(chatID int64) string {
|
|||
return "me"
|
||||
}
|
||||
}
|
||||
fc := c.FormatContact(chatID)
|
||||
rp, err := gateway.ResourcePrep(fc)
|
||||
if err == nil {
|
||||
// additionally check for non-BMP characters
|
||||
for _, r := range rp {
|
||||
if r > bmpCeil {
|
||||
err = errors.New("Non-BMP character")
|
||||
break
|
||||
|
||||
chat, user, err := c.GetContactByID(chatID, nil, false)
|
||||
var fc string
|
||||
switch {
|
||||
case err != nil:
|
||||
fc = "unknown contact: " + err.Error()
|
||||
// user must be checked before chat: GetContactByID resolves a non-nil
|
||||
// chat (the private-chat wrapper) for any positive user id too, not
|
||||
// just actual groups - checking chat first would always shadow user.
|
||||
case user != nil:
|
||||
var usernames string
|
||||
if user.Usernames != nil {
|
||||
usernames = c.usernamesToString(user.Usernames.ActiveUsernames)
|
||||
}
|
||||
name := spaceRegex.ReplaceAllString(fmt.Sprintf("%s %s", user.FirstName, user.LastName), " ")
|
||||
if collides != nil && usernames == "" {
|
||||
if rp, ok := resourcePrepBMP(name); ok && !collides(rp) {
|
||||
return rp
|
||||
}
|
||||
}
|
||||
idOrUsername := usernames
|
||||
if idOrUsername == "" {
|
||||
idOrUsername = strconv.FormatInt(chatID, 10)
|
||||
}
|
||||
fc = fmt.Sprintf("%s (%v)", name, idOrUsername)
|
||||
case chat != nil:
|
||||
title := spaceRegex.ReplaceAllString(chat.Title, " ")
|
||||
if collides != nil {
|
||||
if rp, ok := resourcePrepBMP(title); ok && !collides(rp) {
|
||||
return rp
|
||||
}
|
||||
}
|
||||
fc = fmt.Sprintf("%s (%v)", chat.Title, chat.Id)
|
||||
default:
|
||||
fc = strconv.FormatInt(chatID, 10)
|
||||
}
|
||||
if err != nil {
|
||||
fc = spaceRegex.ReplaceAllString(fc, " ")
|
||||
|
||||
rp, ok := resourcePrepBMP(fc)
|
||||
if !ok {
|
||||
log.Warnf("Resourceprep for %v failed, falling back to chat ID", fc)
|
||||
|
||||
var usernames string
|
||||
_, user, _ := c.GetContactByID(chatID, nil, false)
|
||||
if user != nil && user.Usernames != nil {
|
||||
usernames = c.usernamesToString(user.Usernames.ActiveUsernames)
|
||||
}
|
||||
|
|
@ -911,7 +972,45 @@ func (c *Client) GetMUCNickname(chatID int64) string {
|
|||
return rp
|
||||
}
|
||||
|
||||
func (c *Client) updateMUCsNickname(memberID int64, newNickname string) {
|
||||
// getMUCNicknameLocked computes the nickname to register for memberId as
|
||||
// an occupant of mucState's room, dropping the "(id)" disambiguator
|
||||
// unless the bare name is already taken by someone else. mucState may be
|
||||
// nil (no room context, e.g. a PM), in which case this degrades to the
|
||||
// plain always-disambiguated buildMUCNickname formatting.
|
||||
// achtung: assuming a locked mucState context
|
||||
func (c *Client) getMUCNicknameLocked(memberId int64, mucState *MUCState) string {
|
||||
// buildMUCNickname resolves a 0 memberId to c.me.Id internally (the
|
||||
// "self" convention GetMUCNickname(chatId, 0) also relies on) - the
|
||||
// collision check below needs that same resolved id, or self's own
|
||||
// registered nickname would look like a collision with someone else's
|
||||
// id 0.
|
||||
resolvedId := memberId
|
||||
if resolvedId == 0 && c.me != nil {
|
||||
resolvedId = c.me.Id
|
||||
}
|
||||
|
||||
var collides func(string) bool
|
||||
if mucState != nil {
|
||||
collides = func(name string) bool {
|
||||
id, ok := mucState.Occupants.GetIdByNickname(name)
|
||||
return ok && id != resolvedId
|
||||
}
|
||||
}
|
||||
return c.buildMUCNickname(memberId, collides)
|
||||
}
|
||||
|
||||
// GetMUCNickname is getMUCNicknameLocked for callers that don't already
|
||||
// hold c.locks.mucCacheLock. chatId 0 (no room context) falls back to the
|
||||
// plain always-disambiguated nickname.
|
||||
func (c *Client) GetMUCNickname(chatId, memberId int64) string {
|
||||
c.locks.mucCacheLock.Lock()
|
||||
mucState := c.mucCache[chatId]
|
||||
nickname := c.getMUCNicknameLocked(memberId, mucState)
|
||||
c.locks.mucCacheLock.Unlock()
|
||||
return nickname
|
||||
}
|
||||
|
||||
func (c *Client) updateMUCsNickname(memberID int64) {
|
||||
c.locks.mucCacheLock.Lock()
|
||||
defer c.locks.mucCacheLock.Unlock()
|
||||
|
||||
|
|
@ -919,6 +1018,11 @@ func (c *Client) updateMUCsNickname(memberID int64, newNickname string) {
|
|||
for mucId, state := range c.mucCache {
|
||||
oldOccupant, ok := state.Occupants.Get(memberID)
|
||||
if ok {
|
||||
newNickname := c.getMUCNicknameLocked(memberID, state)
|
||||
if newNickname == oldOccupant.Nickname {
|
||||
continue
|
||||
}
|
||||
|
||||
c.DelayedStatusesLock.Lock()
|
||||
delete(c.DelayedStatuses, mucId)
|
||||
c.DelayedStatusesLock.Unlock()
|
||||
|
|
@ -949,6 +1053,7 @@ func (c *Client) updateMUCsNickname(memberID int64, newNickname string) {
|
|||
gateway.SPMUCNick(newNickname),
|
||||
gateway.SPMUCStatusCodes(unavailableStatusCodes),
|
||||
gateway.SPMUCJid(realJid),
|
||||
gateway.SPOccupantId(gateway.CHATNODE(memberID)),
|
||||
gateway.SPToJids(toJids),
|
||||
)
|
||||
c.sendPresence(
|
||||
|
|
@ -959,6 +1064,7 @@ func (c *Client) updateMUCsNickname(memberID int64, newNickname string) {
|
|||
gateway.SPMUCRole(oldOccupant.Role),
|
||||
gateway.SPMUCStatusCodes(availableStatusCodes),
|
||||
gateway.SPMUCJid(realJid),
|
||||
gateway.SPOccupantId(gateway.CHATNODE(memberID)),
|
||||
gateway.SPToJids(toJids),
|
||||
)
|
||||
}
|
||||
|
|
@ -1157,7 +1263,7 @@ func (c *Client) getMessageReply(message *client.Message, preview bool, noConten
|
|||
replyTo.Quote.Text.Text,
|
||||
replyTo.Quote.Text.Entities,
|
||||
c.getFormatter(),
|
||||
c,
|
||||
mucMentionRetriever{c, replyTo.ChatId},
|
||||
)
|
||||
// make the whole quote fit one line
|
||||
text = strings.ReplaceAll(text, "\n", " ")
|
||||
|
|
@ -1187,10 +1293,11 @@ func (c *Client) getMessageReply(message *client.Message, preview bool, noConten
|
|||
Id: replyId,
|
||||
}
|
||||
} else if !noContent {
|
||||
// it's safe to assume there's no need to pass ChatId here
|
||||
// as it's needed only for pin messages which are not allowed in replies
|
||||
// replyTo.ChatId, not message.ChatId: this quotes a message
|
||||
// from another chat, and its mentions should resolve against
|
||||
// that chat's own occupants, not the replying message's.
|
||||
if text == "" && replyTo.Content != nil {
|
||||
text = c.messageContentToText(replyTo.Content, 0, preview)
|
||||
text = c.messageContentToText(replyTo.Content, replyTo.ChatId, preview)
|
||||
}
|
||||
|
||||
if text == "" {
|
||||
|
|
@ -1544,7 +1651,7 @@ func (c *Client) messageContentToText(content client.MessageContent, chatId int6
|
|||
photo.Caption.Text,
|
||||
photo.Caption.Entities,
|
||||
markupMode,
|
||||
c,
|
||||
mucMentionRetriever{c, chatId},
|
||||
)
|
||||
}
|
||||
case client.TypeMessageAudio:
|
||||
|
|
@ -1556,7 +1663,7 @@ func (c *Client) messageContentToText(content client.MessageContent, chatId int6
|
|||
audio.Caption.Text,
|
||||
audio.Caption.Entities,
|
||||
markupMode,
|
||||
c,
|
||||
mucMentionRetriever{c, chatId},
|
||||
)
|
||||
}
|
||||
case client.TypeMessageVideo:
|
||||
|
|
@ -1568,7 +1675,7 @@ func (c *Client) messageContentToText(content client.MessageContent, chatId int6
|
|||
video.Caption.Text,
|
||||
video.Caption.Entities,
|
||||
markupMode,
|
||||
c,
|
||||
mucMentionRetriever{c, chatId},
|
||||
)
|
||||
}
|
||||
case client.TypeMessageDocument:
|
||||
|
|
@ -1580,7 +1687,7 @@ func (c *Client) messageContentToText(content client.MessageContent, chatId int6
|
|||
document.Caption.Text,
|
||||
document.Caption.Entities,
|
||||
markupMode,
|
||||
c,
|
||||
mucMentionRetriever{c, chatId},
|
||||
)
|
||||
}
|
||||
case client.TypeMessageText:
|
||||
|
|
@ -1592,7 +1699,7 @@ func (c *Client) messageContentToText(content client.MessageContent, chatId int6
|
|||
text.Text.Text,
|
||||
text.Text.Entities,
|
||||
markupMode,
|
||||
c,
|
||||
mucMentionRetriever{c, chatId},
|
||||
)
|
||||
}
|
||||
case client.TypeMessageVoiceNote:
|
||||
|
|
@ -1604,7 +1711,7 @@ func (c *Client) messageContentToText(content client.MessageContent, chatId int6
|
|||
voice.Caption.Text,
|
||||
voice.Caption.Entities,
|
||||
markupMode,
|
||||
c,
|
||||
mucMentionRetriever{c, chatId},
|
||||
)
|
||||
}
|
||||
case client.TypeMessageVideoNote:
|
||||
|
|
@ -1618,7 +1725,7 @@ func (c *Client) messageContentToText(content client.MessageContent, chatId int6
|
|||
animation.Caption.Text,
|
||||
animation.Caption.Entities,
|
||||
markupMode,
|
||||
c,
|
||||
mucMentionRetriever{c, chatId},
|
||||
)
|
||||
}
|
||||
case client.TypeMessageContact:
|
||||
|
|
@ -1909,7 +2016,7 @@ func (c *Client) ProcessIncomingMessage(chatId int64, message *client.Message) {
|
|||
|
||||
switch message.Content.MessageContentType() {
|
||||
case client.TypeMessageChatJoinByLink:
|
||||
c.mucOccupantRolePresence(chatId, senderId, ChatMemberStatusUnmuted, c.GetMUCNickname(senderId))
|
||||
c.mucOccupantRolePresence(chatId, senderId, ChatMemberStatusUnmuted, c.GetMUCNickname(chatId, senderId))
|
||||
case client.TypeMessageChatAddMembers:
|
||||
addMembers, _ := message.Content.(*client.MessageChatAddMembers)
|
||||
for _, memberId := range addMembers.MemberUserIds {
|
||||
|
|
@ -1918,11 +2025,11 @@ func (c *Client) ProcessIncomingMessage(chatId int64, message *client.Message) {
|
|||
gateway.InviteToMUC(chatId, jid, c.xmpp)
|
||||
}
|
||||
}
|
||||
c.mucOccupantRolePresence(chatId, memberId, ChatMemberStatusUnmuted, c.GetMUCNickname(memberId))
|
||||
c.mucOccupantRolePresence(chatId, memberId, ChatMemberStatusUnmuted, c.GetMUCNickname(chatId, memberId))
|
||||
}
|
||||
case client.TypeMessageChatDeleteMember:
|
||||
deleteMember, _ := message.Content.(*client.MessageChatDeleteMember)
|
||||
c.mucOccupantRolePresence(chatId, deleteMember.UserId, ChatMemberStatusKicked, c.GetMUCNickname(deleteMember.UserId))
|
||||
c.mucOccupantRolePresence(chatId, deleteMember.UserId, ChatMemberStatusKicked, c.GetMUCNickname(chatId, deleteMember.UserId))
|
||||
case client.TypeMessageBasicGroupChatCreate, client.TypeMessageSupergroupChatCreate, client.TypeMessageChatUpgradeTo:
|
||||
inviteChatId := chatId
|
||||
if message.Content.MessageContentType() == client.TypeMessageChatUpgradeTo {
|
||||
|
|
@ -1938,7 +2045,7 @@ func (c *Client) ProcessIncomingMessage(chatId int64, message *client.Message) {
|
|||
|
||||
safeToSend = c.assureMUCOccupant(chatId, senderId, message.SenderId, chat)
|
||||
|
||||
groupChatFrom = gateway.MUCJID(chatId) + "/" + c.GetMUCNickname(senderId)
|
||||
groupChatFrom = gateway.MUCJID(chatId) + "/" + c.GetMUCNickname(chatId, senderId)
|
||||
var ok bool
|
||||
ok, groupChatTos = c.getMUCJoinedJIDs(chatId, nil, true)
|
||||
if !ok {
|
||||
|
|
@ -1960,6 +2067,7 @@ func (c *Client) SendMessageToGateway(chatId int64, message *client.Message, id
|
|||
var jids []string
|
||||
var isGroupchat bool
|
||||
var originalFrom string
|
||||
senderId := c.getMessageSenderId(message)
|
||||
if len(groupChatTos) == 0 {
|
||||
isCarbon = c.isCarbonsEnabled() && message.IsOutgoing
|
||||
jids = c.GetCarbonFullJids(isCarbon, "", true)
|
||||
|
|
@ -1967,7 +2075,6 @@ func (c *Client) SendMessageToGateway(chatId int64, message *client.Message, id
|
|||
isGroupchat = true
|
||||
jids = groupChatTos
|
||||
|
||||
senderId := c.getMessageSenderId(message)
|
||||
if senderId != 0 {
|
||||
originalFrom = gateway.CHATJID(senderId, true)
|
||||
}
|
||||
|
|
@ -2189,12 +2296,18 @@ func (c *Client) SendMessageToGateway(chatId int64, message *client.Message, id
|
|||
}
|
||||
}
|
||||
|
||||
var occupantId string
|
||||
if isGroupchat && senderId != 0 {
|
||||
occupantId = gateway.CHATNODE(senderId)
|
||||
}
|
||||
|
||||
for _, jid := range jids {
|
||||
commonArgs := []args.V{
|
||||
gateway.SMReply(reply), gateway.SMTimestamp(timestamp), gateway.SMIsCarbon(isCarbon),
|
||||
gateway.SMIsGroupchat(isGroupchat), gateway.SMRequestReceipt(c.Session.Receipts),
|
||||
gateway.SMOriginalFrom(originalFrom), gateway.SMMamQueryId(mamQueryId),
|
||||
gateway.SMMucJID(mucJID), gateway.SMMucUserItem(mucUserItem),
|
||||
gateway.SMOccupantId(occupantId),
|
||||
}
|
||||
if omemoFailed {
|
||||
gateway.SendMessage(jid, from, c.xmpp, append(commonArgs,
|
||||
|
|
@ -2237,7 +2350,7 @@ func (c *Client) SendDelayedMUCMessage(chatId int64, message *client.Message, to
|
|||
message,
|
||||
msgId,
|
||||
true,
|
||||
gateway.MUCJID(chatId) + "/" + c.GetMUCNickname(c.getMessageSenderId(message)),
|
||||
gateway.MUCJID(chatId) + "/" + c.GetMUCNickname(chatId, c.getMessageSenderId(message)),
|
||||
[]string{toJid},
|
||||
mamQueryId,
|
||||
)
|
||||
|
|
@ -2868,7 +2981,7 @@ func (c *Client) GetChatDescription(chat *client.Chat) string {
|
|||
fullInfo.Bio.Text,
|
||||
fullInfo.Bio.Entities,
|
||||
c.getFormatter(),
|
||||
c,
|
||||
mucMentionRetriever{c, 0},
|
||||
)
|
||||
} else if fullInfo.BotInfo != nil {
|
||||
if fullInfo.BotInfo.ShortDescription != "" {
|
||||
|
|
@ -3266,8 +3379,21 @@ func (c *Client) memberStatusToAffiliationAndRole(memberStatus client.ChatMember
|
|||
|
||||
// TgMemberToMUCMember resolves useful data to generate a MUC occupant
|
||||
func (c *Client) TgMemberToMUCOccupant(member *client.ChatMember, chat *client.Chat) (senderId int64, nickname, affiliation, role string) {
|
||||
var mucState *MUCState
|
||||
if chat != nil {
|
||||
c.locks.mucCacheLock.Lock()
|
||||
mucState = c.mucCache[chat.Id]
|
||||
defer c.locks.mucCacheLock.Unlock()
|
||||
}
|
||||
return c.tgMemberToMUCOccupantLocked(member, chat, mucState)
|
||||
}
|
||||
|
||||
// tgMemberToMUCOccupantLocked is TgMemberToMUCOccupant for callers that
|
||||
// already hold c.locks.mucCacheLock (mirrors updateMUCOccupants' locking
|
||||
// convention).
|
||||
func (c *Client) tgMemberToMUCOccupantLocked(member *client.ChatMember, chat *client.Chat, mucState *MUCState) (senderId int64, nickname, affiliation, role string) {
|
||||
senderId = c.GetSenderId(member.MemberId)
|
||||
nickname = c.GetMUCNickname(senderId)
|
||||
nickname = c.getMUCNicknameLocked(senderId, mucState)
|
||||
affiliation, role = c.memberStatusToAffiliationAndRole(member.Status, chat)
|
||||
return
|
||||
}
|
||||
|
|
@ -3299,12 +3425,14 @@ func (c *Client) sendMessagesReverse(chatID int64, messages []*client.Message, p
|
|||
|
||||
var originalFrom string
|
||||
var from string
|
||||
var occupantId string
|
||||
if isMUC {
|
||||
senderId := c.getMessageSenderId(message)
|
||||
if senderId != 0 {
|
||||
originalFrom = gateway.CHATJID(senderId, true)
|
||||
occupantId = gateway.CHATNODE(senderId)
|
||||
}
|
||||
from = mucJid + "/" + c.GetMUCNickname(senderId)
|
||||
from = mucJid + "/" + c.GetMUCNickname(chatID, senderId)
|
||||
} else {
|
||||
from = sChatId
|
||||
}
|
||||
|
|
@ -3349,7 +3477,7 @@ func (c *Client) sendMessagesReverse(chatID int64, messages []*client.Message, p
|
|||
gateway.SendMessage(to, from, c.xmpp,
|
||||
gateway.SMBody(body), gateway.SMId(sId),
|
||||
gateway.SMReply(reply), gateway.SMIsGroupchat(isMUC), gateway.SMOriginalFrom(originalFrom),
|
||||
gateway.SMOMEMOEnvelope(envelope),
|
||||
gateway.SMOMEMOEnvelope(envelope), gateway.SMOccupantId(occupantId),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
|
@ -3518,17 +3646,19 @@ func (c *Client) leaveChat(chatID int64) error {
|
|||
|
||||
// achtung: assuming a locked mucState context
|
||||
func (c *Client) kickMeFromMUC(chatID int64, statusCodes []uint16, destroy bool, mucState *MUCState) error {
|
||||
var myJid string
|
||||
var myJid, myOccupantId string
|
||||
if c.me != nil {
|
||||
myJid = gateway.CHATJID(c.me.Id, true)
|
||||
myOccupantId = gateway.CHATNODE(c.me.Id)
|
||||
}
|
||||
_, toJids := c.getMUCJoinedJIDs(chatID, mucState, mucState == nil)
|
||||
args := []args.V{
|
||||
gateway.SPFrom(gateway.MUCNODE(chatID)),
|
||||
gateway.SPResource(c.GetMUCNickname(0)),
|
||||
gateway.SPResource(c.getMUCNicknameLocked(0, mucState)),
|
||||
gateway.SPMUCAffiliation("none"),
|
||||
gateway.SPMUCRole("none"),
|
||||
gateway.SPMUCJid(myJid),
|
||||
gateway.SPOccupantId(myOccupantId),
|
||||
gateway.SPMUCStatusCodes(statusCodes),
|
||||
gateway.SPToJids(toJids),
|
||||
}
|
||||
|
|
@ -3562,6 +3692,7 @@ func (c *Client) kickStaleOccupant(chatID int64, deleted *MUCOccupant, mucState
|
|||
gateway.SPMUCAffiliation(deleted.Affiliation),
|
||||
gateway.SPMUCRole(deleted.Role),
|
||||
gateway.SPMUCStatusCodes([]uint16{307, 333}),
|
||||
gateway.SPOccupantId(gateway.CHATNODE(deleted.id)),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -3719,6 +3850,7 @@ func (c *Client) mucOccupantRolePresence(chatID, userID int64, status ChatMember
|
|||
gateway.SPResource(nickname),
|
||||
gateway.SPImmed(true),
|
||||
gateway.SPMUCJid(gateway.CHATJID(userID, true)),
|
||||
gateway.SPOccupantId(gateway.CHATNODE(userID)),
|
||||
gateway.SPToJids(toJids),
|
||||
}
|
||||
|
||||
|
|
@ -3827,16 +3959,29 @@ func (c *Client) getChatMemberStatus(status client.ChatMemberStatus) ChatMemberS
|
|||
return ChatMemberStatusIllegal
|
||||
}
|
||||
|
||||
// GetMUCNicknameByUsername implement the MentionRetriever interface for message formatters
|
||||
func (c *Client) GetMUCNicknameByUsername(username string) (string, error) {
|
||||
chat, err := c.client.SearchPublicChat(&client.SearchPublicChatRequest{
|
||||
// mucMentionRetriever implements formatter.MentionRetriever bound to a
|
||||
// single chat, so an @mention inside one of that chat's messages renders
|
||||
// with the same nickname shown in its occupant list (see GetMUCNickname).
|
||||
// chatId 0 (no particular room in scope) falls back to the plain
|
||||
// always-disambiguated nickname.
|
||||
type mucMentionRetriever struct {
|
||||
c *Client
|
||||
chatId int64
|
||||
}
|
||||
|
||||
func (m mucMentionRetriever) GetMUCNickname(id int64) string {
|
||||
return m.c.GetMUCNickname(m.chatId, id)
|
||||
}
|
||||
|
||||
func (m mucMentionRetriever) GetMUCNicknameByUsername(username string) (string, error) {
|
||||
chat, err := m.c.client.SearchPublicChat(&client.SearchPublicChatRequest{
|
||||
Username: username,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return c.GetMUCNickname(chat.Id), nil
|
||||
return m.c.GetMUCNickname(m.chatId, chat.Id), nil
|
||||
}
|
||||
|
||||
// FindMessageByTime retrieves the closest message before the given timestamp
|
||||
|
|
|
|||
|
|
@ -333,6 +333,12 @@ type MessageOriginId struct {
|
|||
Id string `xml:"id,attr"`
|
||||
}
|
||||
|
||||
// OccupantId is from XEP-0421, carried on both MUC messages and presence
|
||||
type OccupantId struct {
|
||||
XMLName xml.Name `xml:"urn:xmpp:occupant-id:0 occupant-id"`
|
||||
Id string `xml:"id,attr"`
|
||||
}
|
||||
|
||||
// EmptySubject is a dummy for MUCs to circumvent omitempty. Not registered as it would conflict with Subject field
|
||||
type EmptySubject struct {
|
||||
XMLName xml.Name `xml:"subject"`
|
||||
|
|
@ -889,6 +895,18 @@ func init() {
|
|||
"origin-id",
|
||||
}, MessageOriginId{})
|
||||
|
||||
// occupant id (message)
|
||||
stanza.TypeRegistry.MapExtension(stanza.PKTMessage, xml.Name{
|
||||
"urn:xmpp:occupant-id:0",
|
||||
"occupant-id",
|
||||
}, OccupantId{})
|
||||
|
||||
// occupant id (presence)
|
||||
stanza.TypeRegistry.MapExtension(stanza.PKTPresence, xml.Name{
|
||||
"urn:xmpp:occupant-id:0",
|
||||
"occupant-id",
|
||||
}, OccupantId{})
|
||||
|
||||
// muc admin query
|
||||
stanza.TypeRegistry.MapExtension(stanza.PKTIQ, xml.Name{
|
||||
"http://jabber.org/protocol/muc#admin",
|
||||
|
|
|
|||
|
|
@ -72,6 +72,9 @@ const NSCaps string = "http://jabber.org/protocol/caps"
|
|||
// NSReactions is the XEP-0444 message reactions namespace
|
||||
const NSReactions string = "urn:xmpp:reactions:0"
|
||||
|
||||
// NSOccupantId is the XEP-0421 occupant id namespace
|
||||
const NSOccupantId string = "urn:xmpp:occupant-id:0"
|
||||
|
||||
// CapsNode is this software's advertised XEP-0115 node URI
|
||||
const CapsNode string = "https://dev.narayana.im/narayana/telegabber/"
|
||||
|
||||
|
|
@ -281,28 +284,11 @@ func SendMessageMarker(to string, from string, component *xmpp.Component, marker
|
|||
|
||||
// SendReactionMessage creates and sends a message stanza with a XEP-0444
|
||||
// reaction set (see Reactions); an empty reactionEmojis clears id's reactions.
|
||||
func SendReactionMessage(to string, from string, component *xmpp.Component, id string, reactionEmojis []string, isGroupchat bool) {
|
||||
sendMessageWrapper(to, from, component, SMReactions(&Reactions{
|
||||
func SendReactionMessage(to string, from string, component *xmpp.Component, id string, reactionEmojis []string, args ...args.V) {
|
||||
sendMessageWrapper(to, from, component, append(args, SMReactions(&Reactions{
|
||||
Id: id,
|
||||
Reactions: reactionEmojis,
|
||||
}), SMIsGroupchat(isGroupchat))
|
||||
}
|
||||
|
||||
// SendMAMReactionMessage is SendReactionMessage wrapped as a XEP-0313 MAM
|
||||
// result: entryId is this result's own id (distinct from id, the
|
||||
// reacted-to message's own id); timestamp stands in for a historical
|
||||
// reaction timestamp, which doesn't exist (only a reaction's current
|
||||
// state, not when it was added).
|
||||
func SendMAMReactionMessage(to string, from string, component *xmpp.Component, id string, reactionEmojis []string, entryId string, timestamp int64, mucJID string, mamQueryId string) {
|
||||
sendMessageWrapper(to, from, component,
|
||||
SMReactions(&Reactions{Id: id, Reactions: reactionEmojis}),
|
||||
SMId(entryId),
|
||||
SMStanzaId(entryId),
|
||||
SMTimestamp(timestamp),
|
||||
SMMamQueryId(mamQueryId),
|
||||
SMMucJID(mucJID),
|
||||
SMIsGroupchat(true),
|
||||
)
|
||||
}))...)
|
||||
}
|
||||
|
||||
// SendMUCInvite creates and send a MUC invitation message
|
||||
|
|
@ -366,6 +352,9 @@ var SMInviteFrom = args.NewString()
|
|||
// SMStanzaId is a XEP-0359 stanza id
|
||||
var SMStanzaId = args.NewString()
|
||||
|
||||
// SMOccupantId is a XEP-0421 occupant id (a stable identifier for a MUC occupant)
|
||||
var SMOccupantId = args.NewString()
|
||||
|
||||
// SMStatusCode is a XEP-0045 muc#user status code
|
||||
var SMStatusCode = args.NewInt64()
|
||||
|
||||
|
|
@ -404,6 +393,7 @@ func sendMessageWrapper(to, from string, component *xmpp.Component, args ...args
|
|||
errorCode := SMErrorCode.Get(args)
|
||||
inviteFrom := SMInviteFrom.Get(args)
|
||||
stanzaId := SMStanzaId.Get(args)
|
||||
occupantId := SMOccupantId.Get(args)
|
||||
statusCode := SMStatusCode.Get(args)
|
||||
mamQueryId := SMMamQueryId.Get(args)
|
||||
mucJID := SMMucJID.Get(args)
|
||||
|
|
@ -619,6 +609,11 @@ func sendMessageWrapper(to, from string, component *xmpp.Component, args ...args
|
|||
})
|
||||
}
|
||||
}
|
||||
if occupantId != "" {
|
||||
message.Extensions = append(message.Extensions, extensions.OccupantId{
|
||||
Id: occupantId,
|
||||
})
|
||||
}
|
||||
|
||||
if isCarbon {
|
||||
carbonMessage := extensions.ClientMessage{
|
||||
|
|
@ -807,6 +802,9 @@ var SPMUCNick = args.NewString()
|
|||
// SPMUCJid is a real jid of a MUC member
|
||||
var SPMUCJid = args.NewString()
|
||||
|
||||
// SPOccupantId is a XEP-0421 occupant id (a stable identifier for a MUC occupant)
|
||||
var SPOccupantId = args.NewString()
|
||||
|
||||
// SPMUCStatusCodes is a set of XEP-0045 MUC status codes
|
||||
var SPMUCStatusCodes = args.New()
|
||||
|
||||
|
|
@ -883,6 +881,14 @@ func newPresence(bareJid string, to string, args ...args.V) stanza.Presence {
|
|||
})
|
||||
}
|
||||
}
|
||||
if SPOccupantId.IsSet(args) {
|
||||
occupantId := SPOccupantId.Get(args)
|
||||
if occupantId != "" {
|
||||
presence.Extensions = append(presence.Extensions, extensions.OccupantId{
|
||||
Id: occupantId,
|
||||
})
|
||||
}
|
||||
}
|
||||
if SPMUCAffiliation.IsSet(args) {
|
||||
affiliation := SPMUCAffiliation.Get(args)
|
||||
if affiliation != "" {
|
||||
|
|
|
|||
|
|
@ -298,13 +298,17 @@ func HandleMessage(s xmpp.Sender, p stanza.Packet) {
|
|||
var replyId int64
|
||||
text := msg.Body
|
||||
|
||||
// OMEMO decrypt hook - personal-chat pseudo-JIDs only (true
|
||||
// MUC/XEP-0045 groupchat OMEMO is out of scope entirely, not
|
||||
// deferred - see the plan doc). A successful decrypt is itself
|
||||
// the auto-upgrade signal for this chat (enablement trigger 2);
|
||||
// the account-wide config toggle (trigger 1) is a separate,
|
||||
// not-yet-wired-up piece (M4).
|
||||
if !isGroupchat {
|
||||
// OMEMO decrypt hook - personal-chat pseudo-JIDs only, XEP-0045
|
||||
// groupchat OMEMO is out of scope entirely. A successful
|
||||
// decrypt marks the chat OMEMO-active. Groupchat OMEMO is
|
||||
// bounced rather than silently dropped, so the sender gets a
|
||||
// clear signal instead of treating it as delivered.
|
||||
if isGroupchat {
|
||||
if hasOMEMOPayload(msg) {
|
||||
gateway.SendErrorMessageWithBody(msg.From, msg.To, msg.Body, "OMEMO encryption is not supported in this room", msg.Id, 406, true, component)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if backend, backendOk := gateway.E2EE.Backend(); backendOk {
|
||||
env, hasEnv, decErr := decodeOMEMOEnvelope(msg)
|
||||
if decErr != nil {
|
||||
|
|
@ -444,14 +448,14 @@ func HandleMessage(s xmpp.Sender, p stanza.Packet) {
|
|||
tgMessage,
|
||||
msg.Id,
|
||||
false,
|
||||
msg.To + "/" + session.GetMUCNickname(session.GetSenderId(tgMessage.SenderId)),
|
||||
msg.To + "/" + session.GetMUCNickname(toID, session.GetSenderId(tgMessage.SenderId)),
|
||||
[]string{msg.From},
|
||||
"",
|
||||
)
|
||||
}
|
||||
} else if isCommand && isGroupchat && session.Session.MUC {
|
||||
// pong outgoing commands back to groupchats
|
||||
gateway.SendMessage(msg.From, msg.To+"/"+session.GetMUCNickname(0), component, gateway.SMBody(text), gateway.SMIsGroupchat(isGroupchat))
|
||||
gateway.SendMessage(msg.From, msg.To+"/"+session.GetMUCNickname(toID, 0), component, gateway.SMBody(text), gateway.SMIsGroupchat(isGroupchat), gateway.SMOccupantId(gateway.CHATNODE(session.MyId())))
|
||||
} else {
|
||||
/*
|
||||
// if a message failed to edit on Telegram side, match new XMPP ID with old Telegram ID anyway
|
||||
|
|
@ -903,6 +907,7 @@ func handleMUCUnavailable(component *xmpp.Component, p stanza.Presence, session
|
|||
gateway.SPMUCAffiliation("member"),
|
||||
gateway.SPMUCRole("none"),
|
||||
gateway.SPMUCJid(p.From),
|
||||
gateway.SPOccupantId(gateway.CHATNODE(session.MyId())),
|
||||
gateway.SPMUCStatusCodes([]uint16{110}),
|
||||
)
|
||||
}
|
||||
|
|
@ -1129,7 +1134,6 @@ func handleGetDiscoInfo(s xmpp.Sender, iq *stanza.IQ, di *stanza.DiscoInfo) {
|
|||
"http://jabber.org/protocol/muc",
|
||||
"muc_persistent",
|
||||
"muc_hidden",
|
||||
"muc_membersonly",
|
||||
"muc_moderated",
|
||||
"muc_nonanonymous",
|
||||
"muc_unsecured",
|
||||
|
|
@ -1142,6 +1146,7 @@ func handleGetDiscoInfo(s xmpp.Sender, iq *stanza.IQ, di *stanza.DiscoInfo) {
|
|||
gateway.NSReactions,
|
||||
"urn:xmpp:sid:0",
|
||||
"vcard-temp",
|
||||
gateway.NSOccupantId,
|
||||
)
|
||||
fields := []*stanza.Field{
|
||||
&stanza.Field{
|
||||
|
|
@ -1215,7 +1220,7 @@ func handleGetDiscoInfo(s xmpp.Sender, iq *stanza.IQ, di *stanza.DiscoInfo) {
|
|||
chat, _, err := session.GetContactByID(toID, nil, true)
|
||||
if err == nil && session.IsGroup(chat) {
|
||||
disco.SetNode(di.Node)
|
||||
disco.AddIdentity(session.GetMUCNickname(0), "conference", "text")
|
||||
disco.AddIdentity(session.GetMUCNickname(toID, 0), "conference", "text")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1340,7 +1345,7 @@ func handleGetQueryRegister(s xmpp.Sender, iq *stanza.IQ) {
|
|||
}
|
||||
defer gateway.ResumableSend(component, answer)
|
||||
|
||||
_, toOk, toIsGroup := toToID(iq.To)
|
||||
toID, toOk, toIsGroup := toToID(iq.To)
|
||||
|
||||
bare, _, ok := gateway.SplitJID(iq.From)
|
||||
var session *telegram.Client
|
||||
|
|
@ -1353,7 +1358,7 @@ func handleGetQueryRegister(s xmpp.Sender, iq *stanza.IQ) {
|
|||
if toIsGroup {
|
||||
nickname := "me"
|
||||
if sessionOk {
|
||||
nickname = session.GetMUCNickname(0)
|
||||
nickname = session.GetMUCNickname(toID, 0)
|
||||
}
|
||||
answer.Payload = extensions.QueryRegister{
|
||||
Instructions: "MUC username is static",
|
||||
|
|
@ -2317,7 +2322,7 @@ func handleSetQueryMucAdmin(s xmpp.Sender, iq *stanza.IQ, query *extensions.Quer
|
|||
return
|
||||
}
|
||||
|
||||
nick := session.GetMUCNickname(userID)
|
||||
nick := session.GetMUCNickname(toID, userID)
|
||||
|
||||
var status telegram.ChatMemberStatus
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue