Python Telegram Bot. Как использовать ConversationQueryCallback с методом экземпляра в качестве обратного вызова? - PullRequest
0 голосов
/ 04 мая 2020

Я устанавливаю оболочку для библиотеки python -telegram-bot только потому, что мне не нравится создавать бота, пишущего 1000 000 строк запасных функций, и диспетчер добавляет.

class TelegramBot:
    _types = {
        "_command_callback": CommandHandler,
        "_message_callback": MessageHandler,
        "_conversation_callback": ConversationHandler
    }

    def __init__(self, token=token):
        self.updater = Updater(token, use_context=True)
        self.dispatcher = self.updater.dispatcher

        self.add_dispatchers()

    def add_dispatchers(self):
        for _type, _class in self._types.items():
            handler_functions = list(filter(lambda x: x.endswith(_type), dir(self)))
            for handler in handler_functions:
                attr_name = handler.replace('callback', "handler")
                if _type == '_message_callback':
                    setattr(self, attr_name, _class(Filters.text, getattr(self, handler)))
                elif _type == '_command_callback':
                    setattr(self, attr_name, _class(handler.replace(_type, ''), getattr(self, handler)))
                elif _type == '_conversation_callback':
                    setattr(self, attr_name, _class(*getattr(self, handler)))
                self.dispatcher.add_handler(getattr(self, attr_name))

    def get_handler(self, name, type):
        _name = f"{name}_{type}_handler"
        return getattr(self, _name)

    def start_polling(self):
        self.updater.start_polling()
        self.updater.idle()

С этим простым классом теперь я могу просто сделать что-то вроде:

class MyCustomBot(TelegramBot):

    def test_command_callback(self, update, context):
        update.message.reply_text("Testing command")

    def echo_message_callback(self, update, context):
        update.message.reply_text(update.message.text)

my_bot = MyCustomBot()
my_bot.start_polling()

С этими 7 строками выше я определяю обработчик команд и простой обработчик сообщений. Довольно чисто.

Теперь я хотел бы добавить обработчик разговора. За пределами класса все работает нормально, но если я определю MyCustomBot следующим образом:

class MyCustomBot(TelegramBot):

    def test_command_callback(self, update, context):
        update.message.reply_text("Testing command")

    def echo_message_callback(self, update, context):
        update.message.reply_text(update.message.text)

    @property
    def test_conversation_callback(self):
        entry_points = [self.get_handler('search', 'command')]
        states = {
            1: [CallbackQueryHandler(self.test_command_callback)]
        }
        fallbacks = entry_points
        return entry_points, states, fallbacks

    def search_command_callback(self, update, context):
        keyboard = [
            [InlineKeyboardButton("1", callback_data=str(1)),
             InlineKeyboardButton("2", callback_data=str(2))]
        ]
        reply_markup = InlineKeyboardMarkup(keyboard)
        # Send message with text and appended InlineKeyboard
        update.message.reply_text(
            "Start handler, Choose a route",
            reply_markup=reply_markup
        )

        return 1


bot = MyCustomBot()
bot.start_polling()

Это не сработает. Если я запускаю /search, он отправляет мне клавиатуру правильно, но затем, если я нажимаю кнопку, я вижу предупреждение, проходящее через журналы, в котором говорится: «разговор возвращен, статус отсутствует».

Я думаю, что проблема может быть здесь может быть?

states = {
            1: [CallbackQueryHandler(self.test_command_callback)]
        }

self.test_command_callback - это метод экземпляра, может ли CallbackQueryHandler использовать его в качестве обратного вызова?

А может я что-то упускаю?

1 Ответ

0 голосов
/ 04 мая 2020

Наконец я обнаружил, что я делаю неправильно.

Я зарегистрировал диспетчер search_command_callback как чистые CommandHandler и также в entry_points из ConversationHandler.

Это не работает. Точки входа не могут быть также зарегистрированными CommandHandlers.

Я не знаю, задокументировано ли это. За пару часов отладки я не нашел этого в документации.

...