如何通过Telegram Bot API获取被@标记用户的ID
Telegram Bot获取指令中@提及用户ID的实现方案
别上来就写正则硬扒文本,Telegram服务端已经提前把消息里的特殊内容做了预标记,直接按官方结构解析就不会出错。
首选方案:读取消息自带的实体信息(无额外权限要求)
不管用户是手动输入@用户名,还是直接从联系人列表选用户发提及,你收到的Message对象里都会自带entities字段(如果是带说明文字的图片、文件类消息,对应字段是caption_entities)。这个字段是数组结构,标记了消息里所有特殊内容的类型、位置、附加信息,遍历筛选对应实体即可:
- 遇到类型为
text_mention的实体:这是用户从联系人列表直接选择生成的提及(被@的用户可能没设置公开用户名),实体里直接带完整的user对象,读取entity.user.id就能直接拿到用户ID,不需要发额外接口请求。 - 遇到类型为
mention的实体:这是纯文本形式的@用户名(比如用户手动敲的@xxx),你可以根据实体的偏移量和长度,截取出对应的@文本,去掉开头的@得到用户名,再调用getChat接口传入这个用户名,返回结果里的id就是目标用户的ID。
注意遍历的时候要跳过类型为
bot_command的实体:如果群里有多个Bot,用户可能会发/command@你的Bot用户名来指定触发你的Bot,这里面的@是指令的一部分,不是要提及的用户。
举个Python版本的实现示例(基于python-telegram-bot库):
from telegram import Update from telegram.ext import Updater, CommandHandler, CallbackContext def handle_command(update: Update, context: CallbackContext): msg = update.effective_message target_uid = None # 遍历所有消息实体 for ent in msg.entities: # 跳过指令本身的实体 if ent.type == "bot_command": continue # 直接读取联系人提及的用户ID if ent.type == "text_mention": target_uid = ent.user.id break # 处理纯文本@用户名的情况 if ent.type == "mention": mention_str = msg.text[ent.offset : ent.offset + ent.length] username = mention_str.lstrip("@") user_info = context.bot.get_chat(f"@{username}") target_uid = user_info.id break if target_uid: msg.reply_text(f"被提及用户ID:{target_uid}") else: msg.reply_text("未检测到@的目标用户") # 替换成你自己的Bot Token updater = Updater("YOUR_BOT_TOKEN") updater.dispatcher.add_handler(CommandHandler("command", handle_command)) updater.start_polling()
常见避坑点
- 别自己写正则匹配文本里的@内容:Telegram计算实体偏移量是按UTF-16编码算的,遇到emoji、小语种特殊字符很容易截错位置,用官方返回的实体字段准确率是100%。
- 不要和回复场景混淆:如果用户是回复某条消息发的
/command,没有@任何人,那目标用户存在msg.reply_to_message.from_user.id里,和@提及的逻辑是分开的。 - 调用
getChat通过用户名查用户ID的时候,记得加异常捕获,遇到无效用户名的时候不会让程序直接崩掉。
内容的提问来源于stack exchange,提问作者Joel
相关产品推荐
相关产品推荐

