#!/usr/bin/env python3 """ CBCFacil - Main Service Entry Point Unified AI service for document processing (audio, PDF, text) """ import logging import sys import time import fcntl import os from pathlib import Path # Configure logging logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] - %(message)s" ) logger = logging.getLogger(__name__) def acquire_lock() -> int: """Acquire single instance lock""" lock_file = Path(os.getenv("LOCAL_STATE_DIR", str(Path(__file__).parent))) / ".main_service.lock" lock_file.parent.mkdir(parents=True, exist_ok=True) lock_fd = open(lock_file, 'w') fcntl.flock(lock_fd.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB) lock_fd.write(str(os.getpid())) lock_fd.flush() logger.info(f"Lock acquired. PID: {os.getpid()}") return lock_fd def release_lock(lock_fd) -> None: """Release lock""" try: fcntl.flock(lock_fd.fileno(), fcntl.LOCK_UN) lock_fd.close() except Exception as e: logger.warning(f"Could not release lock: {e}") def initialize_services() -> None: """Initialize all services""" from config import settings from services.webdav_service import webdav_service from services.vram_manager import vram_manager from services.telegram_service import telegram_service from storage.processed_registry import processed_registry # Configure Telegram if credentials available if settings.TELEGRAM_TOKEN and settings.TELEGRAM_CHAT_ID: telegram_service.configure(settings.TELEGRAM_TOKEN, settings.TELEGRAM_CHAT_ID) telegram_service.send_start_notification() # Initialize WebDAV if configured if settings.has_webdav_config: webdav_service.initialize() # Initialize VRAM manager vram_manager.initialize() # Initialize processed registry processed_registry.initialize() logger.info("All services initialized") def run_main_loop() -> None: """Main processing loop""" from config import settings from services.webdav_service import webdav_service from storage.processed_registry import processed_registry from processors.audio_processor import AudioProcessor from processors.pdf_processor import PDFProcessor from processors.text_processor import TextProcessor audio_processor = AudioProcessor() pdf_processor = PDFProcessor() text_processor = TextProcessor() while True: try: logger.info("--- Polling for new files ---") processed_registry.load() # Process PDFs if settings.has_webdav_config: webdav_service.mkdir(settings.REMOTE_PDF_FOLDER) pdf_files = webdav_service.list(settings.REMOTE_PDF_FOLDER) for file_path in pdf_files: if file_path.lower().endswith('.pdf'): if not processed_registry.is_processed(file_path): pdf_processor.process(file_path) processed_registry.save(file_path) # Process Audio files if settings.has_webdav_config: audio_files = webdav_service.list(settings.REMOTE_AUDIOS_FOLDER) for file_path in audio_files: if any(file_path.lower().endswith(ext) for ext in settings.AUDIO_EXTENSIONS): if not processed_registry.is_processed(file_path): audio_processor.process(file_path) processed_registry.save(file_path) # Process Text files if settings.has_webdav_config: text_files = webdav_service.list(settings.REMOTE_TXT_FOLDER) for file_path in text_files: if any(file_path.lower().endswith(ext) for ext in settings.TXT_EXTENSIONS): if not processed_registry.is_processed(file_path): text_processor.process(file_path) processed_registry.save(file_path) except Exception as e: logger.error(f"Error in main loop: {e}") logger.info(f"Cycle completed. Waiting {settings.POLL_INTERVAL} seconds...") time.sleep(settings.POLL_INTERVAL) def main(): """Main entry point""" lock_fd = acquire_lock() try: logger.info("=== CBCFacil Service Started ===") initialize_services() run_main_loop() except KeyboardInterrupt: logger.info("Shutdown requested") finally: release_lock(lock_fd) if __name__ == "__main__": # Handle CLI commands if len(sys.argv) > 1: command = sys.argv[1] if command == "whisper" and len(sys.argv) == 4: from processors.audio_processor import AudioProcessor AudioProcessor().process(sys.argv[2]) elif command == "pdf" and len(sys.argv) == 4: from processors.pdf_processor import PDFProcessor PDFProcessor().process(sys.argv[2]) else: print("Usage: python main.py [whisper|pdf]") sys.exit(1) else: main()