fix arr api

This commit is contained in:
jxxghp 2023-06-14 15:27:54 +08:00
parent b18d6cabd9
commit 0eb789f711
10 changed files with 157 additions and 72 deletions

View File

@ -1,3 +1,4 @@
from pathlib import Path
from typing import Any, List
from fastapi import APIRouter, HTTPException, Depends
@ -7,6 +8,7 @@ from app import schemas
from app.chain.identify import IdentifyChain
from app.chain.subscribe import SubscribeChain
from app.core.config import settings
from app.core.metainfo import MetaInfo
from app.db import get_db
from app.db.models.subscribe import Subscribe
from app.schemas import RadarrMovie, SonarrSeries
@ -206,12 +208,14 @@ async def arr_movies(apikey: str, db: Session = Depends(get_db)) -> Any:
result.append(RadarrMovie(
id=subscribe.id,
title=subscribe.name,
year=subscribe.year,
isAvailable=True,
monitored=True,
tmdbId=subscribe.tmdbid,
imdbId=subscribe.imdbid,
profileId=1,
qualityProfileId=1,
hasFile=False,
hasFile=False
))
return result
@ -228,26 +232,49 @@ async def arr_movie_lookup(apikey: str, term: str, db: Session = Depends(get_db)
detail="认证失败!",
)
tmdbid = term.replace("tmdb:", "")
subscribe = Subscribe.get_by_tmdbid(db, int(tmdbid))
if subscribe:
# 查询媒体信息
mediainfo = IdentifyChain().recognize_media(mtype=MediaType.MOVIE, tmdbid=int(tmdbid))
if not mediainfo:
return [RadarrMovie()]
# 查询是否已存在
exists = IdentifyChain().media_exists(mediainfo=mediainfo)
if not exists:
# 文件不存在
hasfile = False
else:
# 文件存在
hasfile = True
# 查询是否已订阅
subscribes = Subscribe.get_by_tmdbid(db, int(tmdbid))
if subscribes:
# 订阅ID
subid = subscribes[0].id
# 已订阅
monitored = True
else:
subid = None
monitored = False
return [RadarrMovie(
id=subscribe.id,
title=subscribe.name,
id=subid,
title=mediainfo.title,
year=mediainfo.year,
isAvailable=True,
monitored=True,
tmdbId=subscribe.tmdbid,
monitored=monitored,
tmdbId=mediainfo.tmdb_id,
imdbId=mediainfo.imdb_id,
titleSlug=mediainfo.original_title,
folderName=mediainfo.title_year,
profileId=1,
qualityProfileId=1,
hasFile=False,
hasFile=hasfile
)]
else:
return [RadarrMovie()]
@arr_router.get("/movie/{mid}", response_model=schemas.RadarrMovie)
async def arr_movie(apikey: str, mid: int, db: Session = Depends(get_db)) -> Any:
"""
查询Rardar电影
查询Rardar电影订阅
"""
if not apikey or apikey != settings.API_TOKEN:
raise HTTPException(
@ -259,12 +286,14 @@ async def arr_movie(apikey: str, mid: int, db: Session = Depends(get_db)) -> Any
return RadarrMovie(
id=subscribe.id,
title=subscribe.name,
year=subscribe.year,
isAvailable=True,
monitored=True,
tmdbId=subscribe.tmdbid,
imdbId=subscribe.imdbid,
profileId=1,
qualityProfileId=1,
hasFile=False,
hasFile=False
)
else:
raise HTTPException(
@ -284,7 +313,7 @@ async def arr_add_movie(apikey: str, movie: RadarrMovie) -> Any:
detail="认证失败!",
)
sid = SubscribeChain().process(title=movie.title,
year=str(movie.year) if movie.year else None,
year=movie.year,
mtype=MediaType.MOVIE,
tmdbid=movie.tmdbId,
userid="Seerr")
@ -446,14 +475,17 @@ async def arr_series(apikey: str, db: Session = Depends(get_db)) -> Any:
"seasonNumber": subscribe.season,
"monitored": True,
}],
remotePoster=subscribe.image,
year=subscribe.year,
isAvailable=True,
monitored=True,
tmdbId=subscribe.tmdbid,
tvdbId=subscribe.tvdbid,
imdbId=subscribe.imdbid,
profileId=1,
languageProfileId=1,
qualityProfileId=1,
hasFile=False,
isAvailable=True,
monitored=True,
hasFile=False
))
return result
@ -468,38 +500,81 @@ async def arr_series_lookup(apikey: str, term: str, db: Session = Depends(get_db
status_code=403,
detail="认证失败!",
)
# 季列表
seasons = []
# 查询TMDB媒体信息
if not term.startswith("tvdb:"):
title = term
subscribe = Subscribe.get_by_title(db, title)
mediainfo = IdentifyChain().recognize_media(meta=MetaInfo(term),
mtype=MediaType.MOVIE)
if not mediainfo:
return [SonarrSeries()]
tvdbid = mediainfo.tvdb_id
tmdbid = mediainfo.tmdb_id
else:
tmdbid = term.replace("tvdb:", "")
subscribe = Subscribe.get_by_tmdbid(db, int(tmdbid))
if not subscribe:
# 查询TMDB季信息
tmdbinfo = IdentifyChain().tvdb_info(tvdbid=int(tmdbid))
if tmdbinfo:
season_num = tmdbinfo.get('season')
if season_num:
seasons = [{"seasonNumber": sea} for sea in range(1, int(season_num) + 1)]
if subscribe:
tvdbid = int(term.replace("tvdb:", ""))
mediainfo = IdentifyChain().recognize_media(mtype=MediaType.MOVIE,
tmdbid=tvdbid)
if not mediainfo:
return [SonarrSeries()]
tmdbid = mediainfo.tmdb_id
# 查询TVDB季信息
seas: List[int] = []
if tvdbid:
tvdbinfo = IdentifyChain().tvdb_info(tvdbid=tvdbid)
if tvdbinfo:
sea_num = tvdbinfo.get('season')
if sea_num:
seas = list(range(1, int(sea_num) + 1))
# 查询是否存在
exists = IdentifyChain().media_exists(mediainfo)
if exists:
hasfile = True
else:
hasfile = False
# 查询订阅信息
seasons: List[dict] = []
subscribes = Subscribe.get_by_tmdbid(db, tmdbid)
if subscribes:
# 已监控
monitored = True
# 已监控季
sub_seas = [sub.season for sub in subscribes]
for sea in seas:
if sea in sub_seas:
seasons.append({
"seasonNumber": sea,
"monitored": True,
})
else:
seasons.append({
"seasonNumber": sea,
"monitored": False,
})
subid = subscribes[-1].id
else:
subid = None
monitored = False
for sea in seas:
seasons.append({
"seasonNumber": sea,
"monitored": False,
})
return [SonarrSeries(
id=subscribe.id,
title=subscribe.name,
seasonCount=1,
seasons=[{"seasonNumber": subscribe.season}],
year=subscribe.year,
isAvailable=True,
monitored=True,
tvdbId=subscribe.tvdbid,
id=subid,
title=mediainfo.title,
seasonCount=len(seasons),
seasons=seasons,
remotePoster=mediainfo.get_poster_image(),
year=mediainfo.year,
tmdbId=mediainfo.tmdb_id,
tvdbId=mediainfo.tvdb_id,
imdbId=mediainfo.imdb_id,
profileId=1,
languageProfileId=1,
qualityProfileId=1,
hasFile=False,
isAvailable=True,
monitored=monitored,
hasFile=hasfile
)]
else:
return [SonarrSeries(seasons=seasons)]
@arr_router.get("/series/{tid}")
@ -523,14 +598,16 @@ async def arr_serie(apikey: str, tid: int, db: Session = Depends(get_db)) -> Any
"monitored": True,
}],
year=subscribe.year,
isAvailable=True,
monitored=True,
remotePoster=subscribe.image,
tmdbId=subscribe.tmdbid,
tvdbId=subscribe.tvdbid,
imdbId=subscribe.imdbid,
profileId=1,
languageProfileId=1,
qualityProfileId=1,
added=True,
hasFile=False,
isAvailable=True,
monitored=True,
hasFile=False
)
else:
raise HTTPException(
@ -554,8 +631,9 @@ async def arr_add_series(apikey: str, tv: schemas.SonarrSeries) -> Any:
if not season.get("monitored"):
continue
sid = SubscribeChain().process(title=tv.title,
year=str(tv.year) if tv.year else None,
year=tv.year,
season=season.get("seasonNumber"),
tmdbid=tv.tmdbId,
mtype=MediaType.TV,
userid="Seerr")

View File

@ -69,7 +69,7 @@ class ChainBase(AbstractSingleton, metaclass=Singleton):
subtitle: str = None) -> Tuple[str, str]:
return self.run_module("prepare_recognize", title=title, subtitle=subtitle)
def recognize_media(self, meta: MetaBase,
def recognize_media(self, meta: MetaBase = None,
mtype: MediaType = None,
tmdbid: int = None) -> Optional[MediaInfo]:
return self.run_module("recognize_media", meta=meta, mtype=mtype, tmdbid=tmdbid)

View File

@ -382,8 +382,7 @@ class DownloadChain(ChainBase):
else:
if not mediainfo.seasons:
# 补充媒体信息
mediainfo: MediaInfo = self.recognize_media(meta=MetaInfo(title=mediainfo.title_year),
mtype=mediainfo.type,
mediainfo: MediaInfo = self.recognize_media(mtype=mediainfo.type,
tmdbid=mediainfo.tmdb_id)
if not mediainfo:
logger.error(f"媒体信息识别失败!")

View File

@ -48,8 +48,7 @@ class SearchChain(ChainBase):
return []
# 补充媒体信息
if not mediainfo.names:
mediainfo: MediaInfo = self.recognize_media(meta=meta,
mtype=mediainfo.type,
mediainfo: MediaInfo = self.recognize_media(mtype=mediainfo.type,
tmdbid=mediainfo.tmdb_id)
if not mediainfo:
logger.error(f'媒体信息识别失败!')

View File

@ -67,8 +67,7 @@ class SubscribeChain(ChainBase):
if not kwargs.get('total_episode'):
if not mediainfo.seasons:
# 补充媒体信息
mediainfo: MediaInfo = self.recognize_media(meta=metainfo,
mtype=mediainfo.type,
mediainfo: MediaInfo = self.recognize_media(mtype=mediainfo.type,
tmdbid=mediainfo.tmdb_id)
if not mediainfo:
logger.error(f"媒体信息识别失败!")

View File

@ -14,6 +14,7 @@ class Subscribe(Base):
type = Column(String)
keyword = Column(String)
tmdbid = Column(Integer, index=True)
imdbid = Column(String)
tvdbid = Column(Integer, index=True)
doubanid = Column(String)
season = Column(Integer)
@ -41,7 +42,7 @@ class Subscribe(Base):
@staticmethod
def get_by_tmdbid(db: Session, tmdbid: int):
return db.query(Subscribe).filter(Subscribe.tmdbid == tmdbid).first()
return db.query(Subscribe).filter(Subscribe.tmdbid == tmdbid).all()
@staticmethod
def get_by_title(db: Session, title: str):

View File

@ -24,6 +24,7 @@ class Subscribes:
year=mediainfo.year,
type=mediainfo.type.value,
tmdbid=mediainfo.tmdb_id,
imdbid=mediainfo.imdb_id,
tvdbid=mediainfo.tvdb_id,
image=mediainfo.get_poster_image(),
description=mediainfo.overview,

View File

@ -40,7 +40,7 @@ class _ModuleBase(metaclass=ABCMeta):
"""
pass
def recognize_media(self, meta: MetaBase,
def recognize_media(self, meta: MetaBase = None,
mtype: MediaType = None,
tmdbid: int = None) -> Optional[MediaInfo]:
"""

View File

@ -41,7 +41,7 @@ class TheMovieDbModule(_ModuleBase):
def init_setting(self) -> Tuple[str, Union[str, bool]]:
pass
def recognize_media(self, meta: MetaBase,
def recognize_media(self, meta: MetaBase = None,
mtype: MediaType = None,
tmdbid: int = None) -> Optional[MediaInfo]:
"""
@ -52,14 +52,17 @@ class TheMovieDbModule(_ModuleBase):
:return: 识别的媒体信息包括剧集信息
"""
if not meta:
return None
cache_info = {}
else:
if mtype:
meta.type = mtype
cache_info = self.cache.get(meta)
if not cache_info or tmdbid:
if not cache_info:
# 缓存没有或者强制不使用缓存
if tmdbid:
# 直接查询详情
info = self.tmdb.get_info(mtype=mtype, tmdbid=tmdbid)
else:
elif meta:
logger.info(f"正在识别 {meta.name} ...")
if meta.type == MediaType.UNKNOWN and not meta.year:
info = self.tmdb.match_multi(meta.name)
@ -97,7 +100,11 @@ class TheMovieDbModule(_ModuleBase):
if info and not info.get("genres"):
info = self.tmdb.get_info(mtype=info.get("media_type"),
tmdbid=info.get("id"))
else:
logger.error("识别媒体信息时未提供元数据或tmdbid")
return None
# 保存到缓存
if meta:
self.cache.update(meta, info)
else:
# 使用缓存信息

View File

@ -5,7 +5,7 @@ from pydantic import BaseModel
class RadarrMovie(BaseModel):
id: Optional[int]
title: Optional[str]
year: Optional[int]
year: Optional[str]
isAvailable: bool = False
monitored: bool = False
tmdbId: Optional[int]
@ -31,7 +31,7 @@ class SonarrSeries(BaseModel):
images: list = []
remotePoster: Optional[str]
seasons: list = []
year: Optional[int]
year: Optional[str]
path: Optional[str]
profileId: Optional[int]
languageProfileId: Optional[int]
@ -39,13 +39,14 @@ class SonarrSeries(BaseModel):
monitored: bool = False
useSceneNumbering: bool = False
runtime: Optional[int]
tmdbId: Optional[int]
imdbId: Optional[str]
tvdbId: Optional[int]
tvRageId: Optional[int]
tvMazeId: Optional[int]
firstAired: Optional[str]
seriesType: Optional[str]
cleanTitle: Optional[str]
imdbId: Optional[str]
titleSlug: Optional[str]
certification: Optional[str]
genres: list = []