[Go] Telegram Bot 進階篇

程式語言:Go
Package:github.com/go-telegram-bot-api/telegram-bot-api
官方介紹
官方 API
telegram-bot-api GitHub

功能:實現各式進階用法

送出訊息

// 送出訊息
func (t *TeleBot) sendMessage(chatID int64, m string) {
    msg := tgbotapi.NewMessage(chatID, m)
    t.botAPI.Send(msg)
}

建立下拉式鍵盤選單

  • location & contact 只能使用在 private chat
    在其餘 chat 使用,會導致無法顯示
func (t *TeleBot) creatReplyKeyboardMarkup(chatID int64) {
    msg := tgbotapi.NewMessage(chatID, "ReplyKeyboardMarkup")
    msg.ReplyMarkup = tgbotapi.ReplyKeyboardMarkup{
        Keyboard: [][]tgbotapi.KeyboardButton{
            tgbotapi.NewKeyboardButtonRow(
                tgbotapi.NewKeyboardButton("button(1,1)"),
                tgbotapi.NewKeyboardButtonLocation("location(1,2)"),
                tgbotapi.NewKeyboardButtonContact("contact(1,3)"),
            ),
            tgbotapi.NewKeyboardButtonRow(
                tgbotapi.NewKeyboardButton("button(2,1)"),
                tgbotapi.NewKeyboardButtonLocation("location(2,2)"),
                tgbotapi.NewKeyboardButtonContact("contact(2,3)"),
            ),
        },
    }

    t.botAPI.Send(msg)
}

移除下拉式鍵盤選單

func (t *TeleBot) removeReplyKeyboardMarkup(chatID int64) {
    msg := tgbotapi.NewMessage(chatID, "remove ReplyKeyboardMarkup")
    msg.ReplyMarkup = tgbotapi.ReplyKeyboardRemove{
        RemoveKeyboard: true,
    }
    t.botAPI.Send(msg)
}

建立一次性鍵盤選單並調整為最佳化尺寸


func (t *TeleBot) creatReplyKeyboardMarkupOnetimeResize(chatID int64) {
    msg := tgbotapi.NewMessage(chatID, "ReplyKeyboardMarkupOneTimeSize")
    msg.ReplyMarkup = tgbotapi.ReplyKeyboardMarkup{
        Keyboard: [][]tgbotapi.KeyboardButton{
            tgbotapi.NewKeyboardButtonRow(
                tgbotapi.NewKeyboardButton("button(1,1)"),
                tgbotapi.NewKeyboardButtonLocation("location(1,2)"),
                tgbotapi.NewKeyboardButtonContact("contact(1,3)"),
            ),
            tgbotapi.NewKeyboardButtonRow(
                tgbotapi.NewKeyboardButton("button(2,1)"),
                tgbotapi.NewKeyboardButtonLocation("location(2,2)"),
                tgbotapi.NewKeyboardButtonContact("contact(2,3)"),
            ),
        },
        OneTimeKeyboard: true,
        ResizeKeyboard:  true,
    }

    t.botAPI.Send(msg)
}

建立聊天選單


func (t *TeleBot) creatInlineKeyboardMarkup(chatID int64) {
    msg := tgbotapi.NewMessage(chatID, "inlineButton")
    str := "cmd"
    msg.ReplyMarkup = tgbotapi.NewInlineKeyboardMarkup(
        tgbotapi.NewInlineKeyboardRow(
            tgbotapi.NewInlineKeyboardButtonData("text(1,1)", "callback_data"),
            tgbotapi.NewInlineKeyboardButtonURL("url(1,3)", "https://core.telegram.org/bots/api#inlinekeyboardmarkup"),
            tgbotapi.NewInlineKeyboardButtonSwitch("switch_inline_query(1,3)", "cmd"),
            tgbotapi.InlineKeyboardButton{
                Text:                         "switch_inline_query_current_chat(1,4)",
                SwitchInlineQueryCurrentChat: &str,
            },
        ),
        tgbotapi.NewInlineKeyboardRow(
            tgbotapi.NewInlineKeyboardButtonData("text(2,1)", "callback_data"),
            tgbotapi.NewInlineKeyboardButtonURL("url(2,2)", "https://core.telegram.org/bots/api#inlinekeyboardmarkup"),
            tgbotapi.NewInlineKeyboardButtonSwitch("switch_inline_query(2,3)", "cmd"),
            tgbotapi.InlineKeyboardButton{
                Text:                         "switch_inline_query_current_chat(2,4)",
                SwitchInlineQueryCurrentChat: &str,
            },
        ),
    )

    t.botAPI.Send(msg)
}

