fix actions

This commit is contained in:
jxxghp
2025-02-28 11:15:24 +08:00
parent f8ed16666c
commit cf62ad5e8e
14 changed files with 174 additions and 131 deletions
+13 -10
View File
@@ -16,28 +16,24 @@ class BaseAction(ABC):
# 完成标志 # 完成标志
_done_flag = False _done_flag = False
@classmethod
@property @property
@abstractmethod @abstractmethod
def name(self) -> str: def name(cls) -> str:
pass pass
@classmethod
@property @property
@abstractmethod @abstractmethod
def description(self) -> str: def description(cls) -> str:
pass pass
@classmethod
@property @property
@abstractmethod @abstractmethod
def data(self) -> dict: def data(cls) -> dict:
pass pass
@abstractmethod
def execute(self, params: ActionParams, context: ActionContext) -> ActionContext:
"""
执行动作
"""
raise NotImplementedError
@property @property
def done(self) -> bool: def done(self) -> bool:
""" """
@@ -58,3 +54,10 @@ class BaseAction(ABC):
标记动作完成 标记动作完成
""" """
self._done_flag = True self._done_flag = True
@abstractmethod
def execute(self, params: ActionParams, context: ActionContext) -> ActionContext:
"""
执行动作
"""
raise NotImplementedError
+6 -3
View File
@@ -29,16 +29,19 @@ class AddDownloadAction(BaseAction):
self.downloadchain = DownloadChain() self.downloadchain = DownloadChain()
self.mediachain = MediaChain() self.mediachain = MediaChain()
@classmethod
@property @property
def name(self) -> str: def name(cls) -> str:
return "添加下载" return "添加下载"
@classmethod
@property @property
def description(self) -> str: def description(cls) -> str:
return "根据资源列表添加下载任务" return "根据资源列表添加下载任务"
@classmethod
@property @property
def data(self) -> dict: def data(cls) -> dict:
return AddDownloadParams().dict() return AddDownloadParams().dict()
@property @property
+17 -12
View File
@@ -1,6 +1,7 @@
from app.actions import BaseAction from app.actions import BaseAction
from app.chain.subscribe import SubscribeChain from app.chain.subscribe import SubscribeChain
from app.core.config import settings from app.core.config import settings
from app.core.context import MediaInfo
from app.db.subscribe_oper import SubscribeOper from app.db.subscribe_oper import SubscribeOper
from app.log import logger from app.log import logger
from app.schemas import ActionParams, ActionContext from app.schemas import ActionParams, ActionContext
@@ -25,16 +26,19 @@ class AddSubscribeAction(BaseAction):
self.subscribechain = SubscribeChain() self.subscribechain = SubscribeChain()
self.subscribeoper = SubscribeOper() self.subscribeoper = SubscribeOper()
@classmethod
@property @property
def name(self) -> str: def name(cls) -> str:
return "添加订阅" return "添加订阅"
@classmethod
@property @property
def description(self) -> str: def description(cls) -> str:
return "根据媒体列表添加订阅" return "根据媒体列表添加订阅"
@classmethod
@property @property
def data(self) -> dict: def data(cls) -> dict:
return AddSubscribeParams().dict() return AddSubscribeParams().dict()
@property @property
@@ -46,18 +50,19 @@ class AddSubscribeAction(BaseAction):
将medias中的信息添加订阅,如果订阅不存在的话 将medias中的信息添加订阅,如果订阅不存在的话
""" """
for media in context.medias: for media in context.medias:
if self.subscribechain.exists(media): mediainfo = MediaInfo()
mediainfo.from_dict(media.dict())
if self.subscribechain.exists(mediainfo):
logger.info(f"{media.title} 已存在订阅") logger.info(f"{media.title} 已存在订阅")
continue continue
# 添加订阅 # 添加订阅
sid, message = self.subscribechain.add(mtype=media.type, sid, message = self.subscribechain.add(mtype=mediainfo.type,
title=media.title, title=mediainfo.title,
year=media.year, year=mediainfo.year,
tmdbid=media.tmdb_id, tmdbid=mediainfo.tmdb_id,
season=media.season, season=mediainfo.season,
doubanid=media.douban_id, doubanid=mediainfo.douban_id,
bangumiid=media.bangumi_id, bangumiid=mediainfo.bangumi_id,
mediaid=media.media_id,
username=settings.SUPERUSER) username=settings.SUPERUSER)
if sid: if sid:
self._added_subscribes.append(sid) self._added_subscribes.append(sid)
+10 -9
View File
@@ -21,29 +21,30 @@ class FetchDownloadsAction(BaseAction):
super().__init__() super().__init__()
self.chain = ActionChain() self.chain = ActionChain()
@classmethod
@property @property
def name(self) -> str: def name(cls) -> str:
return "获取下载任务" return "获取下载任务"
@classmethod
@property @property
def description(self) -> str: def description(cls) -> str:
return "获取下载任务,更新任务状态" return "获取下载任务,更新任务状态"
@classmethod
@property @property
def data(self) -> dict: def data(cls) -> dict:
return FetchDownloadsParams().dict() return FetchDownloadsParams().dict()
@property @property
def success(self) -> bool: def success(self) -> bool:
if not self._downloads: return self.done
return True
return True if all([d.completed for d in self._downloads]) else False
def execute(self, params: dict, context: ActionContext) -> ActionContext: def execute(self, params: dict, context: ActionContext) -> ActionContext:
""" """
更新downloads中的下载任务状态 更新downloads中的下载任务状态
""" """
self._downloads = context.downloads __all_complete = False
for download in self._downloads: for download in self._downloads:
logger.info(f"获取下载任务 {download.download_id} 状态 ...") logger.info(f"获取下载任务 {download.download_id} 状态 ...")
torrents = self.chain.list_torrents(hashs=[download.download_id]) torrents = self.chain.list_torrents(hashs=[download.download_id])
@@ -55,6 +56,6 @@ class FetchDownloadsAction(BaseAction):
if t.progress >= 100: if t.progress >= 100:
logger.info(f"下载任务 {download.download_id} 已完成") logger.info(f"下载任务 {download.download_id} 已完成")
download.completed = True download.completed = True
if all([d.completed for d in self._downloads]):
self.job_done() self.job_done()
return context return context
+74 -62
View File
@@ -3,6 +3,7 @@ from typing import List
from pydantic import Field from pydantic import Field
from app.actions import BaseAction from app.actions import BaseAction
from app.chain.recommend import RecommendChain
from app.schemas import ActionParams, ActionContext from app.schemas import ActionParams, ActionContext
from app.core.config import settings from app.core.config import settings
from app.core.event import eventmanager from app.core.event import eventmanager
@@ -24,65 +25,68 @@ class FetchMediasAction(BaseAction):
获取媒体数据 获取媒体数据
""" """
__inner_sources = [ __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 = [] __medias = []
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.__inner_sources = [
{
"func": RecommendChain().tmdb_trending,
"name": '流行趋势',
},
{
"func": RecommendChain().douban_movie_showing,
"name": '正在热映',
},
{
"func": RecommendChain().bangumi_calendar,
"name": 'Bangumi每日放送',
},
{
"func": RecommendChain().tmdb_movies,
"name": 'TMDB热门电影',
},
{
"func": RecommendChain().tmdb_tvs,
"name": 'TMDB热门电视剧',
},
{
"func": RecommendChain().douban_movie_hot,
"name": '豆瓣热门电影',
},
{
"func": RecommendChain().douban_tv_hot,
"name": '豆瓣热门电视剧',
},
{
"func": RecommendChain().douban_tv_animation,
"name": '豆瓣热门动漫',
},
{
"func": RecommendChain().douban_movies,
"name": '豆瓣最新电影',
},
{
"func": RecommendChain().douban_tvs,
"name": '豆瓣最新电视剧',
},
{
"func": RecommendChain().douban_movie_top250,
"name": '豆瓣电影TOP250',
},
{
"func": RecommendChain().douban_tv_weekly_chinese,
"name": '豆瓣国产剧集榜',
},
{
"func": RecommendChain().douban_tv_weekly_global,
"name": '豆瓣全球剧集榜',
}
]
# 广播事件,请示额外的推荐数据源支持 # 广播事件,请示额外的推荐数据源支持
event_data = RecommendSourceEventData() event_data = RecommendSourceEventData()
event = eventmanager.send_event(ChainEventType.RecommendSource, event_data) event = eventmanager.send_event(ChainEventType.RecommendSource, event_data)
@@ -92,16 +96,19 @@ class FetchMediasAction(BaseAction):
if event_data.extra_sources: if event_data.extra_sources:
self.__inner_sources.extend([s.dict() for s in event_data.extra_sources]) self.__inner_sources.extend([s.dict() for s in event_data.extra_sources])
@classmethod
@property @property
def name(self) -> str: def name(cls) -> str:
return "获取媒体数据" return "获取媒体数据"
@classmethod
@property @property
def description(self) -> str: def description(cls) -> str:
return "获取榜单等媒体数据列表" return "获取榜单等媒体数据列表"
@classmethod
@property @property
def data(self) -> dict: def data(cls) -> dict:
return FetchMediasParams().dict() return FetchMediasParams().dict()
@property @property
@@ -127,11 +134,16 @@ class FetchMediasAction(BaseAction):
if not source: if not source:
continue continue
logger.info(f"获取媒体数据 {source} ...") logger.info(f"获取媒体数据 {source} ...")
# 调用内部API获取数据 results = []
api_url = f"http://127.0.0.1:{settings.PORT}/api/v1/{source['api_path']}?token={settings.API_TOKEN}" if source.get("func"):
res = RequestUtils(timeout=15).post_res(api_url) results = source['func']()
if res: else:
results = res.json() # 调用内部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()
if results:
logger.info(f"{name} 获取到 {len(results)} 条数据") logger.info(f"{name} 获取到 {len(results)} 条数据")
self.__medias.extend([MediaInfo(**r) for r in results]) self.__medias.extend([MediaInfo(**r) for r in results])
else: else:
+6 -3
View File
@@ -35,16 +35,19 @@ class FetchRssAction(BaseAction):
self.rsshelper = RssHelper() self.rsshelper = RssHelper()
self.chain = ActionChain() self.chain = ActionChain()
@classmethod
@property @property
def name(self) -> str: def name(cls) -> str:
return "获取RSS资源" return "获取RSS资源"
@classmethod
@property @property
def description(self) -> str: def description(cls) -> str:
return "订阅RSS地址获取资源" return "订阅RSS地址获取资源"
@classmethod
@property @property
def data(self) -> dict: def data(cls) -> dict:
return FetchRssParams().dict() return FetchRssParams().dict()
@property @property
+6 -3
View File
@@ -30,16 +30,19 @@ class FetchTorrentsAction(BaseAction):
super().__init__() super().__init__()
self.searchchain = SearchChain() self.searchchain = SearchChain()
@classmethod
@property @property
def name(self) -> str: def name(cls) -> str:
return "搜索站点资源" return "搜索站点资源"
@classmethod
@property @property
def description(self) -> str: def description(cls) -> str:
return "根据关键字搜索站点种子资源" return "根据关键字搜索站点种子资源"
@classmethod
@property @property
def data(self) -> dict: def data(cls) -> dict:
return FetchTorrentsParams().dict() return FetchTorrentsParams().dict()
@property @property
+6 -3
View File
@@ -24,16 +24,19 @@ class FilterMediasAction(BaseAction):
__medias = [] __medias = []
@classmethod
@property @property
def name(self) -> str: def name(cls) -> str:
return "过滤媒体数据" return "过滤媒体数据"
@classmethod
@property @property
def description(self) -> str: def description(cls) -> str:
return "对媒体数据列表进行过滤" return "对媒体数据列表进行过滤"
@classmethod
@property @property
def data(self) -> dict: def data(cls) -> dict:
return FilterMediasParams().dict() return FilterMediasParams().dict()
@property @property
+6 -3
View File
@@ -32,16 +32,19 @@ class FilterTorrentsAction(BaseAction):
self.torrenthelper = TorrentHelper() self.torrenthelper = TorrentHelper()
self.chain = ActionChain() self.chain = ActionChain()
@classmethod
@property @property
def name(self) -> str: def name(cls) -> str:
return "过滤资源" return "过滤资源"
@classmethod
@property @property
def description(self) -> str: def description(cls) -> str:
return "对资源列表数据进行过滤" return "对资源列表数据进行过滤"
@classmethod
@property @property
def data(self) -> dict: def data(cls) -> dict:
return FilterTorrentsParams().dict() return FilterTorrentsParams().dict()
@property @property
+6 -3
View File
@@ -27,16 +27,19 @@ class ScrapeFileAction(BaseAction):
self.storagechain = StorageChain() self.storagechain = StorageChain()
self.mediachain = MediaChain() self.mediachain = MediaChain()
@classmethod
@property @property
def name(self) -> str: def name(cls) -> str:
return "刮削文件" return "刮削文件"
@classmethod
@property @property
def description(self) -> str: def description(cls) -> str:
return "刮削媒体信息和图片" return "刮削媒体信息和图片"
@classmethod
@property @property
def data(self) -> dict: def data(cls) -> dict:
return ScrapeFileParams().dict() return ScrapeFileParams().dict()
@property @property
+6 -3
View File
@@ -17,16 +17,19 @@ class SendEventAction(BaseAction):
发送事件 发送事件
""" """
@classmethod
@property @property
def name(self) -> str: def name(cls) -> str:
return "发送事件" return "发送事件"
@classmethod
@property @property
def description(self) -> str: def description(cls) -> str:
return "发送队列中的所有事件" return "发送队列中的所有事件"
@classmethod
@property @property
def data(self) -> dict: def data(cls) -> dict:
return SendEventParams().dict() return SendEventParams().dict()
@property @property
+6 -3
View File
@@ -24,16 +24,19 @@ class SendMessageAction(BaseAction):
super().__init__() super().__init__()
self.chain = ActionChain() self.chain = ActionChain()
@classmethod
@property @property
def name(self) -> str: def name(cls) -> str:
return "发送消息" return "发送消息"
@classmethod
@property @property
def description(self) -> str: def description(cls) -> str:
return "发送队列中的所有消息" return "发送队列中的所有消息"
@classmethod
@property @property
def data(self) -> dict: def data(cls) -> dict:
return SendMessageParams().dict() return SendMessageParams().dict()
@property @property
+6 -3
View File
@@ -26,16 +26,19 @@ class TransferFileAction(BaseAction):
self.transferchain = TransferChain() self.transferchain = TransferChain()
self.storagechain = StorageChain() self.storagechain = StorageChain()
@classmethod
@property @property
def name(self) -> str: def name(cls) -> str:
return "整理文件" return "整理文件"
@classmethod
@property @property
def description(self) -> str: def description(cls) -> str:
return "整理下载队列中的文件" return "整理下载队列中的文件"
@classmethod
@property @property
def data(self) -> dict: def data(cls) -> dict:
return TransferFileParams().dict() return TransferFileParams().dict()
@property @property
+6 -11
View File
@@ -44,7 +44,7 @@ class WorkFlowManager(metaclass=Singleton):
for action in actions: for action in actions:
logger.debug(f"加载动作: {action.__name__}") logger.debug(f"加载动作: {action.__name__}")
try: try:
self._actions[action.__name__] = action() self._actions[action.__name__] = action
except Exception as err: except Exception as err:
logger.error(f"加载动作失败: {action.__name__} - {err}") logger.error(f"加载动作失败: {action.__name__} - {err}")
@@ -62,7 +62,7 @@ class WorkFlowManager(metaclass=Singleton):
context = ActionContext() context = ActionContext()
if action.type in self._actions: if action.type in self._actions:
# 实例化 # 实例化
action_obj = self._actions[action.type] action_obj = self._actions[action.type]()
# 执行 # 执行
logger.info(f"执行动作: {action.id} - {action.name}") logger.info(f"执行动作: {action.id} - {action.name}")
try: try:
@@ -70,10 +70,6 @@ class WorkFlowManager(metaclass=Singleton):
except Exception as err: except Exception as err:
logger.error(f"{action.name} 执行失败: {err}") logger.error(f"{action.name} 执行失败: {err}")
return False, context return False, context
if action_obj.success:
logger.info(f"{action.name} 执行成功")
else:
logger.error(f"{action.name} 执行失败")
loop = action.data.get("loop") loop = action.data.get("loop")
loop_interval = action.data.get("loop_interval") loop_interval = action.data.get("loop_interval")
if loop and loop_interval: if loop and loop_interval:
@@ -84,11 +80,10 @@ class WorkFlowManager(metaclass=Singleton):
# 执行 # 执行
logger.info(f"继续执行动作: {action.id} - {action.name}") logger.info(f"继续执行动作: {action.id} - {action.name}")
result_context = action_obj.execute(action.data, result_context) result_context = action_obj.execute(action.data, result_context)
if action_obj.success: if action_obj.success:
logger.info(f"{action.name} 执行成功") logger.info(f"{action.name} 执行成功")
else: else:
logger.error(f"{action.name} 执行失败") logger.error(f"{action.name} 执行失败")
logger.info(f"{action.name} 执行完成")
return action_obj.success, result_context return action_obj.success, result_context
else: else:
logger.error(f"未找到动作: {action.type} - {action.name}") logger.error(f"未找到动作: {action.type} - {action.name}")