mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-22 08:43:37 +08:00
feat: unify media source identity flow (#6129)
This commit is contained in:
112
app/utils/media.py
Normal file
112
app/utils/media.py
Normal file
@@ -0,0 +1,112 @@
|
||||
from typing import Any, Optional, Tuple
|
||||
|
||||
|
||||
MEDIA_SOURCE_ALIASES = {
|
||||
"tmdb": "themoviedb",
|
||||
"themoviedb": "themoviedb",
|
||||
"douban": "douban",
|
||||
"bangumi": "bangumi",
|
||||
"anilist": "anilist",
|
||||
}
|
||||
|
||||
MEDIA_SOURCE_PREFIXES = {
|
||||
"themoviedb": "tmdb",
|
||||
"douban": "douban",
|
||||
"bangumi": "bangumi",
|
||||
"anilist": "anilist",
|
||||
}
|
||||
|
||||
MEDIA_SOURCE_ID_FIELDS = {
|
||||
"themoviedb": ("tmdb_id", "tmdbid"),
|
||||
"douban": ("douban_id", "doubanid"),
|
||||
"bangumi": ("bangumi_id", "bangumiid"),
|
||||
"anilist": ("anilist_id", "anilistid"),
|
||||
}
|
||||
|
||||
|
||||
def normalize_media_source(source: Optional[str]) -> Optional[str]:
|
||||
"""规范化媒体数据源名称,兼容外部使用的 ``tmdb`` 前缀。"""
|
||||
if not source:
|
||||
return None
|
||||
normalized = str(source).strip().casefold()
|
||||
return MEDIA_SOURCE_ALIASES.get(normalized, normalized or None)
|
||||
|
||||
|
||||
def parse_media_key(media_key: Optional[str]) -> Tuple[Optional[str], Optional[str]]:
|
||||
"""解析带来源前缀的媒体键,返回规范化数据源与原生 ID。"""
|
||||
if not media_key or ":" not in str(media_key):
|
||||
return None, None
|
||||
prefix, media_id = str(media_key).split(":", 1)
|
||||
source = normalize_media_source(prefix)
|
||||
media_id = media_id.strip()
|
||||
if not source or not media_id:
|
||||
return None, None
|
||||
return source, media_id
|
||||
|
||||
|
||||
def resolve_media_identity(
|
||||
media: Any = None,
|
||||
source: Optional[str] = None,
|
||||
media_id: Optional[Any] = None,
|
||||
tmdbid: Optional[Any] = None,
|
||||
doubanid: Optional[Any] = None,
|
||||
bangumiid: Optional[Any] = None,
|
||||
anilistid: Optional[Any] = None,
|
||||
) -> Tuple[Optional[str], Optional[str]]:
|
||||
"""
|
||||
从统一媒体对象、通用身份或兼容 ID 中解析主媒体身份。
|
||||
|
||||
显式 ``source/media_id`` 优先;未指定来源时按 TMDB、豆瓣、Bangumi、
|
||||
AniList 的兼容顺序选择首个有效 ID。
|
||||
"""
|
||||
normalized_source = normalize_media_source(source)
|
||||
if normalized_source and media_id is not None and str(media_id).strip():
|
||||
return normalized_source, str(media_id).strip()
|
||||
|
||||
values = {
|
||||
"themoviedb": tmdbid,
|
||||
"douban": doubanid,
|
||||
"bangumi": bangumiid,
|
||||
"anilist": anilistid,
|
||||
}
|
||||
if media is not None:
|
||||
normalized_source = normalized_source or normalize_media_source(
|
||||
getattr(media, "source", None) or getattr(media, "media_source", None)
|
||||
)
|
||||
object_media_id = getattr(media, "media_id", None)
|
||||
if normalized_source and object_media_id is not None and str(object_media_id).strip():
|
||||
return normalized_source, str(object_media_id).strip()
|
||||
for media_source, fields in MEDIA_SOURCE_ID_FIELDS.items():
|
||||
for field in fields:
|
||||
value = getattr(media, field, None)
|
||||
if value is not None and str(value).strip():
|
||||
values[media_source] = value
|
||||
break
|
||||
|
||||
legacy_source, legacy_media_id = parse_media_key(
|
||||
getattr(media, "mediaid", None)
|
||||
)
|
||||
if not normalized_source and legacy_source and legacy_media_id:
|
||||
return legacy_source, legacy_media_id
|
||||
|
||||
if normalized_source:
|
||||
value = values.get(normalized_source)
|
||||
return (
|
||||
normalized_source,
|
||||
str(value).strip() if value is not None and str(value).strip() else None,
|
||||
)
|
||||
|
||||
for media_source in MEDIA_SOURCE_ID_FIELDS:
|
||||
value = values.get(media_source)
|
||||
if value is not None and str(value).strip():
|
||||
return media_source, str(value).strip()
|
||||
return None, None
|
||||
|
||||
|
||||
def build_media_key(source: Optional[str], media_id: Optional[Any]) -> str:
|
||||
"""构造 API 使用的带来源前缀媒体键。"""
|
||||
normalized_source = normalize_media_source(source)
|
||||
if not normalized_source or media_id is None or not str(media_id).strip():
|
||||
return ""
|
||||
prefix = MEDIA_SOURCE_PREFIXES.get(normalized_source, normalized_source)
|
||||
return f"{prefix}:{str(media_id).strip()}"
|
||||
Reference in New Issue
Block a user