送出強迫回覆訊息


func (t *TeleBot) sendForceReply(chatID int64) {
    msg := tgbotapi.NewMessage(chatID, "ForceReply")

    msg.ReplyMarkup = tgbotapi.ForceReply{
        ForceReply: true,
    }

    t.botAPI.Send(msg)
}

送出 Markdown 格式


func (t *TeleBot) sendMarkdown(chatID int64) {

    markdown := `*bold text*"
    _italic text_"
    [inline URL](http://www.example.com/)"
    [inline mention of a user](tg://user?id=123456789)`
    markdown += "`inline fixed-width code`\n"
    markdown += "```block_language\npre-formatted fixed-width code block```"
    msg := tgbotapi.NewMessage(chatID, markdown)
    msg.ParseMode = tgbotapi.ModeMarkdown
    t.botAPI.Send(msg)
}

送出 HTML 格式


func (t *TeleBot) sendHTML(chatID int64) {
    htmlT := `<b>bold</b>, <strong>bold</strong>
    <i>italic</i>, <em>italic</em>
    <a href="http://www.example.com/">inline URL</a>
    <a href="tg://user?id=123456789">inline mention of a user</a>
    <code>inline fixed-width code</code>
    <pre>pre-formatted fixed-width code block</pre>`
    msg := tgbotapi.NewMessage(chatID, htmlT)
    msg.ParseMode = tgbotapi.ModeHTML
    t.botAPI.Send(msg)
}

送出照片


func (t *TeleBot) sendPhoto(chatID int64) {
    msg := tgbotapi.NewPhotoShare(chatID, "https://www.logaster.com/blog/wp-content/uploads/2013/06/jpg.png")
    msg.Caption = "caption"

    t.botAPI.Send(msg)
}

針對聊天選單做出回覆


// demo 聊天選單
var replyMarkup = tgbotapi.NewInlineKeyboardMarkup(
    ...
    tgbotapi.NewInlineKeyboardRow(
        tgbotapi.NewInlineKeyboardButtonData("callback_data", "callback_data"),
        tgbotapi.NewInlineKeyboardButtonData("callback_data_alert", "callback_data_alert"),
    ),
    tgbotapi.NewInlineKeyboardRow(
        tgbotapi.NewInlineKeyboardButtonData("edited text(也可改 markup)", "edited_text"),
    ),
    tgbotapi.NewInlineKeyboardRow(
        tgbotapi.NewInlineKeyboardButtonData("edited reply markup", "edited_reply_markup"),
    ),
)

// 回覆空訊息,表示已處理 CallbackQuery
func (t *TeleBot) emptyAnswer(CallbackQueryID string) {
    configAlert := tgbotapi.NewCallback(CallbackQueryID, "")
    t.botAPI.AnswerCallbackQuery(configAlert)
}

// 送出對應的 CallbackQuery 回覆 & 對應指令的動作
func (t *TeleBot) sendAnswerCallbackQuery() {
    for update := range t.updates {
        if update.Message == nil && update.CallbackQuery == nil {
            continue
        }

        if update.Message != nil {
            switch update.Message.Text {
            case "/demo":
                t.demo(update.Message.Chat.ID)
            }
        }

        if update.CallbackQuery != nil {
            chatID := update.CallbackQuery.Message.Chat.ID
            switch update.CallbackQuery.Data {
            case "ReplyKeyboardMarkup":
                go t.creatReplyKeyboardMarkup(chatID)
                go t.emptyAnswer(update.CallbackQuery.ID)
            ...
            case "callback_data":
                config := tgbotapi.NewCallback(update.CallbackQuery.ID, "callbackAnswer")
                go t.botAPI.AnswerCallbackQuery(config)
            case "callback_data_alert":
                configAlert := tgbotapi.NewCallbackWithAlert(update.CallbackQuery.ID, "callbackAnswerAlert")
                go t.botAPI.AnswerCallbackQuery(configAlert)
            case "edited_text":
                editText := tgbotapi.NewEditMessageText(
                    update.CallbackQuery.Message.Chat.ID,
                    update.CallbackQuery.Message.MessageID,
                    "edited text(有改到)",
                )

                replyMarkup.InlineKeyboard[7][0].Text = "edited text(也可改 markup) 已修改"

                editText.ReplyMarkup = &replyMarkup

                go t.botAPI.Send(editText)
                go t.emptyAnswer(update.CallbackQuery.ID)
            case "edited_reply_markup":
                replyMarkup.InlineKeyboard[8][0].Text = "edited reply markup 已修改"

                editReplyMarkup := tgbotapi.NewEditMessageReplyMarkup(
                    update.CallbackQuery.Message.Chat.ID,
                    update.CallbackQuery.Message.MessageID,
                    replyMarkup,
                )

                go t.botAPI.Send(editReplyMarkup)
                go t.emptyAnswer(update.CallbackQuery.ID)
            }

        }
    }
}

