mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 23:47:41 +08:00
feat:工作流手动中止
This commit is contained in:
@@ -56,7 +56,7 @@ class BaseAction(ABC):
|
||||
self._done_flag = True
|
||||
|
||||
@abstractmethod
|
||||
def execute(self, params: ActionParams, context: ActionContext) -> ActionContext:
|
||||
def execute(self, workflow_id: int, params: ActionParams, context: ActionContext) -> ActionContext:
|
||||
"""
|
||||
执行动作
|
||||
"""
|
||||
|
||||
@@ -3,6 +3,7 @@ from pydantic import Field
|
||||
from app.actions import BaseAction
|
||||
from app.chain.download import DownloadChain
|
||||
from app.chain.media import MediaChain
|
||||
from app.core.config import global_vars
|
||||
from app.core.metainfo import MetaInfo
|
||||
from app.log import logger
|
||||
from app.schemas import ActionParams, ActionContext, DownloadTask, MediaType
|
||||
@@ -50,12 +51,14 @@ class AddDownloadAction(BaseAction):
|
||||
def success(self) -> bool:
|
||||
return not self._has_error
|
||||
|
||||
def execute(self, params: dict, context: ActionContext) -> ActionContext:
|
||||
def execute(self, workflow_id: int, params: dict, context: ActionContext) -> ActionContext:
|
||||
"""
|
||||
将上下文中的torrents添加到下载任务中
|
||||
"""
|
||||
params = AddDownloadParams(**params)
|
||||
for t in context.torrents:
|
||||
if global_vars.is_workflow_stopped(workflow_id):
|
||||
break
|
||||
if not t.meta_info:
|
||||
t.meta_info = MetaInfo(title=t.title, subtitle=t.description)
|
||||
if not t.media_info:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from app.actions import BaseAction
|
||||
from app.chain.subscribe import SubscribeChain
|
||||
from app.core.config import settings
|
||||
from app.core.config import settings, global_vars
|
||||
from app.core.context import MediaInfo
|
||||
from app.db.subscribe_oper import SubscribeOper
|
||||
from app.log import logger
|
||||
@@ -46,11 +46,13 @@ class AddSubscribeAction(BaseAction):
|
||||
def success(self) -> bool:
|
||||
return not self._has_error
|
||||
|
||||
def execute(self, params: dict, context: ActionContext) -> ActionContext:
|
||||
def execute(self, workflow_id: int, params: dict, context: ActionContext) -> ActionContext:
|
||||
"""
|
||||
将medias中的信息添加订阅,如果订阅不存在的话
|
||||
"""
|
||||
for media in context.medias:
|
||||
if global_vars.is_workflow_stopped(workflow_id):
|
||||
break
|
||||
mediainfo = MediaInfo()
|
||||
mediainfo.from_dict(media.dict())
|
||||
if self.subscribechain.exists(mediainfo):
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from app.actions import BaseAction, ActionChain
|
||||
from app.core.config import global_vars
|
||||
from app.schemas import ActionParams, ActionContext
|
||||
from app.log import logger
|
||||
|
||||
@@ -40,12 +41,14 @@ class FetchDownloadsAction(BaseAction):
|
||||
def success(self) -> bool:
|
||||
return self.done
|
||||
|
||||
def execute(self, params: dict, context: ActionContext) -> ActionContext:
|
||||
def execute(self, workflow_id: int, params: dict, context: ActionContext) -> ActionContext:
|
||||
"""
|
||||
更新downloads中的下载任务状态
|
||||
"""
|
||||
__all_complete = False
|
||||
for download in self._downloads:
|
||||
if global_vars.is_workflow_stopped(workflow_id):
|
||||
break
|
||||
logger.info(f"获取下载任务 {download.download_id} 状态 ...")
|
||||
torrents = self.chain.list_torrents(hashs=[download.download_id])
|
||||
if not torrents:
|
||||
|
||||
@@ -5,7 +5,7 @@ from pydantic import Field
|
||||
from app.actions import BaseAction
|
||||
from app.chain.recommend import RecommendChain
|
||||
from app.schemas import ActionParams, ActionContext
|
||||
from app.core.config import settings
|
||||
from app.core.config import settings, global_vars
|
||||
from app.core.event import eventmanager
|
||||
from app.log import logger
|
||||
from app.schemas import RecommendSourceEventData, MediaInfo
|
||||
@@ -124,12 +124,14 @@ class FetchMediasAction(BaseAction):
|
||||
return s
|
||||
return None
|
||||
|
||||
def execute(self, params: dict, context: ActionContext) -> ActionContext:
|
||||
def execute(self, workflow_id: int, params: dict, context: ActionContext) -> ActionContext:
|
||||
"""
|
||||
获取媒体数据,填充到medias
|
||||
"""
|
||||
params = FetchMediasParams(**params)
|
||||
for name in params.sources:
|
||||
if global_vars.is_workflow_stopped(workflow_id):
|
||||
break
|
||||
source = self.__get_source(name)
|
||||
if not source:
|
||||
continue
|
||||
|
||||
@@ -3,7 +3,7 @@ from typing import Optional
|
||||
from pydantic import Field
|
||||
|
||||
from app.actions import BaseAction, ActionChain
|
||||
from app.core.config import settings
|
||||
from app.core.config import settings, global_vars
|
||||
from app.core.context import Context
|
||||
from app.core.metainfo import MetaInfo
|
||||
from app.helper.rss import RssHelper
|
||||
@@ -55,7 +55,7 @@ class FetchRssAction(BaseAction):
|
||||
def success(self) -> bool:
|
||||
return not self._has_error
|
||||
|
||||
def execute(self, params: dict, context: ActionContext) -> ActionContext:
|
||||
def execute(self, workflow_id: int, params: dict, context: ActionContext) -> ActionContext:
|
||||
"""
|
||||
请求RSS地址获取数据,并解析为资源列表
|
||||
"""
|
||||
@@ -86,6 +86,8 @@ class FetchRssAction(BaseAction):
|
||||
|
||||
# 组装种子
|
||||
for item in rss_items:
|
||||
if global_vars.is_workflow_stopped(workflow_id):
|
||||
break
|
||||
if not item.get("title"):
|
||||
continue
|
||||
torrentinfo = TorrentInfo(
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import random
|
||||
import time
|
||||
from typing import Optional, List
|
||||
|
||||
from pydantic import Field
|
||||
|
||||
from app.actions import BaseAction
|
||||
from app.chain.search import SearchChain
|
||||
from app.core.config import global_vars
|
||||
from app.log import logger
|
||||
from app.schemas import ActionParams, ActionContext, MediaType
|
||||
|
||||
@@ -12,7 +15,8 @@ class FetchTorrentsParams(ActionParams):
|
||||
"""
|
||||
获取站点资源参数
|
||||
"""
|
||||
name: str = Field(None, description="资源名称")
|
||||
search_type: Optional[str] = Field("keyword", description="搜索类型")
|
||||
name: Optional[str] = Field(None, description="资源名称")
|
||||
year: Optional[str] = Field(None, description="年份")
|
||||
type: Optional[str] = Field(None, description="资源类型 (电影/电视剧)")
|
||||
season: Optional[int] = Field(None, description="季度")
|
||||
@@ -49,29 +53,49 @@ class FetchTorrentsAction(BaseAction):
|
||||
def success(self) -> bool:
|
||||
return self.done
|
||||
|
||||
def execute(self, params: dict, context: ActionContext) -> ActionContext:
|
||||
def execute(self, workflow_id: int, params: dict, context: ActionContext) -> ActionContext:
|
||||
"""
|
||||
搜索站点,获取资源列表
|
||||
"""
|
||||
params = FetchTorrentsParams(**params)
|
||||
torrents = self.searchchain.search_by_title(title=params.name, sites=params.sites, cache_local=False)
|
||||
for torrent in torrents:
|
||||
if params.year and torrent.meta_info.year != params.year:
|
||||
continue
|
||||
if params.type and torrent.media_info and torrent.media_info.type != MediaType(params.type):
|
||||
continue
|
||||
if params.season and torrent.meta_info.begin_season != params.season:
|
||||
continue
|
||||
# 识别媒体信息
|
||||
torrent.media_info = self.searchchain.recognize_media(torrent.meta_info)
|
||||
if not torrent.media_info:
|
||||
logger.warning(f"{torrent.torrent_info.title} 未识别到媒体信息")
|
||||
continue
|
||||
self._torrents.append(torrent)
|
||||
if params.search_type == "keyword":
|
||||
# 按关键字搜索
|
||||
torrents = self.searchchain.search_by_title(title=params.name, sites=params.sites, cache_local=False)
|
||||
for torrent in torrents:
|
||||
if global_vars.is_workflow_stopped(workflow_id):
|
||||
break
|
||||
if params.year and torrent.meta_info.year != params.year:
|
||||
continue
|
||||
if params.type and torrent.media_info and torrent.media_info.type != MediaType(params.type):
|
||||
continue
|
||||
if params.season and torrent.meta_info.begin_season != params.season:
|
||||
continue
|
||||
# 识别媒体信息
|
||||
torrent.media_info = self.searchchain.recognize_media(torrent.meta_info)
|
||||
if not torrent.media_info:
|
||||
logger.warning(f"{torrent.torrent_info.title} 未识别到媒体信息")
|
||||
continue
|
||||
self._torrents.append(torrent)
|
||||
else:
|
||||
# 搜索媒体列表
|
||||
for media in context.medias:
|
||||
if global_vars.is_workflow_stopped(workflow_id):
|
||||
break
|
||||
torrents = self.searchchain.search_by_id(tmdbid=media.tmdb_id,
|
||||
doubanid=media.douban_id,
|
||||
mtype=MediaType(media.type),
|
||||
sites=params.sites)
|
||||
for torrent in torrents:
|
||||
self._torrents.append(torrent)
|
||||
|
||||
# 随机休眠 10-60秒
|
||||
sleep_time = random.randint(10, 60)
|
||||
logger.info(f"随机休眠 {sleep_time} 秒 ...")
|
||||
time.sleep(sleep_time)
|
||||
|
||||
if self._torrents:
|
||||
context.torrents.extend(self._torrents)
|
||||
logger.info(f"搜索到 {len(self._torrents)} 条资源")
|
||||
logger.info(f"共搜索到 {len(self._torrents)} 条资源")
|
||||
|
||||
self.job_done()
|
||||
return context
|
||||
|
||||
@@ -3,6 +3,7 @@ from typing import Optional
|
||||
from pydantic import Field
|
||||
|
||||
from app.actions import BaseAction
|
||||
from app.core.config import global_vars
|
||||
from app.schemas import ActionParams, ActionContext
|
||||
|
||||
|
||||
@@ -42,12 +43,14 @@ class FilterMediasAction(BaseAction):
|
||||
def success(self) -> bool:
|
||||
return self.done
|
||||
|
||||
def execute(self, params: dict, context: ActionContext) -> ActionContext:
|
||||
def execute(self, workflow_id: int, params: dict, context: ActionContext) -> ActionContext:
|
||||
"""
|
||||
过滤medias中媒体数据
|
||||
"""
|
||||
params = FilterMediasParams(**params)
|
||||
for media in context.medias:
|
||||
if global_vars.is_workflow_stopped(workflow_id):
|
||||
break
|
||||
if params.type and media.type != params.type:
|
||||
continue
|
||||
if params.category and media.category != params.category:
|
||||
|
||||
@@ -3,6 +3,7 @@ from typing import Optional, List
|
||||
from pydantic import Field
|
||||
|
||||
from app.actions import BaseAction, ActionChain
|
||||
from app.core.config import global_vars
|
||||
from app.helper.torrent import TorrentHelper
|
||||
from app.schemas import ActionParams, ActionContext
|
||||
|
||||
@@ -51,12 +52,14 @@ class FilterTorrentsAction(BaseAction):
|
||||
def success(self) -> bool:
|
||||
return self.done
|
||||
|
||||
def execute(self, params: dict, context: ActionContext) -> ActionContext:
|
||||
def execute(self, workflow_id: int, params: dict, context: ActionContext) -> ActionContext:
|
||||
"""
|
||||
过滤torrents中的资源
|
||||
"""
|
||||
params = FilterTorrentsParams(**params)
|
||||
for torrent in context.torrents:
|
||||
if global_vars.is_workflow_stopped(workflow_id):
|
||||
break
|
||||
if self.torrenthelper.filter_torrent(
|
||||
torrent_info=torrent.torrent_info,
|
||||
filter_params={
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from pathlib import Path
|
||||
|
||||
from app.actions import BaseAction
|
||||
from app.core.config import global_vars
|
||||
from app.schemas import ActionParams, ActionContext
|
||||
from app.chain.media import MediaChain
|
||||
from app.chain.storage import StorageChain
|
||||
@@ -47,11 +48,13 @@ class ScrapeFileAction(BaseAction):
|
||||
def success(self) -> bool:
|
||||
return not self._has_error
|
||||
|
||||
def execute(self, params: dict, context: ActionContext) -> ActionContext:
|
||||
def execute(self, workflow_id: int, params: dict, context: ActionContext) -> ActionContext:
|
||||
"""
|
||||
刮削fileitems中的所有文件
|
||||
"""
|
||||
for fileitem in context.fileitems:
|
||||
if global_vars.is_workflow_stopped(workflow_id):
|
||||
break
|
||||
if fileitem in self._scraped_files:
|
||||
continue
|
||||
if not self.storagechain.exists(fileitem):
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import copy
|
||||
|
||||
from app.actions import BaseAction
|
||||
from app.core.config import global_vars
|
||||
from app.schemas import ActionParams, ActionContext
|
||||
from app.core.event import eventmanager
|
||||
|
||||
@@ -36,7 +37,7 @@ class SendEventAction(BaseAction):
|
||||
def success(self) -> bool:
|
||||
return self.done
|
||||
|
||||
def execute(self, params: dict, context: ActionContext) -> ActionContext:
|
||||
def execute(self, workflow_id: int, params: dict, context: ActionContext) -> ActionContext:
|
||||
"""
|
||||
发送events中的事件
|
||||
"""
|
||||
@@ -44,6 +45,8 @@ class SendEventAction(BaseAction):
|
||||
# 按优先级排序,优先级高的先发送
|
||||
context.events.sort(key=lambda x: x.priority, reverse=True)
|
||||
for event in copy.deepcopy(context.events):
|
||||
if global_vars.is_workflow_stopped(workflow_id):
|
||||
break
|
||||
eventmanager.send_event(etype=event.event_type, data=event.event_data)
|
||||
context.events.remove(event)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ from typing import List, Optional, Union
|
||||
from pydantic import Field
|
||||
|
||||
from app.actions import BaseAction, ActionChain
|
||||
from app.core.config import global_vars
|
||||
from app.schemas import ActionParams, ActionContext
|
||||
|
||||
|
||||
@@ -43,11 +44,13 @@ class SendMessageAction(BaseAction):
|
||||
def success(self) -> bool:
|
||||
return self.done
|
||||
|
||||
def execute(self, params: dict, context: ActionContext) -> ActionContext:
|
||||
def execute(self, workflow_id: int, params: dict, context: ActionContext) -> ActionContext:
|
||||
"""
|
||||
发送messages中的消息
|
||||
"""
|
||||
for message in copy.deepcopy(context.messages):
|
||||
if global_vars.is_workflow_stopped(workflow_id):
|
||||
break
|
||||
if params.client:
|
||||
message.source = params.client
|
||||
if params.userid:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from pathlib import Path
|
||||
|
||||
from app.actions import BaseAction
|
||||
from app.core.config import global_vars
|
||||
from app.schemas import ActionParams, ActionContext
|
||||
from app.chain.storage import StorageChain
|
||||
from app.chain.transfer import TransferChain
|
||||
@@ -46,11 +47,13 @@ class TransferFileAction(BaseAction):
|
||||
def success(self) -> bool:
|
||||
return not self._has_error
|
||||
|
||||
def execute(self, params: dict, context: ActionContext) -> ActionContext:
|
||||
def execute(self, workflow_id: int, params: dict, context: ActionContext) -> ActionContext:
|
||||
"""
|
||||
从downloads中整理文件,记录到fileitems
|
||||
"""
|
||||
for download in context.downloads:
|
||||
if global_vars.is_workflow_stopped(workflow_id):
|
||||
break
|
||||
if not download.completed:
|
||||
logger.info(f"下载任务 {download.download_id} 未完成")
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user