feat(SerieScanner): add warning event for duplicate series keys
- Add on_warning event system with subscribe/unsubscribe methods - Change duplicate key handling from error to warning - Fire on_warning event when duplicate series detected - Include metadata: key, duplicate_folder, existing_folder
This commit is contained in:
@@ -99,6 +99,7 @@ class SerieScanner:
|
||||
|
||||
self.events.on_progress = []
|
||||
self.events.on_error = []
|
||||
self.events.on_warning = []
|
||||
self.events.on_completion = []
|
||||
|
||||
logger.info("Initialized SerieScanner with base path: %s", abs_path)
|
||||
@@ -191,7 +192,25 @@ class SerieScanner:
|
||||
"""
|
||||
if handler in self.events.on_error:
|
||||
self.events.on_error.remove(handler)
|
||||
|
||||
|
||||
def subscribe_on_warning(self, handler):
|
||||
"""
|
||||
Subscribe a handler to an event.
|
||||
Args:
|
||||
handler: Callable to handle the event
|
||||
"""
|
||||
if handler not in self.events.on_warning:
|
||||
self.events.on_warning.append(handler)
|
||||
|
||||
def unsubscribe_on_warning(self, handler):
|
||||
"""
|
||||
Unsubscribe a handler from an event.
|
||||
Args:
|
||||
handler: Callable to remove
|
||||
"""
|
||||
if handler in self.events.on_warning:
|
||||
self.events.on_warning.remove(handler)
|
||||
|
||||
def subscribe_on_completion(self, handler):
|
||||
"""
|
||||
Subscribe a handler to an event.
|
||||
@@ -454,11 +473,27 @@ class SerieScanner:
|
||||
|
||||
# Store by key (primary identifier), not folder
|
||||
if serie.key in self.keyDict:
|
||||
logger.error(
|
||||
"Duplicate series found with key '%s' "
|
||||
"(folder: '%s')",
|
||||
existing = self.keyDict[serie.key]
|
||||
logger.warning(
|
||||
"Duplicate series found with key '%s': "
|
||||
"folder '%s' maps to same key as existing folder '%s'. "
|
||||
"Skipping duplicate folder.",
|
||||
serie.key,
|
||||
folder
|
||||
folder,
|
||||
existing.folder
|
||||
)
|
||||
self._safe_call_event(
|
||||
self.events.on_warning,
|
||||
{
|
||||
"operation_id": self._current_operation_id,
|
||||
"warning": "duplicate_key",
|
||||
"message": f"Duplicate series skipped: '{folder}' maps to key '{serie.key}' already used by '{existing.folder}'",
|
||||
"metadata": {
|
||||
"key": serie.key,
|
||||
"duplicate_folder": folder,
|
||||
"existing_folder": existing.folder,
|
||||
}
|
||||
}
|
||||
)
|
||||
else:
|
||||
self.keyDict[serie.key] = serie
|
||||
|
||||
@@ -115,6 +115,29 @@ def _is_series_being_downloaded(series_folder: str) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
def _cleanup_stale_files_after_rename(new_path: Path, new_name: str) -> None:
|
||||
"""Remove legacy 'key' file after successful folder rename.
|
||||
|
||||
Also checks for orphaned folders with the same key that may have been
|
||||
left behind from previous rename operations.
|
||||
|
||||
Args:
|
||||
new_path: The new folder path after rename.
|
||||
new_name: The new folder name.
|
||||
"""
|
||||
key_file = new_path / "key"
|
||||
if key_file.exists():
|
||||
try:
|
||||
key_file.unlink()
|
||||
logger.info(
|
||||
"Removed legacy 'key' file after rename: %s", key_file
|
||||
)
|
||||
except OSError as exc:
|
||||
logger.warning(
|
||||
"Could not remove legacy 'key' file %s: %s", key_file, exc
|
||||
)
|
||||
|
||||
|
||||
async def _update_database_paths(
|
||||
old_folder: str,
|
||||
new_folder: str,
|
||||
@@ -315,6 +338,9 @@ async def validate_and_rename_series_folders() -> Dict[str, int]:
|
||||
# Update database records
|
||||
await _update_database_paths(current_name, expected_name, anime_dir)
|
||||
|
||||
# Clean up stale/legacy files after successful rename
|
||||
_cleanup_stale_files_after_rename(expected_path, expected_name)
|
||||
|
||||
except PermissionError as exc:
|
||||
logger.error(
|
||||
"Permission denied renaming '%s' → '%s': %s",
|
||||
|
||||
Reference in New Issue
Block a user