完整程式碼

package main

import (
    "log"

    "github.com/go-telegram-bot-api/telegram-bot-api"
)

type TeleBot struct {
    botAPI  *tgbotapi.BotAPI
    updates tgbotapi.UpdatesChannel
}

// 送出訊息
func (t *TeleBot) sendMessage(chatID int64, m string) {
    msg := tgbotapi.NewMessage(chatID, m)
    t.botAPI.Send(msg)
}

// 建立下拉式鍵盤選單
func (t *TeleBot) creatReplyKeyboardMarkup(chatID int64) {
    msg := tgbotapi.NewMessage(chatID, "ReplyKeyboardMarkup")
    msg.ReplyMarkup = tgbotapi.ReplyKeyboardMarkup{
        Keyboard: [][]tgbotapi.KeyboardButton{
            tgbotapi.NewKeyboardButtonRow(
                tgbotapi.NewKeyboardButton("button(1,1)"),
                tgbotapi.NewKeyboardButtonLocation("location(1,2)"),
                tgbotapi.NewKeyboardButtonContact("contact(1,3)"),
            ),
            tgbotapi.NewKeyboardButtonRow(
                tgbotapi.NewKeyboardButton("button(2,1)"),
                tgbotapi.NewKeyboardButtonLocation("location(2,2)"),
                tgbotapi.NewKeyboardButtonContact("contact(2,3)"),
            ),
        },
    }

    t.botAPI.Send(msg)
}

// 移除下拉式鍵盤選單
func (t *TeleBot) removeReplyKeyboardMarkup(chatID int64) {
    msg := tgbotapi.NewMessage(chatID, "remove ReplyKeyboardMarkup")
    msg.ReplyMarkup = tgbotapi.ReplyKeyboardRemove{
        RemoveKeyboard: true,
    }
    t.botAPI.Send(msg)
}

// 建立一次性鍵盤選單並調整為最佳化尺寸
func (t *TeleBot) creatReplyKeyboardMarkupOnetimeResize(chatID int64) {
    msg := tgbotapi.NewMessage(chatID, "ReplyKeyboardMarkupOneTimeSize")
    msg.ReplyMarkup = tgbotapi.ReplyKeyboardMarkup{
        Keyboard: [][]tgbotapi.KeyboardButton{
            tgbotapi.NewKeyboardButtonRow(
                tgbotapi.NewKeyboardButton("button(1,1)"),
                tgbotapi.NewKeyboardButtonLocation("location(1,2)"),
                tgbotapi.NewKeyboardButtonContact("contact(1,3)"),
            ),
            tgbotapi.NewKeyboardButtonRow(
                tgbotapi.NewKeyboardButton("button(2,1)"),
                tgbotapi.NewKeyboardButtonLocation("location(2,2)"),
                tgbotapi.NewKeyboardButtonContact("contact(2,3)"),
            ),
        },
        OneTimeKeyboard: true,
        ResizeKeyboard:  true,
    }

    t.botAPI.Send(msg)
}

