telegram-bot - Python Telegram Bot ConversationHandler 无法与 webhook 一起使用
问题描述
我想在我的机器人中创建一个使用 webhook 的 ConversationHandler,ConversationHandler 只在入口点运行该函数,之后它既不运行状态函数,也不运行回退函数。当 bot 通过轮询运行时,此 CommandHandler 运行良好。
对话处理程序:
conv_handler = ConversationHandler(
entry_points=[CommandHandler("start", start)],
states={
NEW_PROJECT: [CallbackQueryHandler(project_name)],
PROJECT_NAME: [MessageHandler(Filters.regex(".*"), store_name_maybe_project_type)],
PROJECT_TYPE: [CallbackQueryHandler(store_type_maybe_admin)]
},
fallbacks=[CommandHandler('cancel', cancel)],
)
所有必需的功能:
def start(update, context):
# Gives button of add project
# We can use for loop to display buttons
keyboard = [
[InlineKeyboardButton("Add Project", callback_data="add_project")],
]
reply_markup = InlineKeyboardMarkup(keyboard)
update.message.reply_text("You have no projects right now.", reply_markup=reply_markup)
# if existing project then PROJECT or else NEW_PROJECT
return NEW_PROJECT
def project_name(update, context):
# asks for project name
query = update.callback_query
update.message.reply_text(text="Okay, Please enter your project name:")
return PROJECT_NAME
def store_name_maybe_project_type(update, context):
# stores project name and conditionally asks for project type
print(update.message.text)
keyboard = [
[InlineKeyboardButton("Telegram Group", callback_data="group")],
[InlineKeyboardButton("Telegram Channel", callback_data="channel")]
]
reply_markup = InlineKeyboardMarkup(keyboard)
update.message.reply_text("What do you want to make?", reply_markup=reply_markup)
return PROJECT_TYPE
def store_type_maybe_admin(update, context):
# stores project type and conditonally asks for making admin
print(update.message.text)
keyboard = [[InlineKeyboardButton("Done", callback_data="done")]]
reply_markup = InlineKeyboardMarkup(keyboard)
update.message.reply_text(f"Make a private {update.message.text} and make this bot the admin", reply_markup=reply_markup)
return ConversationHandler.END
def cancel(update, context):
update.message.reply_text("Awww, that's too bad")
return ConversationHandler.END
这就是我设置 webhook 的方式(我认为问题出在某个地方):
@app.route(f"/{TOKEN}", methods=["POST"])
def respond():
"""Run the bot."""
update = telegram.Update.de_json(request.get_json(force=True), bot)
dispatcher = setup(bot, update)
dispatcher.process_update(update)
return "ok"
设置功能
def setup(bot, update):
# Create bot, update queue and dispatcher instances
dispatcher = Dispatcher(bot, None, workers=0)
##### Register handlers here #####
bot_handlers = initialize_bot(update)
for handler in bot_handlers:
dispatcher.add_handler(handler)
return dispatcher
然后我使用这条路线手动设置 webhook:
@app.route("/setwebhook", methods=["GET", "POST"])
def set_webhook():
s = bot.setWebhook(f"{URL}{TOKEN}")
if s:
return "webhook setup ok"
else:
return "webhook setup failed"
解决方案
ConversationHandler
将当前状态存储在内存中,因此一旦conv_handler
到达其生命周期的末尾(即变量被删除或进程关闭),它就会丢失。现在您的代码片段没有显示您在哪里初始化ConversationHandler
,但我觉得您为每个传入的更新重新创建它 - 每个新实例都不知道前一个实例。
我有这种感觉,因为您Dispatcher
也会为每次更新创建一个新的。这没有必要,事实上我强烈建议不要这样做。不仅需要时间来初始化Dispatcher
,您可以保存它,而且如果您正在使用chat/user/bot_data
,每次创建新实例时数据都会丢失。
该initialize_bot
函数在 中调用setup
,您在其中创建新的Dispatcher
,这就是为什么我的猜测是您ConversationHandler
为每次更新创建一个新的。在我看来,该函数的返回值似乎取决于update
- 调度程序使用的处理程序应该是固定的,这对我来说似乎很奇怪......
免责声明:我目前是python-telegram-bot
推荐阅读
- android - 尝试通过 Cordova 插件为 Firebase Cloud Messaging 推送通知时,设备令牌为空
- functional-programming - Clojure 排序字符串值 - 不区分大小写
- java - 内存中发生了什么,一个新进程是否总是在 Java 中打开一个新的 JVM?
- julia - LoadError: MethodError: convert(::Type{Union{}}, ::LinearAlgebra.Adjoint{Float64,Array{Float64,1}}) 不明确
- powershell - 带有 Powershell 的 IE 自动化发送 ENTER 键
- redis - Redis Sentinel Rename-Command Ignored
- angular - Angular formly-expressionProperties 和 hideExpression 有什么区别
- python - Django 3 与 MySQL 5.7 兼容吗?
- scala - 如果列存在则更新增量表,否则添加为新列
- laravel - 我无法在 Alpinejs 中调度事件