diff --git a/app/api/endpoints/douban.py b/app/api/endpoints/douban.py index b16a4c5e..7de690f1 100644 --- a/app/api/endpoints/douban.py +++ b/app/api/endpoints/douban.py @@ -5,7 +5,6 @@ from fastapi import BackgroundTasks from app import schemas from app.chain.douban import DoubanChain -from app.chain.media import MediaChain from app.core.context import MediaInfo from app.db.models.user import User from app.db.userauth import get_current_active_superuser @@ -39,7 +38,7 @@ async def recognize_doubanid(doubanid: str, 根据豆瓣ID识别媒体信息 """ # 识别媒体信息 - context = MediaChain().recognize_by_doubanid(doubanid=doubanid) + context = DoubanChain().recognize_by_doubanid(doubanid=doubanid) return context.to_dict() @@ -48,7 +47,7 @@ async def douban_info(doubanid: str) -> Any: """ 根据豆瓣ID查询豆瓣媒体信息 """ - doubaninfo = MediaChain().douban_info(doubanid=doubanid) + doubaninfo = DoubanChain().douban_info(doubanid=doubanid) if doubaninfo: return MediaInfo(douban_info=doubaninfo).to_dict() else: @@ -64,7 +63,7 @@ async def douban_movies(sort: str = "R", """ 浏览豆瓣电影信息 """ - movies = MediaChain().douban_movies(sort=sort, tags=tags, start=start, count=count) + movies = DoubanChain().douban_movies(sort=sort, tags=tags, start=start, count=count) return [movie.to_dict() for movie in movies] @@ -77,5 +76,16 @@ async def douban_tvs(sort: str = "R", """ 浏览豆瓣剧集信息 """ - tvs = MediaChain().douban_tvs(sort=sort, tags=tags, start=start, count=count) + tvs = DoubanChain().douban_tvs(sort=sort, tags=tags, start=start, count=count) return [tv.to_dict() for tv in tvs] + + +@router.get("/top250", response_model=List[schemas.MediaInfo]) +async def movie_top250(page: int = 1, + count: int = 30, + _: User = Depends(get_current_active_user)) -> Any: + """ + 浏览豆瓣剧集信息 + """ + movies = DoubanChain().movie_top250(page=page, count=count) + return [movie.to_dict() for movie in movies] diff --git a/app/api/endpoints/tmdb.py b/app/api/endpoints/tmdb.py index c3e5f0f2..d0d74e1a 100644 --- a/app/api/endpoints/tmdb.py +++ b/app/api/endpoints/tmdb.py @@ -4,7 +4,7 @@ from fastapi import APIRouter, Depends from app import schemas from app.chain.media import MediaChain -from app.core.context import MediaInfo +from app.chain.tmdb import TmdbChain from app.db.models.user import User from app.db.userauth import get_current_active_user from app.schemas.types import MediaType @@ -34,10 +34,10 @@ async def tmdb_movies(sort_by: str = "popularity.desc", """ 浏览TMDB电影信息 """ - movies = MediaChain().tmdb_movies(sort_by=sort_by, - with_genres=with_genres, - with_original_language=with_original_language, - page=page) + movies = TmdbChain().tmdb_movies(sort_by=sort_by, + with_genres=with_genres, + with_original_language=with_original_language, + page=page) return [movie.to_dict() for movie in movies] @@ -50,8 +50,8 @@ async def tmdb_tvs(sort_by: str = "popularity.desc", """ 浏览TMDB剧集信息 """ - tvs = MediaChain().tmdb_tvs(sort_by=sort_by, - with_genres=with_genres, - with_original_language=with_original_language, - page=page) + tvs = TmdbChain().tmdb_tvs(sort_by=sort_by, + with_genres=with_genres, + with_original_language=with_original_language, + page=page) return [tv.to_dict() for tv in tvs] diff --git a/app/chain/__init__.py b/app/chain/__init__.py index 95bbd767..8a6612ad 100644 --- a/app/chain/__init__.py +++ b/app/chain/__init__.py @@ -317,3 +317,11 @@ class ChainBase(AbstractSingleton, metaclass=Singleton): sort_by=sort_by, with_genres=with_genres, with_original_language=with_original_language, page=page) + + def movie_top250(self, page: int = 1, count: int = 30) -> List[dict]: + """ + 获取豆瓣电影TOP250 + :param page: 页码 + :param count: 每页数量 + """ + return self.__run_module("movie_top250", page=page, count=count) diff --git a/app/chain/douban.py b/app/chain/douban.py index 1572ca8e..c4e0e29a 100644 --- a/app/chain/douban.py +++ b/app/chain/douban.py @@ -1,15 +1,18 @@ from pathlib import Path -from typing import Optional, Union +from typing import Optional, List +from typing import Union from app.chain import ChainBase from app.chain.download import DownloadChain from app.chain.search import SearchChain from app.chain.subscribe import SubscribeChain from app.core.config import settings -from app.core.metainfo import MetaInfo +from app.core.context import Context from app.core.context import MediaInfo +from app.core.metainfo import MetaInfo from app.helper.rss import RssHelper from app.log import logger +from app.schemas import MediaType class DoubanChain(ChainBase): @@ -28,6 +31,48 @@ class DoubanChain(ChainBase): self.searchchain = SearchChain() self.subscribechain = SubscribeChain() + def recognize_by_doubanid(self, doubanid: str) -> Optional[Context]: + """ + 根据豆瓣ID识别媒体信息 + """ + logger.info(f'开始识别媒体信息,豆瓣ID:{doubanid} ...') + # 查询豆瓣信息 + doubaninfo = self.douban_info(doubanid=doubanid) + if not doubaninfo: + logger.warn(f'未查询到豆瓣信息,豆瓣ID:{doubanid}') + return None + meta = MetaInfo(title=doubaninfo.get("original_title") or doubaninfo.get("title")) + # 识别媒体信息 + mediainfo: MediaInfo = self.recognize_media(meta=meta) + if not mediainfo: + logger.warn(f'{meta.name} 未识别到TMDB媒体信息') + return Context(meta=meta, mediainfo=MediaInfo(douban_info=doubaninfo)) + logger.info(f'{doubanid} 识别到媒体信息:{mediainfo.type.value} {mediainfo.title_year}{meta.season}') + mediainfo.set_douban_info(doubaninfo) + return Context(meta=meta, mediainfo=mediainfo) + + def douban_movies(self, sort: str, tags: str, start: int = 0, count: int = 30) -> List[MediaInfo]: + """ + 浏览豆瓣电影列表 + """ + logger.info(f'开始获取豆瓣电影列表,排序:{sort},标签:{tags}') + movies = self.douban_discover(mtype=MediaType.MOVIE, sort=sort, tags=tags, start=start, count=count) + if not movies: + logger.warn(f'豆瓣电影列表为空,排序:{sort},标签:{tags}') + return [] + return [MediaInfo(douban_info=movie) for movie in movies] + + def douban_tvs(self, sort: str, tags: str, start: int = 0, count: int = 30) -> List[MediaInfo]: + """ + 浏览豆瓣剧集列表 + """ + logger.info(f'开始获取豆瓣剧集列表,排序:{sort},标签:{tags}') + tvs = self.douban_discover(mtype=MediaType.TV, sort=sort, tags=tags, start=start, count=count) + if not tvs: + logger.warn(f'豆瓣剧集列表为空,排序:{sort},标签:{tags}') + return [] + return [MediaInfo(douban_info=tv) for tv in tvs] + def remote_sync(self, userid: Union[int, str]): """ 同步豆瓣想看数据,发送消息 diff --git a/app/chain/media.py b/app/chain/media.py index c8381f65..0b663f08 100644 --- a/app/chain/media.py +++ b/app/chain/media.py @@ -5,7 +5,6 @@ from app.core.context import Context, MediaInfo from app.core.meta import MetaBase from app.core.metainfo import MetaInfo from app.log import logger -from app.schemas import MediaType from app.utils.string import StringUtils @@ -36,26 +35,6 @@ class MediaChain(ChainBase): # 返回上下文 return Context(meta=metainfo, mediainfo=mediainfo, title=title, subtitle=subtitle) - def recognize_by_doubanid(self, doubanid: str) -> Optional[Context]: - """ - 根据豆瓣ID识别媒体信息 - """ - logger.info(f'开始识别媒体信息,豆瓣ID:{doubanid} ...') - # 查询豆瓣信息 - doubaninfo = self.douban_info(doubanid=doubanid) - if not doubaninfo: - logger.warn(f'未查询到豆瓣信息,豆瓣ID:{doubanid}') - return None - meta = MetaInfo(title=doubaninfo.get("original_title") or doubaninfo.get("title")) - # 识别媒体信息 - mediainfo: MediaInfo = self.recognize_media(meta=meta) - if not mediainfo: - logger.warn(f'{meta.name} 未识别到TMDB媒体信息') - return Context(meta=meta, mediainfo=MediaInfo(douban_info=doubaninfo)) - logger.info(f'{doubanid} 识别到媒体信息:{mediainfo.type.value} {mediainfo.title_year}{meta.season}') - mediainfo.set_douban_info(doubaninfo) - return Context(meta=meta, mediainfo=mediainfo) - def search(self, title: str) -> Tuple[MetaBase, List[MediaInfo]]: """ 搜索媒体信息 @@ -87,57 +66,3 @@ class MediaChain(ChainBase): logger.info(f"{content} 搜索到 {len(medias)} 条相关媒体信息") # 识别的元数据,媒体信息列表 return meta, medias - - def douban_movies(self, sort: str, tags: str, start: int = 0, count: int = 30) -> List[MediaInfo]: - """ - 浏览豆瓣电影列表 - """ - logger.info(f'开始获取豆瓣电影列表,排序:{sort},标签:{tags}') - movies = self.douban_discover(mtype=MediaType.MOVIE, sort=sort, tags=tags, start=start, count=count) - if not movies: - logger.warn(f'豆瓣电影列表为空,排序:{sort},标签:{tags}') - return [] - return [MediaInfo(douban_info=movie) for movie in movies] - - def douban_tvs(self, sort: str, tags: str, start: int = 0, count: int = 30) -> List[MediaInfo]: - """ - 浏览豆瓣剧集列表 - """ - logger.info(f'开始获取豆瓣剧集列表,排序:{sort},标签:{tags}') - tvs = self.douban_discover(mtype=MediaType.TV, sort=sort, tags=tags, start=start, count=count) - if not tvs: - logger.warn(f'豆瓣剧集列表为空,排序:{sort},标签:{tags}') - return [] - return [MediaInfo(douban_info=tv) for tv in tvs] - - def tmdb_movies(self, sort_by: str, with_genres: str, with_original_language: str, - page: int = 1) -> List[MediaInfo]: - """ - 浏览TMDB电影信息 - """ - logger.info(f'开始获取TMDB电影列表,排序:{sort_by},类型:{with_genres},语言:{with_original_language}') - movies = self.tmdb_discover(mtype=MediaType.MOVIE, - sort_by=sort_by, - with_genres=with_genres, - with_original_language=with_original_language, - page=page) - if not movies: - logger.warn(f'TMDB电影列表为空,排序:{sort_by},类型:{with_genres},语言:{with_original_language}') - return [] - return [MediaInfo(tmdb_info=movie) for movie in movies] - - def tmdb_tvs(self, sort_by: str, with_genres: str, with_original_language: str, - page: int = 1) -> List[MediaInfo]: - """ - 浏览TMDB剧集信息 - """ - logger.info(f'开始获取TMDB剧集列表,排序:{sort_by},类型:{with_genres},语言:{with_original_language}') - tvs = self.tmdb_discover(mtype=MediaType.TV, - sort_by=sort_by, - with_genres=with_genres, - with_original_language=with_original_language, - page=page) - if not tvs: - logger.warn(f'TMDB剧集列表为空,排序:{sort_by},类型:{with_genres},语言:{with_original_language}') - return [] - return [MediaInfo(tmdb_info=tv) for tv in tvs] diff --git a/app/chain/tmdb.py b/app/chain/tmdb.py new file mode 100644 index 00000000..b690e056 --- /dev/null +++ b/app/chain/tmdb.py @@ -0,0 +1,41 @@ +from typing import List + +from app.chain import ChainBase +from app.core.context import MediaInfo +from app.log import logger +from app.schemas import MediaType + + +class TmdbChain(ChainBase): + + def tmdb_movies(self, sort_by: str, with_genres: str, with_original_language: str, + page: int = 1) -> List[MediaInfo]: + """ + 浏览TMDB电影信息 + """ + logger.info(f'开始获取TMDB电影列表,排序:{sort_by},类型:{with_genres},语言:{with_original_language}') + movies = self.tmdb_discover(mtype=MediaType.MOVIE, + sort_by=sort_by, + with_genres=with_genres, + with_original_language=with_original_language, + page=page) + if not movies: + logger.warn(f'TMDB电影列表为空,排序:{sort_by},类型:{with_genres},语言:{with_original_language}') + return [] + return [MediaInfo(tmdb_info=movie) for movie in movies] + + def tmdb_tvs(self, sort_by: str, with_genres: str, with_original_language: str, + page: int = 1) -> List[MediaInfo]: + """ + 浏览TMDB剧集信息 + """ + logger.info(f'开始获取TMDB剧集列表,排序:{sort_by},类型:{with_genres},语言:{with_original_language}') + tvs = self.tmdb_discover(mtype=MediaType.TV, + sort_by=sort_by, + with_genres=with_genres, + with_original_language=with_original_language, + page=page) + if not tvs: + logger.warn(f'TMDB剧集列表为空,排序:{sort_by},类型:{with_genres},语言:{with_original_language}') + return [] + return [MediaInfo(tmdb_info=tv) for tv in tvs] diff --git a/app/modules/douban/__init__.py b/app/modules/douban/__init__.py index 2fad52b7..0467af1d 100644 --- a/app/modules/douban/__init__.py +++ b/app/modules/douban/__init__.py @@ -118,6 +118,16 @@ class DoubanModule(_ModuleBase): return item_obj return {} + def movie_top250(self, page: int = 1, count: int = 30) -> List[dict]: + """ + 获取豆瓣电影TOP250 + """ + infos = self.doubanapi.movie_top250(start=(page - 1) * count, + count=count) + if not infos: + return [] + return infos.get("subject_collection_items") + def scrape_metadata(self, path: Path, mediainfo: MediaInfo) -> None: """ 刮削元数据