- 后端
- 即时通讯
- API设计
【免费下载链接】aiogram
aiogram is a modern and fully asynchronous framework for Telegram Bot API written in Python using asyncio
导读
BotCommandScopeChatMember是 aiogram 中用于表示"Bot 命令作用域覆盖某个群组/超级群组中特定成员"的类型对象,是 Telegram Bot API 命令菜单(bot commands)精细化权限控制的最后一环。本文将以 docs/api/types/bot_command_scope_chat_member.rst 对应的源码实现为主线,结合setMyCommands/getMyCommands的实际调用链,讲解该作用域的三个字段、它与另外六种作用域的关系、pydantic 判别式联合的序列化原理,以及将命令仅暴露给单个用户的可运行示例。读完本文,你将掌握如何让一个群里的某个成员看到专属命令菜单,而其他人不受影响。
一、类型定位:七种 Bot 命令作用域之一
在 Telegram Bot API 中,作用域(BotCommandScope)定义了 Bot 命令列表对哪些用户生效。aiogram 的基类 bot_command_scope.py 明确列出当前支持的7 种作用域:
| 作用域类 | type值 | 生效范围 |
|---|---|---|
BotCommandScopeDefault | default | 所有用户(默认) |
BotCommandScopeAllPrivateChats | all_private_chats | 所有私聊 |
BotCommandScopeAllGroupChats | all_group_chats | 所有群组/超级群组 |
BotCommandScopeAllChatAdministrators | all_chat_administrators | 所有群聊管理员 |
BotCommandScopeChat | chat | 单个聊天内的所有用户 |
BotCommandScopeChatAdministrators | chat_administrators | 单个聊天内的管理员 |
BotCommandScopeChatMember | chat_member | 单个聊天内的单个成员 |
BotCommandScopeChatMember是其中粒度最细的一档:它把命令菜单精确到"哪个群 + 哪个人",而本文的关联文档 bot_command_scope_chat_member.rst 正是该类型在 API 参考中的正式条目,通过 Sphinxautomodule指令自动生成类与字段文档。
二、字段详解:type、chat_id、user_id
BotCommandScopeChatMember的全部内容实现在 aiogram/types/bot_command_scope_chat_member.py,共三个字段,且三个字段均为必填:
class BotCommandScopeChatMember(BotCommandScope): type: Literal[BotCommandScopeType.CHAT_MEMBER] = BotCommandScopeType.CHAT_MEMBER chat_id: ChatIdUnion user_id: int2.1type:作用域类型,固定为chat_member
字段声明为Literal[BotCommandScopeType.CHAT_MEMBER],且默认值就是BotCommandScopeType.CHAT_MEMBER(即字符串"chat_member")。该枚举定义在 aiogram/enums/bot_command_scope_type.py 中,与 Telegram API 文档保持一致。
由于是Literal类型且带默认值,实际使用时无需手动传入type,aiogram 会自动补全。这一点与后面要讲的判别式序列化直接相关。
2.2chat_id:目标群组标识
chat_id的类型是ChatIdUnion,其定义在 aiogram/types/chat_id_union.py:
ChatIdUnion: TypeAlias = int | str即可以传入:
- 数字 ID:群组/超级群组的唯一数字标识,如
-1001234567890; - 字符串用户名:目标超级群组的
@username形式(仅超级群组支持以用户名定位)。
需要特别注意的是 Telegram API 的硬性限制:频道私信(Channel Direct Messages)聊天和频道(Channel)聊天不受支持,即chat_id不能指向频道类聊天。
2.3user_id:目标用户标识
user_id是目标用户的唯一数字标识(int)。该用户必须是该群组/超级群组的成员——作用域天然只对"群内成员"有意义,如果对非成员指定命令,命令菜单不会对其生效。
三、源码级原理:判别式联合与序列化
aiogram 并非把BotCommandScopeChatMember当作孤立的模型,而是通过 pydantic 的**判别式联合(discriminated union)**把它和其他六种作用域统一收口。定义在 aiogram/types/bot_command_scope_union.py:
BotCommandScopeUnion: TypeAlias = Annotated[ BotCommandScopeDefault | BotCommandScopeAllPrivateChats | BotCommandScopeAllGroupChats | BotCommandScopeAllChatAdministrators | BotCommandScopeChat | BotCommandScopeChatAdministrators | BotCommandScopeChatMember, Field(discriminator="type"), ]这里Field(discriminator="type")意味着:当SetMyCommands.scope字段(类型为BotCommandScopeUnion)被序列化或反序列化时,pydantic 会以type字段的值作为判别键,自动路由到正确的子类。因此:
- 你构造
BotCommandScopeChatMember(chat_id=..., user_id=...)时,type自动为"chat_member",序列化后得到{"type": "chat_member", "chat_id": ..., "user_id": ...}; - 收到 Telegram 返回的数据时,
"type": "chat_member"也会被正确还原为BotCommandScopeChatMember实例。
所有作用域类型都在 aiogram/types/init.py 中统一导出,因此使用方直接from aiogram.types import BotCommandScopeChatMember即可,无需关心模块内部路径。
四、实战:为群内单个成员定制命令菜单
BotCommandScopeChatMember的典型应用场景是setMyCommands/getMyCommands这两个 API。在 aiogram 中,它们分别对应 SetMyCommands 与 GetMyCommands 两个方法类,并通过Bot实例封装为便捷方法(见 aiogram/client/bot.py 的bot.set_my_commands(...)与 aiogram/client/bot.py 的bot.get_my_commands(...))。
4.1 只给某个成员设置专属命令
假设你的 Bot 管理着一个超级群组(ID-1001234567890),你希望只有用户 ID 为76543210的成员能看到/admin命令菜单,其余成员不受影响:
import asyncio from aiogram import Bot from aiogram.types import BotCommand, BotCommandScopeChatMember async def main() -> None: bot = Bot(token="YOUR_BOT_TOKEN") ok: bool = await bot.set_my_commands( commands=[ BotCommand(command="admin", description="打开管理面板"), BotCommand(command="stats", description="查看群统计"), ], scope=BotCommandScopeChatMember( chat_id=-1001234567890, # 目标超级群组数字 ID user_id=76543210, # 目标成员 ), # language_code 可省略,或指定为 "zh" / "en" 等两个字母的 ISO 639-1 代码 language_code="zh", ) print("设置成功" if ok else "设置失败") await bot.session.close() if __name__ == "__main__": asyncio.run(main())要点说明:
commands:BotCommand列表,最多 100 条。每条命令的command字段限 1–32 字符,只能包含小写英文字母、数字和下划线;description限 1–256 字符(见 aiogram/types/bot_command.py)。language_code:可选参数,两个字母的 ISO 639-1 语言代码。若省略,该作用域命令会应用于该群内没有专属语言命令的所有相关用户;指定后仅对该语言用户生效,可实现多语言命令菜单并存。scope:由于BotCommandScopeUnion的判别式机制,直接把BotCommandScopeChatMember实例传入即可。
4.2 查询某个成员当前看到的命令
与之对应,用getMyCommands可以反查某作用域下已设置的命令列表:
from aiogram.types import BotCommandScopeChatMember commands = await bot.get_my_commands( scope=BotCommandScopeChatMember( chat_id=-1001234567890, user_id=76543210, ), ) # 返回 list[BotCommand];若未设置,返回空列表当scope参数缺省时,两者都默认使用BotCommandScopeDefault(作用于所有用户),这是 Telegram API 的默认行为,定义见 SetMyCommands 与 GetMyCommands 的字段说明。
4.3 与命令作用域的组合使用
实际项目中常把多级作用域叠加使用,实现"默认全员可见 + 特定成员额外可见"的菜单策略:
from aiogram.types import ( BotCommand, BotCommandScopeChatMember, BotCommandScopeDefault, ) # 第一步:对全员设置通用命令 await bot.set_my_commands( commands=[BotCommand(command="start", description="开始")], scope=BotCommandScopeDefault(), ) # 第二步:仅对某群内的某成员追加管理命令 await bot.set_my_commands( commands=[BotCommand(command="admin", description="管理面板")], scope=BotCommandScopeChatMember(chat_id=-1001234567890, user_id=76543210), )此时该成员的命令菜单为"通用命令 + 专属命令"的并集,而其他成员只看到通用命令——这正是 Telegram 命令作用域"从默认到具体逐级覆盖"机制的实际应用。
五、使用限制与注意事项
结合 aiogram/types/bot_command_scope_chat_member.py 中字段注释与 Telegram API 约束,使用时有几点需要牢记:
- 不支持频道:
chat_id不能是频道(Channel)或频道私信(Channel Direct Messages)聊天,仅限普通群组/超级群组; user_id必须是群成员:作用域对象本身不做成员校验,若目标用户不在群内,命令不会对其生效;- 三个字段全必填:构造时必须同时提供
chat_id与user_id(type有默认值可省略),缺少任一必填字段会导致 pydantic 校验失败; - 数字 ID 与用户名二选一:
chat_id用int传数字 ID、用str传@username,注意字符串形式只对超级群组有效; - 命令数上限:单个
setMyCommands调用最多 100 条命令,超限会请求失败。
六、测试与验证
aiogram 仓库为setMyCommands/getMyCommands提供了 MockedBot 级别的 API 测试,可作为验证调用链的参考:
- tests/test_api/test_methods/test_set_my_commands.py:通过
bot.add_result_for(SetMyCommands, ok=True, ...)模拟响应,并断言bot.set_my_commands(commands=[])返回True; - tests/test_api/test_methods/test_get_my_commands.py:验证
bot.get_my_commands()返回list[BotCommand]。
从源码结构可以看出,Bot.set_my_commands内部实际是构造SetMyCommands方法对象并交给请求中间件执行(aiogram/client/bot.py),scope对象在序列化时由BotCommandScopeUnion的判别式字段保证正确输出"type": "chat_member"。因此,当你传入BotCommandScopeChatMember时,最终发给 Telegram 的 JSON 载荷形如:
{ "commands": [{"command": "admin", "description": "打开管理面板"}], "scope": { "type": "chat_member", "chat_id": -1001234567890, "user_id": 76543210 }, "language_code": "zh" }结语
BotCommandScopeChatMember是 aiogram 命令作用域体系中精度最高的类型:通过chat_id(int | str)锁定群组、user_id锁定成员、type固定为chat_member,配合BotCommandScopeUnion的判别式联合,它在setMyCommands/getMyCommands调用链中实现"一人一菜单"的精准控制。无论是搭建带管理后台的社群 Bot,还是实现按成员等级展示命令的复杂菜单体系,掌握该作用域都是不可或缺的一环。
- 后端
- 即时通讯
- API设计
【免费下载链接】aiogram
aiogram is a modern and fully asynchronous framework for Telegram Bot API written in Python using asyncio
相关推荐
aiogram 中的 BotCommandScopeChatAdministrators:为指定群组管理员单独设置机器人命令作用域
aiogram 中的 BotCommandScopeChatAdministrators:为指定群组管理员单独设置机器人命令作用域 BotCommandScop
后端即时通讯API设计aiogram 中使用 setChatAdministratorCustomTitle:为超级群组管理员设置自定义头衔的完整指南
aiogram 中使用 setChatAdministratorCustomTitle:为超级群组管理员设置自定义头衔的完整指南 本文围绕 aiogram 框架
后端即时通讯API设计Karmada karmadactl taint 命令详解:为成员集群打污点并控制联邦调度
Karmada karmadactl taint 命令详解:为成员集群打污点并控制联邦调度 本文围绕 Karmada 的 karmadactl taint 命令
音视频桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考