Resend chat statuses on probe presence

This commit is contained in:
bodqhrohro 2020-01-05 15:03:10 +02:00
parent a435a0a556
commit b8fcac6ae2
4 changed files with 79 additions and 11 deletions

View file

@ -6,20 +6,30 @@ import (
"github.com/zelenin/go-tdlib/client"
)
// Status stores formatted data for XMPP presence
type Status struct {
ID int64
XMPP string
Description string
}
// Cache allows operating the chats and users cache in
// a thread-safe manner
type Cache struct {
chats map[int64]*client.Chat
users map[int32]*client.User
chatsLock sync.Mutex
usersLock sync.Mutex
chats map[int64]*client.Chat
users map[int32]*client.User
statuses map[int64]*Status
chatsLock sync.Mutex
usersLock sync.Mutex
statusesLock sync.Mutex
}
// NewCache initializes a cache
func NewCache() *Cache {
return &Cache{
chats: map[int64]*client.Chat{},
users: map[int32]*client.User{},
chats: map[int64]*client.Chat{},
users: map[int32]*client.User{},
statuses: map[int64]*Status{},
}
}
@ -49,6 +59,26 @@ func (cache *Cache) UsersKeys() []int32 {
return keys
}
// StatusesRange loops through the map in a thread-safe manner
func (cache *Cache) StatusesRange() chan *Status {
cache.statusesLock.Lock()
statusChan := make(chan *Status, 1)
go func() {
defer func() {
cache.statusesLock.Unlock()
close(statusChan)
}()
for _, status := range cache.statuses {
statusChan <- status
}
}()
return statusChan
}
// GetChat retrieves chat by id if it's present in the cache
func (cache *Cache) GetChat(id int64) (*client.Chat, bool) {
cache.chatsLock.Lock()
@ -67,6 +97,15 @@ func (cache *Cache) GetUser(id int32) (*client.User, bool) {
return user, ok
}
// GetStatus retrieves status by id if it's present in the cache
func (cache *Cache) GetStatus(id int64) (*Status, bool) {
cache.statusesLock.Lock()
defer cache.statusesLock.Unlock()
status, ok := cache.statuses[id]
return status, ok
}
// SetChat stores a chat in the cache
func (cache *Cache) SetChat(id int64, chat *client.Chat) {
cache.chatsLock.Lock()
@ -82,3 +121,15 @@ func (cache *Cache) SetUser(id int32, user *client.User) {
cache.users[id] = user
}
// SetStatus stores a status in the cache
func (cache *Cache) SetStatus(id int64, show string, status string) {
cache.statusesLock.Lock()
defer cache.statusesLock.Unlock()
cache.statuses[id] = &Status{
ID: id,
XMPP: show,
Description: status,
}
}

View file

@ -120,13 +120,13 @@ func (c *Client) updateHandler() {
func (c *Client) updateUser(update *client.UpdateUser) {
c.cache.SetUser(update.User.Id, update.User)
show, status := c.userStatusToText(update.User.Status)
go c.processStatusUpdate(int64(update.User.Id), status, show)
go c.ProcessStatusUpdate(int64(update.User.Id), status, show)
}
// user status changed
func (c *Client) updateUserStatus(update *client.UpdateUserStatus) {
show, status := c.userStatusToText(update.Status)
go c.processStatusUpdate(int64(update.UserId), status, show, gateway.SPImmed(false))
go c.ProcessStatusUpdate(int64(update.UserId), status, show, gateway.SPImmed(false))
}
// new chat discovered
@ -166,7 +166,7 @@ func (c *Client) updateNewChat(update *client.UpdateNewChat) {
}
if update.Chat.Id < 0 {
c.processStatusUpdate(update.Chat.Id, update.Chat.Title, "chat")
c.ProcessStatusUpdate(update.Chat.Id, update.Chat.Title, "chat")
}
}()
}

View file

@ -14,6 +14,7 @@ import (
"strings"
"time"
"dev.narayana.im/narayana/telegabber/telegram/cache"
"dev.narayana.im/narayana/telegabber/xmpp/gateway"
log "github.com/sirupsen/logrus"
@ -129,8 +130,8 @@ func (c *Client) userStatusToText(status client.UserStatus) (string, string) {
return show, textStatus
}
// set contact status
func (c *Client) processStatusUpdate(chatID int64, status string, show string, args ...args.V) error {
// ProcessStatusUpdate sets contact status
func (c *Client) ProcessStatusUpdate(chatID int64, status string, show string, args ...args.V) error {
if !c.Online() {
return nil
}
@ -171,6 +172,8 @@ func (c *Client) processStatusUpdate(chatID int64, status string, show string, a
}
}
c.cache.SetStatus(chatID, show, status)
gateway.SendPresence(
c.xmpp,
c.jid,
@ -512,3 +515,8 @@ func (c *Client) ProcessOutgoingMessage(chatID int64, text string, messageID int
}
}
}
// StatusesRange proxies the following function from unexported cache
func (c *Client) StatusesRange() chan *cache.Status {
return c.cache.StatusesRange()
}

View file

@ -176,6 +176,15 @@ func handlePresence(s xmpp.Sender, p stanza.Presence) {
err = session.Connect()
if err != nil {
log.Error(errors.Wrap(err, "TDlib connection failure"))
} else {
for status := range session.StatusesRange() {
go session.ProcessStatusUpdate(
status.ID,
status.XMPP,
status.Description,
gateway.SPImmed(false),
)
}
}
}()
}