// 建立聊天選單
func (t *TeleBot) creatInlineKeyboardMarkup(chatID int64) {
    msg := tgbotapi.NewMessage(chatID, "inlineButton")
    str := "cmd"
    msg.ReplyMarkup = tgbotapi.NewInlineKeyboardMarkup(
        tgbotapi.NewInlineKeyboardRow(
            tgbotapi.NewInlineKeyboardButtonData("text(1,1)", "callback_data"),
            tgbotapi.NewInlineKeyboardButtonURL("url(1,3)", "https://core.telegram.org/bots/api#inlinekeyboardmarkup"),
            tgbotapi.NewInlineKeyboardButtonSwitch("switch_inline_query(1,3)", "cmd"),
            tgbotapi.InlineKeyboardButton{
                Text:                         "switch_inline_query_current_chat(1,4)",
                SwitchInlineQueryCurrentChat: &str,
            },
        ),
        tgbotapi.NewInlineKeyboardRow(
            tgbotapi.NewInlineKeyboardButtonData("text(2,1)", "callback_data"),
            tgbotapi.NewInlineKeyboardButtonURL("url(2,2)", "https://core.telegram.org/bots/api#inlinekeyboardmarkup"),
            tgbotapi.NewInlineKeyboardButtonSwitch("switch_inline_query(2,3)", "cmd"),
            tgbotapi.InlineKeyboardButton{
                Text:                         "switch_inline_query_current_chat(2,4)",
                SwitchInlineQueryCurrentChat: &str,
            },
        ),
    )

    t.botAPI.Send(msg)
}

// 送出強迫回覆訊息
func (t *TeleBot) sendForceReply(chatID int64) {
    msg := tgbotapi.NewMessage(chatID, "ForceReply")

    msg.ReplyMarkup = tgbotapi.ForceReply{
        ForceReply: true,
    }

    t.botAPI.Send(msg)
}

// demo 聊天選單
var replyMarkup = tgbotapi.NewInlineKeyboardMarkup(
    tgbotapi.NewInlineKeyboardRow(
        tgbotapi.NewInlineKeyboardButtonData("ReplyKeyboardMarkup", "ReplyKeyboardMarkup"),
        tgbotapi.NewInlineKeyboardButtonData("removeReplyKeyboardMarkup", "removeReplyKeyboardMarkup"),
    ),
    tgbotapi.NewInlineKeyboardRow(
        tgbotapi.NewInlineKeyboardButtonData("ReplyKeyboardMarkupOneTimeSize", "ReplyKeyboardMarkupOneTimeSize"),
    ),
    tgbotapi.NewInlineKeyboardRow(
        tgbotapi.NewInlineKeyboardButtonData("InlineKeyboardMarkup", "InlineKeyboardMarkup"),
    ),
    tgbotapi.NewInlineKeyboardRow(
        tgbotapi.NewInlineKeyboardButtonData("ForceReply", "ForceReply"),
    ),
    tgbotapi.NewInlineKeyboardRow(
        tgbotapi.NewInlineKeyboardButtonData("Markdown_HTML", "Markdown_HTML"),
    ),
    tgbotapi.NewInlineKeyboardRow(
        tgbotapi.NewInlineKeyboardButtonData("Photo", "Photo"),
    ),
    tgbotapi.NewInlineKeyboardRow(
        tgbotapi.NewInlineKeyboardButtonData("callback_data", "callback_data"),
        tgbotapi.NewInlineKeyboardButtonData("callback_data_alert", "callback_data_alert"),
    ),
    tgbotapi.NewInlineKeyboardRow(
        tgbotapi.NewInlineKeyboardButtonData("edited text(也可改 markup)", "edited_text"),
    ),
    tgbotapi.NewInlineKeyboardRow(
        tgbotapi.NewInlineKeyboardButtonData("edited reply markup", "edited_reply_markup"),
    ),
)

// demo 指令用
func (t *TeleBot) demo(chatID int64) {
    msg := tgbotapi.NewMessage(chatID, "inlineButton")
    msg.ReplyMarkup = replyMarkup

    t.botAPI.Send(msg)
}

// 回覆空訊息,表示已處理 CallbackQuery
func (t *TeleBot) emptyAnswer(CallbackQueryID string) {
    configAlert := tgbotapi.NewCallback(CallbackQueryID, "")
    t.botAPI.AnswerCallbackQuery(configAlert)
}

