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 }