from typing import List from pydantic import Field from app.actions import BaseAction from app.schemas import ActionParams, ActionContext from core.config import settings from core.event import eventmanager from log import logger from schemas import RecommendSourceEventData, MediaInfo from schemas.types import ChainEventType from utils.http import RequestUtils class FetchMediasParams(ActionParams): """ 获取媒体数据参数 """ sources: List[str] = Field([], description="媒体数据来源") class FetchMediasAction(BaseAction): """ 获取媒体数据 """ __inner_sources = [ { "api_path": 'recommend/tmdb_trending', "name": '流行趋势', }, { "api_path": 'recommend/douban_showing', "name": '正在热映', }, { "api_path": 'bangumi/calendar', "name": 'Bangumi每日放送', }, { "api_path": 'recommend/tmdb_movies', "name": 'TMDB热门电影', }, { "api_path": 'recommend/tmdb_tvs?with_original_language=zh|en|ja|ko', "name": 'TMDB热门电视剧', }, { "api_path": 'recommend/douban_movie_hot', "name": '豆瓣热门电影', }, { "api_path": 'recommend/douban_tv_hot', "name": '豆瓣热门电视剧', }, { "api_path": 'recommend/douban_tv_animation', "name": '豆瓣热门动漫', }, { "api_path": 'recommend/douban_movies', "name": '豆瓣最新电影', }, { "api_path": 'recommend/douban_tvs', "name": '豆瓣最新电视剧', }, { "api_path": 'recommend/douban_movie_top250', "name": '豆瓣电影TOP250', }, { "api_path": 'recommend/douban_tv_weekly_chinese', "name": '豆瓣国产剧集榜', }, { "api_path": 'recommend/douban_tv_weekly_global', "name": '豆瓣全球剧集榜', } ] __medias = [] @property def name(self) -> str: return "获取媒体数据" @property def description(self) -> str: return "获取媒体数据" @property def success(self) -> bool: return True if self.__medias else False def __get_source(self, source: str): """ 获取数据源 """ for s in self.__inner_sources: if s['name'] == source: return s return None async def execute(self, params: FetchMediasParams, context: ActionContext) -> ActionContext: """ 获取媒体数据,填充到medias """ # 广播事件,请示额外的推荐数据源支持 event_data = RecommendSourceEventData() event = eventmanager.send_event(ChainEventType.RecommendSource, event_data) # 使用事件返回的上下文数据 if event and event.event_data: event_data: RecommendSourceEventData = event.event_data if event_data.extra_sources: self.__inner_sources.extend([s.dict() for s in event_data.extra_sources]) for name in params.sources: source = self.__get_source(name) if not source: continue logger.info(f"获取媒体数据 {source} ...") # 调用内部API获取数据 api_url = f"http://127.0.0.1:{settings.PORT}/api/v1/{source['api_path']}?token={settings.API_TOKEN}" res = RequestUtils(timeout=15).post_res(api_url) if res: results = res.json() logger.info(f"{name} 获取到 {len(results)} 条数据") self.__medias.extend([MediaInfo(**r) for r in results]) else: logger.error(f"{name} 获取数据失败") if self.__medias: context.medias.extend(self.__medias) self.job_done() return context