penguin/golifehk

@golifehk bot in Telegram

adaptors/tg/botsend.go

raw ยท 3092 bytes

package tg

import (
	"fmt"
	"strings"

	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
	i18n "github.com/tgckpg/golifehk/i18n"
	query "github.com/tgckpg/golifehk/query"
	utils "github.com/tgckpg/golifehk/utils"
)

func BotSendText(lang string, bot *tgbotapi.BotAPI, update *tgbotapi.Update, mesg *string) error {
	if update == nil || update.Message == nil || mesg == nil {
		return fmt.Errorf("nil update/message/text")
	}

	chatID := update.Message.Chat.ID
	replyTo := update.Message.MessageID

	msg := tgbotapi.NewMessage(chatID, *mesg)
	msg.ParseMode = "MarkdownV2"
	msg.ReplyToMessageID = replyTo

	return sendMessageOrFile(lang, bot, msg, *mesg)
}

func BotSend(bot *tgbotapi.BotAPI, update *tgbotapi.Update, qResult query.IQueryResult) (bool, error) {
	mesg, err := qResult.Message()
	if err != nil {
		return false, err
	}

	mesgType := qResult.DataType()

	switch mesgType {
	case "IGNORE":
		return false, nil
	}

	chatID, replyTo, err := getChatAndReply(update)
	if err != nil {
		return false, err
	}

	msg := tgbotapi.NewMessage(chatID, mesg)
	msg.ParseMode = "MarkdownV2"

	if replyTo != 0 {
		msg.ReplyToMessageID = replyTo
	}

	switch mesgType {
	case "PlainText":

	case "Table":
		buttonRows := [][]tgbotapi.InlineKeyboardButton{}

		for _, row := range qResult.GetTableData() {
			buttons := []tgbotapi.InlineKeyboardButton{}

			for _, cell := range row {
				button := tgbotapi.NewInlineKeyboardButtonData(cell.Name, cell.Value)
				buttons = append(buttons, button)
			}

			buttonRows = append(buttonRows, buttons)
		}

		msg.ReplyMarkup = tgbotapi.NewInlineKeyboardMarkup(buttonRows...)
	}

	if err := sendMessageOrFile(qResult.UserLang(), bot, msg, mesg); err != nil {
		return false, err
	}

	return true, nil
}

func getChatAndReply(update *tgbotapi.Update) (chatID int64, replyTo int, err error) {
	if update == nil {
		return 0, 0, fmt.Errorf("nil update")
	}

	if update.Message != nil {
		return update.Message.Chat.ID, update.Message.MessageID, nil
	}

	if update.CallbackQuery != nil && update.CallbackQuery.Message != nil {
		return update.CallbackQuery.Message.Chat.ID, 0, nil
	}

	return 0, 0, fmt.Errorf("update has no message or callback message")
}

func sendMessageOrFile(lang string, bot *tgbotapi.BotAPI, msg tgbotapi.MessageConfig, text string) error {
	_, err := bot.Send(msg)
	if err == nil {
		return nil
	}

	if !strings.Contains(err.Error(), "message is too long") {
		return err
	}

	doc := tgbotapi.NewDocument(
		msg.ChatID,
		tgbotapi.FileBytes{
			Name:  "message.txt",
			Bytes: []byte(utils.UnescapeMDv2Text(text)),
		},
	)

	langPack, err := i18n.LoadKeys(lang)
	doc.Caption = i18n.TG_MESG_TOO_LONG.Text(langPack)

	if msg.ReplyToMessageID != 0 {
		doc.ReplyToMessageID = msg.ReplyToMessageID
	}

	// Keep inline keyboard if this was a table result.
	//
	// This is useful when the text is too long but the buttons are still needed.
	doc.ReplyMarkup = msg.ReplyMarkup

	_, docErr := bot.Send(doc)
	if docErr != nil {
		return fmt.Errorf("send message failed: %w; send document failed: %w", err, docErr)
	}

	return nil
}