parent
bcf222b53d
commit
dbe87fafa8
@ -0,0 +1,38 @@
|
||||
package telegram
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/zelenin/go-tdlib/client"
|
||||
)
|
||||
|
||||
func uhOh() {
|
||||
log.Fatal("Update type mismatch")
|
||||
}
|
||||
|
||||
func (c *Client) updateHandler() {
|
||||
listener := c.client.GetListener()
|
||||
defer listener.Close()
|
||||
|
||||
for update := range listener.Updates {
|
||||
if update.GetClass() == client.ClassUpdate {
|
||||
switch update.GetType() {
|
||||
case client.TypeUpdateUser:
|
||||
typedUpdate, ok := update.(*client.UpdateUser)
|
||||
if !ok {
|
||||
uhOh()
|
||||
}
|
||||
c.updateUser(typedUpdate)
|
||||
default:
|
||||
// log only handled types
|
||||
continue
|
||||
}
|
||||
|
||||
log.Debugf("%#v", update)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) updateUser(update *client.UpdateUser) {
|
||||
cache.users[update.User.Id] = update.User
|
||||
c.processStatusUpdate(update.User.Id, &update.User.Status)
|
||||
}
|
@ -0,0 +1,170 @@
|
||||
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 (c *Client) processStatusUpdate(chatID int32, status *client.UserStatus, 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 == nil && user != nil {
|
||||
status = &user.Status
|
||||
}
|
||||
|
||||
var show, textStatus string
|
||||
if status == nil {
|
||||
show = "chat"
|
||||
if chat.Title != "" {
|
||||
textStatus = chat.Title
|
||||
}
|
||||
} else {
|
||||
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:03 02/01/2006")
|
||||
}
|
||||
}
|
||||
|
||||
gateway.SendPresence(
|
||||
c.xmpp,
|
||||
c.jid,
|
||||
gateway.SPFrom(strconv.Itoa(int(chatID))),
|
||||
gateway.SPShow(show),
|
||||
gateway.SPStatus(textStatus),
|
||||
gateway.SPPhoto(photo),
|
||||
gateway.SPImmed(gateway.SPImmed.Get(args)),
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) ProcessOutgoingMessage(chatID int, text string, messageID int) {
|
||||
// TODO
|
||||
}
|
Loading…
Reference in new issue