aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBohdan Horbeshko <bodqhrohro@gmail.com>2023-10-04 01:56:37 +0300
committerBohdan Horbeshko <bodqhrohro@gmail.com>2023-10-04 01:56:37 +0300
commit1e7e761c6ce7bda3850ed23d0e64d884a28f60a7 (patch)
tree4db6cc5ffc62ac91f4e662b2546a17fb62621e00
parentb8a57c06b646edbad340c9e1c6c79e11a8a666e3 (diff)
Reflect name change of Telegram user in all MUCs
-rw-r--r--telegram/client.go25
-rw-r--r--telegram/handlers.go7
-rw-r--r--telegram/utils.go91
-rw-r--r--xmpp/extensions/extensions.go1
-rw-r--r--xmpp/gateway/gateway.go6
5 files changed, 111 insertions, 19 deletions
diff --git a/telegram/client.go b/telegram/client.go
index 6033c7c..f3bfe4a 100644
--- a/telegram/client.go
+++ b/telegram/client.go
@@ -41,6 +41,25 @@ type DelayedStatus struct {
TimestampExpired int64
}
+// MUCState holds MUC metadata
+type MUCState struct {
+ Resources map[string]bool
+ Members map[int64]*MUCMember
+}
+
+// MUCMember represents a MUC member
+type MUCMember struct {
+ Nickname string
+ Affiliation string
+}
+
+func NewMUCState() *MUCState {
+ return &MUCState{
+ Resources: make(map[string]bool),
+ Members: make(map[int64]*MUCMember),
+ }
+}
+
// Client stores the metadata for lazily invoked TDlib instance
type Client struct {
client *client.Client
@@ -64,7 +83,7 @@ type Client struct {
lastMsgHashes map[int64]uint64
msgHashSeed maphash.Seed
- mucResources map[int64]map[string]bool
+ mucCache map[int64]*MUCState
locks clientLocks
SendMessageLock sync.Mutex
@@ -75,7 +94,7 @@ type clientLocks struct {
chatMessageLocks map[int64]*sync.Mutex
resourcesLock sync.Mutex
outboxLock sync.Mutex
- mucResourcesLock sync.Mutex
+ mucCacheLock sync.Mutex
lastMsgHashesLock sync.Mutex
authorizerReadLock sync.Mutex
@@ -136,7 +155,7 @@ func NewClient(conf config.TelegramConfig, jid string, component *xmpp.Component
Session: session,
resources: make(map[string]bool),
outbox: make(map[string]string),
- mucResources: make(map[int64]map[string]bool),
+ mucCache: make(map[int64]*MUCState),
content: &conf.Content,
cache: cache.NewCache(),
options: options,
diff --git a/telegram/handlers.go b/telegram/handlers.go
index 8facc10..c7185f5 100644
--- a/telegram/handlers.go
+++ b/telegram/handlers.go
@@ -153,6 +153,13 @@ func (c *Client) updateHandler() {
// new user discovered
func (c *Client) updateUser(update *client.UpdateUser) {
+ // check if MUC nicknames should be updated
+ cacheUser, ok := c.cache.GetUser(update.User.Id)
+ if ok && (cacheUser.FirstName != update.User.FirstName || cacheUser.LastName != update.User.LastName) {
+ newNickname := c.GetMUCNickname(update.User.Id)
+ c.updateMUCsNickname(update.User.Id, newNickname)
+ }
+
c.cache.SetUser(update.User.Id, update.User)
show, status, presenceType := c.userStatusToText(update.User.Status, update.User.Id)
go c.ProcessStatusUpdate(update.User.Id, status, show, gateway.SPType(presenceType))
diff --git a/telegram/utils.go b/telegram/utils.go
index cab450f..addeee8 100644
--- a/telegram/utils.go
+++ b/telegram/utils.go
@@ -306,21 +306,19 @@ func (c *Client) ProcessStatusUpdate(chatID int64, status string, show string, o
// JoinMUC saves MUC join fact and sends initialization data
func (c *Client) JoinMUC(chatId int64, resource string, limit int32) {
// save the nickname in this MUC, also as a marker of join
- c.locks.mucResourcesLock.Lock()
- oldMap, ok := c.mucResources[chatId]
+ c.locks.mucCacheLock.Lock()
+ mucState, ok := c.mucCache[chatId]
+ if !ok || mucState == nil {
+ mucState = NewMUCState()
+ c.mucCache[chatId] = mucState
+ }
+ _, ok = mucState.Resources[resource]
if ok {
- _, ok := oldMap[resource]
- if ok {
- // already joined, initializing anyway
- } else {
- oldMap[resource] = true
- }
+ // already joined, initializing anyway
} else {
- newMap := make(map[string]bool)
- newMap[resource] = true
- c.mucResources[chatId] = newMap
+ mucState.Resources[resource] = true
}
- c.locks.mucResourcesLock.Unlock()
+ c.locks.mucCacheLock.Unlock()
c.sendMUCStatuses(chatId)
@@ -332,14 +330,27 @@ func (c *Client) JoinMUC(chatId int64, resource string, limit int32) {
c.sendMUCSubject(chatId, resource)
}
+func (c *Client) getFullName(user *client.User) string {
+ fullName := user.FirstName
+ if user.LastName != "" {
+ fullName = fullName + " " + user.LastName
+ }
+ return fullName
+}
+
func (c *Client) sendMUCStatuses(chatID int64) {
+ c.locks.mucCacheLock.Lock()
+ defer c.locks.mucCacheLock.Unlock()
+ mucState, ok := c.mucCache[chatID]
+ if !ok || mucState == nil {
+ mucState = NewMUCState()
+ c.mucCache[chatID] = mucState
+ }
+
sChatId := strconv.FormatInt(chatID, 10)
myNickname := "me"
if c.me != nil {
- myNickname := c.me.FirstName
- if c.me.LastName != "" {
- myNickname = myNickname + " " + c.me.LastName
- }
+ myNickname = c.getFullName(c.me)
}
myAffiliation := "member"
@@ -364,6 +375,11 @@ func (c *Client) sendMUCStatuses(chatID int64) {
nickname := c.GetMUCNickname(senderId)
affiliation := c.memberStatusToAffiliation(member.Status)
+ mucState.Members[senderId] = &MUCMember{
+ Nickname: nickname,
+ Affiliation: affiliation,
+ }
+
if c.me != nil && senderId == c.me.Id {
myNickname = nickname
myAffiliation = affiliation
@@ -419,6 +435,49 @@ func (c *Client) GetMUCNickname(chatID int64) string {
return c.formatContact(chatID)
}
+func (c *Client) updateMUCsNickname(memberID int64, newNickname string) {
+ c.locks.mucCacheLock.Lock()
+ defer c.locks.mucCacheLock.Unlock()
+
+ for mucId, state := range c.mucCache {
+ oldMember, ok := state.Members[memberID]
+ if ok {
+ state.Members[memberID] = &MUCMember{
+ Nickname: newNickname,
+ Affiliation: oldMember.Affiliation,
+ }
+
+ sMucId := strconv.FormatInt(mucId, 10)
+ unavailableStatusCodes := []uint16{303, 210}
+ availableStatusCodes := []uint16{100, 210}
+ if c.me != nil && memberID == c.me.Id {
+ unavailableStatusCodes = append(unavailableStatusCodes, 110)
+ availableStatusCodes = append(availableStatusCodes, 110)
+ }
+ gateway.SendPresence(
+ c.xmpp,
+ c.jid,
+ gateway.SPType("unavailable"),
+ gateway.SPFrom(sMucId),
+ gateway.SPResource(oldMember.Nickname),
+ gateway.SPImmed(true),
+ gateway.SPMUCAffiliation(oldMember.Affiliation),
+ gateway.SPMUCNick(newNickname),
+ gateway.SPMUCStatusCodes(unavailableStatusCodes),
+ )
+ gateway.SendPresence(
+ c.xmpp,
+ c.jid,
+ gateway.SPFrom(sMucId),
+ gateway.SPResource(newNickname),
+ gateway.SPImmed(true),
+ gateway.SPMUCAffiliation(oldMember.Affiliation),
+ gateway.SPMUCStatusCodes(availableStatusCodes),
+ )
+ }
+ }
+}
+
func (c *Client) formatContact(chatID int64) string {
if chatID == 0 {
return ""
diff --git a/xmpp/extensions/extensions.go b/xmpp/extensions/extensions.go
index 8ff034d..45ab839 100644
--- a/xmpp/extensions/extensions.go
+++ b/xmpp/extensions/extensions.go
@@ -225,6 +225,7 @@ type PresenceXMucUserItem struct {
XMLName xml.Name `xml:"item"`
Affiliation string `xml:"affiliation,attr"`
Jid string `xml:"jid,attr"`
+ Nick string `xml:"nick,attr,omitempty"`
Role string `xml:"role,attr"`
}
diff --git a/xmpp/gateway/gateway.go b/xmpp/gateway/gateway.go
index 1a37cc7..9007f6b 100644
--- a/xmpp/gateway/gateway.go
+++ b/xmpp/gateway/gateway.go
@@ -328,6 +328,9 @@ var SPImmed = args.NewBool(args.Default(true))
// SPMUCAffiliation is a XEP-0045 MUC affiliation
var SPMUCAffiliation = args.NewString()
+// SPMUCNick is a XEP-0045 MUC user nick
+var SPMUCNick = args.NewString()
+
// SPMUCJid is a real jid of a MUC member
var SPMUCJid = args.NewString()
@@ -398,6 +401,9 @@ func newPresence(bareJid string, to string, args ...args.V) stanza.Presence {
Role: affilationToRole(affiliation),
},
}
+ if SPMUCNick.IsSet(args) {
+ userExt.Item.Nick = SPMUCNick.Get(args)
+ }
if SPMUCJid.IsSet(args) {
userExt.Item.Jid = SPMUCJid.Get(args)
}