前言
Telegram 在超级群组(Supergroup)中引入了 Topics(话题) 功能,使得群组内的讨论更加有条理。每个话题都有一个唯一的 ID,我们可以使用 Golang 通过 Telegram Bot API 发送消息到特定的话题。
这个功能在以下场景特别有用:
- 自动化运维:将不同服务的监控告警发送到对应的话题中
- 项目管理:自动将 CI/CD 状态、代码提交信息发送到特定话题
- 社区管理:根据内容类型自动分类消息到不同话题
本文将介绍如何使用 gopkg.in/telebot.v3
库,结合 Telegram Bot API 发送消息到指定的 Topic,并提供完整的示例代码,帮助你快速实现该功能。
1. 前提条件
在开始之前,请确保你已经具备以下条件:
- Telegram 机器人:已创建 Telegram 机器人(通过 BotFather 获取 Bot Token)。
- 超级群组(Supergroup):开启Topic的群组。
- 获取群组 ID 和话题 ID:你需要知道群组的
chat ID
和message_thread_id
(即话题 ID)。 - Golang 开发环境:已安装 Golang。
2. 安装依赖
我们将使用 telebot
库来与 Telegram 交互。安装它的方法如下:
go get gopkg.in/telebot.v3
3. 获取群组 ID 和 Topic ID
在 Telegram 超级群组中,每个 Topic 都有一个唯一的 message_thread_id
。获取 message_thread_id
的方法如下:
方式 1: 在Share link中获取
- 进入 Telegram 群组中,选中一个Topic,点击Channel名字,进入Info页面
- 在Info页面上有share link, 类似:
https://t.me/1234567890/1
- share link的格式是这样的:
https://t.me/chatId/topicId
(Group的chatId需要在前面加上-100
, 比如上面的chatId, 针对group就是:-1001234567890
), 1是topicId
方式 2:从消息的share link中获取
- 进入 Telegram 群组,找到目标话题。
- 发送一条消息。
- 右键(电脑)或者长按(手机)发出的消息,选择 Copy Message Link, Message Link的格式类似 share link,只是多了messageId, 格式是这样的:
https://t.me/chatId/topicId/messageId
, chatId类似也需要加上-100
方式 3:代码获取
你也可以使用 Telegram Bot 监听群组消息并自动获取 chat_id
和 message_thread_id
,需要设置Bot为管理员,这样才可以收到消息,这里获取到的chatId已经包含了-100
,代码示例如下:
bot.Handle(telebot.OnText, func(c telebot.Context) error {
fmt.Printf("Message: %s, Chat ID: %d, Thread ID: %d\n", c.Text(), msg.Chat.ID, msg.ThreadID)
return nil
})
4. 发送消息到指定话题
以下是完整的 Golang 代码示例,展示如何使用 telebot
发送消息到指定话题。
代码示例
package main
import (
"flag"
"fmt"
"time"
"gopkg.in/telebot.v3"
)
func main() {
// 定义命令行参数
botToken := flag.String("token", "", "Telegram Bot Token")
chatID := flag.Int64("chat", 0, "Chat ID (supergroup ID, 需要带-100前缀)")
topicID := flag.Int("topic", 0, "Topic message thread ID (可选,General话题不需要指定)")
messageText := flag.String("message", "Hello, Topic!", "要发送的消息内容")
flag.Parse()
// 验证必需的参数
if *botToken == "" || *chatID == 0 {
fmt.Println("Usage:")
flag.PrintDefaults()
return
}
// 初始化bot,设置10秒超时
bot, err := telebot.NewBot(telebot.Settings{
Token: *botToken,
Poller: &telebot.LongPoller{Timeout: 10 * time.Second},
})
if err != nil {
panic(err)
}
// 准备发送选项,如果指定了topicID则添加到选项中
options := &telebot.SendOptions{}
if *topicID != 0 {
options.ThreadID = *topicID
}
// 发送消息
sentMessage, err := bot.Send(&telebot.Chat{ID: *chatID}, *messageText, options)
if err != nil {
fmt.Println("发送失败:", err)
} else {
fmt.Println("消息发送成功:", sentMessage.ID)
}
}
对于General Topic, ID是1,发送给这个Topic的消息TopicId不需要指定,如果设置成1会提示错误:
发送失败: telegram: Bad Request: message thread not found (400)
5. 进阶用法
发送 Markdown 或 HTML 格式的消息
可以使用 Markdown 或 HTML 格式化文本消息:
options.ParseMode = telebot.ModeMarkdown
sentMessage, err := bot.Send(&telebot.Chat{ID: *chatID}, fmt.Sprintf("*%s*", *messageText), options)
或 HTML 方式:
options.ParseMode = telebot.ModeHTML
sentMessage, err := bot.Send(&telebot.Chat{ID: *chatID}, fmt.Sprintf("<b>%s</b>", *messageText), options)
发送图片到指定话题
photo := &telebot.Photo{File: telebot.FromURL("https://www.baidu.com/img/flexible/logo/pc/result.png")}
sentMessage, err := bot.Send(&telebot.Chat{ID: *chatID}, photo, options)
6. 运行代码
运行的时候输入参数 token
、chat
和 topic
为你的实际值后,topic
为可选参数,比如发给 #General
的消息就可以为空,运行以下命令:
go run main.go -token=your-bot-token -chat=-1001234567890 -topic=12345
成功后,你应该能在指定的 Telegram 话题中看到机器人发送的消息。
7. 总结
本文介绍了如何使用 Golang 通过 telebot
库将消息发送到 Telegram 超级群组的 指定话题(Topic) 中。
核心步骤包括:
- 获取
message_thread_id
(话题 ID)。 - 使用
telebot
发送消息到指定话题。 - 监听消息获取
Topic ID
并进行进阶应用。
通过这些方法,你可以轻松地在 Telegram Bot 中管理不同话题的消息发送。如果你在实践过程中遇到问题,欢迎留言讨论!🚀
8. 常见问题与解决方案
8.1 权限问题
- 确保 Bot 是群组的管理员
- Bot 需要有发送消息的权限
- 如果要发送媒体文件,需要确保有发送媒体的权限
8.2 常见错误码
400 Bad Request: message thread not found
: 话题ID不存在或者是General话题(ID=1)400 Bad Request: chat not found
: Chat ID 错误或 Bot 不在群组中403 Forbidden: bot was blocked by the user
: Bot被移出群组或被封禁
8.3 最佳实践
- 建议实现错误重试机制
- 对于重要消息,可以添加发送确认和状态检查
- 考虑实现消息限流,避免触发 Telegram API 限制
示例代码:
// 实现简单的重试机制
func sendWithRetry(bot *telebot.Bot, chat *telebot.Chat, message string, options *telebot.SendOptions) (*telebot.Message, error) {
maxRetries := 3
for i := 0; i < maxRetries; i++ {
sentMessage, err := bot.Send(chat, message, options)
if err == nil {
return sentMessage, nil
}
time.Sleep(time.Second * time.Duration(i+1))
}
return nil, fmt.Errorf("failed after %d retries", maxRetries)
}