#!/usr/bin/env python3 """ NFOGuard - Main application entry point Automated NFO file management for Radarr and Sonarr """ import os import signal import sys import uvicorn from datetime import datetime, timezone from fastapi import FastAPI # Import configuration first from config.settings import config # Import other components from core.database import NFOGuardDatabase from core.nfo_manager import NFOManager from core.path_mapper import PathMapper from processors.tv_processor import TVProcessor from processors.movie_processor import MovieProcessor from webhooks.webhook_batcher import WebhookBatcher # --------------------------- # Version and Build Info # --------------------------- def get_version() -> str: """Get version from VERSION file with build information""" try: with open("VERSION", "r", encoding="utf-8") as f: version = f.read().strip() except FileNotFoundError: version = "development" # Add build source suffix for identification build_source = os.environ.get("BUILD_SOURCE", "") if build_source == "gitea": if "gitea" not in version: # Don't double-add gitea suffix version = f"{version}-gitea" return version # --------------------------- # Application Setup # --------------------------- version = get_version() app = FastAPI( title="NFOGuard", description="Webhook server for preserving media import dates", version=version ) start_time = datetime.now(timezone.utc) # Initialize components db = NFOGuardDatabase(config.db_path) nfo_manager = NFOManager(config.manager_brand, config.debug) path_mapper = PathMapper(config) tv_processor = TVProcessor(db, nfo_manager, path_mapper) movie_processor = MovieProcessor(db, nfo_manager, path_mapper) batcher = WebhookBatcher(nfo_manager) # Import and register routes from api.routes import register_routes register_routes(app, tv_processor, movie_processor, batcher, db, start_time, version) # --------------------------- # Signal Handlers # --------------------------- def signal_handler(signum, frame): """Handle shutdown signals gracefully""" print(f"Received signal {signum}, shutting down gracefully...") sys.exit(0) # --------------------------- # Main Entry Point # --------------------------- if __name__ == "__main__": # Register signal handlers for graceful shutdown signal.signal(signal.SIGTERM, signal_handler) signal.signal(signal.SIGINT, signal_handler) print("Starting NFOGuard") print(f"Version: {version}") print(f"TV paths: {[str(p) for p in config.tv_paths]}") print(f"Movie paths: {[str(p) for p in config.movie_paths]}") print(f"Database: {config.db_path}") print(f"Config: manage_nfo={config.manage_nfo}, fix_mtimes={config.fix_dir_mtimes}") print(f"Movie priority: {config.movie_priority}") try: uvicorn.run( app, host="0.0.0.0", port=int(os.environ.get("PORT", "8080")), reload=False ) except KeyboardInterrupt: print("NFOGuard stopped by user") except Exception as e: print(f"NFOGuard crashed: {e}") sys.exit(1)