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
|
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
|
// Client stores the metadata for lazily invoked TDlib instance
|
||||||
type Client struct {
|
type Client struct {
|
||||||
client *client.Client
|
client *client.Client
|
||||||
|
@ -64,7 +83,7 @@ type Client struct {
|
||||||
lastMsgHashes map[int64]uint64
|
lastMsgHashes map[int64]uint64
|
||||||
msgHashSeed maphash.Seed
|
msgHashSeed maphash.Seed
|
||||||
|
|
||||||
mucResources map[int64]map[string]bool
|
mucCache map[int64]*MUCState
|
||||||
|
|
||||||
locks clientLocks
|
locks clientLocks
|
||||||
SendMessageLock sync.Mutex
|
SendMessageLock sync.Mutex
|
||||||
|
@ -75,7 +94,7 @@ type clientLocks struct {
|
||||||
chatMessageLocks map[int64]*sync.Mutex
|
chatMessageLocks map[int64]*sync.Mutex
|
||||||
resourcesLock sync.Mutex
|
resourcesLock sync.Mutex
|
||||||
outboxLock sync.Mutex
|
outboxLock sync.Mutex
|
||||||
mucResourcesLock sync.Mutex
|
mucCacheLock sync.Mutex
|
||||||
lastMsgHashesLock sync.Mutex
|
lastMsgHashesLock sync.Mutex
|
||||||
|
|
||||||
authorizerReadLock sync.Mutex
|
authorizerReadLock sync.Mutex
|
||||||
|
@ -136,7 +155,7 @@ func NewClient(conf config.TelegramConfig, jid string, component *xmpp.Component
|
||||||
Session: session,
|
Session: session,
|
||||||
resources: make(map[string]bool),
|
resources: make(map[string]bool),
|
||||||
outbox: make(map[string]string),
|
outbox: make(map[string]string),
|
||||||
mucResources: make(map[int64]map[string]bool),
|
mucCache: make(map[int64]*MUCState),
|
||||||
content: &conf.Content,
|
content: &conf.Content,
|
||||||
cache: cache.NewCache(),
|
cache: cache.NewCache(),
|
||||||
options: options,
|
options: options,
|
||||||
|
|
|
@ -153,6 +153,13 @@ func (c *Client) updateHandler() {
|
||||||
|
|
||||||
// new user discovered
|
// new user discovered
|
||||||
func (c *Client) updateUser(update *client.UpdateUser) {
|
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)
|
c.cache.SetUser(update.User.Id, update.User)
|
||||||
show, status, presenceType := c.userStatusToText(update.User.Status, update.User.Id)
|
show, status, presenceType := c.userStatusToText(update.User.Status, update.User.Id)
|
||||||
go c.ProcessStatusUpdate(update.User.Id, status, show, gateway.SPType(presenceType))
|
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
|
// JoinMUC saves MUC join fact and sends initialization data
|
||||||
func (c *Client) JoinMUC(chatId int64, resource string, limit int32) {
|
func (c *Client) JoinMUC(chatId int64, resource string, limit int32) {
|
||||||
// save the nickname in this MUC, also as a marker of join
|
// save the nickname in this MUC, also as a marker of join
|
||||||
c.locks.mucResourcesLock.Lock()
|
c.locks.mucCacheLock.Lock()
|
||||||
oldMap, ok := c.mucResources[chatId]
|
mucState, ok := c.mucCache[chatId]
|
||||||
if ok {
|
if !ok || mucState == nil {
|
||||||
_, ok := oldMap[resource]
|
mucState = NewMUCState()
|
||||||
|
c.mucCache[chatId] = mucState
|
||||||
|
}
|
||||||
|
_, ok = mucState.Resources[resource]
|
||||||
if ok {
|
if ok {
|
||||||
// already joined, initializing anyway
|
// already joined, initializing anyway
|
||||||
} else {
|
} else {
|
||||||
oldMap[resource] = true
|
mucState.Resources[resource] = true
|
||||||
}
|
}
|
||||||
} else {
|
c.locks.mucCacheLock.Unlock()
|
||||||
newMap := make(map[string]bool)
|
|
||||||
newMap[resource] = true
|
|
||||||
c.mucResources[chatId] = newMap
|
|
||||||
}
|
|
||||||
c.locks.mucResourcesLock.Unlock()
|
|
||||||
|
|
||||||
c.sendMUCStatuses(chatId)
|
c.sendMUCStatuses(chatId)
|
||||||
|
|
||||||
|
@ -332,14 +330,27 @@ func (c *Client) JoinMUC(chatId int64, resource string, limit int32) {
|
||||||
c.sendMUCSubject(chatId, resource)
|
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) {
|
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)
|
sChatId := strconv.FormatInt(chatID, 10)
|
||||||
myNickname := "me"
|
myNickname := "me"
|
||||||
if c.me != nil {
|
if c.me != nil {
|
||||||
myNickname := c.me.FirstName
|
myNickname = c.getFullName(c.me)
|
||||||
if c.me.LastName != "" {
|
|
||||||
myNickname = myNickname + " " + c.me.LastName
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
myAffiliation := "member"
|
myAffiliation := "member"
|
||||||
|
|
||||||
|
@ -364,6 +375,11 @@ func (c *Client) sendMUCStatuses(chatID int64) {
|
||||||
|
|
||||||
nickname := c.GetMUCNickname(senderId)
|
nickname := c.GetMUCNickname(senderId)
|
||||||
affiliation := c.memberStatusToAffiliation(member.Status)
|
affiliation := c.memberStatusToAffiliation(member.Status)
|
||||||
|
mucState.Members[senderId] = &MUCMember{
|
||||||
|
Nickname: nickname,
|
||||||
|
Affiliation: affiliation,
|
||||||
|
}
|
||||||
|
|
||||||
if c.me != nil && senderId == c.me.Id {
|
if c.me != nil && senderId == c.me.Id {
|
||||||
myNickname = nickname
|
myNickname = nickname
|
||||||
myAffiliation = affiliation
|
myAffiliation = affiliation
|
||||||
|
@ -419,6 +435,49 @@ func (c *Client) GetMUCNickname(chatID int64) string {
|
||||||
return c.formatContact(chatID)
|
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 {
|
func (c *Client) formatContact(chatID int64) string {
|
||||||
if chatID == 0 {
|
if chatID == 0 {
|
||||||
return ""
|
return ""
|
||||||
|
|
|
@ -225,6 +225,7 @@ type PresenceXMucUserItem struct {
|
||||||
XMLName xml.Name `xml:"item"`
|
XMLName xml.Name `xml:"item"`
|
||||||
Affiliation string `xml:"affiliation,attr"`
|
Affiliation string `xml:"affiliation,attr"`
|
||||||
Jid string `xml:"jid,attr"`
|
Jid string `xml:"jid,attr"`
|
||||||
|
Nick string `xml:"nick,attr,omitempty"`
|
||||||
Role string `xml:"role,attr"`
|
Role string `xml:"role,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -328,6 +328,9 @@ var SPImmed = args.NewBool(args.Default(true))
|
||||||
// SPMUCAffiliation is a XEP-0045 MUC affiliation
|
// SPMUCAffiliation is a XEP-0045 MUC affiliation
|
||||||
var SPMUCAffiliation = args.NewString()
|
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
|
// SPMUCJid is a real jid of a MUC member
|
||||||
var SPMUCJid = args.NewString()
|
var SPMUCJid = args.NewString()
|
||||||
|
|
||||||
|
@ -398,6 +401,9 @@ func newPresence(bareJid string, to string, args ...args.V) stanza.Presence {
|
||||||
Role: affilationToRole(affiliation),
|
Role: affilationToRole(affiliation),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
if SPMUCNick.IsSet(args) {
|
||||||
|
userExt.Item.Nick = SPMUCNick.Get(args)
|
||||||
|
}
|
||||||
if SPMUCJid.IsSet(args) {
|
if SPMUCJid.IsSet(args) {
|
||||||
userExt.Item.Jid = SPMUCJid.Get(args)
|
userExt.Item.Jid = SPMUCJid.Get(args)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue