Mark expired online statuses as away

This commit is contained in:
Bohdan Horbeshko 2022-01-31 09:31:05 -05:00
parent 8c20aaa30d
commit 3cdb625c5e
5 changed files with 61 additions and 9 deletions

View file

@ -34,6 +34,12 @@ func stringToLogConstant(c string) int32 {
return level
}
// DelayedStatus describes an online status expiring on timeout
type DelayedStatus struct {
TimestampOnline int64
TimestampExpired int64
}
// Client stores the metadata for lazily invoked TDlib instance
type Client struct {
client *client.Client
@ -50,6 +56,9 @@ type Client struct {
cache *cache.Cache
online bool
DelayedStatuses map[int64]*DelayedStatus
DelayedStatusesLock sync.Mutex
locks clientLocks
}
@ -115,6 +124,7 @@ func NewClient(conf config.TelegramConfig, jid string, component *xmpp.Component
content: &conf.Content,
cache: cache.NewCache(),
options: options,
DelayedStatuses: make(map[int64]*DelayedStatus),
locks: clientLocks{
chatMessageLocks: make(map[int64]*sync.Mutex),
},

View file

@ -119,13 +119,13 @@ func (c *Client) updateHandler() {
// new user discovered
func (c *Client) updateUser(update *client.UpdateUser) {
c.cache.SetUser(update.User.Id, update.User)
show, status := c.userStatusToText(update.User.Status)
show, status := c.userStatusToText(update.User.Status, update.User.Id)
go c.ProcessStatusUpdate(update.User.Id, status, show)
}
// user status changed
func (c *Client) updateUserStatus(update *client.UpdateUserStatus) {
show, status := c.userStatusToText(update.Status)
show, status := c.userStatusToText(update.Status, update.UserId)
go c.ProcessStatusUpdate(update.UserId, status, show, gateway.SPImmed(false))
}

View file

@ -94,14 +94,27 @@ func (c *Client) GetContactByID(id int64, chat *client.Chat) (*client.Chat, *cli
return chat, user, nil
}
func (c *Client) userStatusToText(status client.UserStatus) (string, string) {
func (c *Client) userStatusToText(status client.UserStatus, chatID int64) (string, string) {
var show, textStatus string
switch status.UserStatusType() {
case client.TypeUserStatusOnline:
onlineStatus, _ := status.(*client.UserStatusOnline)
c.DelayedStatusesLock.Lock()
c.DelayedStatuses[chatID] = &DelayedStatus{
TimestampOnline: time.Now().Unix(),
TimestampExpired: int64(onlineStatus.Expires),
}
c.DelayedStatusesLock.Unlock()
textStatus = "Online"
case client.TypeUserStatusRecently:
show, textStatus = "dnd", "Last seen recently"
c.DelayedStatusesLock.Lock()
delete(c.DelayedStatuses, chatID)
c.DelayedStatusesLock.Unlock()
case client.TypeUserStatusLastWeek:
show, textStatus = "unavailable", "Last seen last week"
case client.TypeUserStatusLastMonth:
@ -111,20 +124,30 @@ func (c *Client) userStatusToText(status client.UserStatus) (string, string) {
case client.TypeUserStatusOffline:
offlineStatus, _ := status.(*client.UserStatusOffline)
// this will stop working in 2038 O\
elapsed := time.Now().Unix() - int64(offlineStatus.WasOnline)
wasOnline := int64(offlineStatus.WasOnline)
elapsed := time.Now().Unix() - wasOnline
if elapsed < 3600 {
show = "away"
} else {
show = "xa"
}
textStatus = time.Unix(int64(offlineStatus.WasOnline), 0).
In(c.Session.TimezoneToLocation()).
Format("Last seen at 15:04 02/01/2006")
textStatus = c.LastSeenStatus(wasOnline)
c.DelayedStatusesLock.Lock()
delete(c.DelayedStatuses, chatID)
c.DelayedStatusesLock.Unlock()
}
return show, textStatus
}
// LastSeenStatus formats a timestamp to a "Last seen at" string
func (c *Client) LastSeenStatus(timestamp int64) string {
return time.Unix(int64(timestamp), 0).
In(c.Session.TimezoneToLocation()).
Format("Last seen at 15:04 02/01/2006")
}
// ProcessStatusUpdate sets contact status
func (c *Client) ProcessStatusUpdate(chatID int64, status string, show string, args ...args.V) error {
if !c.Online() {
@ -161,7 +184,7 @@ func (c *Client) ProcessStatusUpdate(chatID int64, status string, show string, a
if status == "" {
if user != nil {
show, status = c.userStatusToText(user.Status)
show, status = c.userStatusToText(user.Status, chatID)
} else {
show, status = "chat", chat.Title
}

View file

@ -85,6 +85,25 @@ func heartbeat(component *xmpp.Component) {
// status updater thread
for {
time.Sleep(60e9)
now := time.Now().Unix()
sessionLock.Lock()
for _, session := range sessions {
session.DelayedStatusesLock.Lock()
for chatID, delayedStatus := range session.DelayedStatuses {
if delayedStatus.TimestampExpired <= now {
go session.ProcessStatusUpdate(
chatID,
session.LastSeenStatus(delayedStatus.TimestampOnline),
"away",
)
delete(session.DelayedStatuses, chatID)
}
}
session.DelayedStatusesLock.Unlock()
}
sessionLock.Unlock()
for key, presence := range gateway.Queue {
err = gateway.ResumableSend(component, presence)
if err != nil {

View file

@ -189,8 +189,8 @@ func handlePresence(s xmpp.Sender, p stanza.Presence) {
for status := range session.StatusesRange() {
go session.ProcessStatusUpdate(
status.ID,
status.XMPP,
status.Description,
status.XMPP,
gateway.SPImmed(false),
)
}