Python Telegram Bot如何等待用户回答问题并返回它

问题描述 投票:4回答:2

上下文:

我正在使用PyTelegramBotAPiPython Telegram Bot

我有一个用户开始对话时正在运行的代码。

[当用户开始对话时,我需要向他发送第一张图片,并询问他是否看到图片中的内容,该功能需要等待用户输入并返回他是否看到它。

此后,我将需要继续循环发送图片,等待答案并对其运行二等分算法。

到目前为止我尝试过的:

我尝试使用等待响应的应答标记或带有处理程序的嵌入式键盘,但由于我的代码正在运行而不等待用户输入,所以我被卡住了。

代码:

@bot.message_handler(func=lambda msg: msg in ['Yes', 'No'])
@bot.message_handler(commands=['start', 'help'])
def main(message):
    """
    This is my main function
    """
    chat_id = message.chat.id
    try:
        reply_answer = message.reply_to_message.text
    except AttributeError:
        reply_answer = '0'
    # TODO : should wait for the answer asynchnonossly
    def tester(n, reply_answer):
        """
        Displays the current candidate to the user and asks them to
        check if they see wildfire damages.
        """
        print('call......')
        bisector.index = n
        bot.send_photo(
            chat_id=chat_id,
            photo=bisector.image.save_image(),
            caption=f"Did you see it Yes or No {bisector.date}",
            reply_markup=types.ForceReply(selective=True))
        # I SHOUL WAIT FOR THE INPUT HERE AND RETURN THE USER INPUT
        return eval(reply_answer)
    culprit = bisect(bisector.count, lambda x: x, partial(tester, reply_answer=reply_answer) )
    bisector.index = culprit
    bot.send_message(chat_id, f"Found! First apparition = {bisector.date}")


bot.polling(none_stop=True)

我在用户输入上运行的算法是这样的:

def bisect(n, mapper, tester):
    """
    Runs a bisection.

    - `n` is the number of elements to be bisected
    - `mapper` is a callable that will transform an integer from "0" to "n"
      into a value that can be tested
    - `tester` returns true if the value is within the "right" range
    """

    if n < 1:
        raise ValueError('Cannot bissect an empty array')

    left = 0
    right = n - 1

    while left + 1 < right:
        mid = int((left + right) / 2)

        val = mapper(mid)
        tester_values = tester(val) # Here is where I am using the ouput from Telegram bot
        if tester_values:
            right = mid
        else:
            left = mid

    return mapper(right)

我希望我能清楚地说明问题,请随时提出任何澄清。如果您知道可以为我指出正确方向的解决方案,请告诉我。

我尝试过类似的问题,但没有得到答案。

python telegram telegram-bot python-telegram-bot
2个回答
5
投票

您应该将用户信息保存在数据库中。基本字段为:

(id, first_name, last_name, username, menu)

什么是菜单?

菜单保留用户的当前状态。当用户向您的机器人发送消息时,您可以检查数据库以了解用户的当前状态。

因此,如果用户不存在,则将其添加到menu设置为MainMenuWelcomeMenu或在您的情况下为PictureMenu的用户表中。

现在您将拥有一个用于更新功能的侦听器,让我们假设每个菜单都有。

@bot.message_handler(commands=['start', 'help'])

因此,当用户发送start时,您将检查功能内的用户菜单字段。

@bot.message_handler(commands=['start', 'help'])
def main(message):
    user = fetch_user_from_db(chat_id)
    if user.menu == "PictureMenu":
        if message.photo is Not None:
            photo = message.photo[0].file_id
            photo_file = download_photo_from_telegram(photo)
            do_other_things()
            user.menu = "Picture2Menu";
            user.save();
        else:
            send_message("Please send a photo")
    if user.menu == "Picture2Menu":
        if message.photo is Not None:
            photo = message.photo[0].file_id
            photo_file = download_photo_from_telegram(photo)
            do_other_things()
            user.menu = "Picture3Menu";
            user.save();
        else:
            send_message("Please send a photo")   
    ...

我希望你明白了。


0
投票

我已经找到答案:

  • 诀窍是使用next_step_handlermessage_handler_function处理以starthelp开始的命令>

    <<
  • 一旦用户回答了所有问题,我就可以根据他的回答运行算法

  • 这是代码中的样子:

    user_dict = {} # Handle '/start' and '/help' @bot.message_handler(commands=['help', 'start']) def send_welcome(message): # initialise the the bisector and bisector = LandsatBisector(LON, LAT) indice = 0 message = send_current_candidate(bot, message, bisector, indice) bot.register_next_step_handler( message, partial( process_step, indice, bisector)) def process_step(indice, bisector, message): # this run a while loop and will that send picture and will stop when the count is reached response = message.text user = User.create_get_user(message, bisector=bisector) if indice < bisector.count - 1: indice += 1 try: # get or create user.responses[bisector.date] = response # save the response message = send_current_candidate(bot, message, bisector, indice) bot.register_next_step_handler( message, partial( process_step, indice, bisector)) except Exception as e: print(e) bot.reply_to(message, 'oooops') else: culprit = bisect(bisector.count, lambda x: x, partial( tester_function, responses=list(user.responses.values()))) bisector.index = culprit bot.reply_to(message, f"Found! First apparition = {bisector.date}")

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