Wenn beim Start keine User in der Datenbank vorhanden sind, wird automatisch ein verifizierter Admin angelegt: E-Mail: admin@localhost Passwort: changeme Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
108 lines
2.9 KiB
Python
108 lines
2.9 KiB
Python
import asyncio
|
|
import logging
|
|
import signal
|
|
import threading
|
|
|
|
from meshbot import config
|
|
from meshbot.auth import hash_password
|
|
from meshbot.database import Database
|
|
from meshbot.bot import MeshBot
|
|
from meshbot.nina import NinaBot
|
|
from meshbot.scheduler import Scheduler
|
|
from meshbot.webserver import WebServer, WebSocketManager
|
|
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
|
|
)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
async def main():
|
|
logger.info("Starting %s v%s", config.get("bot.name"), config.get("version"))
|
|
|
|
# Database
|
|
db = Database(config.get("database.path", "data/meshdd.db"))
|
|
await db.connect()
|
|
|
|
# Seed initial admin if no users exist
|
|
if not await db.get_all_users():
|
|
await db.create_user(
|
|
email="admin@localhost",
|
|
password=hash_password("changeme"),
|
|
name="Administrator",
|
|
role="admin",
|
|
is_verified=1,
|
|
)
|
|
logger.info("Initial admin created: admin@localhost / changeme <- bitte Passwort aendern!")
|
|
|
|
# WebSocket Manager
|
|
ws_manager = WebSocketManager()
|
|
|
|
# Bot
|
|
loop = asyncio.get_event_loop()
|
|
bot = MeshBot(db, loop)
|
|
bot.ws_manager = ws_manager
|
|
|
|
# Scheduler
|
|
scheduler = Scheduler(bot, ws_manager)
|
|
|
|
# NINA
|
|
nina = NinaBot(bot.send_message, ws_manager)
|
|
|
|
# Webserver
|
|
webserver = WebServer(db, ws_manager, bot, scheduler, nina)
|
|
runner = await webserver.start(config.get("web.host", "0.0.0.0"), config.get("web.port", 8080))
|
|
|
|
# Connect Meshtastic in a thread (blocking call)
|
|
connect_thread = threading.Thread(target=bot.connect, daemon=True)
|
|
connect_thread.start()
|
|
|
|
# Watch config for changes
|
|
asyncio.create_task(config.watch())
|
|
|
|
# Scheduler tasks
|
|
asyncio.create_task(scheduler.watch())
|
|
asyncio.create_task(scheduler.run())
|
|
|
|
# NINA tasks
|
|
asyncio.create_task(nina.watch())
|
|
await nina.start()
|
|
|
|
# Wait for shutdown
|
|
stop_event = asyncio.Event()
|
|
|
|
def _signal_handler():
|
|
logger.info("Shutdown signal received")
|
|
stop_event.set()
|
|
|
|
for sig in (signal.SIGINT, signal.SIGTERM):
|
|
loop.add_signal_handler(sig, _signal_handler)
|
|
|
|
try:
|
|
await stop_event.wait()
|
|
finally:
|
|
logger.info("Shutting down...")
|
|
try:
|
|
await nina.stop()
|
|
except Exception:
|
|
logger.exception("Error stopping NINA")
|
|
try:
|
|
bot.disconnect()
|
|
except Exception:
|
|
logger.exception("Error disconnecting bot")
|
|
try:
|
|
await ws_manager.close_all()
|
|
except Exception:
|
|
logger.exception("Error closing WebSocket connections")
|
|
try:
|
|
await runner.cleanup()
|
|
except Exception:
|
|
logger.exception("Error cleaning up web runner")
|
|
await db.close()
|
|
logger.info("Shutdown complete")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|