diff --git a/app/api/endpoints/media.py b/app/api/endpoints/media.py index 85c4cb080..c3d921077 100644 --- a/app/api/endpoints/media.py +++ b/app/api/endpoints/media.py @@ -521,6 +521,11 @@ async def detail( # 识别 if mediainfo: await mediachain.async_obtain_images(mediainfo) + # 电视剧且有 TVDB ID 时,补充获取 slug 用于构建 TheTvDb 直达链接 + if mediainfo.type == MediaType.TV and mediainfo.tvdb_id and not mediainfo.tvdb_slug: + slug = mediachain.tvdb_slug(mediainfo.tvdb_id) + if slug: + mediainfo.tvdb_slug = slug return mediainfo.to_dict() return schemas.MediaInfo() diff --git a/app/chain/__init__.py b/app/chain/__init__.py index 91ed6112d..1fb9d483b 100644 --- a/app/chain/__init__.py +++ b/app/chain/__init__.py @@ -1040,6 +1040,14 @@ class ChainBase(metaclass=ABCMeta): """ return self.run_module("tvdb_info", tvdbid=tvdbid) + def tvdb_slug(self, tvdbid: int) -> Optional[str]: + """ + 获取TVDB剧集 slug(别名),用于构建 TheTvDb 直达链接。 + :param tvdbid: int + :return: slug 字符串 + """ + return self.run_module("tvdb_slug", tvdbid=tvdbid) + def tmdb_info( self, tmdbid: int, mtype: MediaType, season: Optional[int] = None ) -> Optional[dict]: diff --git a/app/chain/media.py b/app/chain/media.py index 4da8f6775..71dc64c6b 100644 --- a/app/chain/media.py +++ b/app/chain/media.py @@ -707,7 +707,7 @@ class MediaChain(ChainBase, ConfigReloadMixin, metaclass=Singleton): mediainfo.category = tmdb_media.category if not mediainfo.genre_ids: mediainfo.genre_ids = list(tmdb_media.genre_ids or []) - for field in ("imdb_id", "tvdb_id", "collection_id"): + for field in ("imdb_id", "tvdb_id", "tvdb_slug", "collection_id"): if not getattr(mediainfo, field, None): setattr(mediainfo, field, getattr(tmdb_media, field, None)) return mediainfo diff --git a/app/core/context.py b/app/core/context.py index 8f51324e4..4cdab1cfb 100644 --- a/app/core/context.py +++ b/app/core/context.py @@ -206,6 +206,11 @@ class MusicInfo: """音乐不使用 TVDB ID,兼容现有下载历史字段。""" return None + @property + def tvdb_slug(self) -> None: + """音乐不使用 TVDB Slug,兼容现有字段。""" + return None + @property def douban_id(self) -> None: """音乐不使用豆瓣 ID,兼容现有下载历史字段。""" @@ -888,6 +893,8 @@ class MediaInfo: imdb_id: str = None # TVDB ID tvdb_id: int = None + # TVDB Slug(别名,用于构建 TheTvDb 直达链接) + tvdb_slug: str = None # 豆瓣ID douban_id: str = None # Bangumi ID diff --git a/app/modules/thetvdb/__init__.py b/app/modules/thetvdb/__init__.py index d7d9baa53..d8065c5f0 100644 --- a/app/modules/thetvdb/__init__.py +++ b/app/modules/thetvdb/__init__.py @@ -143,6 +143,21 @@ class TheTvDbModule(_ModuleBase): logger.error(f"获取TVDB信息失败: {str(err)}") return None + def tvdb_slug(self, tvdbid: int) -> Optional[str]: + """ + 获取TVDB剧集的 slug(别名),用于构建 TheTvDb 直达链接。 + :param tvdbid: int + :return: slug 字符串,如 "speed-and-love" + """ + try: + result = self._handle_tvdb_call("get_series", tvdbid) + if result and isinstance(result, dict): + return result.get("slug") + return None + except Exception as err: + logger.error(f"获取TVDB slug 失败: {str(err)}") + return None + def search_tvdb(self, title: str) -> list: """ 用标题搜索TVDB剧集 diff --git a/app/schemas/context.py b/app/schemas/context.py index 7e20e8d45..1099906f9 100644 --- a/app/schemas/context.py +++ b/app/schemas/context.py @@ -105,6 +105,8 @@ class MediaInfo(BaseModel): imdb_id: Optional[str] = None # TVDB ID tvdb_id: Optional[int] = None + # TVDB Slug(别名,用于构建 TheTvDb 直达链接) + tvdb_slug: Optional[str] = None # 豆瓣ID douban_id: Optional[str] = None # Bangumi ID