fix(mediaserver): fallback stale tv item ids

This commit is contained in:
InfinityPacer
2026-05-09 06:54:39 +08:00
committed by jxxghp
parent 94d7e4385e
commit bedab9ab92
5 changed files with 89 additions and 13 deletions
+12
View File
@@ -407,6 +407,7 @@ class Emby:
""" """
if not self._host or not self._apikey: if not self._host or not self._apikey:
return None, None return None, None
cached_item_id = item_id
# 电视剧 # 电视剧
if not item_id: if not item_id:
item_id = self.__get_emby_series_id_by_name(title, year) item_id = self.__get_emby_series_id_by_name(title, year)
@@ -416,6 +417,17 @@ class Emby:
return None, {} return None, {}
# 验证tmdbid是否相同 # 验证tmdbid是否相同
item_info = self.get_iteminfo(item_id) item_info = self.get_iteminfo(item_id)
if not item_info and cached_item_id and title:
# 媒体删除后重新入库会导致缓存ID失效,回退到标题搜索避免误判整部剧缺失。
logger.warning(f"Emby缓存的电视剧媒体ID {cached_item_id} 已失效,尝试按标题重新搜索:{title}")
item_id = self.__get_emby_series_id_by_name(title, year)
if item_id is None:
return None, None
if not item_id:
return None, {}
item_info = self.get_iteminfo(item_id)
if not item_info:
return None, {}
if item_info: if item_info:
if tmdb_id and item_info.tmdbid: if tmdb_id and item_info.tmdbid:
if str(tmdb_id) != str(item_info.tmdbid): if str(tmdb_id) != str(item_info.tmdbid):
+12
View File
@@ -429,6 +429,7 @@ class Jellyfin:
""" """
if not self._host or not self._apikey or not self.user: if not self._host or not self._apikey or not self.user:
return None, None return None, None
cached_item_id = item_id
# 查TVID # 查TVID
if not item_id: if not item_id:
item_id = self.__get_jellyfin_series_id_by_name(title, year) item_id = self.__get_jellyfin_series_id_by_name(title, year)
@@ -438,6 +439,17 @@ class Jellyfin:
return None, {} return None, {}
# 验证tmdbid是否相同 # 验证tmdbid是否相同
item_info = self.get_iteminfo(item_id) item_info = self.get_iteminfo(item_id)
if not item_info and cached_item_id and title:
# 媒体删除后重新入库会导致缓存ID失效,回退到标题搜索避免误判整部剧缺失。
logger.warning(f"Jellyfin缓存的电视剧媒体ID {cached_item_id} 已失效,尝试按标题重新搜索:{title}")
item_id = self.__get_jellyfin_series_id_by_name(title, year)
if item_id is None:
return None, None
if not item_id:
return None, {}
item_info = self.get_iteminfo(item_id)
if not item_info:
return None, {}
if item_info: if item_info:
if tmdb_id and item_info.tmdbid: if tmdb_id and item_info.tmdbid:
if str(tmdb_id) != str(item_info.tmdbid): if str(tmdb_id) != str(item_info.tmdbid):
+37 -13
View File
@@ -3,6 +3,7 @@ from pathlib import Path
from typing import List, Optional, Dict, Tuple, Generator, Any, Union from typing import List, Optional, Dict, Tuple, Generator, Any, Union
from urllib.parse import quote_plus from urllib.parse import quote_plus
from plexapi.exceptions import NotFound
from plexapi.myplex import MyPlexAccount from plexapi.myplex import MyPlexAccount
from plexapi.server import PlexServer from plexapi.server import PlexServer
from requests import Response, Session from requests import Response, Session
@@ -260,20 +261,18 @@ class Plex:
if not self._plex: if not self._plex:
return None, {} return None, {}
if item_id: if item_id:
videos = self.__fetch_item(item_id) try:
videos = self.__fetch_item(item_id)
except NotFound:
# Plex删除并重新入库后metadata id会变化,缓存的旧item_id失效时回退到搜索路径。
logger.warning(f"Plex缓存的电视剧媒体ID {item_id} 已失效,尝试按标题重新搜索:{title}")
videos = self.__search_show(title=title,
original_title=original_title,
year=year)
else: else:
# 兼容年份为空的场景 videos = self.__search_show(title=title,
kwargs = {"year": year} if year else {} original_title=original_title,
# 根据标题和年份模糊搜索,该结果不够准确 year=year)
videos = self._plex.library.search(title=title,
libtype="show",
**kwargs)
if (not videos
and original_title
and str(original_title) != str(title)):
videos = self._plex.library.search(title=original_title,
libtype="show",
**kwargs)
if not videos: if not videos:
return None, {} return None, {}
@@ -293,6 +292,31 @@ class Plex:
season_episodes[episode.seasonNumber].append(episode.index) season_episodes[episode.seasonNumber].append(episode.index)
return videos.key, season_episodes return videos.key, season_episodes
def __search_show(self,
title: Optional[str] = None,
original_title: Optional[str] = None,
year: Optional[str] = None) -> Any:
"""
按标题搜索Plex电视剧条目,供常规查询和缓存item_id失效后的回退查询复用。
:param title: 标题
:param original_title: 原产地标题
:param year: 年份,可以为空,为空时不按年份过滤
:return: Plex搜索返回的电视剧条目列表
"""
# 兼容年份为空的场景
kwargs = {"year": year} if year else {}
# 根据标题和年份模糊搜索,该结果不够准确,后续仍会通过tmdb_id校验。
videos = self._plex.library.search(title=title,
libtype="show",
**kwargs)
if (not videos
and original_title
and str(original_title) != str(title)):
videos = self._plex.library.search(title=original_title,
libtype="show",
**kwargs)
return videos
def get_remote_image_by_id(self, def get_remote_image_by_id(self,
item_id: str, item_id: str,
image_type: str, image_type: str,
+8
View File
@@ -307,12 +307,20 @@ class TrimeMedia:
if not self.is_authenticated(): if not self.is_authenticated():
return None, None return None, None
cached_item_id = item_id
if not item_id: if not item_id:
item_id = self.__get_series_id_by_name(title, year) item_id = self.__get_series_id_by_name(title, year)
if item_id is None: if item_id is None:
return None, None return None, None
item_info = self.get_iteminfo(item_id) item_info = self.get_iteminfo(item_id)
if not item_info and cached_item_id and title:
# 媒体删除后重新入库会导致缓存ID失效,回退到标题搜索避免误判整部剧缺失。
logger.warning(f"飞牛影视缓存的电视剧媒体ID {cached_item_id} 已失效,尝试按标题重新搜索:{title}")
item_id = self.__get_series_id_by_name(title, year)
if item_id is None:
return None, None
item_info = self.get_iteminfo(item_id)
if not item_info: if not item_info:
return None, {} return None, {}
+20
View File
@@ -653,9 +653,19 @@ class Ugreen:
tmdb_id: Optional[int] = None, tmdb_id: Optional[int] = None,
season: Optional[int] = None, season: Optional[int] = None,
) -> tuple[Optional[str], Optional[Dict[int, list]]]: ) -> tuple[Optional[str], Optional[Dict[int, list]]]:
"""
根据标题、年份、TMDB ID和季号查询绿联媒体库中的电视剧已入库集数。
:param item_id: 绿联媒体库中的剧集ID,存在缓存ID时优先使用
:param title: 标题
:param year: 年份
:param tmdb_id: TMDB ID
:param season: 季号
:return: 命中的剧集ID及每季已入库集数
"""
if not self.is_authenticated() or not self._api: if not self.is_authenticated() or not self._api:
return None, None return None, None
cached_item_id = item_id
if not item_id: if not item_id:
if not title: if not title:
return None, None return None, None
@@ -669,6 +679,16 @@ class Ugreen:
item_id = str(item_id) item_id = str(item_id)
item_info = self.get_iteminfo(item_id) item_info = self.get_iteminfo(item_id)
if not item_info and cached_item_id and title:
# 媒体删除后重新入库会导致缓存ID失效,回退到标题搜索避免误判整部剧缺失。
logger.warning(f"绿联缓存的电视剧媒体ID {cached_item_id} 已失效,尝试按标题重新搜索:{title}")
if not (tv_info := self.__search_tv_item(title, year, tmdb_id)):
return None, {}
found_item_id = tv_info.get("ug_video_info_id")
if found_item_id is None:
return None, {}
item_id = str(found_item_id)
item_info = self.get_iteminfo(item_id)
if not item_info: if not item_info:
return None, {} return None, {}
if tmdb_id and item_info.tmdbid and tmdb_id != item_info.tmdbid: if tmdb_id and item_info.tmdbid and tmdb_id != item_info.tmdbid: