【问题标题】:How to send a InlineKeyboardButton in telegram bot, periodically?如何定期在电报机器人中发送 InlineKeyboardButton?
【发布时间】:2021-10-28 14:22:06
【问题描述】:

我正在尝试每 x 秒发送一次InlineKeyboardHandler。为此,我使用了updater.job_queue.run_repeating,但它的行为很奇怪。

除非我先与机器人进行另一次交互,否则键盘不起作用。我写了一段简单的代码,你可以测试一下。

from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import Updater, CommandHandler, ConversationHandler, CallbackContext, CallbackQueryHandler

user_id = '*********'
tlg_token = '******************************'
SELECTING_COMMAND=1
keyboard = [[InlineKeyboardButton('Button: Print Clicked', callback_data=1)],]
reply_markup = InlineKeyboardMarkup(keyboard)

def menu(update: Update, context: CallbackContext) -> int:
    update.message.reply_text('sent by command button:', reply_markup=reply_markup)
    return SELECTING_COMMAND

def InlineKeyboardHandler(update: Update, _: CallbackContext) -> None:
    print('clicked')
    return 1

def cancel(update: Update, context: CallbackContext) -> int:
    return ConversationHandler.END    

updater = Updater(tlg_token, use_context=True)
dispatcher = updater.dispatcher

conv_handler = ConversationHandler(
    entry_points=[CommandHandler('request_button', menu)],
    states={
        SELECTING_COMMAND: [CallbackQueryHandler(InlineKeyboardHandler)],
    },
    fallbacks=[CommandHandler('cancel', cancel)],
)
dispatcher.add_handler(conv_handler)

j = updater.job_queue

def talker(update):    
    update.bot.sendMessage(chat_id=user_id, text='sent by talker:', reply_markup=reply_markup)
        
j.run_repeating(talker, interval=10, first=0)
updater.start_polling()
updater.bot.sendMessage(chat_id=user_id, text='/request_button')
updater.idle()

我希望在单击按钮后可以看到打印的“已单击”,但除非您先单击 /request_button,否则它不会起作用。为什么?我该如何解决?

【问题讨论】:

  • 您的意思是您必须单击/request_button 一次 才能处理任何内联键盘按钮?如果是这样,这是意料之中的,因为没有发送 /request_button 对话还没有开始,因此永远不会调用 SELECTING_COMMAND: [CallbackQueryHandler(InlineKeyboardHandler)] 处理程序,因为对话不处于 SELECTING_COMMAND 状态(顺便说一下,您可能想要返回 @987654328 @来自InlineKeyboardHandler?)。
  • 我的意思是当状态是SELECTING_COMMAND,而且返回1和SELECTING_COMMAND没有区别
  • 嗯,这并没有回答我打算澄清问题的第一个问题。
  • 是的,我必须单击一次按钮才能工作。起初,我没有正确理解您的问题。

标签: python telegram telegram-bot


【解决方案1】:

cmets中提到的a_guest代码的问题是InlineKeyboardHandler只有在调用request_button命令后才会开始工作。

这是一个独立注册InlineKeyboardHandler的工作版本:

from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import Updater, CommandHandler, ConversationHandler, CallbackContext, CallbackQueryHandler

#################################
user_id = 0
tlg_token = 'bot_token'
SELECTING_COMMAND = 1
keyboard = [[InlineKeyboardButton('Button: Print Clicked', callback_data=1)], ]
reply_markup = InlineKeyboardMarkup(keyboard)


#################################

def menu(update: Update, context: CallbackContext) -> int:
    update.message.reply_text('sent by command button:', reply_markup=reply_markup)
    return SELECTING_COMMAND


def InlineKeyboardHandler(update: Update, _: CallbackContext) -> None:
    print('clicked')
    return 1


def cancel(update: Update, context: CallbackContext) -> int:
    return ConversationHandler.END


updater = Updater(tlg_token, use_context=True)
dispatcher = updater.dispatcher
updater.dispatcher.add_handler(CallbackQueryHandler(InlineKeyboardHandler))
updater.dispatcher.add_handler(CommandHandler('request_button', menu))
j = updater.job_queue


def talker(update):
    update.bot.sendMessage(chat_id=user_id, text='sent by talker:', reply_markup=reply_markup)


j.run_repeating(talker, interval=10, first=0)
updater.start_polling()
updater.bot.sendMessage(chat_id=user_id, text='/request_button')
updater.idle()

该问题的另一个解决方案是 OP 自己在 cmets 中提到的,您在其中添加 CallbackQueryHandler 作为入口点:

entry_points=[CommandHandler('request_button', menu),                   CallbackQueryHandler(InlineKeyboardHandler)]

【讨论】:

  • 它可以工作,但是您更改了代码的主要部分。由于 InlineKeyboardHander 无法再更改状态。不过,我明白会发生什么。因此,如果您将 InlineKeyboardHander 添加到 entry_points,这将是一个正确的答案。
  • “状态”是什么意思?
  • 我使用了 ConversationHandler 因为我需要状态,但你删除了它。
  • 这里的status有什么用?因为我认为你可以用其他方式处理它。我看不到这里的状态是什么,详细说明一下,我会给你一个解决方法
  • 在这个例子中什么都没有,但在我的程序中我需要它。在您回答之后,我发现如果我以这种方式更改 entry_points 行,它可以正常工作:entry_points=[CommandHandler('request_button', menu), CallbackQueryHandler(InlineKeyboardHandler)], 然后我有状态并且它也可以正常工作。我已接受您的回答,但我建议您以这种方式进行更改。
猜你喜欢
  • 2020-10-05
  • 2021-08-23
  • 2023-03-22
  • 1970-01-01
  • 2018-02-25
  • 2016-03-11
  • 2016-08-15
  • 2019-10-30
  • 2019-06-02
相关资源
最近更新 更多