首页 > 解决方案 > 如何通过机器人回复触发对话处理程序?[电报机器人] [Python] [python-telegram-bot]

问题描述

逻辑如下:

我使用这些示例作为我的起点:

我的代码是这个:

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来启动对话处理程序。对话的入口点是发布字符串“文件 1”,当我发送“asdklhasdlkh 文件 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!

标签: pythontelegrampython-telegram-bot

解决方案


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

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


免责声明:我目前是python-telegram-bot.


推荐阅读