Telethon中普通Bot与UserBot消息ID不一致及相关问题排查
问题分析与解决方案
1. 消息ID不一致的原因与解决
核心原因
这是Telegram的设计机制,并非Telethon的Bug:
- 当Bot收到用户消息时,
event.message.id是Bot与该用户对话中的本地消息ID,此时对话的chat.id是发送消息的用户ID; - 当UserBot调用
iter_messages(normal_bot_user.username)时,查询的是UserBot与该Bot的对话,此时对话的chat.id是Bot的ID,消息ID是这个对话中的本地ID; - 两个对话属于完全独立的上下文,Telegram会为每个对话维护独立的消息ID序列,因此同一条消息在两个视角下的ID自然不同。
解决存储问题
不要单独使用message.id作为唯一标识,改用对话ID+消息ID的组合作为全局唯一键:
- Bot侧存储时使用:
(event.message.chat.id, event.message.id) - UserBot侧存储时使用:
(message.chat.id, message.id)
如果需要跨客户端关联同一条消息,可以通过message.text、message.date等内容字段辅助验证,核心依赖对话+消息ID的组合键。
2. get_input_entity返回错误结果的原因与解决
核心原因
从normal_bot_client.get_me()获取的User对象,其access_hash是Bot会话的缓存值,对于UserBot客户端无效。当将这个完整的User对象传递给UserBot的get_input_entity时,Telethon无法正确验证实体身份,导致错误匹配为当前客户端自身(InputPeerSelf())。
解决方案
- 避免跨客户端传递完整的User实体,改用用户名、用户ID等全局标识让目标客户端重新查询:
# 推荐方式:使用用户ID normal_bot_id = (await normal_bot_client.get_me()).id something = await user_bot_client.get_input_entity(normal_bot_id) # 或者使用用户名 something = await user_bot_client.get_input_entity(normal_bot_user.username) - 如果必须传递实体信息,只提取
id、username等无状态字段,不要传递包含会话专属access_hash的完整对象。
代码修改示例
调整原handler中的对话查询逻辑,明确对话标识的差异:
@normal_bot_client.on(events.NewMessage) async def handler(event): print(f'{event.message.id=}') print(f'{event.message.chat.id=}') # 输出为发送消息的用户ID print(f'{event.message.text=}') print('-----------------') async with user_bot_client: bot_username = (await normal_bot_client.get_me()).username async for message in user_bot_client.iter_messages(bot_username, 3): print(f'{message.id=}') print(f'{message.chat.id=}') # 输出为Bot的ID print(f'{message.text=}') print()
内容的提问来源于stack exchange,提问作者Flana Ban
相关产品推荐
相关产品推荐

