mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-04 23:17:20 +08:00
fix(mediaserver): fallback stale tv item ids
This commit is contained in:
@@ -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):
|
||||||
|
|||||||
@@ -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
@@ -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,
|
||||||
|
|||||||
@@ -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, {}
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user