diff --git a/telegram/handlers.go b/telegram/handlers.go index 348fd9a..5ff5dad 100644 --- a/telegram/handlers.go +++ b/telegram/handlers.go @@ -1,6 +1,8 @@ package telegram import ( + "strconv" + "dev.narayana.im/narayana/telegabber/xmpp/gateway" log "github.com/sirupsen/logrus" @@ -30,6 +32,12 @@ func (c *Client) updateHandler() { uhOh() } c.updateUserStatus(typedUpdate) + case client.TypeUpdateNewChat: + typedUpdate, ok := update.(*client.UpdateNewChat) + if !ok { + uhOh() + } + c.updateNewChat(typedUpdate) default: // log only handled types continue @@ -42,9 +50,50 @@ func (c *Client) updateHandler() { func (c *Client) updateUser(update *client.UpdateUser) { cache.users[update.User.Id] = update.User - c.processStatusUpdate(update.User.Id, &update.User.Status) + show, status := userStatusToText(update.User.Status) + c.processStatusUpdate(update.User.Id, status, show) } func (c *Client) updateUserStatus(update *client.UpdateUserStatus) { - c.processStatusUpdate(update.UserId, &update.Status, gateway.SPImmed(false)) + show, status := userStatusToText(update.Status) + c.processStatusUpdate(update.UserId, status, show, gateway.SPImmed(false)) +} + +func (c *Client) updateNewChat(update *client.UpdateNewChat) { + if update.Chat != nil && update.Chat.Photo != nil && update.Chat.Photo.Small != nil { + _, err := c.client.DownloadFile(&client.DownloadFileRequest{ + FileId: update.Chat.Photo.Small.Id, + Priority: 32, + Synchronous: true, + }) + + if err != nil { + log.Error("Failed to download the chat photo") + } + } + + cache.chats[update.Chat.Id] = update.Chat + + var isChannel = false + if update.Chat.Type.ChatTypeType() == client.TypeChatTypeSupergroup { + typeSupergroup, ok := update.Chat.Type.(*client.ChatTypeSupergroup) + if !ok { + uhOh() + } + isChannel = typeSupergroup.IsChannel + } + + if !(isChannel && update.Chat.LastReadInboxMessageId == 0) { + gateway.SendPresence( + c.xmpp, + c.jid, + gateway.SPFrom(strconv.Itoa(int(update.Chat.Id))), + gateway.SPType("subscribe"), + gateway.SPNickname(update.Chat.Title), + ) + } + + if update.Chat.Id < 0 { + c.processStatusUpdate(int32(update.Chat.Id), update.Chat.Title, "chat") + } } diff --git a/telegram/utils.go b/telegram/utils.go index 7fb78d9..172bc38 100644 --- a/telegram/utils.go +++ b/telegram/utils.go @@ -80,7 +80,40 @@ func (c *Client) GetContactByID(id int32, chat *client.Chat) (*client.Chat, *cli return chat, user, nil } -func (c *Client) processStatusUpdate(chatID int32, status *client.UserStatus, args ...args.V) error { +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:03 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 } @@ -113,42 +146,11 @@ func (c *Client) processStatusUpdate(chatID int32, status *client.UserStatus, ar } } - 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") + if status == "" { + if user != nil { + show, status = userStatusToText(user.Status) + } else { + show, status = "chat", chat.Title } } @@ -157,7 +159,7 @@ func (c *Client) processStatusUpdate(chatID int32, status *client.UserStatus, ar c.jid, gateway.SPFrom(strconv.Itoa(int(chatID))), gateway.SPShow(show), - gateway.SPStatus(textStatus), + gateway.SPStatus(status), gateway.SPPhoto(photo), gateway.SPImmed(gateway.SPImmed.Get(args)), ) diff --git a/telegram/utils_test.go b/telegram/utils_test.go new file mode 100644 index 0000000..8b1b025 --- /dev/null +++ b/telegram/utils_test.go @@ -0,0 +1,42 @@ +package telegram + +import ( + "testing" + "time" + + "github.com/zelenin/go-tdlib/client" +) + +const testTimeFormat string = "15:03 02/01/2006" + +func TestOnlineStatus(t *testing.T) { + show, status := userStatusToText(client.UserStatus(&client.UserStatusOnline{})) + if show != "" || status != "Online" { + t.Errorf("Wrong online status: %v, %v", show, status) + } +} + +func TestOnlineRecently(t *testing.T) { + show, status := userStatusToText(client.UserStatus(&client.UserStatusRecently{})) + if show != "dnd" || status != "Last seen recently" { + t.Errorf("Wrong recently status: %v, %v", show, status) + } +} + +func TestOnlineOfflineAway(t *testing.T) { + timestamp := time.Now().Unix() - 3599 + time := time.Unix(timestamp, 0) + show, status := userStatusToText(client.UserStatus(&client.UserStatusOffline{WasOnline: int32(timestamp)})) + if show != "away" || status != "Last seen at "+time.Format(testTimeFormat) { + t.Errorf("Wrong away status: %v, %v", show, status) + } +} + +func TestOnlineOfflineXa(t *testing.T) { + timestamp := time.Now().Unix() - 3601 + time := time.Unix(timestamp, 0) + show, status := userStatusToText(client.UserStatus(&client.UserStatusOffline{WasOnline: int32(timestamp)})) + if show != "xa" || status != "Last seen at "+time.Format(testTimeFormat) { + t.Errorf("Wrong xa status: %v, %v", show, status) + } +}