from __future__ import annotations from dataclasses import asdict from pathlib import Path from threading import RLock from biliup_next.core.config import SettingsService from biliup_next.core.registry import Registry from biliup_next.infra.db import Database from biliup_next.infra.plugin_loader import PluginLoader from biliup_next.infra.task_repository import TaskRepository from biliup_next.modules.collection.service import CollectionService from biliup_next.modules.comment.service import CommentService from biliup_next.modules.ingest.service import IngestService from biliup_next.modules.publish.service import PublishService from biliup_next.modules.song_detect.service import SongDetectService from biliup_next.modules.split.service import SplitService from biliup_next.modules.transcribe.service import TranscribeService def project_root() -> Path: return Path(__file__).resolve().parents[3] _APP_STATE: dict[str, object] | None = None _APP_STATE_LOCK = RLock() def reset_initialized_state() -> None: global _APP_STATE with _APP_STATE_LOCK: _APP_STATE = None def ensure_initialized() -> dict[str, object]: global _APP_STATE with _APP_STATE_LOCK: if _APP_STATE is not None: return _APP_STATE root = project_root() settings_service = SettingsService(root) bundle = settings_service.load() db_path = (root / bundle.settings["runtime"]["database_path"]).resolve() db = Database(db_path) db.initialize() repo = TaskRepository(db) registry = Registry() plugin_loader = PluginLoader(root) manifests = plugin_loader.load_manifests() for manifest in manifests: if not manifest.enabled_by_default: continue provider = plugin_loader.instantiate_provider(manifest) provider_manifest = getattr(provider, "manifest", None) if provider_manifest is None: raise RuntimeError(f"provider missing manifest: {manifest.entrypoint}") if provider_manifest.id != manifest.id or provider_manifest.provider_type != manifest.provider_type: raise RuntimeError(f"provider manifest mismatch: {manifest.entrypoint}") registry.register( manifest.provider_type, manifest.id, provider, provider_manifest, ) ingest_service = IngestService(registry, repo) transcribe_service = TranscribeService(registry, repo) song_detect_service = SongDetectService(registry, repo) split_service = SplitService(registry, repo) publish_service = PublishService(registry, repo) comment_service = CommentService(registry, repo) collection_service = CollectionService(registry, repo) _APP_STATE = { "root": root, "settings": bundle.settings, "db": db, "repo": repo, "registry": registry, "manifests": [asdict(m) for m in manifests], "ingest_service": ingest_service, "transcribe_service": transcribe_service, "song_detect_service": song_detect_service, "split_service": split_service, "publish_service": publish_service, "comment_service": comment_service, "collection_service": collection_service, } return _APP_STATE