feat: implement adapter/telegram/ with aiogram 3.x
Virtual DM chats, FSM (idle/waiting_response/settings states), SQLite local DB for tg_users+chats, converter, keyboards, and handlers for /start, /new, /chats, /settings, confirm callbacks.
This commit is contained in:
parent
a3449fc864
commit
9c555261b3
15 changed files with 791 additions and 0 deletions
101
adapter/telegram/bot.py
Normal file
101
adapter/telegram/bot.py
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
# adapter/telegram/bot.py
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
import structlog
|
||||
from aiogram import Bot, Dispatcher
|
||||
from aiogram.fsm.storage.memory import MemoryStorage
|
||||
|
||||
from adapter.telegram import db
|
||||
from adapter.telegram.handlers import auth, chat, confirm, settings
|
||||
from core.auth import AuthManager
|
||||
from core.chat import ChatManager
|
||||
from core.handler import EventDispatcher
|
||||
from core.handlers.callback import handle_confirm as core_handle_confirm
|
||||
from core.handlers.chat import handle_archive, handle_list_chats, handle_new_chat, handle_rename
|
||||
from core.handlers.message import handle_message
|
||||
from core.handlers.settings import (
|
||||
handle_settings,
|
||||
handle_settings_skills,
|
||||
)
|
||||
from core.handlers.start import handle_start
|
||||
from core.settings import SettingsManager
|
||||
from core.store import InMemoryStore
|
||||
from platform.mock import MockPlatformClient
|
||||
|
||||
logger = structlog.get_logger(__name__)
|
||||
|
||||
|
||||
class DispatcherMiddleware:
|
||||
"""Injects EventDispatcher into every handler via data dict."""
|
||||
|
||||
def __init__(self, dispatcher: EventDispatcher) -> None:
|
||||
self._dispatcher = dispatcher
|
||||
|
||||
async def __call__(self, handler, event, data):
|
||||
data["dispatcher"] = self._dispatcher
|
||||
return await handler(event, data)
|
||||
|
||||
|
||||
def build_event_dispatcher(platform: MockPlatformClient) -> EventDispatcher:
|
||||
store = InMemoryStore()
|
||||
chat_mgr = ChatManager(platform, store)
|
||||
auth_mgr = AuthManager(platform, store)
|
||||
settings_mgr = SettingsManager(platform, store)
|
||||
|
||||
ed = EventDispatcher(
|
||||
platform=platform,
|
||||
chat_mgr=chat_mgr,
|
||||
auth_mgr=auth_mgr,
|
||||
settings_mgr=settings_mgr,
|
||||
)
|
||||
|
||||
# Register core handlers
|
||||
ed.register(type(None).__mro__[0], "start", handle_start) # placeholder
|
||||
from core.protocol import IncomingCommand, IncomingMessage, IncomingCallback
|
||||
ed.register(IncomingCommand, "start", handle_start)
|
||||
ed.register(IncomingCommand, "settings", handle_settings)
|
||||
ed.register(IncomingCommand, "settings_skills", handle_settings_skills)
|
||||
ed.register(IncomingCommand, "new", handle_new_chat)
|
||||
ed.register(IncomingCommand, "chats", handle_list_chats)
|
||||
ed.register(IncomingCommand, "rename", handle_rename)
|
||||
ed.register(IncomingCommand, "archive", handle_archive)
|
||||
ed.register(IncomingMessage, "*", handle_message)
|
||||
ed.register(IncomingCallback, "confirm", core_handle_confirm)
|
||||
ed.register(IncomingCallback, "cancel", core_handle_confirm)
|
||||
|
||||
return ed
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
token = os.environ.get("BOT_TOKEN")
|
||||
if not token:
|
||||
raise RuntimeError("BOT_TOKEN env variable is not set")
|
||||
|
||||
db.init_db()
|
||||
|
||||
bot = Bot(token=token)
|
||||
storage = MemoryStorage()
|
||||
dp = Dispatcher(storage=storage)
|
||||
|
||||
platform = MockPlatformClient()
|
||||
event_dispatcher = build_event_dispatcher(platform)
|
||||
|
||||
# Register middleware on all update types
|
||||
dp.message.middleware(DispatcherMiddleware(event_dispatcher))
|
||||
dp.callback_query.middleware(DispatcherMiddleware(event_dispatcher))
|
||||
|
||||
# Include routers
|
||||
dp.include_router(auth.router)
|
||||
dp.include_router(chat.router)
|
||||
dp.include_router(settings.router)
|
||||
dp.include_router(confirm.router)
|
||||
|
||||
logger.info("Bot starting")
|
||||
await dp.start_polling(bot)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue