MultiCustomerMessenger supporting Telegram (python-telegram-bot), WhatsApp (Green API) and SMS (python-gsmmodem-new). REST API with Bearer-token auth, SQLAlchemy models for MariaDB, APScheduler for background polling, and Textual TUI running in same asyncio event-loop.
104 lines
2.9 KiB
Python
104 lines
2.9 KiB
Python
"""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
|
||
from tasks.receiver import build_scheduler
|
||
|
||
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. Hintergrund-Tasks starten (WhatsApp-Polling etc.)
|
||
scheduler = build_scheduler(whatsapp)
|
||
scheduler.start()
|
||
|
||
# 7. 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)")
|
||
await api_task
|
||
finally:
|
||
logger.info("MCM shutting down…")
|
||
scheduler.shutdown(wait=False)
|
||
await telegram.stop()
|
||
await whatsapp.stop()
|
||
await sms.stop()
|
||
api_task.cancel()
|
||
|
||
|
||
if __name__ == "__main__":
|
||
no_tui = "--no-tui" in sys.argv
|
||
try:
|
||
asyncio.run(main(with_tui=not no_tui))
|
||
except KeyboardInterrupt:
|
||
pass
|