173 lines
3.8 KiB
Go
173 lines
3.8 KiB
Go
package telegram
|
|
|
|
import (
|
|
"crypto/sha1"
|
|
"github.com/pkg/errors"
|
|
"io"
|
|
"os"
|
|
"strconv"
|
|
"time"
|
|
|
|
"dev.narayana.im/narayana/telegabber/xmpp/gateway"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
"github.com/soheilhy/args"
|
|
"github.com/zelenin/go-tdlib/client"
|
|
)
|
|
|
|
var errOffline = errors.New("TDlib instance is offline")
|
|
|
|
// GetContactByUsername resolves username to user id retrieves user and chat information
|
|
func (c *Client) GetContactByUsername(username string) (*client.Chat, *client.User, error) {
|
|
if !c.online {
|
|
return nil, nil, errOffline
|
|
}
|
|
|
|
chat, err := c.client.SearchPublicChat(&client.SearchPublicChatRequest{
|
|
Username: username,
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
return c.GetContactByID(int32(chat.Id), chat)
|
|
}
|
|
|
|
// GetContactByID gets user and chat information from cache (or tries to retrieve it, if missing)
|
|
func (c *Client) GetContactByID(id int32, chat *client.Chat) (*client.Chat, *client.User, error) {
|
|
if !c.online {
|
|
return nil, nil, errOffline
|
|
}
|
|
|
|
var user *client.User
|
|
var cacheChat *client.Chat
|
|
var ok bool
|
|
var err error
|
|
|
|
user, ok = cache.users[id]
|
|
if !ok && id > 0 {
|
|
user, err = c.client.GetUser(&client.GetUserRequest{
|
|
UserId: id,
|
|
})
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
cache.users[id] = user
|
|
}
|
|
|
|
chatID := int64(id)
|
|
cacheChat, ok = cache.chats[chatID]
|
|
if !ok {
|
|
if chat == nil {
|
|
cacheChat, err = c.client.GetChat(&client.GetChatRequest{
|
|
ChatId: chatID,
|
|
})
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
cache.chats[chatID] = cacheChat
|
|
} else {
|
|
cache.chats[chatID] = chat
|
|
}
|
|
}
|
|
if chat == nil {
|
|
chat = cacheChat
|
|
}
|
|
|
|
return chat, user, nil
|
|
}
|
|
|
|
func userStatusToText(status client.UserStatus) (string, string) {
|
|
var show, textStatus string
|
|
|
|
switch status.UserStatusType() {
|
|
case client.TypeUserStatusOnline:
|
|
textStatus = "Online"
|
|
case client.TypeUserStatusRecently:
|
|
show, textStatus = "dnd", "Last seen recently"
|
|
case client.TypeUserStatusLastWeek:
|
|
show, textStatus = "unavailable", "Last seen last week"
|
|
case client.TypeUserStatusLastMonth:
|
|
show, textStatus = "unavailable", "Last seen last month"
|
|
case client.TypeUserStatusEmpty:
|
|
show, textStatus = "unavailable", "Last seen a long time ago"
|
|
case client.TypeUserStatusOffline:
|
|
offlineStatus, ok := status.(*client.UserStatusOffline)
|
|
if !ok {
|
|
log.Fatal("Status type changed before conversion!")
|
|
}
|
|
// this will stop working in 2038 O\
|
|
elapsed := time.Now().Unix() - int64(offlineStatus.WasOnline)
|
|
if elapsed < 3600 {
|
|
show = "away"
|
|
} else {
|
|
show = "xa"
|
|
}
|
|
// TODO: timezone
|
|
textStatus = time.Unix(int64(offlineStatus.WasOnline), 0).Format("Last seen at 15:04 02/01/2006")
|
|
}
|
|
|
|
return show, textStatus
|
|
}
|
|
|
|
func (c *Client) processStatusUpdate(chatID int32, status string, show string, args ...args.V) error {
|
|
if !c.online {
|
|
return nil
|
|
}
|
|
|
|
log.WithFields(log.Fields{
|
|
"chat_id": chatID,
|
|
}).Info("Status update for")
|
|
|
|
chat, user, err := c.GetContactByID(chatID, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var photo string
|
|
if chat != nil && chat.Photo != nil {
|
|
path := chat.Photo.Small.Local.Path
|
|
file, err := os.Open(path)
|
|
if err == nil {
|
|
defer file.Close()
|
|
|
|
hash := sha1.New()
|
|
_, err = io.Copy(hash, file)
|
|
if err == nil {
|
|
photo = string(hash.Sum(nil))
|
|
} else {
|
|
log.Errorf("Error calculating hash: %v", path)
|
|
}
|
|
} else if path != "" {
|
|
log.Errorf("Photo does not exist: %v", path)
|
|
}
|
|
}
|
|
|
|
if status == "" {
|
|
if user != nil {
|
|
show, status = userStatusToText(user.Status)
|
|
} else {
|
|
show, status = "chat", chat.Title
|
|
}
|
|
}
|
|
|
|
gateway.SendPresence(
|
|
c.xmpp,
|
|
c.jid,
|
|
gateway.SPFrom(strconv.Itoa(int(chatID))),
|
|
gateway.SPShow(show),
|
|
gateway.SPStatus(status),
|
|
gateway.SPPhoto(photo),
|
|
gateway.SPImmed(gateway.SPImmed.Get(args)),
|
|
)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *Client) ProcessOutgoingMessage(chatID int, text string, messageID int) {
|
|
// TODO
|
|
}
|