From 1eef95421afb2609d5cc7f5beeb85b4de9101f06 Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Sun, 22 Dec 2024 01:00:47 +0800 Subject: [PATCH 1/6] feat(recommend): add RecommendChain --- app/chain/recommend.py | 123 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 app/chain/recommend.py diff --git a/app/chain/recommend.py b/app/chain/recommend.py new file mode 100644 index 00000000..51f37e45 --- /dev/null +++ b/app/chain/recommend.py @@ -0,0 +1,123 @@ +from typing import Any + +from app.chain import ChainBase +from app.chain.bangumi import BangumiChain +from app.chain.douban import DoubanChain +from app.chain.tmdb import TmdbChain +from app.schemas import MediaType +from app.utils.singleton import Singleton + + +class RecommendChain(ChainBase, metaclass=Singleton): + """ + 推荐处理链,单例运行 + """ + + def __init__(self): + super().__init__() + self.tmdbchain = TmdbChain() + self.doubanchain = DoubanChain() + self.bangumichain = BangumiChain() + + def tmdb_movies(self, sort_by: str = "popularity.desc", with_genres: str = "", + with_original_language: str = "", page: int = 1) -> Any: + """ + TMDB热门电影 + """ + movies = self.tmdbchain.tmdb_discover(mtype=MediaType.MOVIE, + sort_by=sort_by, + with_genres=with_genres, + with_original_language=with_original_language, + page=page) + return [movie.to_dict() for movie in movies] if movies else [] + + def tmdb_tvs(self, sort_by: str = "popularity.desc", with_genres: str = "", + with_original_language: str = "", page: int = 1) -> Any: + """ + TMDB热门电视剧 + """ + tvs = self.tmdbchain.tmdb_discover(mtype=MediaType.TV, + sort_by=sort_by, + with_genres=with_genres, + with_original_language=with_original_language, + page=page) + return [tv.to_dict() for tv in tvs] if tvs else [] + + def tmdb_trending(self, page: int = 1) -> Any: + """ + TMDB流行趋势 + """ + infos = self.tmdbchain.tmdb_trending(page=page) + return [info.to_dict() for info in infos] if infos else [] + + def bangumi_calendar(self, page: int = 1, count: int = 30) -> Any: + """ + Bangumi每日放送 + """ + medias = self.bangumichain.calendar() + return [media.to_dict() for media in medias[(page - 1) * count: page * count]] if medias else [] + + def movie_showing(self, page: int = 1, count: int = 30) -> Any: + """ + 豆瓣正在热映 + """ + movies = self.doubanchain.movie_showing(page=page, count=count) + return [media.to_dict() for media in movies] if movies else [] + + def douban_movies(self, sort: str = "R", tags: str = "", page: int = 1, count: int = 30) -> Any: + """ + 豆瓣最新电影 + """ + movies = self.doubanchain.douban_discover(mtype=MediaType.MOVIE, + sort=sort, tags=tags, page=page, count=count) + return [media.to_dict() for media in movies] if movies else [] + + def douban_tvs(self, sort: str = "R", tags: str = "", page: int = 1, count: int = 30) -> Any: + """ + 豆瓣最新电视剧 + """ + tvs = self.doubanchain.douban_discover(mtype=MediaType.TV, + sort=sort, tags=tags, page=page, count=count) + return [media.to_dict() for media in tvs] if tvs else [] + + def movie_top250(self, page: int = 1, count: int = 30) -> Any: + """ + 豆瓣电影TOP250 + """ + movies = self.doubanchain.movie_top250(page=page, count=count) + return [media.to_dict() for media in movies] if movies else [] + + def tv_weekly_chinese(self, page: int = 1, count: int = 30) -> Any: + """ + 豆瓣国产剧集榜 + """ + tvs = self.doubanchain.tv_weekly_chinese(page=page, count=count) + return [media.to_dict() for media in tvs] if tvs else [] + + def tv_weekly_global(self, page: int = 1, count: int = 30) -> Any: + """ + 豆瓣全球剧集榜 + """ + tvs = self.doubanchain.tv_weekly_global(page=page, count=count) + return [media.to_dict() for media in tvs] if tvs else [] + + def tv_animation(self, page: int = 1, count: int = 30) -> Any: + """ + 豆瓣热门动漫 + """ + tvs = self.doubanchain.tv_animation(page=page, count=count) + return [media.to_dict() for media in tvs] if tvs else [] + + def movie_hot(self, page: int = 1, count: int = 30) -> Any: + """ + 豆瓣热门电影 + """ + movies = self.doubanchain.movie_hot(page=page, count=count) + return [media.to_dict() for media in movies] if movies else [] + + def tv_hot(self, page: int = 1, count: int = 30) -> Any: + """ + 豆瓣热门电视剧 + """ + tvs = self.doubanchain.tv_hot(page=page, count=count) + return [media.to_dict() for media in tvs] if tvs else [] From 98247fa47aa0910566a02e01a026643a570ad50d Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Sun, 22 Dec 2024 01:02:07 +0800 Subject: [PATCH 2/6] feat: add log_execution_time decorator --- app/utils/common.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/app/utils/common.py b/app/utils/common.py index 4ba1aa7e..92d9cca6 100644 --- a/app/utils/common.py +++ b/app/utils/common.py @@ -1,5 +1,6 @@ import time -from typing import Any +from functools import wraps +from typing import Any, Callable from app.schemas import ImmediateException @@ -36,3 +37,27 @@ def retry(ExceptionToCheck: Any, return f_retry return deco_retry + + +def log_execution_time(logger: Any = None): + """ + 记录函数执行时间的装饰器 + :param logger: 日志记录器对象,用于记录异常信息 + """ + + def decorator(func: Callable): + @wraps(func) + def wrapper(*args, **kwargs): + start_time = time.time() + result = func(*args, **kwargs) + end_time = time.time() + msg = f"{func.__name__} execution time: {end_time - start_time:.2f} seconds" + if logger: + logger.debug(msg) + else: + print(msg) + return result + + return wrapper + + return decorator From de1c2c98d2ebb4411fadb7a564ea5c90cce93b17 Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Sun, 22 Dec 2024 01:03:44 +0800 Subject: [PATCH 3/6] feat(recommend): add log_execution_time decorator to RecommendChain methods --- app/chain/recommend.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/app/chain/recommend.py b/app/chain/recommend.py index 51f37e45..811001ba 100644 --- a/app/chain/recommend.py +++ b/app/chain/recommend.py @@ -4,7 +4,9 @@ from app.chain import ChainBase from app.chain.bangumi import BangumiChain from app.chain.douban import DoubanChain from app.chain.tmdb import TmdbChain +from app.log import logger from app.schemas import MediaType +from app.utils.common import log_execution_time from app.utils.singleton import Singleton @@ -19,6 +21,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): self.doubanchain = DoubanChain() self.bangumichain = BangumiChain() + @log_execution_time(logger=logger) def tmdb_movies(self, sort_by: str = "popularity.desc", with_genres: str = "", with_original_language: str = "", page: int = 1) -> Any: """ @@ -31,6 +34,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): page=page) return [movie.to_dict() for movie in movies] if movies else [] + @log_execution_time(logger=logger) def tmdb_tvs(self, sort_by: str = "popularity.desc", with_genres: str = "", with_original_language: str = "", page: int = 1) -> Any: """ @@ -43,6 +47,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): page=page) return [tv.to_dict() for tv in tvs] if tvs else [] + @log_execution_time(logger=logger) def tmdb_trending(self, page: int = 1) -> Any: """ TMDB流行趋势 @@ -50,6 +55,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): infos = self.tmdbchain.tmdb_trending(page=page) return [info.to_dict() for info in infos] if infos else [] + @log_execution_time(logger=logger) def bangumi_calendar(self, page: int = 1, count: int = 30) -> Any: """ Bangumi每日放送 @@ -57,6 +63,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): medias = self.bangumichain.calendar() return [media.to_dict() for media in medias[(page - 1) * count: page * count]] if medias else [] + @log_execution_time(logger=logger) def movie_showing(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣正在热映 @@ -64,6 +71,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): movies = self.doubanchain.movie_showing(page=page, count=count) return [media.to_dict() for media in movies] if movies else [] + @log_execution_time(logger=logger) def douban_movies(self, sort: str = "R", tags: str = "", page: int = 1, count: int = 30) -> Any: """ 豆瓣最新电影 @@ -72,6 +80,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): sort=sort, tags=tags, page=page, count=count) return [media.to_dict() for media in movies] if movies else [] + @log_execution_time(logger=logger) def douban_tvs(self, sort: str = "R", tags: str = "", page: int = 1, count: int = 30) -> Any: """ 豆瓣最新电视剧 @@ -80,6 +89,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): sort=sort, tags=tags, page=page, count=count) return [media.to_dict() for media in tvs] if tvs else [] + @log_execution_time(logger=logger) def movie_top250(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣电影TOP250 @@ -87,6 +97,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): movies = self.doubanchain.movie_top250(page=page, count=count) return [media.to_dict() for media in movies] if movies else [] + @log_execution_time(logger=logger) def tv_weekly_chinese(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣国产剧集榜 @@ -94,6 +105,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): tvs = self.doubanchain.tv_weekly_chinese(page=page, count=count) return [media.to_dict() for media in tvs] if tvs else [] + @log_execution_time(logger=logger) def tv_weekly_global(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣全球剧集榜 @@ -101,6 +113,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): tvs = self.doubanchain.tv_weekly_global(page=page, count=count) return [media.to_dict() for media in tvs] if tvs else [] + @log_execution_time(logger=logger) def tv_animation(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣热门动漫 @@ -108,6 +121,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): tvs = self.doubanchain.tv_animation(page=page, count=count) return [media.to_dict() for media in tvs] if tvs else [] + @log_execution_time(logger=logger) def movie_hot(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣热门电影 @@ -115,6 +129,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): movies = self.doubanchain.movie_hot(page=page, count=count) return [media.to_dict() for media in movies] if movies else [] + @log_execution_time(logger=logger) def tv_hot(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣热门电视剧 From ec77213ca6512f894fc8b9f3b5123bbadc6e61fd Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Sun, 22 Dec 2024 01:09:06 +0800 Subject: [PATCH 4/6] feat(recommend): add cached_with_empty_check decorator --- app/chain/recommend.py | 65 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/app/chain/recommend.py b/app/chain/recommend.py index 811001ba..5f4a3e5b 100644 --- a/app/chain/recommend.py +++ b/app/chain/recommend.py @@ -1,4 +1,8 @@ -from typing import Any +from functools import wraps +from typing import Any, Callable + +from cachetools import TTLCache +from cachetools.keys import hashkey from app.chain import ChainBase from app.chain.bangumi import BangumiChain @@ -9,6 +13,35 @@ from app.schemas import MediaType from app.utils.common import log_execution_time from app.utils.singleton import Singleton +# 推荐相关的专用缓存 +recommend_ttl = 6 * 3600 +recommend_cache = TTLCache(maxsize=256, ttl=recommend_ttl) + + +# 推荐缓存装饰器,避免偶发网络获取数据为空时,页面由于缓存长时间渲染异常问题 +def cached_with_empty_check(func: Callable): + """ + 缓存装饰器,用于缓存函数的返回结果,仅在结果非空时进行缓存 + + :param func: 被装饰的函数 + :return: 包装后的函数 + """ + + @wraps(func) + def wrapper(*args, **kwargs): + # 使用 cachetools 缓存,构造缓存键 + cache_key = hashkey(*args, **kwargs) + if cache_key in recommend_cache: + return recommend_cache[cache_key] + result = func(*args, **kwargs) + # 如果返回值为空,则不缓存 + if result in [None, [], {}]: + return result + recommend_cache[cache_key] = result + return result + + return wrapper + class RecommendChain(ChainBase, metaclass=Singleton): """ @@ -21,7 +54,25 @@ class RecommendChain(ChainBase, metaclass=Singleton): self.doubanchain = DoubanChain() self.bangumichain = BangumiChain() + def refresh_recommend(self): + """ + 刷新推荐 + """ + self.tmdb_movies() + self.tmdb_tvs() + self.tmdb_trending() + self.bangumi_calendar() + self.douban_movies() + self.douban_tvs() + self.movie_top250() + self.tv_weekly_chinese() + self.tv_weekly_global() + self.tv_animation() + self.movie_hot() + self.tv_hot() + @log_execution_time(logger=logger) + @cached_with_empty_check def tmdb_movies(self, sort_by: str = "popularity.desc", with_genres: str = "", with_original_language: str = "", page: int = 1) -> Any: """ @@ -35,6 +86,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): return [movie.to_dict() for movie in movies] if movies else [] @log_execution_time(logger=logger) + @cached_with_empty_check def tmdb_tvs(self, sort_by: str = "popularity.desc", with_genres: str = "", with_original_language: str = "", page: int = 1) -> Any: """ @@ -48,6 +100,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): return [tv.to_dict() for tv in tvs] if tvs else [] @log_execution_time(logger=logger) + @cached_with_empty_check def tmdb_trending(self, page: int = 1) -> Any: """ TMDB流行趋势 @@ -56,6 +109,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): return [info.to_dict() for info in infos] if infos else [] @log_execution_time(logger=logger) + @cached_with_empty_check def bangumi_calendar(self, page: int = 1, count: int = 30) -> Any: """ Bangumi每日放送 @@ -64,6 +118,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): return [media.to_dict() for media in medias[(page - 1) * count: page * count]] if medias else [] @log_execution_time(logger=logger) + @cached_with_empty_check def movie_showing(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣正在热映 @@ -72,6 +127,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): return [media.to_dict() for media in movies] if movies else [] @log_execution_time(logger=logger) + @cached_with_empty_check def douban_movies(self, sort: str = "R", tags: str = "", page: int = 1, count: int = 30) -> Any: """ 豆瓣最新电影 @@ -81,6 +137,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): return [media.to_dict() for media in movies] if movies else [] @log_execution_time(logger=logger) + @cached_with_empty_check def douban_tvs(self, sort: str = "R", tags: str = "", page: int = 1, count: int = 30) -> Any: """ 豆瓣最新电视剧 @@ -90,6 +147,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): return [media.to_dict() for media in tvs] if tvs else [] @log_execution_time(logger=logger) + @cached_with_empty_check def movie_top250(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣电影TOP250 @@ -98,6 +156,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): return [media.to_dict() for media in movies] if movies else [] @log_execution_time(logger=logger) + @cached_with_empty_check def tv_weekly_chinese(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣国产剧集榜 @@ -106,6 +165,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): return [media.to_dict() for media in tvs] if tvs else [] @log_execution_time(logger=logger) + @cached_with_empty_check def tv_weekly_global(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣全球剧集榜 @@ -114,6 +174,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): return [media.to_dict() for media in tvs] if tvs else [] @log_execution_time(logger=logger) + @cached_with_empty_check def tv_animation(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣热门动漫 @@ -122,6 +183,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): return [media.to_dict() for media in tvs] if tvs else [] @log_execution_time(logger=logger) + @cached_with_empty_check def movie_hot(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣热门电影 @@ -130,6 +192,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): return [media.to_dict() for media in movies] if movies else [] @log_execution_time(logger=logger) + @cached_with_empty_check def tv_hot(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣热门电视剧 From 3339bbca5038b4f48c5c2c865c5ad7390e47547d Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Sun, 22 Dec 2024 01:27:11 +0800 Subject: [PATCH 5/6] feat(recommend): switch API calls to use RecommendChain --- app/api/endpoints/bangumi.py | 6 ++--- app/api/endpoints/douban.py | 48 ++++++++---------------------------- app/api/endpoints/tmdb.py | 32 +++++++++--------------- app/chain/recommend.py | 26 +++++++++---------- 4 files changed, 36 insertions(+), 76 deletions(-) diff --git a/app/api/endpoints/bangumi.py b/app/api/endpoints/bangumi.py index 999ca51f..f9ac4f46 100644 --- a/app/api/endpoints/bangumi.py +++ b/app/api/endpoints/bangumi.py @@ -4,6 +4,7 @@ from fastapi import APIRouter, Depends from app import schemas from app.chain.bangumi import BangumiChain +from app.chain.recommend import RecommendChain from app.core.context import MediaInfo from app.core.security import verify_token @@ -17,10 +18,7 @@ def calendar(page: int = 1, """ 浏览Bangumi每日放送 """ - medias = BangumiChain().calendar() - if medias: - return [media.to_dict() for media in medias[(page - 1) * count: page * count]] - return [] + return RecommendChain().bangumi_calendar(page=page, count=count) @router.get("/credits/{bangumiid}", summary="查询Bangumi演职员表", response_model=List[schemas.MediaPerson]) diff --git a/app/api/endpoints/douban.py b/app/api/endpoints/douban.py index 3de5ad8d..6be0e8e7 100644 --- a/app/api/endpoints/douban.py +++ b/app/api/endpoints/douban.py @@ -4,6 +4,7 @@ from fastapi import APIRouter, Depends from app import schemas from app.chain.douban import DoubanChain +from app.chain.recommend import RecommendChain from app.core.context import MediaInfo from app.core.security import verify_token from app.schemas import MediaType @@ -40,10 +41,7 @@ def movie_showing(page: int = 1, """ 浏览豆瓣正在热映 """ - movies = DoubanChain().movie_showing(page=page, count=count) - if movies: - return [media.to_dict() for media in movies] - return [] + return RecommendChain().douban_movie_showing(page=page, count=count) @router.get("/movies", summary="豆瓣电影", response_model=List[schemas.MediaInfo]) @@ -55,11 +53,7 @@ def douban_movies(sort: str = "R", """ 浏览豆瓣电影信息 """ - movies = DoubanChain().douban_discover(mtype=MediaType.MOVIE, - sort=sort, tags=tags, page=page, count=count) - if movies: - return [media.to_dict() for media in movies] - return [] + return RecommendChain().douban_movies(sort=sort, tags=tags, page=page, count=count) @router.get("/tvs", summary="豆瓣剧集", response_model=List[schemas.MediaInfo]) @@ -71,11 +65,7 @@ def douban_tvs(sort: str = "R", """ 浏览豆瓣剧集信息 """ - tvs = DoubanChain().douban_discover(mtype=MediaType.TV, - sort=sort, tags=tags, page=page, count=count) - if tvs: - return [media.to_dict() for media in tvs] - return [] + return RecommendChain().douban_tvs(sort=sort, tags=tags, page=page, count=count) @router.get("/movie_top250", summary="豆瓣电影TOP250", response_model=List[schemas.MediaInfo]) @@ -85,10 +75,7 @@ def movie_top250(page: int = 1, """ 浏览豆瓣剧集信息 """ - movies = DoubanChain().movie_top250(page=page, count=count) - if movies: - return [media.to_dict() for media in movies] - return [] + return RecommendChain().douban_movie_top250(page=page, count=count) @router.get("/tv_weekly_chinese", summary="豆瓣国产剧集周榜", response_model=List[schemas.MediaInfo]) @@ -98,10 +85,7 @@ def tv_weekly_chinese(page: int = 1, """ 中国每周剧集口碑榜 """ - tvs = DoubanChain().tv_weekly_chinese(page=page, count=count) - if tvs: - return [media.to_dict() for media in tvs] - return [] + return RecommendChain().douban_tv_weekly_chinese(page=page, count=count) @router.get("/tv_weekly_global", summary="豆瓣全球剧集周榜", response_model=List[schemas.MediaInfo]) @@ -111,10 +95,7 @@ def tv_weekly_global(page: int = 1, """ 全球每周剧集口碑榜 """ - tvs = DoubanChain().tv_weekly_global(page=page, count=count) - if tvs: - return [media.to_dict() for media in tvs] - return [] + return RecommendChain().douban_tv_weekly_global(page=page, count=count) @router.get("/tv_animation", summary="豆瓣动画剧集", response_model=List[schemas.MediaInfo]) @@ -124,10 +105,7 @@ def tv_animation(page: int = 1, """ 热门动画剧集 """ - tvs = DoubanChain().tv_animation(page=page, count=count) - if tvs: - return [media.to_dict() for media in tvs] - return [] + return RecommendChain().douban_tv_animation(page=page, count=count) @router.get("/movie_hot", summary="豆瓣热门电影", response_model=List[schemas.MediaInfo]) @@ -137,10 +115,7 @@ def movie_hot(page: int = 1, """ 热门电影 """ - movies = DoubanChain().movie_hot(page=page, count=count) - if movies: - return [media.to_dict() for media in movies] - return [] + return RecommendChain().douban_movie_hot(page=page, count=count) @router.get("/tv_hot", summary="豆瓣热门电视剧", response_model=List[schemas.MediaInfo]) @@ -150,10 +125,7 @@ def tv_hot(page: int = 1, """ 热门电视剧 """ - tvs = DoubanChain().tv_hot(page=page, count=count) - if tvs: - return [media.to_dict() for media in tvs] - return [] + return RecommendChain().douban_tv_hot(page=page, count=count) @router.get("/credits/{doubanid}/{type_name}", summary="豆瓣演员阵容", response_model=List[schemas.MediaPerson]) diff --git a/app/api/endpoints/tmdb.py b/app/api/endpoints/tmdb.py index 7deb70d6..18cb2d94 100644 --- a/app/api/endpoints/tmdb.py +++ b/app/api/endpoints/tmdb.py @@ -3,6 +3,7 @@ from typing import List, Any from fastapi import APIRouter, Depends from app import schemas +from app.chain.recommend import RecommendChain from app.chain.tmdb import TmdbChain from app.core.security import verify_token from app.schemas.types import MediaType @@ -108,14 +109,10 @@ def tmdb_movies(sort_by: str = "popularity.desc", """ 浏览TMDB电影信息 """ - movies = TmdbChain().tmdb_discover(mtype=MediaType.MOVIE, - sort_by=sort_by, - with_genres=with_genres, - with_original_language=with_original_language, - page=page) - if not movies: - return [] - return [movie.to_dict() for movie in movies] + return RecommendChain().tmdb_movies(sort_by=sort_by, + with_genres=with_genres, + with_original_language=with_original_language, + page=page) @router.get("/tvs", summary="TMDB剧集", response_model=List[schemas.MediaInfo]) @@ -127,26 +124,19 @@ def tmdb_tvs(sort_by: str = "popularity.desc", """ 浏览TMDB剧集信息 """ - tvs = TmdbChain().tmdb_discover(mtype=MediaType.TV, - sort_by=sort_by, - with_genres=with_genres, - with_original_language=with_original_language, - page=page) - if not tvs: - return [] - return [tv.to_dict() for tv in tvs] + return RecommendChain().tmdb_tvs(sort_by=sort_by, + with_genres=with_genres, + with_original_language=with_original_language, + page=page) @router.get("/trending", summary="TMDB流行趋势", response_model=List[schemas.MediaInfo]) def tmdb_trending(page: int = 1, _: schemas.TokenPayload = Depends(verify_token)) -> Any: """ - 浏览TMDB剧集信息 + TMDB流行趋势 """ - infos = TmdbChain().tmdb_trending(page=page) - if not infos: - return [] - return [info.to_dict() for info in infos] + return RecommendChain().tmdb_trending(page=page) @router.get("/{tmdbid}/{season}", summary="TMDB季所有集", response_model=List[schemas.TmdbEpisode]) diff --git a/app/chain/recommend.py b/app/chain/recommend.py index 5f4a3e5b..48d66f81 100644 --- a/app/chain/recommend.py +++ b/app/chain/recommend.py @@ -64,12 +64,12 @@ class RecommendChain(ChainBase, metaclass=Singleton): self.bangumi_calendar() self.douban_movies() self.douban_tvs() - self.movie_top250() - self.tv_weekly_chinese() - self.tv_weekly_global() - self.tv_animation() - self.movie_hot() - self.tv_hot() + self.douban_movie_top250() + self.douban_tv_weekly_chinese() + self.douban_tv_weekly_global() + self.douban_tv_animation() + self.douban_movie_hot() + self.douban_tv_hot() @log_execution_time(logger=logger) @cached_with_empty_check @@ -119,7 +119,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): @log_execution_time(logger=logger) @cached_with_empty_check - def movie_showing(self, page: int = 1, count: int = 30) -> Any: + def douban_movie_showing(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣正在热映 """ @@ -148,7 +148,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): @log_execution_time(logger=logger) @cached_with_empty_check - def movie_top250(self, page: int = 1, count: int = 30) -> Any: + def douban_movie_top250(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣电影TOP250 """ @@ -157,7 +157,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): @log_execution_time(logger=logger) @cached_with_empty_check - def tv_weekly_chinese(self, page: int = 1, count: int = 30) -> Any: + def douban_tv_weekly_chinese(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣国产剧集榜 """ @@ -166,7 +166,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): @log_execution_time(logger=logger) @cached_with_empty_check - def tv_weekly_global(self, page: int = 1, count: int = 30) -> Any: + def douban_tv_weekly_global(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣全球剧集榜 """ @@ -175,7 +175,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): @log_execution_time(logger=logger) @cached_with_empty_check - def tv_animation(self, page: int = 1, count: int = 30) -> Any: + def douban_tv_animation(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣热门动漫 """ @@ -184,7 +184,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): @log_execution_time(logger=logger) @cached_with_empty_check - def movie_hot(self, page: int = 1, count: int = 30) -> Any: + def douban_movie_hot(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣热门电影 """ @@ -193,7 +193,7 @@ class RecommendChain(ChainBase, metaclass=Singleton): @log_execution_time(logger=logger) @cached_with_empty_check - def tv_hot(self, page: int = 1, count: int = 30) -> Any: + def douban_tv_hot(self, page: int = 1, count: int = 30) -> Any: """ 豆瓣热门电视剧 """ From 1fb791455e93738cd8e197b8095a646f5ab0e3e9 Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Sun, 22 Dec 2024 01:37:25 +0800 Subject: [PATCH 6/6] chore(recommend): update comment --- app/chain/recommend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/chain/recommend.py b/app/chain/recommend.py index 48d66f81..3783ca45 100644 --- a/app/chain/recommend.py +++ b/app/chain/recommend.py @@ -18,7 +18,7 @@ recommend_ttl = 6 * 3600 recommend_cache = TTLCache(maxsize=256, ttl=recommend_ttl) -# 推荐缓存装饰器,避免偶发网络获取数据为空时,页面由于缓存长时间渲染异常问题 +# 推荐缓存装饰器,避免偶发网络获取数据为空时,页面由于缓存为空长时间渲染异常问题 def cached_with_empty_check(func: Callable): """ 缓存装饰器,用于缓存函数的返回结果,仅在结果非空时进行缓存