You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

python-telegram-bot点击按钮触发ConversationHandler实现教程

Telegram文件共享机器人开发问题与解决方案

需求逻辑

我正在基于python-telegram-bot库开发Telegram机器人,核心逻辑如下:

  1. 用户发送/start指令时,机器人返回带按钮的主菜单,每个按钮对应用户可申请访问的文件;
  2. 用户点击任意按钮后启动对话流程,机器人索要用户的Gmail邮箱地址;
  3. 用户提交Gmail地址后,机器人校验格式,格式正确则授予文件访问权限并推送文件链接到对话窗口。

我参考了官方两个示例项目作为开发基础:

  • conversationbot.py
  • conversationbot2.py

初始代码与问题

我编写的初始代码如下:

from telegram import (
    Bot,
    Update,
    InlineKeyboardMarkup,
    InlineKeyboardButton,
)
from telegram.ext import (
    Updater,
    CommandHandler,
    MessageHandler,
    Filters,
    CallbackContext,
    CallbackQueryHandler,
    ConversationHandler,
)


def startCommand(update: Update, context: CallbackContext):
    keyboardMarkup = InlineKeyboardMarkup(
        [[InlineKeyboardButton('共享文件1', callback_data='sharingFile1')]]
    )
    update.message.reply_text(f'你好, {update.effective_user.first_name}。\n这里是主菜单。',
                              reply_markup=keyboardMarkup)


def convGetGMailAddr(update: Update, context: CallbackContext):
    update.message.reply_text('请提供你的Gmail邮箱地址。\n\n发送/end可终止当前流程。')
    return convEmailAddr


def convMismatch(update: Update, context: CallbackContext):
    text = """抱歉,你提供的Gmail地址格式不正确。
请重新提交你的Gmail地址。\n\n发送/end可终止当前流程。
"""
    update.message.reply_text(text)
    return convEmailAddr


def convGiveLink(update: Update, context: CallbackContext):
    link = 'https://docs.google.com/spreadsheets/d/1ZP1xZ0WaH8w2yaQTSx99gafNZWawQabcdVW5DSngavQ'
    update.message.reply_text(f'感谢配合!这是你申请的共享文件链接:\n{link}')
    return ConversationHandler.END


def convEnd(update: Update, context: CallbackContext):
    update.message.reply_text('已终止当前流程。\n\n发送/start可返回主菜单。')
    return ConversationHandler.END


def sharingFileHandler(update: Update, context: CallbackContext):
    if update.callback_query.data == 'sharingFile1':
        update.callback_query.edit_message_text(
            update.effective_message.text,
            reply_markup=InlineKeyboardMarkup([])
        )
        conv_sharing = ConversationHandler(
            entry_points=[MessageHandler(Filters.regex('.*[文件1]*.*'), convGetGMailAddr)],
            states={
                convEmailAddr: [
                    MessageHandler(~Filters.regex('.*@gmail.com$') & ~Filters.command, convMismatch),
                    MessageHandler(Filters.regex('.*@gmail.com$'), convGiveLink),
                ],
            },
            fallbacks=[CommandHandler('end', convEnd)],
        )
        disp.add_handler(conv_sharing)
        bot.send_message(update.effective_chat.id, '我将为你共享文件1。')


bot_token = 'abcd1234'
bot = Bot(bot_token)
updater = Updater(bot_token, use_context=True)
convEmailAddr = ''

disp = updater.dispatcher
disp.add_handler(CommandHandler('start', startCommand))
disp.add_handler(CallbackQueryHandler(sharingFileHandler))

updater.start_polling(drop_pending_updates=True)
updater.idle()

当前遇到两个待解决问题:

  1. 机器人无法识别自身在sharingFileHandler函数中发送的回复来触发对话处理器,当前对话入口设置为匹配字符串"文件1",只有用户主动发送包含"文件1"的内容时流程才能正常启动;
  2. 希望机器人仅在对话流程生效期间监听用户提交的邮箱地址,当前convGetGMailAddr函数会在任意时刻被触发,请问该如何实现该需求?

2021-10-20更新:解决方案

修改代码后问题已全部解决,我删除了convGetGMailAddr函数,修改后的sharingFileHandler和核心处理器注册逻辑如下:

def sharingFileHandler(update: Update, context: CallbackContext):
    if update.callback_query.data == 'sharingFile1':
        update.callback_query.edit_message_text(
            update.effective_message.text,
            reply_markup=InlineKeyboardMarkup([])
        )
        text = """我将把文件1共享到你的Google账户。
请提供你的Gmail邮箱地址。\n\n发送/end可终止当前流程。"""
        bot.send_message(update.effective_chat.id, text)
        return convEmailAddr


bot_token = '1234abcd'
bot = Bot(bot_token)
updater = Updater(bot_token, use_context=True)
convEmailAddr = ''

disp = updater.dispatcher
disp.add_handler(CommandHandler('start', startCommand))
conv_sharing = ConversationHandler(
    entry_points=[CallbackQueryHandler(sharingFileHandler)],
    states={
        convEmailAddr: [
            MessageHandler(~Filters.regex('.*@gmail.com$') & ~Filters.command, convMismatch),
            MessageHandler(Filters.regex('.*@gmail.com$'), convGiveLink),
        ],
    },
    fallbacks=[CommandHandler('end', convEnd)],
)
disp.add_handler(conv_sharing)

updater.start_polling(drop_pending_updates=True)
updater.idle()

修改后机器人运行完全符合预期,所有需求均已实现。


内容的提问来源于stack exchange,提问作者Serge-M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 23:24:03