Переработана система Middleware
This commit is contained in:
parent
e0e7bb53b6
commit
c8dd896691
@ -2,7 +2,8 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
from typing import Any, Callable, Dict, List, TYPE_CHECKING, Optional
|
import functools
|
||||||
|
from typing import Any, Awaitable, Callable, Dict, List, TYPE_CHECKING, Optional
|
||||||
from asyncio.exceptions import TimeoutError as AsyncioTimeoutError
|
from asyncio.exceptions import TimeoutError as AsyncioTimeoutError
|
||||||
|
|
||||||
from aiohttp import ClientConnectorError
|
from aiohttp import ClientConnectorError
|
||||||
@ -120,6 +121,17 @@ class Dispatcher:
|
|||||||
self.bot._me = me
|
self.bot._me = me
|
||||||
|
|
||||||
logger_dp.info(f'Бот: @{me.username} first_name={me.first_name} id={me.user_id}')
|
logger_dp.info(f'Бот: @{me.username} first_name={me.first_name} id={me.user_id}')
|
||||||
|
|
||||||
|
def build_middleware_chain(
|
||||||
|
self,
|
||||||
|
middlewares: list[BaseMiddleware],
|
||||||
|
handler: Callable[[Any, dict[str, Any]], Awaitable[Any]]
|
||||||
|
) -> Callable[[Any, dict[str, Any]], Awaitable[Any]]:
|
||||||
|
|
||||||
|
for mw in reversed(middlewares):
|
||||||
|
handler = functools.partial(mw, handler)
|
||||||
|
|
||||||
|
return handler
|
||||||
|
|
||||||
def include_routers(self, *routers: 'Router'):
|
def include_routers(self, *routers: 'Router'):
|
||||||
|
|
||||||
@ -169,38 +181,18 @@ class Dispatcher:
|
|||||||
new_ctx = MemoryContext(chat_id, user_id)
|
new_ctx = MemoryContext(chat_id, user_id)
|
||||||
self.contexts.append(new_ctx)
|
self.contexts.append(new_ctx)
|
||||||
return new_ctx
|
return new_ctx
|
||||||
|
|
||||||
async def process_middlewares(
|
async def call_handler(self, handler, event_object, data):
|
||||||
self,
|
|
||||||
middlewares: List[BaseMiddleware],
|
|
||||||
event_object: UpdateUnion,
|
|
||||||
result_data_kwargs: Dict[str, Any]
|
|
||||||
):
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Последовательно обрабатывает middleware цепочку.
|
Правка аргументов конечной функции хендлера и ее вызов
|
||||||
|
|
||||||
:param middlewares: Список middleware.
|
|
||||||
:param event_object: Объект события.
|
|
||||||
:param result_data_kwargs: Аргументы, передаваемые обработчику.
|
|
||||||
:return: Изменённые аргументы или None.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
for middleware in middlewares:
|
func_args = handler.func_event.__annotations__.keys()
|
||||||
result = await middleware.process_middleware(
|
kwargs_filtered = {k: v for k, v in data.items() if k in func_args}
|
||||||
event_object=event_object,
|
|
||||||
result_data_kwargs=result_data_kwargs
|
await handler.func_event(event_object, **kwargs_filtered)
|
||||||
)
|
|
||||||
|
|
||||||
if result is None or result is False:
|
|
||||||
return
|
|
||||||
|
|
||||||
elif result is True:
|
|
||||||
continue
|
|
||||||
|
|
||||||
result_data_kwargs.update(result)
|
|
||||||
|
|
||||||
return result_data_kwargs
|
|
||||||
|
|
||||||
async def handle(self, event_object: UpdateUnion):
|
async def handle(self, event_object: UpdateUnion):
|
||||||
|
|
||||||
@ -232,12 +224,6 @@ class Dispatcher:
|
|||||||
if not filter_attrs(event_object, *router.filters):
|
if not filter_attrs(event_object, *router.filters):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
kwargs = await self.process_middlewares(
|
|
||||||
middlewares=router.middlewares,
|
|
||||||
event_object=event_object,
|
|
||||||
result_data_kwargs=kwargs
|
|
||||||
)
|
|
||||||
|
|
||||||
for handler in router.event_handlers:
|
for handler in router.event_handlers:
|
||||||
|
|
||||||
if not handler.update_type == event_object.update_type:
|
if not handler.update_type == event_object.update_type:
|
||||||
@ -252,20 +238,19 @@ class Dispatcher:
|
|||||||
|
|
||||||
func_args = handler.func_event.__annotations__.keys()
|
func_args = handler.func_event.__annotations__.keys()
|
||||||
|
|
||||||
kwargs = await self.process_middlewares(
|
if isinstance(router, Router):
|
||||||
middlewares=handler.middlewares,
|
full_middlewares = self.middlewares + router.middlewares + handler.middlewares
|
||||||
event_object=event_object,
|
elif isinstance(router, Dispatcher):
|
||||||
result_data_kwargs=kwargs
|
full_middlewares = self.middlewares + handler.middlewares
|
||||||
)
|
|
||||||
|
|
||||||
if not kwargs:
|
handler_chain = self.build_middleware_chain(
|
||||||
continue
|
full_middlewares,
|
||||||
|
functools.partial(self.call_handler, handler)
|
||||||
|
)
|
||||||
|
|
||||||
|
kwargs_filtered = {k: v for k, v in kwargs.items() if k in func_args}
|
||||||
|
|
||||||
for key in kwargs.copy().keys():
|
await handler_chain(event_object, kwargs_filtered)
|
||||||
if key not in func_args:
|
|
||||||
del kwargs[key]
|
|
||||||
|
|
||||||
await handler.func_event(event_object, **kwargs)
|
|
||||||
|
|
||||||
logger_dp.info(f'Обработано: {router_id} | {process_info}')
|
logger_dp.info(f'Обработано: {router_id} | {process_info}')
|
||||||
|
|
||||||
|
@ -1,27 +1,10 @@
|
|||||||
from typing import Any, Dict
|
from typing import Any, Callable, Awaitable
|
||||||
from ..types.updates import UpdateUnion
|
|
||||||
|
|
||||||
|
|
||||||
class BaseMiddleware:
|
class BaseMiddleware:
|
||||||
def __init__(self):
|
async def __call__(
|
||||||
...
|
self,
|
||||||
|
handler: Callable[[Any, dict[str, Any]], Awaitable[Any]],
|
||||||
async def process_middleware(
|
event_object: Any,
|
||||||
self,
|
data: dict[str, Any]
|
||||||
result_data_kwargs: Dict[str, Any],
|
) -> Any:
|
||||||
event_object: UpdateUnion
|
return await handler(event_object, data)
|
||||||
):
|
|
||||||
|
|
||||||
# пока что заглушка
|
|
||||||
if result_data_kwargs is None:
|
|
||||||
return {}
|
|
||||||
|
|
||||||
kwargs_temp = {'data': result_data_kwargs.copy()}
|
|
||||||
|
|
||||||
for key in kwargs_temp.copy().keys():
|
|
||||||
if key not in self.__call__.__annotations__.keys(): # type: ignore
|
|
||||||
del kwargs_temp[key]
|
|
||||||
|
|
||||||
result: Dict[str, Any] = await self(event_object, **kwargs_temp) # type: ignore
|
|
||||||
|
|
||||||
return result
|
|
Loading…
x
Reference in New Issue
Block a user