Обработка нескольких вопросов для бота Telegram на Python

Я программирую бота Telegram на Python, используя API бота Telegram. Я столкнулся с проблемой управления вопросами, на которые нужен ответ пользователя. Проблема возникает, когда программа ожидает ответа одного пользователя, а другой пользователь запрашивает информацию или задает другой вопрос до того, как первый пользователь ответит.

API Telegram использует код для обработки запроса. Когда вы запрашиваете обновления, вы включаете код. Если код, который вы отправляете, превышает код запроса, он помечается как обработанный, и телеграмма удаляет его и больше не отображается в обновлениях. Этот код является последовательным, поэтому, если вы отметите обновление 3 как обработанное, обновления 1 и 2 также будут удалены.

Возникает вопрос: почему это лучший фитонический / элегантный способ обрабатывать несколько запросов, требующих ответа для пользователей?


person Dargor    schedule 22.08.2015    source источник


Ответы (2)


Это не самый питонический способ сделать это. Это проблема, которую вы должны запрограммировать, чтобы решить.

По сути, вы должны поддерживать некоторые переменные состояния для каждого пользователя. Когда приходит новое сообщение, бот проверяет, в каком состоянии находится этот пользователь, и отвечает соответствующим образом.

Предположим, у вас есть функция handle(msg), которая вызывается для каждого поступающего сообщения:

user_states = {}

def handle(msg):
    chat_id = msg['chat']['id']

    if chat_id not in user_states:
        user_states[chat_id] = some initial state ...

    state = user_states[chat_id]

    # respond according to `state`

Это подойдет для простой программы.

В более сложных ситуациях я рекомендую использовать telepot, фреймворк Python, который я создал для Telegram Bot API. . В нем есть функции, которые решают именно такие проблемы.

Например, ниже показан бот, который подсчитывает, сколько сообщений было отправлено отдельным пользователем. Если в течение 10 секунд не было получено ни одного сообщения, он запускается заново (тайм-аут). Подсчет ведется за чат - это важный момент.

import sys
import telepot
from telepot.delegate import per_chat_id, create_open

class MessageCounter(telepot.helper.ChatHandler):
    def __init__(self, seed_tuple, timeout):
        super(MessageCounter, self).__init__(seed_tuple, timeout)
        self._count = 0

    def on_message(self, msg):
        self._count += 1
        self.sender.sendMessage(self._count)

TOKEN = sys.argv[1]  # get token from command-line

bot = telepot.DelegatorBot(TOKEN, [
    (per_chat_id(), create_open(MessageCounter, timeout=10)),
])
bot.notifyOnMessage(run_forever=True)

Запустите программу:

python messagecounter.py <token>

Перейдите на страницу проекта, чтобы узнать больше, если вам интересно. Есть много документации и нетривиальных примеров.

person Nick Lee    schedule 30.10.2015
comment
Вау, спасибо большое! Есть шанс поработать в вашем проекте? Дела, которые необходимо сделать? Ошибки и проблемы? Заранее спасибо! - person Dargor; 30.10.2015
comment
Спасибо. Лучший способ помочь мне - сообщить мне, что вам нужно, чего нет в библиотеке, или какие-либо ошибки. Еще один лучший способ помочь мне - рассказать о телепоте. Я искренне верю, что это может облегчить разработку ботов Telegram. Третий лучший способ - использовать телепот в своей работе. В этом весь смысл публикации библиотеки. Еще раз спасибо. - person Nick Lee; 31.10.2015
comment
Четвертый способ помочь мне - сделать мой ответ вашим принятым ответом, если вы не против. Спасибо. - person Nick Lee; 31.10.2015

В своих ботах я использую веб-перехватчик. Если вы можете использовать веб-хуки - сделайте это, это более удобный способ взаимодействия с ботами Telegram.

Если вы не можете использовать веб-перехватчик (например, проблемы с ssl), для вас есть обходной путь. Используйте ForceReply, чтобы получить предыдущий ответ бота и написать логику на основе ответов пользователей.

Проверьте, есть ли в обновлении ответ (ключ reply_to_message), затем сделайте ответ бота на основе этого ответа. Эти действия должны быть асинхронными, чтобы обеспечить высокую производительность бота.

Если вы программист на Python, я рекомендую для этих целей Tornado.

person Ivan Menshenin    schedule 22.08.2015
comment
Это интересно. Хотя ваш метод подходит, я считаю, что это немного беспорядочно, когда, например, несколько пользователей должны ответить на вопрос бота. Я думаю, что есть способ решить эту проблему, не убивая вопрос другого пользователя. Но это только моя надежда. - person Dargor; 23.08.2015