go-bot

May 29, 2026 · View on GitHub

聊天平台 bot 封裝庫。實裝 Telegram(long polling)、Discord(WebSocket gateway)、LINE(webhook)、TTS。Telegram / Discord 為 outbound 連線,本機 / NAT 後皆可跑;LINE 走 webhook(inbound),需公開 HTTPS endpoint。

telegram

API用途
New(token, opts ...Option)建立 *Bot
Start(ctx)啟動 long polling
Close()停止;冪等
Status(){Running, Username, UserID}
Reply(handler)註冊 sync handler
Send(ctx, chatID, replyTo, text, opts...)發訊息
Delete(ctx, chatID, msgID)刪訊息
SendFile(ctx, chatID, t, path, caption...)t = TypeDocument / TypeVideo / TypeAudio
SendPhoto(ctx, chatID, paths, caption...)1–10 張
SendVoice(ctx, chatID, text, apiKey, caption...)TTS → OGG 上傳
SendInput(ctx, chatID, replyTo, text, opts...)ForceReply prompt
SendSelect(ctx, chatID, replyTo, text, items, opts...)inline keyboard single-select
SendMultiSelect(ctx, chatID, replyTo, text, items, opts...)inline keyboard multi-select
SendStatus(ctx, chatID, replyTo, text, opts...)「思考中」訊息 + reaction;debounce 1s
FinishStatus(ctx, chatID)清 reaction + 刪 status
SaveFile(ctx, fileID, dir)下載落地;UUID 命名;20 MB cap

OptionWithHTTPClient / WithPollTimeout MessageOptionWithSendType(TypeMarkdown / TypeHTML) StatusOptionWithStatusEmoji / WithStatusSendType

InputChatID / ChatName / MessageID / UserID / Username / Text / Caption / Photo / Document / CallbackData / CallbackPicks / Raw

bot, _ := telegram.New(token)
defer bot.Close()

bot.Reply(func(ctx context.Context, in telegram.Input) string {
    return "echo: " + in.Text
})
bot.Start(ctx)

bot.Send(ctx, chatID, 0, "*hello*", telegram.WithSendType(telegram.TypeMarkdown))
bot.SendFile(ctx, chatID, telegram.TypeDocument, "./report.pdf")
bot.SendPhoto(ctx, chatID, []string{"./a.png", "./b.png"}, "caption")
bot.SendVoice(ctx, chatID, "今天天氣不錯", geminiAPIKey)
bot.SendSelect(ctx, chatID, msgID, "選個顏色", []string{"紅", "綠", "藍"})
bot.SendMultiSelect(ctx, chatID, msgID, "選興趣", []string{"閱讀", "電影"})
bot.SendInput(ctx, chatID, msgID, "你叫什麼名字?")
bot.SendStatus(ctx, chatID, msgID, "處理中...")
bot.FinishStatus(ctx, chatID)

path, _ := bot.SaveFile(ctx, in.Photo[len(in.Photo)-1].FileID, "./tmp")

discord

底層 bwmarrin/discordgo;WebSocket gateway。

API用途
New(token)建立 *Bot
Start(ctx)驗 token + 開 WebSocket
Close()停止;冪等
Status(){Running, Username, UserID}
Reply(handler)註冊 sync handler
Send(ctx, channelID, replyTo, text)發訊息
Delete(ctx, channelID, messageID)刪訊息
SendFiles(ctx, channelID, replyTo, paths, caption...)1–10 個 attachment
SendVoice(ctx, channelID, replyTo, text, apiKey, caption...)TTS → OGG attachment
SendInput(ctx, channelID, replyTo, prompt)Button → Modal → ReplyHandler
SendSelect(ctx, channelID, replyTo, text, items)StringSelectMenu single-pick
SendMultiSelect(ctx, channelID, replyTo, text, items)StringSelectMenu multi-pick
SendStatus(ctx, channelID, replyTo, text, opts...)「思考中」訊息 + reaction;debounce 1s
FinishStatus(ctx, channelID)清 reaction + 刪 status
Save(ctx, att, dir)下載 attachment 落地;UUID 命名;25 MiB cap

StatusOptionWithStatusEmoji

InputChannelID / ChannelName / GuildID / MessageID / UserID / Username / Text / Attachments / CallbackPicks / Raw

需在 Developer Portal 開 Message Content Intent,否則 Text 為空(mention / DM / 自己訊息除外)。

bot, _ := discord.New(token)
defer bot.Close()

bot.Reply(func(ctx context.Context, in discord.Input) string {
    for _, att := range in.Attachments {
        bot.Save(ctx, att, "./tmp")
    }
    return "echo: " + in.Text
})
bot.Start(ctx)

bot.Send(ctx, channelID, "", "hello")
bot.SendFiles(ctx, channelID, "", []string{"./a.png", "./b.png"}, "caption")
bot.SendVoice(ctx, channelID, "", "今天天氣不錯", geminiAPIKey)
bot.SendInput(ctx, channelID, msgID, "你叫什麼名字?")
bot.SendSelect(ctx, channelID, msgID, "選個顏色", []string{"紅", "綠", "藍"})
bot.SendMultiSelect(ctx, channelID, msgID, "選興趣", []string{"閱讀", "電影"})
bot.SendStatus(ctx, channelID, msgID, "思考中...")
bot.FinishStatus(ctx, channelID)
bot.Delete(ctx, channelID, promptID)

line

底層 line-bot-sdk-go/v8;webhook server(inbound,需公開 HTTPS endpoint)。範疇最小:只有 Reply + Send,無互動元件。

API用途
New(secret, token, port, opts ...Option)建立 *Bot;listen :port
Start(ctx)驗 token + 起 webhook server
Close()停止;冪等
Status(){Running, UserID, BasicID, DisplayName}
Reply(handler)註冊 sync handler;走 reply token 回覆
Send(ctx, to, text)PushMessage 到指定 target(user / group / room id)
Save(ctx, messageID, dir)下載 image/video/audio/file 訊息內容落地;UUID 命名;50 MiB cap

OptionWithPath(webhook path,預設 /linebot/webhook

InputSourceType / UserID / Username / GroupID / RoomID / ReplyToken / MessageID / MessageType / Text / FileName / Raw

Username 為 sender DisplayName,dispatch 依 source type 自動打 profile API 取得(每訊息一次 REST,best-effort)。MessageTypetext/image/video/audio/file;非 text 訊息走 Save(ctx, in.MessageID, dir) 落地。

需在 LINE Developer Console 回填 webhook URL(https://<domain>/linebot/webhook)、開 Use webhook、關 auto-reply。

bot, _ := line.New(secret, token, "16722")
defer bot.Close()

bot.Reply(func(ctx context.Context, in line.Input) string {
    if in.MessageType != "text" {
        path, _ := bot.Save(ctx, in.MessageID, "./tmp")
        return "saved: " + path
    }
    return "echo: " + in.Text
})
bot.Start(ctx)

bot.Send(ctx, userID, "hello")

tts

API用途
Get(ctx, apiKey, text)Gemini TTS → OGG/OPUS bytes

ffmpeg in PATH。

ogg, err := tts.Get(ctx, apiKey, "今天天氣不錯")