Reflect name change of Telegram user in all MUCs
This commit is contained in:
parent
b8a57c06b6
commit
1e7e761c6c
|
@ -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,
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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]
|
||||
if ok {
|
||||
_, ok := oldMap[resource]
|
||||
if ok {
|
||||
// already joined, initializing anyway
|
||||
} else {
|
||||
oldMap[resource] = true
|
||||
}
|
||||
} else {
|
||||
newMap := make(map[string]bool)
|
||||
newMap[resource] = true
|
||||
c.mucResources[chatId] = newMap
|
||||
c.locks.mucCacheLock.Lock()
|
||||
mucState, ok := c.mucCache[chatId]
|
||||
if !ok || mucState == nil {
|
||||
mucState = NewMUCState()
|
||||
c.mucCache[chatId] = mucState
|
||||
}
|
||||
c.locks.mucResourcesLock.Unlock()
|
||||
_, ok = mucState.Resources[resource]
|
||||
if ok {
|
||||
// already joined, initializing anyway
|
||||
} else {
|
||||
mucState.Resources[resource] = true
|
||||
}
|
||||
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 ""
|
||||
|
|
|
@ -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"`
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue