Fix partial series completion for watchlist and Jellyfin

This commit is contained in:
Dymas
2026-05-25 23:09:14 +02:00
parent c006fb2d1d
commit 94ded2725e
6 changed files with 123 additions and 20 deletions
+43 -6
View File
@@ -950,14 +950,40 @@ def watchlist_item_ready_for_jellyfin(item):
return False, "category"
if normalize_media_type(item.get("media_type")) == "movie":
return True, "ready"
preferred_mode = watchlist_preferred_completion_mode(item)
return watchlist_item_download_complete(item, mode=preferred_mode)
def watchlist_preferred_completion_mode(item, fallback_mode=""):
fallback = str(fallback_mode or "").strip().lower()
if fallback in MODE_CHOICES:
return fallback
configured = str((item or {}).get("auto_download_mode") or "").strip().lower()
if configured in MODE_CHOICES:
return configured
downloaded_dub = len((item or {}).get("downloaded_dub_episodes") or [])
downloaded_sub = len((item or {}).get("downloaded_sub_episodes") or [])
if downloaded_dub and not downloaded_sub:
return "dub"
if downloaded_sub and not downloaded_dub:
return "sub"
return "dub"
def watchlist_item_download_complete(item, mode=""):
if not isinstance(item, dict):
return False, "invalid_item"
normalized_mode = watchlist_preferred_completion_mode(item, fallback_mode=mode)
expected_count = int(item.get("expected_count") or 0)
if expected_count < 1:
return False, "expected_count"
if normalize_animeschedule_status(item.get("airing_status")) != "Finished":
return False, "airing_status"
downloaded_sub = len(item.get("downloaded_sub_episodes") or [])
downloaded_dub = len(item.get("downloaded_dub_episodes") or [])
if max(downloaded_sub, downloaded_dub) < expected_count:
available_count = int(item.get(f"{normalized_mode}_count") or 0)
if available_count < expected_count:
return False, "episodes_unavailable"
downloaded_count = len(item.get(f"downloaded_{normalized_mode}_episodes") or [])
if downloaded_count < expected_count:
return False, "episodes_missing"
return True, "ready"
@@ -1949,14 +1975,19 @@ class WatchlistStore:
sub_payload = encode_episode_values(existing_item.get("downloaded_sub_episodes", []) + downloaded_episode_values)
elif normalized_mode == "dub" and downloaded_episode_values:
dub_payload = encode_episode_values(existing_item.get("downloaded_dub_episodes", []) + downloaded_episode_values)
completed_item = dict(existing_item)
completed_item["downloaded_sub_episodes"] = decode_episode_values(sub_payload)
completed_item["downloaded_dub_episodes"] = decode_episode_values(dub_payload)
is_complete, _reason = watchlist_item_download_complete(completed_item, mode=normalized_mode)
target_category = "finished" if is_complete else existing_item["category"]
conn.execute(
"""
UPDATE watchlist
SET category = 'finished', downloaded = 1, status = 'queued', status_message = ?, updated_at = ?,
SET category = ?, downloaded = 1, status = 'queued', status_message = ?, updated_at = ?,
downloaded_sub_episodes_json = ?, downloaded_dub_episodes_json = ?
WHERE show_id = ?
""",
("Queued refresh after successful download.", now, sub_payload, dub_payload, normalized_show_id),
(target_category, "Queued refresh after successful download.", now, sub_payload, dub_payload, normalized_show_id),
)
else:
matched_row = self._find_download_title_match_conn(conn, normalized_title, exclude_show_id=normalized_show_id)
@@ -1970,13 +2001,18 @@ class WatchlistStore:
sub_payload = encode_episode_values(matched_item.get("downloaded_sub_episodes", []) + downloaded_episode_values)
elif normalized_mode == "dub" and downloaded_episode_values:
dub_payload = encode_episode_values(matched_item.get("downloaded_dub_episodes", []) + downloaded_episode_values)
completed_item = dict(matched_item)
completed_item["downloaded_sub_episodes"] = decode_episode_values(sub_payload)
completed_item["downloaded_dub_episodes"] = decode_episode_values(dub_payload)
is_complete, _reason = watchlist_item_download_complete(completed_item, mode=normalized_mode)
target_category = "finished" if is_complete else matched_item["category"]
conn.execute(
"""
UPDATE watchlist
SET
show_id = ?,
title = ?,
category = 'finished',
category = ?,
downloaded = 1,
status = 'queued',
status_message = ?,
@@ -1988,6 +2024,7 @@ class WatchlistStore:
(
normalized_show_id,
resolved_title,
target_category,
"Queued refresh after successful download.",
now,
sub_payload,