// 送出對應的 CallbackQuery 回覆 & 對應指令的動作
func (t *TeleBot) sendAnswerCallbackQuery() {
    for update := range t.updates {
        if update.Message == nil && update.CallbackQuery == nil {
            continue
        }

        if update.Message != nil {
            switch update.Message.Text {
            case "/demo":
                t.demo(update.Message.Chat.ID)
            }
        }

        if update.CallbackQuery != nil {
            chatID := update.CallbackQuery.Message.Chat.ID
            switch update.CallbackQuery.Data {
            case "ReplyKeyboardMarkup":
                go t.creatReplyKeyboardMarkup(chatID)
                go t.emptyAnswer(update.CallbackQuery.ID)
            case "removeReplyKeyboardMarkup":
                go t.removeReplyKeyboardMarkup(chatID)
                go t.emptyAnswer(update.CallbackQuery.ID)
            case "ReplyKeyboardMarkupOneTimeSize":
                go t.creatReplyKeyboardMarkupOnetimeResize(chatID)
                go t.emptyAnswer(update.CallbackQuery.ID)
            case "InlineKeyboardMarkup":
                go t.creatInlineKeyboardMarkup(chatID)
                go t.emptyAnswer(update.CallbackQuery.ID)
            case "ForceReply":
                go t.sendForceReply(chatID)
                go t.emptyAnswer(update.CallbackQuery.ID)
            case "Markdown_HTML":
                go t.sendMarkdown(chatID)
                go t.sendHTML(chatID)
                go t.emptyAnswer(update.CallbackQuery.ID)
            case "Photo":
                go t.sendPhoto(chatID)
                go t.emptyAnswer(update.CallbackQuery.ID)
            case "callback_data":
                config := tgbotapi.NewCallback(update.CallbackQuery.ID, "callbackAnswer")
                go t.botAPI.AnswerCallbackQuery(config)
            case "callback_data_alert":
                configAlert := tgbotapi.NewCallbackWithAlert(update.CallbackQuery.ID, "callbackAnswerAlert")
                go t.botAPI.AnswerCallbackQuery(configAlert)
            case "edited_text":
                editText := tgbotapi.NewEditMessageText(
                    update.CallbackQuery.Message.Chat.ID,
                    update.CallbackQuery.Message.MessageID,
                    "edited text(有改到)",
                )

                replyMarkup.InlineKeyboard[7][0].Text = "edited text(也可改 markup) 已修改"

                editText.ReplyMarkup = &replyMarkup

                go t.botAPI.Send(editText)
                go t.emptyAnswer(update.CallbackQuery.ID)
            case "edited_reply_markup":
                replyMarkup.InlineKeyboard[8][0].Text = "edited reply markup 已修改"

                editReplyMarkup := tgbotapi.NewEditMessageReplyMarkup(
                    update.CallbackQuery.Message.Chat.ID,
                    update.CallbackQuery.Message.MessageID,
                    replyMarkup,
                )

                go t.botAPI.Send(editReplyMarkup)
                go t.emptyAnswer(update.CallbackQuery.ID)
            }

        }
    }
}

// 送出 markdown 格式
func (t *TeleBot) sendMarkdown(chatID int64) {

    markdown := `*bold text*"
    _italic text_"
    [inline URL](http://www.example.com/)"
    [inline mention of a user](tg://user?id=123456789)`
    markdown += "`inline fixed-width code`\n"
    markdown += "```block_language\npre-formatted fixed-width code block```"
    msg := tgbotapi.NewMessage(chatID, markdown)
    msg.ParseMode = tgbotapi.ModeMarkdown
    t.botAPI.Send(msg)
}

// 送出 HTML 格式
func (t *TeleBot) sendHTML(chatID int64) {
    htmlT := `<b>bold</b>, <strong>bold</strong>
    <i>italic</i>, <em>italic</em>
    <a href="http://www.example.com/">inline URL</a>
    <a href="tg://user?id=123456789">inline mention of a user</a>
    <code>inline fixed-width code</code>
    <pre>pre-formatted fixed-width code block</pre>`
    msg := tgbotapi.NewMessage(chatID, htmlT)
    msg.ParseMode = tgbotapi.ModeHTML
    t.botAPI.Send(msg)
}

// 送出照片
func (t *TeleBot) sendPhoto(chatID int64) {
    msg := tgbotapi.NewPhotoShare(chatID, "https://www.logaster.com/blog/wp-content/uploads/2013/06/jpg.png")
    msg.Caption = "caption"

    t.botAPI.Send(msg)
}

func main() {
    bot, err := tgbotapi.NewBotAPI("595702885:AAFIXbar3bl-a0H0YyWiKOvbX_u9X6s0FPs")
    if err != nil {
        log.Fatal(err)
    }
    bot.Debug = true

    teleBot := TeleBot{
        botAPI: bot,
    }

    u := tgbotapi.NewUpdate(0)
    u.Timeout = 60

    teleBot.updates, err = bot.GetUpdatesChan(u)
    teleBot.sendAnswerCallbackQuery()
}

留言