KaraokeVideoDownloader/karaoke_downloader/data_path_manager.py

185 lines
5.9 KiB
Python

"""
Data path management utilities for the karaoke downloader.
Provides centralized data directory path management and file path resolution.
"""
import os
from pathlib import Path
from typing import Optional
from .config_manager import get_config_manager
class DataPathManager:
"""
Manages data directory paths and provides utilities for resolving file paths
relative to the configured data directory.
"""
def __init__(self, data_dir: Optional[str] = None):
"""
Initialize the data path manager.
Args:
data_dir: Optional custom data directory path. If None, uses config.
"""
self._data_dir = data_dir
# If a custom data directory is provided, look for config.json in that directory
if data_dir:
config_file = Path(data_dir) / "config.json"
self._config_manager = get_config_manager(str(config_file))
else:
# Otherwise, use the default config.json in the root directory
self._config_manager = get_config_manager()
@property
def data_dir(self) -> Path:
"""
Get the configured data directory path.
Returns:
Path to the data directory
"""
if self._data_dir:
return Path(self._data_dir)
# Get from config
config = self._config_manager.get_config()
data_dir = getattr(config.folder_structure, 'data_dir', 'data')
return Path(data_dir)
def get_path(self, filename: str) -> Path:
"""
Get the full path to a file in the data directory.
Args:
filename: Name of the file (e.g., 'config.json', 'channels.json')
Returns:
Full path to the file
"""
return self.data_dir / filename
def get_channels_json_path(self) -> Path:
"""Get path to channels.json file."""
return self.get_path('channels.json')
def get_channels_txt_path(self) -> Path:
"""Get path to channels.txt file."""
return self.get_path('channels.txt')
def get_songlist_path(self) -> Path:
"""Get path to songList.json file."""
return self.get_path('songList.json')
def get_songlist_tracking_path(self) -> Path:
"""Get path to songlist_tracking.json file."""
return self.get_path('songlist_tracking.json')
def get_karaoke_tracking_path(self) -> Path:
"""Get path to karaoke_tracking.json file."""
return self.get_path('karaoke_tracking.json')
def get_server_duplicates_tracking_path(self) -> Path:
"""Get path to server_duplicates_tracking.json file."""
return self.get_path('server_duplicates_tracking.json')
def get_manual_videos_path(self) -> Path:
"""Get path to manual_videos.json file."""
return self.get_path('manual_videos.json')
def get_songs_path(self) -> Path:
"""Get path to songs.json file."""
return self.get_path('songs.json')
def get_channel_cache_dir(self) -> Path:
"""Get path to channel_cache directory."""
return self.get_path('channel_cache')
def get_channel_cache_path(self, channel_id: str) -> Path:
"""Get path to a specific channel cache file."""
return self.get_channel_cache_dir() / f"{channel_id}.json"
def get_download_plan_cache_path(self, plan_name: str, **kwargs) -> Path:
"""Get path to download plan cache file."""
# Create a hash from kwargs for unique cache files
import hashlib
if kwargs:
kwargs_str = str(sorted(kwargs.items()))
hash_suffix = hashlib.md5(kwargs_str.encode()).hexdigest()[:8]
plan_name = f"{plan_name}_{hash_suffix}"
return self.get_path(f"plan_latest_per_channel_{plan_name}.json")
def get_unmatched_report_path(self, timestamp: Optional[str] = None) -> Path:
"""Get path to unmatched songs report file."""
if timestamp:
return self.get_path(f"unmatched_songs_report_{timestamp}.json")
return self.get_path("unmatched_songs_report.json")
def ensure_data_dir_exists(self) -> None:
"""Ensure the data directory exists."""
self.data_dir.mkdir(parents=True, exist_ok=True)
def list_data_files(self) -> list:
"""List all files in the data directory."""
if not self.data_dir.exists():
return []
files = []
for file_path in self.data_dir.iterdir():
if file_path.is_file():
files.append(file_path.name)
return sorted(files)
def file_exists(self, filename: str) -> bool:
"""Check if a file exists in the data directory."""
return self.get_path(filename).exists()
# Global data path manager instance
_data_path_manager: Optional[DataPathManager] = None
def get_data_path_manager(data_dir: Optional[str] = None) -> DataPathManager:
"""
Get the global data path manager instance.
Args:
data_dir: Optional custom data directory path
Returns:
DataPathManager instance
"""
global _data_path_manager
if _data_path_manager is None or data_dir is not None:
_data_path_manager = DataPathManager(data_dir)
return _data_path_manager
def get_data_path(filename: str, data_dir: Optional[str] = None) -> Path:
"""
Get the full path to a file in the data directory.
Args:
filename: Name of the file
data_dir: Optional custom data directory path
Returns:
Full path to the file
"""
return get_data_path_manager(data_dir).get_path(filename)
def get_data_dir(data_dir: Optional[str] = None) -> Path:
"""
Get the configured data directory path.
Args:
data_dir: Optional custom data directory path
Returns:
Path to the data directory
"""
return get_data_path_manager(data_dir).data_dir