mirror of
https://github.com/jxxghp/MoviePilot-Plugins.git
synced 2026-03-27 10:05:57 +00:00
Merge pull request #914 from wumode/imdbsource
This commit is contained in:
@@ -453,11 +453,12 @@
|
||||
"name": "IMDb源",
|
||||
"description": "让探索,推荐和媒体识别支持IMDb数据源。",
|
||||
"labels": "探索",
|
||||
"version": "1.6.1",
|
||||
"version": "1.6.2",
|
||||
"icon": "IMDb_IOS-OSX_App.png",
|
||||
"author": "wumode",
|
||||
"level": 1,
|
||||
"history": {
|
||||
"v1.6.2": "修复 API 查询错误重试问题",
|
||||
"v1.6.1": "添加中文主屏幕组件; 修复 bug",
|
||||
"v1.5.8": "修改UA",
|
||||
"v1.5.7": "改进异常处理",
|
||||
|
||||
@@ -30,7 +30,7 @@ class ImdbSource(_PluginBase):
|
||||
# 插件图标
|
||||
plugin_icon = "IMDb_IOS-OSX_App.png"
|
||||
# 插件版本
|
||||
plugin_version = "1.6.1"
|
||||
plugin_version = "1.6.2"
|
||||
# 插件作者
|
||||
plugin_author = "wumode"
|
||||
# 作者主页
|
||||
|
||||
@@ -35,7 +35,7 @@ class ImdbApiClient:
|
||||
client=self._free_api_client
|
||||
)
|
||||
|
||||
@retry(Exception, logger=logger)
|
||||
@retry(Exception, logger=logger, delay=1)
|
||||
@cached(maxsize=1024, ttl=CACHE_LIFESPAN)
|
||||
def _free_imdb_api(self, path: str, params: Optional[dict] = None) -> Optional[dict]:
|
||||
r = self._req.get_res(url=f"{self.BASE_URL}{path}", params=params, raise_exception=True)
|
||||
@@ -49,7 +49,7 @@ class ImdbApiClient:
|
||||
return None
|
||||
return r.json()
|
||||
|
||||
@retry(Exception, logger=logger)
|
||||
@retry(Exception, logger=logger, delay=1)
|
||||
@cached(maxsize=1024, ttl=CACHE_LIFESPAN)
|
||||
async def _async_free_imdb_api(self, path: str, params: Optional[dict] = None) -> Optional[dict]:
|
||||
r = await self._async_req.get_res(url=f"{self.BASE_URL}{path}", params=params, raise_exception=True)
|
||||
|
||||
@@ -13,7 +13,6 @@ from app.utils.http import RequestUtils, AsyncRequestUtils
|
||||
from .schema.imdbtypes import ImdbType
|
||||
from .schema import VerticalList, AdvancedTitleSearchResponse, AdvancedTitleSearch, TitleEdge, SearchParams
|
||||
|
||||
|
||||
INTERESTS_ID: Final[Dict[str, Dict[str, str]]] = {
|
||||
"Action": {
|
||||
"Action": "in0000001",
|
||||
@@ -277,45 +276,45 @@ INTERESTS_ID: Final[Dict[str, Dict[str, str]]] = {
|
||||
}
|
||||
CACHE_LIFETIME: Final[int] = 86400
|
||||
IMDB_GRAPHQL_QUERY: Final[str] = \
|
||||
"""query VerticalListPageItems( $titles: [ID!]! $names: [ID!]! $images: [ID!]! $videos: [ID!]!) {
|
||||
titles(ids: $titles) { ...TitleParts meterRanking { currentRank meterType rankChange {changeDirection difference} } ratingsSummary { aggregateRating } }
|
||||
names(ids: $names) { ...NameParts }
|
||||
videos(ids: $videos) { ...VideoParts }
|
||||
images(ids: $images) { ...ImageParts }
|
||||
}
|
||||
fragment TitleParts on Title {
|
||||
id
|
||||
titleText { text }
|
||||
titleType { id }
|
||||
releaseYear { year }
|
||||
akas(first: 50) { edges { node { text country { id text } language { text } } } }
|
||||
plot { plotText {plainText}}
|
||||
primaryImage { id url width height }
|
||||
releaseDate {day month year}
|
||||
titleGenres {genres {genre { text }}}
|
||||
certificate { rating }
|
||||
originalTitleText{ text }
|
||||
runtime { seconds }
|
||||
}
|
||||
fragment NameParts on Name {
|
||||
id
|
||||
nameText { text }
|
||||
primaryImage { id url width height }
|
||||
}
|
||||
fragment ImageParts on Image {
|
||||
id
|
||||
height
|
||||
width
|
||||
url
|
||||
}
|
||||
fragment VideoParts on Video {
|
||||
id
|
||||
name { value }
|
||||
contentType { displayName { value } id }
|
||||
previewURLs { displayName { value } url videoDefinition videoMimeType }
|
||||
playbackURLs { displayName { value } url videoDefinition videoMimeType }
|
||||
thumbnail { height url width }
|
||||
}"""
|
||||
"""query VerticalListPageItems( $titles: [ID!]! $names: [ID!]! $images: [ID!]! $videos: [ID!]!) {
|
||||
titles(ids: $titles) { ...TitleParts meterRanking { currentRank meterType rankChange {changeDirection difference} } ratingsSummary { aggregateRating } }
|
||||
names(ids: $names) { ...NameParts }
|
||||
videos(ids: $videos) { ...VideoParts }
|
||||
images(ids: $images) { ...ImageParts }
|
||||
}
|
||||
fragment TitleParts on Title {
|
||||
id
|
||||
titleText { text }
|
||||
titleType { id }
|
||||
releaseYear { year }
|
||||
akas(first: 50) { edges { node { text country { id text } language { text } } } }
|
||||
plot { plotText {plainText}}
|
||||
primaryImage { id url width height }
|
||||
releaseDate {day month year}
|
||||
titleGenres {genres {genre { text }}}
|
||||
certificate { rating }
|
||||
originalTitleText{ text }
|
||||
runtime { seconds }
|
||||
}
|
||||
fragment NameParts on Name {
|
||||
id
|
||||
nameText { text }
|
||||
primaryImage { id url width height }
|
||||
}
|
||||
fragment ImageParts on Image {
|
||||
id
|
||||
height
|
||||
width
|
||||
url
|
||||
}
|
||||
fragment VideoParts on Video {
|
||||
id
|
||||
name { value }
|
||||
contentType { displayName { value } id }
|
||||
previewURLs { displayName { value } url videoDefinition videoMimeType }
|
||||
playbackURLs { displayName { value } url videoDefinition videoMimeType }
|
||||
thumbnail { height url width }
|
||||
}"""
|
||||
|
||||
|
||||
class PersistedQueryNotFound(Exception):
|
||||
@@ -332,7 +331,7 @@ class OfficialApiClient:
|
||||
self._req = RequestUtils(accept_type="application/json",
|
||||
content_type="application/json",
|
||||
timeout=10,
|
||||
ua=None,
|
||||
ua=ua,
|
||||
proxies=proxies,
|
||||
session=requests.Session())
|
||||
if proxies:
|
||||
@@ -358,7 +357,7 @@ class OfficialApiClient:
|
||||
return {'error': error}
|
||||
return data.get("data")
|
||||
|
||||
@retry(Exception, logger=logger)
|
||||
@retry(Exception, logger=logger, delay=1)
|
||||
@cached(maxsize=1024, ttl=CACHE_LIFETIME)
|
||||
def _query_graphql(self, query: str, variables: Dict[str, Any]) -> Optional[dict]:
|
||||
params = {'query': query, 'variables': variables}
|
||||
@@ -370,7 +369,7 @@ class OfficialApiClient:
|
||||
return {'error': error}
|
||||
return data.get("data")
|
||||
|
||||
@retry(Exception, logger=logger)
|
||||
@retry(Exception, logger=logger, delay=1)
|
||||
@cached(maxsize=1024, ttl=CACHE_LIFETIME)
|
||||
async def _async_query_graphql(self, query: str, variables: Dict[str, Any]) -> Optional[Dict]:
|
||||
params = {'query': query, 'variables': variables}
|
||||
@@ -438,12 +437,12 @@ class OfficialApiClient:
|
||||
|
||||
return ret
|
||||
|
||||
@retry(Exception, logger=logger)
|
||||
@retry(Exception, logger=logger, delay=1)
|
||||
async def async_advanced_title_search(self,
|
||||
params: SearchParams,
|
||||
sha256: str,
|
||||
last_cursor: Optional[str] = None,
|
||||
) -> Optional[AdvancedTitleSearch]:
|
||||
params: SearchParams,
|
||||
sha256: str,
|
||||
last_cursor: Optional[str] = None,
|
||||
) -> Optional[AdvancedTitleSearch]:
|
||||
|
||||
variables: Dict[str, Any] = {"first": 50,
|
||||
"locale": "en-US",
|
||||
@@ -457,7 +456,7 @@ class OfficialApiClient:
|
||||
if title_type in ImdbType._value2member_map_:
|
||||
title_type_ids.append(title_type)
|
||||
if len(title_type_ids):
|
||||
variables["titleTypeConstraint"] = {"anyTitleTypeIds": params.title_types}
|
||||
variables["titleTypeConstraint"] = {"anyTitleTypeIds": title_type_ids}
|
||||
if params.genres:
|
||||
variables["genreConstraint"] = {"allGenreIds": params.genres, "excludeGenreIds": []}
|
||||
if params.countries:
|
||||
@@ -504,11 +503,7 @@ class OfficialApiClient:
|
||||
|
||||
params = {"operationName": operation_name,
|
||||
"variables": variables}
|
||||
try:
|
||||
data = await self._async_request(params, sha256)
|
||||
except Exception as e:
|
||||
logger.debug(f"An error occurred while querying {operation_name}: {e}")
|
||||
return None
|
||||
data = await self._async_request(params, sha256)
|
||||
if not data:
|
||||
return None
|
||||
if 'error' in data:
|
||||
@@ -525,7 +520,8 @@ class OfficialApiClient:
|
||||
return None
|
||||
return ret.advanced_title_search
|
||||
|
||||
async def advanced_title_search_generator(self, params: SearchParams, sha256: str) -> AsyncGenerator[TitleEdge, None]:
|
||||
async def advanced_title_search_generator(self, params: SearchParams, sha256: str) -> AsyncGenerator[
|
||||
TitleEdge, None]:
|
||||
last_cursor = None
|
||||
while True:
|
||||
response = await self.async_advanced_title_search(params, sha256, last_cursor=last_cursor)
|
||||
|
||||
Reference in New Issue
Block a user