mirror of
https://github.com/d0zingcat/MoviePilot-Plugins.git
synced 2026-05-13 15:09:12 +00:00
update(ImdbSource) 改进媒体id转换
This commit is contained in:
@@ -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": "为仪表盘组件添加缓存",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user