"""MCM – MultiCustomerMessenger Entry Point: Startet FastAPI (Uvicorn) und Textual TUI im selben asyncio-Event-Loop. Für den systemd-Dienst (ohne TUI) siehe main_api_only.py. """ from __future__ import annotations import asyncio import logging import sys import uvicorn from api.app import app as fastapi_app from api.routes import channels as channels_router from channels.sms_channel import SmsChannel from channels.telegram_channel import TelegramChannel from channels.whatsapp_channel import WhatsAppChannel from config import settings from db.database import init_db from services import message_service logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s", ) logger = logging.getLogger("mcm") async def _run_api() -> None: """Uvicorn als Task in der bestehenden Event-Loop.""" config = uvicorn.Config( fastapi_app, host=settings.host, port=settings.port, log_level="warning", access_log=False, ) server = uvicorn.Server(config) await server.serve() async def main(with_tui: bool = True) -> None: logger.info("MCM starting…") # 1. Datenbank initialisieren init_db() # 2. Kanäle instanziieren telegram = TelegramChannel() whatsapp = WhatsAppChannel() sms = SmsChannel() # 3. Inbound-Callback setzen telegram.set_inbound_callback(message_service.handle_inbound) whatsapp.set_inbound_callback(message_service.handle_inbound) sms.set_inbound_callback(message_service.handle_inbound) # 4. Channel-Referenzen in Services/Routes registrieren message_service.register_channels(telegram, whatsapp, sms) channels_router.register(telegram, whatsapp, sms) # 5. Kanäle starten await telegram.start() await whatsapp.start() await sms.start() # 6. Uvicorn als Hintergrund-Task starten api_task = asyncio.create_task(_run_api(), name="mcm-api") logger.info("API running on http://%s:%d", settings.host, settings.port) try: if with_tui: # 8a. TUI starten (blockiert bis der Nutzer beendet) from tui.app import MCMApp tui = MCMApp() await tui.run_async() else: # 8b. Nur API – wartet auf Ctrl-C / SIGTERM logger.info("Running in API-only mode (no TUI)") try: await api_task except asyncio.CancelledError: pass finally: logger.info("MCM shutting down…") api_task.cancel() try: await api_task except asyncio.CancelledError: pass await telegram.stop() await whatsapp.stop() await sms.stop() logger.info("MCM stopped.") if __name__ == "__main__": no_tui = "--no-tui" in sys.argv try: asyncio.run(main(with_tui=not no_tui)) except KeyboardInterrupt: pass