Mark expired online statuses as away
This commit is contained in:
parent
8c20aaa30d
commit
3cdb625c5e
|
@ -34,6 +34,12 @@ func stringToLogConstant(c string) int32 {
|
||||||
return level
|
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
|
// Client stores the metadata for lazily invoked TDlib instance
|
||||||
type Client struct {
|
type Client struct {
|
||||||
client *client.Client
|
client *client.Client
|
||||||
|
@ -50,6 +56,9 @@ type Client struct {
|
||||||
cache *cache.Cache
|
cache *cache.Cache
|
||||||
online bool
|
online bool
|
||||||
|
|
||||||
|
DelayedStatuses map[int64]*DelayedStatus
|
||||||
|
DelayedStatusesLock sync.Mutex
|
||||||
|
|
||||||
locks clientLocks
|
locks clientLocks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,6 +124,7 @@ func NewClient(conf config.TelegramConfig, jid string, component *xmpp.Component
|
||||||
content: &conf.Content,
|
content: &conf.Content,
|
||||||
cache: cache.NewCache(),
|
cache: cache.NewCache(),
|
||||||
options: options,
|
options: options,
|
||||||
|
DelayedStatuses: make(map[int64]*DelayedStatus),
|
||||||
locks: clientLocks{
|
locks: clientLocks{
|
||||||
chatMessageLocks: make(map[int64]*sync.Mutex),
|
chatMessageLocks: make(map[int64]*sync.Mutex),
|
||||||
},
|
},
|
||||||
|
|
|
@ -119,13 +119,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) {
|
||||||
c.cache.SetUser(update.User.Id, update.User)
|
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)
|
go c.ProcessStatusUpdate(update.User.Id, status, show)
|
||||||
}
|
}
|
||||||
|
|
||||||
// user status changed
|
// user status changed
|
||||||
func (c *Client) updateUserStatus(update *client.UpdateUserStatus) {
|
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))
|
go c.ProcessStatusUpdate(update.UserId, status, show, gateway.SPImmed(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,14 +94,27 @@ func (c *Client) GetContactByID(id int64, chat *client.Chat) (*client.Chat, *cli
|
||||||
return chat, user, nil
|
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
|
var show, textStatus string
|
||||||
|
|
||||||
switch status.UserStatusType() {
|
switch status.UserStatusType() {
|
||||||
case client.TypeUserStatusOnline:
|
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"
|
textStatus = "Online"
|
||||||
case client.TypeUserStatusRecently:
|
case client.TypeUserStatusRecently:
|
||||||
show, textStatus = "dnd", "Last seen recently"
|
show, textStatus = "dnd", "Last seen recently"
|
||||||
|
|
||||||
|
c.DelayedStatusesLock.Lock()
|
||||||
|
delete(c.DelayedStatuses, chatID)
|
||||||
|
c.DelayedStatusesLock.Unlock()
|
||||||
case client.TypeUserStatusLastWeek:
|
case client.TypeUserStatusLastWeek:
|
||||||
show, textStatus = "unavailable", "Last seen last week"
|
show, textStatus = "unavailable", "Last seen last week"
|
||||||
case client.TypeUserStatusLastMonth:
|
case client.TypeUserStatusLastMonth:
|
||||||
|
@ -111,20 +124,30 @@ func (c *Client) userStatusToText(status client.UserStatus) (string, string) {
|
||||||
case client.TypeUserStatusOffline:
|
case client.TypeUserStatusOffline:
|
||||||
offlineStatus, _ := status.(*client.UserStatusOffline)
|
offlineStatus, _ := status.(*client.UserStatusOffline)
|
||||||
// this will stop working in 2038 O\
|
// 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 {
|
if elapsed < 3600 {
|
||||||
show = "away"
|
show = "away"
|
||||||
} else {
|
} else {
|
||||||
show = "xa"
|
show = "xa"
|
||||||
}
|
}
|
||||||
textStatus = time.Unix(int64(offlineStatus.WasOnline), 0).
|
textStatus = c.LastSeenStatus(wasOnline)
|
||||||
In(c.Session.TimezoneToLocation()).
|
|
||||||
Format("Last seen at 15:04 02/01/2006")
|
c.DelayedStatusesLock.Lock()
|
||||||
|
delete(c.DelayedStatuses, chatID)
|
||||||
|
c.DelayedStatusesLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
return show, textStatus
|
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
|
// ProcessStatusUpdate sets contact status
|
||||||
func (c *Client) ProcessStatusUpdate(chatID int64, status string, show string, args ...args.V) error {
|
func (c *Client) ProcessStatusUpdate(chatID int64, status string, show string, args ...args.V) error {
|
||||||
if !c.Online() {
|
if !c.Online() {
|
||||||
|
@ -161,7 +184,7 @@ func (c *Client) ProcessStatusUpdate(chatID int64, status string, show string, a
|
||||||
|
|
||||||
if status == "" {
|
if status == "" {
|
||||||
if user != nil {
|
if user != nil {
|
||||||
show, status = c.userStatusToText(user.Status)
|
show, status = c.userStatusToText(user.Status, chatID)
|
||||||
} else {
|
} else {
|
||||||
show, status = "chat", chat.Title
|
show, status = "chat", chat.Title
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,25 @@ func heartbeat(component *xmpp.Component) {
|
||||||
// status updater thread
|
// status updater thread
|
||||||
for {
|
for {
|
||||||
time.Sleep(60e9)
|
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 {
|
for key, presence := range gateway.Queue {
|
||||||
err = gateway.ResumableSend(component, presence)
|
err = gateway.ResumableSend(component, presence)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -189,8 +189,8 @@ func handlePresence(s xmpp.Sender, p stanza.Presence) {
|
||||||
for status := range session.StatusesRange() {
|
for status := range session.StatusesRange() {
|
||||||
go session.ProcessStatusUpdate(
|
go session.ProcessStatusUpdate(
|
||||||
status.ID,
|
status.ID,
|
||||||
status.XMPP,
|
|
||||||
status.Description,
|
status.Description,
|
||||||
|
status.XMPP,
|
||||||
gateway.SPImmed(false),
|
gateway.SPImmed(false),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue