# core/handler.py from __future__ import annotations from typing import Awaitable, Callable import structlog from core.auth import AuthManager from core.chat import ChatManager from core.protocol import ( IncomingCallback, IncomingCommand, IncomingEvent, IncomingMessage, OutgoingEvent, ) from core.settings import SettingsManager from sdk.interface import PlatformClient logger = structlog.get_logger(__name__) HandlerFn = Callable[..., Awaitable[list[OutgoingEvent]]] class EventDispatcher: def __init__( self, platform: PlatformClient, chat_mgr: ChatManager, auth_mgr: AuthManager, settings_mgr: SettingsManager, ) -> None: self._platform = platform self._chat_mgr = chat_mgr self._auth_mgr = auth_mgr self._settings_mgr = settings_mgr self._handlers: dict[type, dict[str, HandlerFn]] = { IncomingCommand: {}, IncomingMessage: {}, IncomingCallback: {}, } def register(self, event_type: type, key: str, handler: HandlerFn) -> None: self._handlers[event_type][key] = handler async def dispatch(self, event: IncomingEvent) -> list[OutgoingEvent]: event_type = type(event) handlers = self._handlers.get(event_type, {}) key = self._routing_key(event) handler = handlers.get(key) or handlers.get("*") if handler is None: logger.warning("No handler registered", event_type=event_type.__name__, key=key) return [] return await handler( event=event, chat_mgr=self._chat_mgr, auth_mgr=self._auth_mgr, settings_mgr=self._settings_mgr, platform=self._platform, ) def _routing_key(self, event: IncomingEvent) -> str: if isinstance(event, IncomingCommand): return event.command if isinstance(event, IncomingCallback): return event.action if isinstance(event, IncomingMessage) and event.attachments: return event.attachments[0].type return "*"