【问题标题】:How to trigger a conversation handler with the bot reply? [Telegram Bot] [Python] [python-telegram-bot]如何通过机器人回复触发对话处理程序? [电报机器人] [Python] [python-telegram-bot]
【发布时间】:2021-12-06 18:21:28
【问题描述】:

逻辑如下:

  • 使用 /start 命令,机器人会显示带有按钮的主菜单(每个按钮代表用户想要访问的文件);
  • 当按下任何按钮时,对话就会从机器人询问 gmail 地址的位置开始;
  • 用户发送他们的 gmail 地址,机器人会检查它,如果地址格式正确,那么机器人会授予查看文件的权限并将链接发布到聊天。

我以这些示例为起点:

我的代码是这个:

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('Share File 1', callback_data='sharingFile1')]]
    )
    update.message.reply_text(f'Howdy, {update.effective_user.first_name}.\nThis is the Main Menu.',
                              reply_markup=keyboardMarkup)


def convGetGMailAddr(update: Update, context: CallbackContext):
    update.message.reply_text('Waiting for your gmail address.\n\nSend /end and I\'ll stop waiting.')
    return convEmailAddr


def convMismatch(update: Update, context: CallbackContext):
    text = f"""Sorry, I don't understand this gmail address.
Please, send me your gmail address again.\n\nSend /end and I\'ll stop waiting.
"""
    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'Thank you! Here\'s your link to the shared file:\n{link}')
    return ConversationHandler.END


def convEnd(update: Update, context: CallbackContext):
    update.message.reply_text('I\'ve stopped waiting.\n\nSend /start to go to the Main Menu.')
    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('.*[File 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, 'I\'ll share the File 1 with you.')


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()

问题是机器人没有在函数sharingFileHandler 中读取它自己的回复来启动对话处理程序。对话的入口点是发布字符串“File 1”,当我发送“asdklhasdlkh file 1 asdaskldha”之类的内容时,一切正常。

另一个问题是机器人是否可以仅在对话内部收听电子邮件地址?现在函数convGetGMailAddr随时启动。


更新 1 (2021-10-20)

根据 CallMeStag 的回答,我更改了代码。
删除函数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 = f"""I\'ll share the File 1 with you to your Google account.
Please, send me your gmail address.\n\nSend /end and I\'ll stop waiting."""
        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()

现在我的机器人完全按照我的意愿去做,它停止做我希望它停止做的事情。 ????
谢谢你,CallMeStag!

【问题讨论】:

    标签: python telegram python-telegram-bot


    【解决方案1】:

    您正在构建一个新的对话处理程序,并在每次调用 sharingFileHandler 时将其添加到调度程序。这肯定不是你想要的。相反,您应该只构建一次并将其添加到调度程序中,也只在添加其他处理程序的地方(在 sn-p 的最后)添加一次。

    然后您应该将CallbackQueryHandler(sharingFileHandler) 设为该对话的入口点。这将自动解决您的第二个问题。


    免责声明:我目前是python-telegram-bot 的维护者。

    【讨论】:

    • 谢谢!这就像一个魅力。修复代码后出现此错误:/.local/lib/python3.9/site-packages/telegram/ext/conversationhandler.py:287: UserWarning: If 'per_message=False', 'CallbackQueryHandler' will not be tracked for每一条消息。我应该在哪里更改属性per_message?在ConversationHandler?
    猜你喜欢
    • 2022-12-15
    • 1970-01-01
    • 2021-02-02
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 1970-01-01
    • 2020-10-28
    • 1970-01-01
    相关资源
    最近更新 更多