python - 如何通过机器人回复触发对话处理程序?[电报机器人] [Python] [python-telegram-bot]
问题描述
逻辑如下:
- 使用 /start 命令,机器人会显示带有按钮的主菜单(每个按钮代表用户想要访问的文件);
- 当按下任何按钮时,对话就会从机器人询问 gmail 地址的位置开始;
- 用户发送他们的 gmail 地址,机器人对其进行检查,如果地址格式正确,则机器人授予查看文件的权限并将链接发布到聊天中。
我使用这些示例作为我的起点:
- https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/conversationbot.py
- https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/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('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!
解决方案
您正在构建一个新的对话处理程序并在每次sharingFileHandler
调用时将其添加到调度程序。这肯定不是你想要的。相反,您应该只构建一次并将其添加到调度程序中,也只在添加其他处理程序的地方(在代码段的最后)添加一次。
然后,您应该成为CallbackQueryHandler(sharingFileHandler)
该对话的切入点。这将自动解决您的第二个问题。
免责声明:我目前是python-telegram-bot
.
推荐阅读
- docker - Docker socket.io
- ms-access - MS 访问将值范围转换为单独的行
- jquery - jQuery 如果这个或那个
- c++ - VS代码:无用文件不断出现
- python - 为什么我的 for 循环会生成一个中断的函数?
- python - Pytorch Cityscapes 数据集,train_distribute 问题 - “类型错误:路径应该是字符串、字节、类路径或整数,而不是 NoneType”
- python - Selenium 搞砸了 xpaths
- python - 从主代码并行运行 Flask 网络服务器?
- python - 从一个链接跳转到另一个链接时出现 Python 错误。一个for循环有效,另一个无效
- php - 在 Mint 上为 PHP 安装 PECL 期望包时出错