在上一篇文章中,我们快速申请并配置了一个 Telegram Bot,并通览了整个开发流程,帮助大家建立了基本的概念。而在本篇文章中,我们将深入细节,聚焦于命令,带你全面掌握 Bot 命令的管理方法。
部署建议
为了保障机器人的稳定运行,建议将 Telegram Bot 部署在香港高防服务器上。此类服务器不仅提供优质的网络带宽和低延迟,还能有效抵御 DDoS 攻击。若需进一步提升全球用户的访问速度,可结合高防CDN服务,分散流量压力并过滤恶意请求,确保命令处理的可靠性。
命令作用域
Telegram Bot 的命令是有作用域的,即命令的可见范围。当我们使用 @BotFather 设置好命令之后,用户输入 / 时,会自动显示命令列表,默认情况下,这些命令所有用户可见,即所有用户都会看到相同的命令列表。然而,在真实的业务中,我们通常有个性化的需求,例如下面的两种场景:
场景1:客服支持机器人
示例命令:
/contact_support – 与客服团队联系
/resolve_ticket – 客服人员标记工单已解决
/assign_ticket - 管理员指派工单给客服人员
显然,对于这些命令,普通用户不适合看到 /resolve_ticket,/assign_ticket两个命令,而客服团队也不适合看到 /contact_support命令。
场景2:订阅提醒机器人
示例命令:
/subscribe - 订阅加密资产行情信息
/event_reminder - 创建群活动提醒
显然,对于这些命令,在机器人的私聊窗口不适合看到 /event_reminder群命令,而在群聊窗口也不适合看到 /subscribe 等个人相关的命令。
遇到这种情况怎么办呢?这就要配置命令的作用域了,不同的作用域,命令的可见范围不一样,使得不同用户,不同角色,在不同的聊天场景下可以看到不同的命令。
重要提醒
命令作用域只能控制命令的显示范围,也就是用户在 Telegram 客户端输入 / 时的命令菜单列表,而不会进行权限检查。权限检查仍然需要在代码逻辑中实现,确保即使用户手动输入隐藏的命令,机器人也会检查其身份,并拒绝执行。而配置命令的目的主要是为了更好的用户体验,方便用户选择的同时,也避免了拼写错误。安全增强建议
除了代码层的权限校验,建议将机器人服务部署于香港高防服务器,并启用高防CDN。前者可防御大规模流量攻击,后者则能加速全球访问并拦截恶意请求,双管齐下提升服务安全性。
优先级
Telegram Bot 一共有 7 种命令作用域类型,如下所示:
- botCommandScopeDefault(默认)
- botCommandScopeAllPrivateChats(所有私聊可见)
- botCommandScopeAllGroupChats(所有群聊可见)
- botCommandScopeAllChatAdministrators(所有群聊管理员可见)
- botCommandScopeChat(特定私聊、群聊可见)
- botCommandScopeChatAdministrators(特定群聊管理员可见)
- botCommandScopeChatMember(特定群聊成员可见)
这些命令类型分别有各自的优先级。在用户输入 / 查看命令时,系统会根据优先级显示命令列表,其中优先级高的命令将覆盖优先级低的命令,确保用户只看到最相关的选项。使用 @BotFather 设置的命令,作用域都是默认类型,即botCommandScopeDefault
,这是优先级最低的命令。如果想设置更高优先级的命令,必须通过Bot API实现。
另外,优先级的高低除了受上面这 7 种作用域的影响,还受到language_code
的影响,language_code
是调用 Bot API 设置命令时的一个传参,具体是如何影响的,下面文章会详细讲解。
需要注意的是,命令的优先级在私聊和群聊这两种场景下是分别处理的。哪些类型适用于私聊,哪些适用于群聊,我已经在前文中做了标注,大家可以对照查看,我们接下来也会分开详细举例讲解。
了解了优先级的基本概念后,接下来我们就来看看,如何实际配置这些不同优先级的命令。
公共代码
Bot API 提供了一个方法:setMyCommands
,通过这个方法,我们可以设置任意自定义命令。为了避免代码示例的重复,这里将设置命令抽象为一个公共函数:setCommand
,下文的每一个示例都直接调用。
// 创建命令的数据结构
type BotCommand struct {
Command string `json:"command"` // 命令名
Description string `json:"description"` // 命令描述
}
// 作用域数据结构
type BotCommandScope struct {
Type string `json:"type"`
ChatId int64 `json:"chat_id"`
UserId int64 `json:"user_id"`
}
// 创建命令 API 的请求参数
// @param commands JSON数组,将要创建的命令集合,可以一次创建多个
// @param scope JSON对象,作用域
// @language_code 字符串,这是一个两位字母的语言代码,符合国际标准 ISO 639-1
type BotCommandRequest struct {
Commands []BotCommand `json:"commands"`
Scope BotCommandScope `json:"scope"`
LanguageCode string `json:"language_code"`
}
// Bot API 的域名地址,从环境变量读取`SOCIAL_TG_TOKEN`,这是你申请机器人成功后获得的 Token
var BotEndpoint = "https://api.telegram.org/bot" + os.Getenv("SOCIAL_TG_TOKEN")
// 设置命令
func setCommand(cmd string, desc string, scope BotCommandScope, languageCode string) {
url := fmt.Sprintf("%s/setMyCommands", BotEndpoint)
req := &BotCommandRequest{
Commands: []BotCommand{{Command: cmd, Description: desc}},
Scope: scope,
LanguageCode: languageCode,
}
reqByte, _ := json.Marshal(req)
http.Post(url, "application/json", bytes.NewBuffer(reqByte))
}
服务器部署提示
在调用 Bot API 时,若需处理高并发请求(例如订阅提醒机器人),建议将后端服务部署在香港高防服务器上,并通过[高防CDN](https://www.cdn07.com/)进行流量分发。这不仅能减少 API 响应延迟,还可避免因突发流量导致的服务器过载。
默认作用域
默认作用域是一个特殊的作用域,通过以下方式创建的命令都是默认作用域:
通过@BotFather设置的所有命令
调用Bot API设置命令未指定作用域
调用Bot API设置命令指定参数scope为default
使用@BotFather创建命令
如上图所示,在@BotFather聊天窗口输入/setcommands命令并发送成功后,会提示你选择自己的Bot,之后根据提示的格式输入要设置的命令,这里是:
命令:cmd_default_botfather
描述:default command by BotFather
注意,命令只能包含英文小写字母、数字和下划线 _,如/start、/get_info、/v2_status等。
收到Success的回复之后,我们就可以回到机器人聊天窗口验证效果了,输入/就可以看到刚刚设置的命令了,如下图所示:
使用Bot API创建命令
创建一条命令cmd_default,并分别配置不同的语言描述,作用域设置为default,这里的第4个参数de表示德语,传空表示不指定语言。
go
scope := BotCommandScope{Type: "default"}
setCommand("cmd_default", "默认", scope, "")
setCommand("cmd_default", "德语", scope, "de")
运行代码,回到机器人聊天窗口,输入/,我们来看看效果:
通过上面的图片,我们可以观察到2个问题:
之前设置的cmd_default_botfather不见了
现在设置的德语命令(即:cmd_default+de)没有显示
第1个问题:在优先级相同的情况下,每一次设置命令都会全部更新。上文我们说过,@BotFather设置的命令都是默认类型,因此,之前设置的cmd_default_botfather与这里设置的默认命令(cmd_default+"")优先级相同,因此被覆盖更新了。
第2个问题:在任何作用域类型下,scope + language_code 都要比单独的 scope 优先级更高。因此,cmd_default+de的优先级要高于cmd_default+""。那为什么没有显示呢?原因是Telegram客户端的默认语言是英语,只有切换到德语模式,才会显示德语命令,所有非德语模式,都显示为默认命令。
现在,我们将 Telegram 客户端语言设置为德语,在Bot聊天窗口输入/看看效果,如下图:
此时,就看到了德语命令(cmd_default+de),在德语模式下,默认命令(cmd_default+"")因为优先级低而被隐藏了。注意不是删除,不同优先级之间设置命令互不影响,不会覆盖更新。当你的 Telegram 客户端切换回其他语言就又会显示默认命令。
私聊命令
一共有 3 种作用域类型适用于私聊场景:
1. botCommandScopeDefault(默认)
2. botCommandScopeAllPrivateChats(所有私聊可见)
3. botCommandScopeChat(特定私聊可见)
创建命令示例:
go
scope = BotCommandScope{Type: "all_private_chats"}
setCommand("cmd_private_1", "所有私聊可见", scope, "")
scope = BotCommandScope{Type: "chat", ChatId: 123456789}
setCommand("cmd_private_2", "指定私聊可见", scope, "")
在创建指定私聊可见的命令时,需要传入一个chat_id的参数。推荐的做法是使用 Bot API 的 getUpdates 接口监听消息,当用户主动向 Bot 发送消息时,可从返回的消息结构中获取chat_id。
温馨提醒
如果目标是一个超级群组,chat_id可以传入该群的用户名(String)或ID(Integer),而对于私聊或普通群组,则只能使用整数类型的chat_id。为了统一处理,示例代码始终使用整数类型的chat_id。
假设指定的 chat_id = 123456789 是 Lucy 的私聊ID,效果如下:
Lucy只能看到cmd_private_2命令(优先级更高的作用域chat)。
其他用户只能看到cmd_private_1命令(优先级低于chat,但高于default)。
性能优化建议
若私聊命令涉及频繁的权限校验或数据查询,建议将机器人服务部署于香港高防服务器,并启用高防CDN。前者可确保低延迟响应,后者则能缓存常用数据,减少服务器负载。
群聊命令
群聊命令生效的前提是必须将 Bot 添加进群,一共有 6 种类型适用于群聊场景:
1. botCommandScopeDefault(默认)
2. botCommandScopeAllGroupChats(所有群聊可见)
3. botCommandScopeAllChatAdministrators(所有群聊管理员可见)
4. botCommandScopeChat(指定群聊可见)
5. botCommandScopeChatAdministrators(指定群聊管理员可见)
6. botCommandScopeChatMember(指定群聊成员可见)
创建命令示例:
go
scope = BotCommandScope{Type: "all_group_chats"}
setCommand("cmd_group_1", "所有群聊可见", scope, "")
scope = BotCommandScope{Type: "all_chat_administrators"}
setCommand("cmd_group_2", "所有群聊管理员可见", scope, "")
scope = BotCommandScope{Type: "chat", ChatId: -123456789}
setCommand("cmd_group_3", "指定群聊可见", scope, "")
scope = BotCommandScope{Type: "chat_administrators", ChatId: -123456789}
setCommand("cmd_group_4", "指定群聊管理员可见", scope, "")
scope = BotCommandScope{Type: "chat_member", ChatId: -123456789, UserId: 123456789}
setCommand("cmd_group_5", "指定群聊成员可见", scope, "")
注意
所有群聊的chat_id均为负数,私聊chat_id为正数。user_id与私聊chat_id相同,可通过消息监听获取。
验证效果:
在指定群聊中,指定成员仅看到cmd_group_5。
在指定群聊中,管理员仅看到cmd_group_4。
在指定群聊中,普通成员仅看到cmd_group_3。
其他群聊中,管理员仅看到cmd_group_2。
其他群聊中,普通成员仅看到cmd_group_1。
获取与删除命令
获取命令
go
func getCommands(scope BotCommandScope, languageCode string) {
url := fmt.Sprintf("%s/getMyCommands", BotEndpoint)
req := &BotCommandRequest{Scope: scope, LanguageCode: languageCode}
reqByte, _ := json.Marshal(req)
resp, _ := http.Post(url, "application/json", bytes.NewBuffer(reqByte))
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
删除命令
go
func deleteCommands(scope BotCommandScope, languageCode string) {
url := fmt.Sprintf("%s/deleteMyCommands", BotEndpoint)
req := &BotCommandRequest{Scope: scope, LanguageCode: languageCode}
reqByte, _ := json.Marshal(req)
http.Post(url, "application/json", bytes.NewBuffer(reqByte))
}
总结
本文详细讲解了 Telegram Bot 命令作用域的知识,其中,scope + language_code 决定了命令显示的优先级,其核心目标是为了控制命令的可见范围。通过设置(setMyCommands)、获取(getMyCommands)、删除(deleteMyCommands)这3个 API 可以灵活地自定义配置命令,满足各种业务场景。
为了确保 Telegram Bot 的高可用性和抵御潜在的网络攻击,推荐将机器人部署在香港高防服务器上,并配合高防CDN服务。香港高防服务器能够提供优质的网络带宽和低延迟访问,同时具备强大的抗 DDoS 能力;而高防 CDN 则能进一步分散流量压力,提升全球用户的访问速度,并有效拦截恶意请求。两者结合可显著增强机器人的稳定性和安全性,保障命令处理和数据传输的可靠性。
扩展建议
在实际部署中,若机器人需要处理敏感操作(如工单管理、订阅服务等),建议将核心业务逻辑部署于香港高防服务器,并通过高防CDN对API请求进行加速和清洗。这不仅提升了用户体验,还能避免因网络攻击导致的服务中断。