update(ImdbSource) 改进媒体id转换

This commit is contained in:
wumode
2025-07-21 18:08:31 +08:00
parent ea31203558
commit 494557bb0e
4 changed files with 85 additions and 27 deletions

View File

@@ -435,11 +435,12 @@
"name": "IMDb源",
"description": "让探索推荐和媒体识别支持IMDb数据源。",
"labels": "探索",
"version": "1.5.0",
"version": "1.5.1",
"icon": "IMDb_IOS-OSX_App.png",
"author": "wumode",
"level": 1,
"history": {
"v1.5.1": "改进媒体id转换",
"v1.5.0": "支持媒体识别",
"v1.4.4": "更新数据源",
"v1.4.3": "为仪表盘组件添加缓存",

View File

@@ -4242,7 +4242,7 @@ const _hoisted_1 = { class: "plugin-page" };
const _hoisted_2 = { key: 2 };
const _hoisted_3 = { class: "mb-6" };
const _hoisted_4 = { class: "pa-4" };
const _hoisted_5 = { class: "d-flex justify-space-between align-center mb-4" };
const _hoisted_5 = { class: "d-flex justify-space-between align-center" };
const _hoisted_6 = { class: "d-flex align-center" };
const _hoisted_7 = ["onDragstart", "onDragover", "onDrop"];
const _hoisted_8 = {
@@ -4253,7 +4253,7 @@ const _hoisted_9 = { class: "d-flex justify-center" };
const _hoisted_10 = { style: {"position":"absolute","right":"0","bottom":"0"} };
const _hoisted_11 = { class: "mb-6" };
const _hoisted_12 = { class: "pa-4" };
const _hoisted_13 = { class: "d-flex justify-space-between align-center mb-4" };
const _hoisted_13 = { class: "d-flex justify-space-between align-center" };
const _hoisted_14 = { class: "d-flex align-center" };
const _hoisted_15 = ["onDragstart", "onDragover", "onDrop"];
const _hoisted_16 = {
@@ -4264,7 +4264,7 @@ const _hoisted_17 = { class: "d-flex justify-center" };
const _hoisted_18 = { style: {"position":"absolute","right":"0","bottom":"0"} };
const _hoisted_19 = { class: "mb-6" };
const _hoisted_20 = { class: "pa-4" };
const _hoisted_21 = { class: "d-flex justify-space-between align-center mb-4" };
const _hoisted_21 = { class: "d-flex justify-space-between align-center" };
const _hoisted_22 = { class: "d-flex" };
const _hoisted_23 = {
class: "position-relative px-4 py-2",
@@ -4274,7 +4274,7 @@ const _hoisted_24 = { class: "d-flex justify-center" };
const _hoisted_25 = { style: {"position":"absolute","right":"0","bottom":"0"} };
const _hoisted_26 = { class: "mb-6" };
const _hoisted_27 = { class: "pa-4" };
const _hoisted_28 = { class: "d-flex justify-space-between align-center mb-4" };
const _hoisted_28 = { class: "d-flex justify-space-between align-center" };
const _hoisted_29 = { class: "d-flex" };
const _hoisted_30 = {
class: "position-relative px-4 py-2",
@@ -4284,7 +4284,7 @@ const _hoisted_31 = { class: "d-flex justify-center" };
const _hoisted_32 = { style: {"position":"absolute","right":"0","bottom":"0"} };
const _hoisted_33 = { class: "mb-6" };
const _hoisted_34 = { class: "pa-4" };
const _hoisted_35 = { class: "d-flex justify-space-between align-center mb-4" };
const _hoisted_35 = { class: "d-flex justify-space-between align-center" };
const _hoisted_36 = { class: "d-flex align-center" };
const _hoisted_37 = {
class: "position-relative px-4 py-2",

View File

@@ -28,7 +28,7 @@ class ImdbSource(_PluginBase):
# 插件图标
plugin_icon = "IMDb_IOS-OSX_App.png"
# 插件版本
plugin_version = "1.5.0"
plugin_version = "1.5.1"
# 插件作者
plugin_author = "wumode"
# 作者主页
@@ -1672,25 +1672,14 @@ class ImdbSource(_PluginBase):
event_data: MediaRecognizeConvertEventData = event.event_data
if not event_data:
return
api_key = settings.TMDB_API_KEY
if event_data.convert_type != "themoviedb" or not api_key:
if event_data.convert_type != "themoviedb":
return
if not event_data.mediaid.startswith("imdb"):
return
imdb_id = event_data.mediaid[5:]
api_url = f"https://{settings.TMDB_API_DOMAIN}/3/find/{imdb_id}?api_key={api_key}&external_source=imdb_id"
ret = RequestUtils(accept_type="application/json").get_res(api_url)
if ret:
data = ret.json()
all_results = []
for result_type in ["movie_results", "tv_results"]:
if data.get(result_type):
all_results.extend(data[result_type])
if not all_results:
return # 无匹配结果
# 按 popularity 降序排序,取最高人气的条目
most_popular_item = max(all_results, key=lambda x: x.get("popularity", -1))
event_data.media_dict["id"] = most_popular_item.get("id")
tmdb_id = ImdbSource.imdb_to_tmdb(imdb_id)
if tmdb_id is not None:
event_data.media_dict["id"] = tmdb_id
@eventmanager.register(ChainEventType.RecommendSource)
def recommend_source(self, event: Event):
@@ -1782,6 +1771,7 @@ class ImdbSource(_PluginBase):
if info:
info = self._imdb_helper.update_info(info.get('id'), info=info) or {}
mediainfo = ImdbSource._convert_mediainfo(info)
mediainfo.tmdb_id = ImdbSource.imdb_to_tmdb(info.get('id'), mediainfo)
logger.info(f"{meta.name} IMDb 识别结果:{mediainfo.type.value} "
f"{mediainfo.title_year} "
f"{mediainfo.imdb_id}")
@@ -1826,3 +1816,70 @@ class ImdbSource(_PluginBase):
if not mediainfo.release_date:
mediainfo.release_date = air_date
return mediainfo
@staticmethod
def imdb_to_tmdb(imdb_id: str, media_info: Optional[MediaInfo] = None) -> Optional[int]:
api_key = settings.TMDB_API_KEY
api_url = (
f"https://{settings.TMDB_API_DOMAIN}/3/find/{imdb_id}"
f"?api_key={api_key}&external_source=imdb_id"
)
ret = RequestUtils(accept_type="application/json").get_res(api_url)
if not ret:
return None
data = ret.json()
# 合并两种结果
all_results = []
for key in ["movie_results", "tv_results"]:
all_results.extend(data.get(key, []))
if not all_results:
return None # 无匹配结果
def pick_most_popular(results):
return max(results, key=lambda x: x.get("popularity", -1), default=None)
# 未提供 media_info直接返回人气最高的
if not media_info:
most_popular = pick_most_popular(all_results)
return most_popular.get("id") if most_popular else None
# 按类型过滤
type_map = {
MediaType.TV: ['tv'],
MediaType.MOVIE: ['movie'],
None: ['tv', 'movie']
}
allowed_types = type_map.get(media_info.type, ['tv', 'movie'])
filtered = [res for res in all_results if res.get('type') in allowed_types]
# 定义一个过滤链:每次过滤后如果只剩一个结果就返回
def filter_and_return(results, predicate):
filtered_res = [res for res in results if predicate(res)]
if not filtered_res:
return None, []
if len(filtered_res) == 1:
return filtered_res[0].get("id"), []
return None, filtered_res
# 通过年份过滤
if media_info.year:
def match_year(res):
date = res.get('first_air_date') or res.get('release_date') or ''
return date[:4] == media_info.year
result_id, filtered = filter_and_return(filtered, match_year)
if result_id:
return result_id
if not filtered:
return None
# 通过名称过滤
if media_info.names:
def match_name(res):
name = res.get('name') or ''
return ImdbHelper.compare_names(name, media_info.names)
result_id, filtered = filter_and_return(filtered, match_name)
if result_id:
return result_id
if not filtered:
return None
# 最终按人气返回
most_popular = pick_most_popular(filtered)
return most_popular.get("id") if most_popular else None

View File

@@ -218,7 +218,7 @@ class ImdbHelper:
return None
@staticmethod
def __compare_names(file_name: str, names: Union[list,str]) -> bool:
def compare_names(file_name: str, names: Union[list,str]) -> bool:
"""
比较文件名是否匹配,忽略大小写和特殊字符
:param file_name: 识别的文件名或者种子名
@@ -688,11 +688,11 @@ class ImdbHelper:
start_year = result.get('startYear')
if year and str(start_year) != year:
continue
if ImdbHelper.__compare_names(name, [result.get('primaryTitle', ''), result.get('originalTitle', '')]):
if ImdbHelper.compare_names(name, [result.get('primaryTitle', ''), result.get('originalTitle', '')]):
ret_info = result
break
names = [edge.get('node', {}).get('text', '') for edge in title.get('akas', {}).get('edges', [])]
if ImdbHelper.__compare_names(name, names):
if ImdbHelper.compare_names(name, names):
ret_info = result
break
if ret_info:
@@ -740,13 +740,13 @@ class ImdbHelper:
title = titles_dict.get(tv.get('id'), {})
akas = [e.get('node', {}) for e in title.get('akas', {}).get('edges', [])]
tv_year = tv.get('startYear')
if self.__compare_names(name, [tv.get('primaryTitle', ''), tv.get('originalTitle', '')]) and \
if self.compare_names(name, [tv.get('primaryTitle', ''), tv.get('originalTitle', '')]) and \
str(tv_year) == season_year:
tv['akas'] = akas
tv['rating'] = title.get('ratingsSummary') or {}
return tv
names = [aka.get('text', '') for aka in akas]
if not tv or not self.__compare_names(name, names):
if not tv or not self.compare_names(name, names):
continue
if __season_match(_tv_info=tv, _season_year=season_year):
tv['akas'] = akas