better db model
This commit is contained in:
@@ -540,7 +540,7 @@ class SerieScanner:
|
||||
Save or update a series in the database.
|
||||
|
||||
Creates a new record if the series doesn't exist, or updates
|
||||
the episode_dict if it has changed.
|
||||
the episodes if they have changed.
|
||||
|
||||
Args:
|
||||
serie: Serie instance to save
|
||||
@@ -549,26 +549,53 @@ class SerieScanner:
|
||||
Returns:
|
||||
Created or updated AnimeSeries instance, or None if unchanged
|
||||
"""
|
||||
from src.server.database.service import AnimeSeriesService
|
||||
from src.server.database.service import AnimeSeriesService, EpisodeService
|
||||
|
||||
# Check if series already exists
|
||||
existing = await AnimeSeriesService.get_by_key(db, serie.key)
|
||||
|
||||
if existing:
|
||||
# Update episode_dict if changed
|
||||
if existing.episode_dict != serie.episodeDict:
|
||||
updated = await AnimeSeriesService.update(
|
||||
db,
|
||||
existing.id,
|
||||
episode_dict=serie.episodeDict,
|
||||
folder=serie.folder
|
||||
)
|
||||
# Build existing episode dict from episodes for comparison
|
||||
existing_episodes = await EpisodeService.get_by_series(
|
||||
db, existing.id
|
||||
)
|
||||
existing_dict: dict[int, list[int]] = {}
|
||||
for ep in existing_episodes:
|
||||
if ep.season not in existing_dict:
|
||||
existing_dict[ep.season] = []
|
||||
existing_dict[ep.season].append(ep.episode_number)
|
||||
for season in existing_dict:
|
||||
existing_dict[season].sort()
|
||||
|
||||
# Update episodes if changed
|
||||
if existing_dict != serie.episodeDict:
|
||||
# Add new episodes
|
||||
new_dict = serie.episodeDict or {}
|
||||
for season, episode_numbers in new_dict.items():
|
||||
existing_eps = set(existing_dict.get(season, []))
|
||||
for ep_num in episode_numbers:
|
||||
if ep_num not in existing_eps:
|
||||
await EpisodeService.create(
|
||||
db=db,
|
||||
series_id=existing.id,
|
||||
season=season,
|
||||
episode_number=ep_num,
|
||||
)
|
||||
|
||||
# Update folder if changed
|
||||
if existing.folder != serie.folder:
|
||||
await AnimeSeriesService.update(
|
||||
db,
|
||||
existing.id,
|
||||
folder=serie.folder
|
||||
)
|
||||
|
||||
logger.info(
|
||||
"Updated series in database: %s (key=%s)",
|
||||
serie.name,
|
||||
serie.key
|
||||
)
|
||||
return updated
|
||||
return existing
|
||||
else:
|
||||
logger.debug(
|
||||
"Series unchanged in database: %s (key=%s)",
|
||||
@@ -584,8 +611,19 @@ class SerieScanner:
|
||||
name=serie.name,
|
||||
site=serie.site,
|
||||
folder=serie.folder,
|
||||
episode_dict=serie.episodeDict,
|
||||
)
|
||||
|
||||
# Create Episode records
|
||||
if serie.episodeDict:
|
||||
for season, episode_numbers in serie.episodeDict.items():
|
||||
for ep_num in episode_numbers:
|
||||
await EpisodeService.create(
|
||||
db=db,
|
||||
series_id=anime_series.id,
|
||||
season=season,
|
||||
episode_number=ep_num,
|
||||
)
|
||||
|
||||
logger.info(
|
||||
"Created series in database: %s (key=%s)",
|
||||
serie.name,
|
||||
@@ -608,7 +646,7 @@ class SerieScanner:
|
||||
Returns:
|
||||
Updated AnimeSeries instance, or None if not found
|
||||
"""
|
||||
from src.server.database.service import AnimeSeriesService
|
||||
from src.server.database.service import AnimeSeriesService, EpisodeService
|
||||
|
||||
existing = await AnimeSeriesService.get_by_key(db, serie.key)
|
||||
if not existing:
|
||||
@@ -619,20 +657,43 @@ class SerieScanner:
|
||||
)
|
||||
return None
|
||||
|
||||
updated = await AnimeSeriesService.update(
|
||||
# Update basic fields
|
||||
await AnimeSeriesService.update(
|
||||
db,
|
||||
existing.id,
|
||||
name=serie.name,
|
||||
site=serie.site,
|
||||
folder=serie.folder,
|
||||
episode_dict=serie.episodeDict,
|
||||
)
|
||||
|
||||
# Update episodes - add any new ones
|
||||
if serie.episodeDict:
|
||||
existing_episodes = await EpisodeService.get_by_series(
|
||||
db, existing.id
|
||||
)
|
||||
existing_dict: dict[int, set[int]] = {}
|
||||
for ep in existing_episodes:
|
||||
if ep.season not in existing_dict:
|
||||
existing_dict[ep.season] = set()
|
||||
existing_dict[ep.season].add(ep.episode_number)
|
||||
|
||||
for season, episode_numbers in serie.episodeDict.items():
|
||||
existing_eps = existing_dict.get(season, set())
|
||||
for ep_num in episode_numbers:
|
||||
if ep_num not in existing_eps:
|
||||
await EpisodeService.create(
|
||||
db=db,
|
||||
series_id=existing.id,
|
||||
season=season,
|
||||
episode_number=ep_num,
|
||||
)
|
||||
|
||||
logger.info(
|
||||
"Updated series in database: %s (key=%s)",
|
||||
serie.name,
|
||||
serie.key
|
||||
)
|
||||
return updated
|
||||
return existing
|
||||
|
||||
def __find_mp4_files(self) -> Iterator[tuple[str, list[str]]]:
|
||||
"""Find all .mp4 files in the directory structure."""
|
||||
|
||||
@@ -147,7 +147,7 @@ class SerieList:
|
||||
if result:
|
||||
print(f"Added series: {result.name}")
|
||||
"""
|
||||
from src.server.database.service import AnimeSeriesService
|
||||
from src.server.database.service import AnimeSeriesService, EpisodeService
|
||||
|
||||
# Check if series already exists in DB
|
||||
existing = await AnimeSeriesService.get_by_key(db, serie.key)
|
||||
@@ -166,9 +166,19 @@ class SerieList:
|
||||
name=serie.name,
|
||||
site=serie.site,
|
||||
folder=serie.folder,
|
||||
episode_dict=serie.episodeDict,
|
||||
)
|
||||
|
||||
# Create Episode records for each episode in episodeDict
|
||||
if serie.episodeDict:
|
||||
for season, episode_numbers in serie.episodeDict.items():
|
||||
for episode_number in episode_numbers:
|
||||
await EpisodeService.create(
|
||||
db=db,
|
||||
series_id=anime_series.id,
|
||||
season=season,
|
||||
episode_number=episode_number,
|
||||
)
|
||||
|
||||
# Also add to in-memory collection
|
||||
self.keyDict[serie.key] = serie
|
||||
|
||||
@@ -267,8 +277,10 @@ class SerieList:
|
||||
# Clear existing in-memory data
|
||||
self.keyDict.clear()
|
||||
|
||||
# Load all series from database
|
||||
anime_series_list = await AnimeSeriesService.get_all(db)
|
||||
# Load all series from database (with episodes for episodeDict)
|
||||
anime_series_list = await AnimeSeriesService.get_all(
|
||||
db, with_episodes=True
|
||||
)
|
||||
|
||||
for anime_series in anime_series_list:
|
||||
serie = self._convert_from_db(anime_series)
|
||||
@@ -288,23 +300,22 @@ class SerieList:
|
||||
|
||||
Args:
|
||||
anime_series: AnimeSeries model from database
|
||||
(must have episodes relationship loaded)
|
||||
|
||||
Returns:
|
||||
Serie entity instance
|
||||
"""
|
||||
# Convert episode_dict from JSON (string keys) to int keys
|
||||
# Build episode_dict from episodes relationship
|
||||
episode_dict: dict[int, list[int]] = {}
|
||||
if anime_series.episode_dict:
|
||||
for season_str, episodes in anime_series.episode_dict.items():
|
||||
try:
|
||||
season = int(season_str)
|
||||
episode_dict[season] = list(episodes)
|
||||
except (ValueError, TypeError):
|
||||
logger.warning(
|
||||
"Invalid season key '%s' in episode_dict for %s",
|
||||
season_str,
|
||||
anime_series.key
|
||||
)
|
||||
if anime_series.episodes:
|
||||
for episode in anime_series.episodes:
|
||||
season = episode.season
|
||||
if season not in episode_dict:
|
||||
episode_dict[season] = []
|
||||
episode_dict[season].append(episode.episode_number)
|
||||
# Sort episode numbers within each season
|
||||
for season in episode_dict:
|
||||
episode_dict[season].sort()
|
||||
|
||||
return Serie(
|
||||
key=anime_series.key,
|
||||
@@ -325,19 +336,11 @@ class SerieList:
|
||||
Returns:
|
||||
Dictionary suitable for AnimeSeriesService.create()
|
||||
"""
|
||||
# Convert episode_dict keys to strings for JSON storage
|
||||
episode_dict = None
|
||||
if serie.episodeDict:
|
||||
episode_dict = {
|
||||
str(k): list(v) for k, v in serie.episodeDict.items()
|
||||
}
|
||||
|
||||
return {
|
||||
"key": serie.key,
|
||||
"name": serie.name,
|
||||
"site": serie.site,
|
||||
"folder": serie.folder,
|
||||
"episode_dict": episode_dict,
|
||||
}
|
||||
|
||||
async def contains_in_db(self, key: str, db: "AsyncSession") -> bool:
|
||||
|
||||
Reference in New Issue
Block a user