Initial MCM project: FastAPI + Textual TUI unified messenger
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. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
103
main.py
Normal file
103
main.py
Normal file
@@ -0,0 +1,103 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user