Telegram内联机器人能否用用户名作chat_id发消息?遇Chat未找到问题
问题:Telegram机器人通过用户名发送消息时提示“聊天未找到”
我有一个Telegram机器人,希望通过指定用户的用户名来给该用户发送消息,但一直收到“聊天未找到”的错误。buyer_username变量来自我调用机器人时传入的查询内容(即@Bot 用户名.)。
我查阅文档后了解到,机器人无法给未向其发送过消息的用户发消息,于是我用目标用户名对应的设备给机器人发了一条消息,但再次尝试后仍出现相同问题。请问这种实现方式可行吗?
以下是处理逻辑的代码片段:
def inline_query(update: Update, context: CallbackContext) -> int: _, _ = User.get_user_and_created(update, context) is_verified: bool = is_seller_verified(update.inline_query.from_user.id) if is_verified: query = update.inline_query.query if len(query) == 0 or query[-1] != '.': print('Empty query, showing message to seller to type username of buyer') results = [ InlineQueryResultArticle( id='Noop', title=noop_title, input_message_content=InputTextMessageContent(noop_description), thumb_url='https://i.imgur.com/1tDhWge.png', thumb_width=64, thumb_height=64 ) ] update.inline_query.answer(results) elif len(query) > 1 and query.endswith('.'): buyer_username = query[:-1] emoji_hash = _random_emoji() seller_username: str = update.inline_query.from_user.username seller_tg_id: int = update.inline_query.from_user.id total_count, buyer_count = get_transaction_info(seller_tg_id, buyer_username) emoji_code: str = _emoji_password(seller_username, update.inline_query.from_user.id) # TODO: make more complex verified_message_1 = verify_message_1 % ( emoji_code, buyer_count, total_count, seller_username, _get_transaction_datetime(), ) keyboard = [ [ InlineKeyboardButton(emoji_code, callback_data=GO_TO_CONFIRM), ], [ InlineKeyboardButton(emoji_hash, callback_data=GO_TO_RETRY), ], ] random.shuffle(keyboard) reply_markup = InlineKeyboardMarkup(keyboard) context.user_data['buyer_username'] = buyer_username print(buyer_username) context.bot.send_message(chat_id=buyer_username, text=verified_message_1, reply_markup=reply_markup) else: keyboard = [ [ InlineKeyboardButton(text=start_verification_title, url='https://t.me/clientverify_bot'), ], ] reply_markup = InlineKeyboardMarkup(keyboard) context.bot.send_message(chat_id=buyer_username, text=start_verification_message, reply_markup=reply_markup ) return IMMUTABLE_STATE
解决方案
通过用户名给用户发消息是可行的,但你的代码存在几个关键问题:
- 用户名格式错误:
send_message的chat_id参数如果传入用户名,必须带@前缀(比如@testuser)。你的buyer_username是从query[:-1]获取的,用户输入的是“用户名.”,所以最终得到的是不带@的纯用户名,机器人无法识别这个格式的聊天ID。 - 隐私设置限制:即使用户给机器人发过消息,如果用户在Telegram隐私设置中开启了“不允许陌生人通过用户名找到我”,机器人依然无法通过用户名发送消息,这种情况下必须使用用户的唯一ID。
- 逻辑漏洞:else分支中的
buyer_username变量未定义,会直接抛出变量未找到的错误,因为这个变量只有在is_verified且query.endswith('.')的分支里才被赋值。
针对这些问题的修复建议:
修正用户名格式:在代码中给
buyer_username自动添加@前缀:buyer_username = f"@{query[:-1]}"或者要求用户输入带@的用户名(比如
@testuser.)。优先使用用户ID:如果能通过历史交互记录获取买家的ID,用ID作为
chat_id比用户名更可靠,因为ID不受隐私设置影响,且是唯一标识。添加错误处理:给
send_message添加异常捕获,处理ChatNotFound等错误,并给卖家返回提示:from telegram.error import ChatNotFound try: context.bot.send_message(chat_id=buyer_username, text=verified_message_1, reply_markup=reply_markup) except ChatNotFound: # 给卖家发送提示消息 update.inline_query.answer([ InlineQueryResultArticle( id='error', title='发送失败', input_message_content=InputTextMessageContent('无法找到该用户,请检查用户名是否正确,或确认用户已给机器人发过消息') ) ])修复else分支逻辑:else分支应该给当前发起请求的卖家发消息,而不是未定义的
buyer_username,修改为:context.bot.send_message(chat_id=update.inline_query.from_user.id, text=start_verification_message, reply_markup=reply_markup )
内容的提问来源于stack exchange,提问作者DzEskobar
相关产品推荐
相关产品推荐

