chore: snapshot current project updates

This commit is contained in:
windyboy
2026-02-13 13:36:39 +08:00
parent 5931f16a71
commit 0be802eac5
74 changed files with 594899 additions and 66082 deletions
+79 -26
View File
@@ -19,6 +19,7 @@ from .config import Config
from .utils import utc_now
from .logging_config import get_logger, log_operation
from .models import QuarantineEntry, QuarantineManifest, OperationResult, FileOperation
from .scanner import categorize_file
class QuarantineManager:
@@ -127,9 +128,39 @@ class QuarantineManager:
)
raise ValueError(error_msg)
# Get category root directory
category_root = self.config.library_root / category
# Get the actual category directory name from the file path
# (not the category name, which may differ due to category mappings)
try:
relative_from_lib = file_path.relative_to(self.config.library_root)
actual_category_dir = relative_from_lib.parts[0] if relative_from_lib.parts else None
except ValueError:
actual_category_dir = None
if not actual_category_dir:
error_msg = f"File is not within library root {self.config.library_root}: {file_path}"
log_operation(
self.logger,
logging.ERROR,
error_msg,
operation_type="quarantine",
file_path=file_path
)
return OperationResult(
operation=FileOperation(
operation_type="quarantine",
source_path=file_path,
destination_path=None,
reason=reason or "Invalid path",
has_conflict=False
),
success=False,
error_message=error_msg,
executed_at=executed_at
)
# Get category root directory using actual directory name
category_root = self.config.library_root / actual_category_dir
# Determine relative path from category root
try:
relative_path = file_path.relative_to(category_root)
@@ -319,31 +350,51 @@ class QuarantineManager:
def _determine_category(self, file_path: Path) -> str:
"""Determine the category of a file based on its path.
Uses the configured category mappings to support custom directory names.
Args:
file_path: Path to the file
Returns:
Category name ("movie", "series", "anime", "other")
"""
# Get path relative to library root
try:
relative_path = file_path.relative_to(self.config.library_root)
except ValueError:
return "other"
# First component of relative path is the category
parts = relative_path.parts
if not parts:
return "other"
category = parts[0].lower()
# Validate category
if category in ("movie", "series", "anime", "other"):
return category
else:
return "other"
# Use the same categorization logic as the scanner
categories_config = self.config.categories or {
"movie": ["movie"],
"series": ["series"],
"anime": ["anime"]
}
return categorize_file(file_path, self.config.library_root, categories_config)
def _find_category_dir(self, category: str) -> Optional[str]:
"""Find the actual directory name for a given category.
Scans the library root for directories that match the category mapping.
Args:
category: Category name ("movie" or "series")
Returns:
Actual directory name if found, or category name as fallback
"""
categories_config = self.config.categories or {
"movie": ["movie"],
"series": ["series"],
"anime": ["anime"]
}
# Get the list of possible directory names for this category
dir_names = categories_config.get(category, [category])
# Check which one actually exists in the library root
for dir_name in dir_names:
candidate = self.config.library_root / dir_name
if candidate.exists() and candidate.is_dir():
return dir_name
# Fallback to category name itself
return category
def _resolve_conflict(self, quarantine_path: Path) -> Path:
"""Resolve destination conflicts by appending numeric suffix.
@@ -387,14 +438,16 @@ class QuarantineManager:
def _get_manifest_path(self, category: str) -> Path:
"""Get the path to the manifest file for a category.
Args:
category: Category name ("movie" or "series")
Returns:
Path to the manifest.json file
"""
category_root = self.config.library_root / category
# Find the actual directory name for this category
actual_dir = self._find_category_dir(category)
category_root = self.config.library_root / actual_dir
quarantine_root = category_root / self.config.quarantine_dir
return quarantine_root / "manifest.json"