尝试使用ConversationHandler使用MessageHandler获取用户输入

问题描述 投票:1回答:1

我试图同时处理InlineKeyboardButton callback_data和自由文本数据。这是我的情况:

提示带有多个按钮的InlineKeyboard,用户单击一个按钮,然后要求输入一些自由文本以供BE使用。

我尝试使用CallbackQueryHandler(回调函数中的几个InlineKeyboardMarkup)作为ConversationHandler的入口点,然后触发MessageHandler,但没有太大的成功。我需要捕获自由文本更新(基本上等待用户输入)。


def start(update, context):
    keyboard = [[InlineKeyboardButton("bal bla", callback_data='1'),
                 InlineKeyboardButton("bla bla", callback_data='2')],
                [InlineKeyboardButton("bla bla)", callback_data='3'),
                InlineKeyboardButton("bla bla", callback_data= '4')],
                [InlineKeyboardButton("bla bla", callback_data='5')]]

    reply_markup = InlineKeyboardMarkup(keyboard)
    update.message.reply_text('Please choose:', reply_markup=reply_markup)


reply_text = {'text': ''}


def reply_message(update, context):
    message = update.message.text
    reply_text['text'] = message
    return reply_text['text']


def button(update, context, user_data):
    query = update.callback_query
    query.edit_message_text(text="Loading....\n \r")

    if query.data == '1':
        pass
    elif query.data == '2':
        pass
    elif query.data == '3':

        keyboard = [[InlineKeyboardButton('BBB', callback_data='21'),
                     InlineKeyboardButton('GGG', callback_data='22')],
                    [InlineKeyboardButton('PPP', callback_data='23')]]

        reply_markup1 = InlineKeyboardMarkup(keyboard)
        query.edit_message_text('Please select:', reply_markup=reply_markup1)

    elif query.data == '21':

        query.edit_message_text('input customer name ')
        return 1

    if : #no idea which condition to give here
        print(reply_text['text'], '\n ^ new free text message here ^')


def main():

    conv_handler= ConversationHandler(
        entry_points=[
            CallbackQueryHandler(button)
        ],
        states={
            1 : [MessageHandler(Filters.text, reply_message)],
        },
        fallbacks= []
    )

    try:
        updater = Updater(bot_token, use_context=True)
        updater.dispatcher.add_handler(CommandHandler('start', start))
        updater.dispatcher.add_handler(CallbackQueryHandler(button))
        updater.dispatcher.add_handler(conv_handler)
        updater.start_polling()
        updater.idle()
    except Exception as e:
        print(e)
python-3.x telegram telegram-bot python-telegram-bot
1个回答
0
投票
def check_user_input(update, context): # get last user text user_input = update.message.text # get user_data context user_data = context.user_data # set new context user_input user_data['user_input'] = user_input context.user_data['user_input'] = user_data['user_input'] if "Text" in user_input: # do something... i.e reply w/o keyboard update.message.reply_text( ("{}?!, sounds interesting, tell me more".format( user_input))) return GUEST_CHOICE else: # ask again reply_keyboard = [['Text'],['Done']] markup = ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True) update.message.reply_text( ("{}?!, i dont know anything...".format( user_input),reply_markup=markup)) return CHECK_CHOICE

这似乎是处理和记住用户输入的首选方法。

现在可以根据需要在ConversationHandler / MessageHandlers中调用此函数。您只需返回指定的ConversationHandler状态。因此,我将创建两个状态,即GUEST_CHOICE和CHECK_CHOICE状态,以处理单个用户输入验证为例。

conv_handler = ConversationHandler( entry_points=[CommandHandler('start', start)], states={ # Ask Guest GUEST_CHOICE: [MessageHandler(Filters.regex('^(Text)$'), guest_choice), ], # Verify input CHECK_CHOICE: [MessageHandler(Filters.text, check_user_input), ], }, fallbacks=[MessageHandler(Filters.regex('^Done$'), done, CommandHandler('start', start))], allow_reentry = False, per_user=True, conversation_timeout=3600, name="test" )

根据定义,/ start用作用户启动对话处理程序。这将调用start()方法,即:

def start(update, context):           
    reply_keyboard = [['Text'],['Done']]
    markup = ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)

    # Setup keyboard and reply
    update.message.reply_text(
            ("Hey {}, how can i help you?".format(
            update.message.chat['first_name'])),
            reply_markup=markup)

    return CHECK_CHOICE

start()将设置标记键盘,之后的任何输入都将以CHECK_CHOICE状态处理,此状态将在此处调用check_user_input(请参见上文)。这将返回GUEST_CHOICE,因此它将调用guest_choice(),即:]

def guest_choice(update, context):  
    user_data = context.user_data

    # Check authentication request
    if "bob" in user_data['user_input']:
        update.message.reply_text("Hey {}".format(user_data['user_input']))         
    else:
        update.message.reply_text("Where is bob?!")
    return CHECK_INPUT

完成方法将清除对话

def done(update, context):
    markup = get_markup(context) 
    update.message.reply_text("Bye")

    return ConversationHandler.END

很快就升级了……我从自己的会话处理程序的工作版本中重写了该代码,请检查是否存在错误:)也许必须在Done方法中清除user_data。

© www.soinside.com 2019 - 2024. All rights reserved.