aboutsummaryrefslogblamecommitdiff
path: root/telegram/handlers.go
blob: d2d5b61c8c856d763f5b569a8d474b0b0108458a (plain) (tree)
1
2
3
4
5
6
7
8


                
                 
                 
 

                                                          




















                                                                              





                                                                                    





                                                                                 





                                                                                    











                                                         

                                                            
 

                                                                    








































                                                                                             
 


















































                                                                                                                
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)
}