package telegram import ( "strconv" "strings" "dev.narayana.im/narayana/telegabber/xmpp/gateway" 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) case client.TypeUpdateUserStatus: typedUpdate, ok := update.(*client.UpdateUserStatus) if !ok { uhOh() } c.updateUserStatus(typedUpdate) case client.TypeUpdateNewChat: typedUpdate, ok := update.(*client.UpdateNewChat) if !ok { uhOh() } c.updateNewChat(typedUpdate) case client.TypeUpdateNewMessage: typedUpdate, ok := update.(*client.UpdateNewMessage) if !ok { uhOh() } c.updateNewMessage(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 show, status := userStatusToText(update.User.Status) c.processStatusUpdate(update.User.Id, status, show) } func (c *Client) updateUserStatus(update *client.UpdateUserStatus) { 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") } } func (c *Client) updateNewMessage(update *client.UpdateNewMessage) { // ignore self outgoing messages if update.Message.IsOutgoing && update.Message.SendingState != nil && update.Message.SendingState.MessageSendingStateType() == client.TypeMessageSendingStatePending { return } log.WithFields(log.Fields{ "chat_id": update.Message.ChatId, }).Warn("New message from chat") text := c.messageToText(update.Message) file, filename := c.contentToFilename(update.Message.Content) // download file(s) if file != nil && !file.Local.IsDownloadingCompleted { c.client.DownloadFile(&client.DownloadFileRequest{ FileId: file.Id, Priority: 32, Synchronous: true, }) } // OTR support (I do not know why would you need it, seriously) if !strings.HasPrefix(text, "?OTR") { var prefix strings.Builder prefix.WriteString(c.messageToPrefix(update.Message, c.formatContent(file, filename))) if text != "" { // \n if it is groupchat and message is not empty if update.Message.ChatId < 0 { prefix.WriteString("\n") } else if update.Message.ChatId > 0 { prefix.WriteString(" | ") } prefix.WriteString(text) } text = prefix.String() } // mark message as read c.client.ViewMessages(&client.ViewMessagesRequest{ ChatId: update.Message.ChatId, MessageIds: []int64{update.Message.Id}, ForceRead: true, }) // forward message to XMPP gateway.SendMessage(c.jid, strconv.Itoa(int(update.Message.ChatId)), text, c.xmpp) }