Skip to content

Мидлвари и return менеджеры

Мидлвари

Мидлвари - так называемые внешние слои, покрывающие обработку хендлеров. У мидлварей есть два состояния - pre и post, pre это то, что происходит до начала поиска хендлера (когда только нашелся нужный view), а post - то что происходит когда хендлер уже был обработан и известно все о прошедшей обработке: какие хендлеры сработали, что они вернули

Чтобы создать мидлварь, импортируйте для начала абстрактный класс для него из корневого пакета:

from vkbottle import BaseMiddleware
from vkbottle.bot import Message

Теперь начните писать ваш собственный класс:

class MiddlewareName(BaseMiddleware[Message]):

Так как наш мидлварь обрабатывает именно сообщения, нужно указать тип в дженерике. В данном случае мы используем класс Message из vkbottle.bot

Middleware без методов pre или/и post бесполезен, нужно разобраться как реализовать каждый из них

async def pre(self)

pre имеет доступ к ивенту (например сообщению) через self и может вернуть ошибку через self.stop или обновить контекст через self.send

Техническая документация

Вот так например можно отсеивать все сообщения от ботов:

1
2
3
4
5
6
7
from vkbottle.bot import Message
from vkbottle import BaseMiddleware, MiddlewareResponse

class NoBotMiddleware(BaseMiddleware[Message]):
    async def pre(self):
        if self.event.from_id < 0:
            self.stop("from_id меньше 0")

async def post(self)

post уже никак не может повлиять на обработку ивента. Обычно его используют для статистики и логов

from vkbottle.bot import Message
from vkbottle import BaseMiddleware
from typing import List, Any

class LogMiddleware(BaseMiddleware[Message]):
    async def post(self):
        if not self.handlers:
            return

        print(f"{len(self.handlers)} хендлеров сработало на сообщение. "
              f"Они вернули {self.handle_responses}, "
              f"все они принадлежали к view {self.view}")

pre и post можно использовать и одновременно в одном мидлваре

Регистрация мидлварей

Чтобы зарегистрировать мидлварь (и он работал) нужно определиться с view к которому он принадлежит, в данном случае это MessageView

В лейблере MessageView располагается по адресу .message_view

У каждого view есть метод register_middleware, воспользуемся им:

bot.labeler.message_view.register_middleware(NoBotMiddleware)
bot.labeler.message_view.register_middleware(LogMiddleware)

Кстати методом register_middleware можно пользоваться и как декоратором.

Полный код с мидлварями вы можете найти в этом экзампле

Return менеджеры

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

Примечание

Создание кастомного менеджера для вашего view выходит за рамки этого туториала, но вы можете прочитать об этом в технической документации, когда посчитаете что готовы

Для общего понимания будет разобран return менеджер из коробки для MessageView

Суть заключается в том, что возвращая значения некоторых типов из хендлера, сработают хендлеры return менеджера которые произведут некоторые действия, вот что будет необходимо знать для комфортной разработки:

тип значения что произойдет
str строка отправится как сообщение
tuple или list все элементы будут конвертированы в строки и отправлены как сообщения
dict словарь распакуется как непозиционные аргументы для метода message.answer

Экзамплы по этой части туториала