fix: prevent duplicate series when same anime key exists in different folder
- Add check for existing series by key in SetupService.run to skip duplicates - Fix Path construction in initialization_service.py cleanup function - Update unit tests to mock get_by_key and get_series_app
This commit is contained in:
@@ -165,7 +165,7 @@ async def _cleanup_legacy_key_files() -> int:
|
|||||||
db_folders: set[str] = {series.folder for series in all_series if series.folder}
|
db_folders: set[str] = {series.folder for series in all_series if series.folder}
|
||||||
|
|
||||||
for folder_name in db_folders:
|
for folder_name in db_folders:
|
||||||
folder_path = settings.anime_directory / folder_name
|
folder_path = Path(settings.anime_directory) / folder_name
|
||||||
key_file = folder_path / "key"
|
key_file = folder_path / "key"
|
||||||
|
|
||||||
if not key_file.exists():
|
if not key_file.exists():
|
||||||
|
|||||||
@@ -378,6 +378,18 @@ class SetupService:
|
|||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Also check if a series with this key already exists (different folder, same anime)
|
||||||
|
existing_by_key = await AnimeSeriesService.get_by_key(db, resolved_key)
|
||||||
|
if existing_by_key:
|
||||||
|
logger.debug(
|
||||||
|
"Series with key already exists, skipping",
|
||||||
|
folder=folder_name,
|
||||||
|
key=resolved_key,
|
||||||
|
existing_folder=existing_by_key.folder
|
||||||
|
)
|
||||||
|
skipped_existing += 1
|
||||||
|
continue
|
||||||
|
|
||||||
# Check filesystem properties
|
# Check filesystem properties
|
||||||
props = cls._get_series_properties(folder)
|
props = cls._get_series_properties(folder)
|
||||||
|
|
||||||
|
|||||||
@@ -167,10 +167,16 @@ class TestSetupServiceRun:
|
|||||||
mock_get_db = MagicMock()
|
mock_get_db = MagicMock()
|
||||||
mock_get_db.__aenter__.return_value = mock_db
|
mock_get_db.__aenter__.return_value = mock_db
|
||||||
mock_get_db.__aexit__.return_value = None
|
mock_get_db.__aexit__.return_value = None
|
||||||
|
mock_series_app = AsyncMock()
|
||||||
|
mock_series_app.search.return_value = []
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
'src.server.services.setup_service.settings'
|
'src.server.services.setup_service.settings'
|
||||||
) as mock_settings, \
|
) as mock_settings, \
|
||||||
|
patch(
|
||||||
|
'src.server.services.setup_service.get_series_app',
|
||||||
|
return_value=mock_series_app
|
||||||
|
), \
|
||||||
patch(
|
patch(
|
||||||
'src.server.services.setup_service.get_db_session',
|
'src.server.services.setup_service.get_db_session',
|
||||||
return_value=mock_get_db
|
return_value=mock_get_db
|
||||||
@@ -179,6 +185,10 @@ class TestSetupServiceRun:
|
|||||||
'src.server.services.setup_service.AnimeSeriesService.get_by_folder',
|
'src.server.services.setup_service.AnimeSeriesService.get_by_folder',
|
||||||
new_callable=AsyncMock, return_value=None
|
new_callable=AsyncMock, return_value=None
|
||||||
), \
|
), \
|
||||||
|
patch(
|
||||||
|
'src.server.services.setup_service.AnimeSeriesService.get_by_key',
|
||||||
|
new_callable=AsyncMock, return_value=None
|
||||||
|
), \
|
||||||
patch(
|
patch(
|
||||||
'src.server.services.setup_service.UnresolvedFolderService.get_by_folder_name',
|
'src.server.services.setup_service.UnresolvedFolderService.get_by_folder_name',
|
||||||
new_callable=AsyncMock, return_value=None
|
new_callable=AsyncMock, return_value=None
|
||||||
@@ -258,10 +268,16 @@ class TestSetupServiceRun:
|
|||||||
mock_get_db = MagicMock()
|
mock_get_db = MagicMock()
|
||||||
mock_get_db.__aenter__.return_value = mock_db
|
mock_get_db.__aenter__.return_value = mock_db
|
||||||
mock_get_db.__aexit__.return_value = None
|
mock_get_db.__aexit__.return_value = None
|
||||||
|
mock_series_app = AsyncMock()
|
||||||
|
mock_series_app.search.return_value = []
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
'src.server.services.setup_service.settings'
|
'src.server.services.setup_service.settings'
|
||||||
) as mock_settings, \
|
) as mock_settings, \
|
||||||
|
patch(
|
||||||
|
'src.server.services.setup_service.get_series_app',
|
||||||
|
return_value=mock_series_app
|
||||||
|
), \
|
||||||
patch(
|
patch(
|
||||||
'src.server.services.setup_service.get_db_session',
|
'src.server.services.setup_service.get_db_session',
|
||||||
return_value=mock_get_db
|
return_value=mock_get_db
|
||||||
@@ -270,6 +286,10 @@ class TestSetupServiceRun:
|
|||||||
'src.server.services.setup_service.AnimeSeriesService.get_by_folder',
|
'src.server.services.setup_service.AnimeSeriesService.get_by_folder',
|
||||||
new_callable=AsyncMock, return_value=None
|
new_callable=AsyncMock, return_value=None
|
||||||
), \
|
), \
|
||||||
|
patch(
|
||||||
|
'src.server.services.setup_service.AnimeSeriesService.get_by_key',
|
||||||
|
new_callable=AsyncMock, return_value=None
|
||||||
|
), \
|
||||||
patch(
|
patch(
|
||||||
'src.server.services.setup_service.UnresolvedFolderService.get_by_folder_name',
|
'src.server.services.setup_service.UnresolvedFolderService.get_by_folder_name',
|
||||||
new_callable=AsyncMock, return_value=None
|
new_callable=AsyncMock, return_value=None
|
||||||
@@ -323,6 +343,10 @@ class TestSetupServiceRun:
|
|||||||
'src.server.services.setup_service.AnimeSeriesService.get_by_folder',
|
'src.server.services.setup_service.AnimeSeriesService.get_by_folder',
|
||||||
new_callable=AsyncMock, return_value=None
|
new_callable=AsyncMock, return_value=None
|
||||||
), \
|
), \
|
||||||
|
patch(
|
||||||
|
'src.server.services.setup_service.AnimeSeriesService.get_by_key',
|
||||||
|
new_callable=AsyncMock, return_value=None
|
||||||
|
), \
|
||||||
patch(
|
patch(
|
||||||
'src.server.services.setup_service.UnresolvedFolderService.get_by_folder_name',
|
'src.server.services.setup_service.UnresolvedFolderService.get_by_folder_name',
|
||||||
new_callable=AsyncMock, return_value=None
|
new_callable=AsyncMock, return_value=None
|
||||||
@@ -401,6 +425,10 @@ class TestSetupServiceRun:
|
|||||||
'src.server.services.setup_service.AnimeSeriesService.get_by_folder',
|
'src.server.services.setup_service.AnimeSeriesService.get_by_folder',
|
||||||
new_callable=AsyncMock, return_value=None
|
new_callable=AsyncMock, return_value=None
|
||||||
), \
|
), \
|
||||||
|
patch(
|
||||||
|
'src.server.services.setup_service.AnimeSeriesService.get_by_key',
|
||||||
|
new_callable=AsyncMock, return_value=None
|
||||||
|
), \
|
||||||
patch(
|
patch(
|
||||||
'src.server.services.setup_service.UnresolvedFolderService.get_by_folder_name',
|
'src.server.services.setup_service.UnresolvedFolderService.get_by_folder_name',
|
||||||
new_callable=AsyncMock, return_value=None
|
new_callable=AsyncMock, return_value=None
|
||||||
|
|||||||
Reference in New Issue
Block a user