Merge branch 'jxxghp:v2' into v2

This commit is contained in:
Timo_Young
2025-02-19 17:28:22 +08:00
committed by GitHub
8 changed files with 154 additions and 17 deletions

View File

@@ -24,6 +24,11 @@ class AddDownloadAction(BaseAction):
# 已添加的下载
_added_downloads = []
def __init__(self):
super().__init__()
self.downloadchain = DownloadChain()
self.mediachain = MediaChain()
@property
def name(self) -> str:
return "添加下载资源"
@@ -44,13 +49,13 @@ class AddDownloadAction(BaseAction):
if not t.meta_info:
t.meta_info = MetaInfo(title=t.title, subtitle=t.description)
if not t.media_info:
t.media_info = MediaChain().recognize_media(meta=t.meta_info)
t.media_info = self.mediachain.recognize_media(meta=t.meta_info)
if not t.media_info:
logger.warning(f"{t.title} 未识别到媒体信息,无法下载")
continue
did = DownloadChain().download_single(context=t,
downloader=params.downloader,
save_path=params.save_path)
did = self.downloadchain.download_single(context=t,
downloader=params.downloader,
save_path=params.save_path)
if did:
self._added_downloads.append(did)
@@ -59,5 +64,6 @@ class AddDownloadAction(BaseAction):
context.downloads.extend(
[DownloadTask(download_id=did, downloader=params.downloader) for did in self._added_downloads]
)
self.job_done()
return context

View File

@@ -1,4 +1,8 @@
from app.actions import BaseAction
from app.chain.subscribe import SubscribeChain
from app.core.config import settings
from app.db.subscribe_oper import SubscribeOper
from app.log import logger
from app.schemas import ActionParams, ActionContext
@@ -14,6 +18,13 @@ class AddSubscribeAction(BaseAction):
添加订阅
"""
_added_subscribes = []
def __init__(self):
super().__init__()
self.subscribechain = SubscribeChain()
self.subscribeoper = SubscribeOper()
@property
def name(self) -> str:
return "添加订阅"
@@ -24,7 +35,33 @@ class AddSubscribeAction(BaseAction):
@property
def success(self) -> bool:
return True
return True if self._added_subscribes else False
async def execute(self, params: AddSubscribeParams, context: ActionContext) -> ActionContext:
pass
"""
将medias中的信息添加订阅如果订阅不存在的话
"""
for media in context.medias:
if self.subscribechain.exists(media):
logger.info(f"{media.title} 已存在订阅")
continue
# 添加订阅
sid, message = self.subscribechain.add(mtype=media.type,
title=media.title,
year=media.year,
tmdbid=media.tmdb_id,
season=media.season,
doubanid=media.douban_id,
bangumiid=media.bangumi_id,
mediaid=media.media_id,
username=settings.SUPERUSER)
if sid:
self._added_subscribes.append(sid)
if self._added_subscribes:
logger.info(f"已添加 {len(self._added_subscribes)} 个订阅")
for sid in self._added_subscribes:
context.subscribes.append(self.subscribeoper.get(sid))
self.job_done()
return context

View File

@@ -1,4 +1,5 @@
from app.actions import BaseAction
from app.chain.download import DownloadChain
from app.schemas import ActionParams, ActionContext
@@ -14,6 +15,12 @@ class FetchDownloadsAction(BaseAction):
获取下载任务
"""
_downloads = []
def __init__(self):
super().__init__()
self.downloadchain = DownloadChain()
@property
def name(self) -> str:
return "获取下载任务"
@@ -24,7 +31,23 @@ class FetchDownloadsAction(BaseAction):
@property
def success(self) -> bool:
return True
if not self._downloads:
return True
return True if all([d.completed for d in self._downloads]) else False
async def execute(self, params: FetchDownloadsParams, context: ActionContext) -> ActionContext:
pass
"""
更新downloads中的下载任务状态
"""
self._downloads = context.downloads
for download in self._downloads:
torrents = self.downloadchain.list_torrents(hashs=[download.download_id])
if not torrents:
download.completed = True
continue
for t in torrents:
if t.progress >= 100:
download.completed = True
self.job_done()
return context

View File

@@ -3,7 +3,13 @@ from typing import Optional
from pydantic import Field
from app.actions import BaseAction
from app.schemas import ActionParams, ActionContext
from app.chain.media import MediaChain
from app.core.config import settings
from app.core.context import Context
from app.core.metainfo import MetaInfo
from app.helper.rss import RssHelper
from app.log import logger
from app.schemas import ActionParams, ActionContext, TorrentInfo
class FetchRssParams(ActionParams):
@@ -13,7 +19,9 @@ class FetchRssParams(ActionParams):
url: str = Field(None, description="RSS地址")
proxy: Optional[bool] = Field(False, description="是否使用代理")
timeout: Optional[int] = Field(15, description="超时时间")
headers: Optional[dict] = Field(None, description="请求头")
content_type: Optional[str] = Field(None, description="Content-Type")
referer: Optional[str] = Field(None, description="Referer")
ua: Optional[str] = Field(None, description="User-Agent")
recognize: Optional[bool] = Field(False, description="是否识别")
@@ -22,6 +30,13 @@ class FetchRssAction(BaseAction):
获取RSS资源列表
"""
_rss_torrents = []
def __init__(self):
super().__init__()
self.rsshelper = RssHelper()
self.mediachain = MediaChain()
@property
def name(self) -> str:
return "获取RSS资源列表"
@@ -32,7 +47,54 @@ class FetchRssAction(BaseAction):
@property
def success(self) -> bool:
return True
return True if self._rss_torrents else False
async def execute(self, params: FetchRssParams, context: ActionContext) -> ActionContext:
pass
"""
请求RSS地址获取数据并解析为资源列表
"""
if not params.url:
return context
headers = {}
if params.content_type:
headers["Content-Type"] = params.content_type
if params.referer:
headers["Referer"] = params.referer
if params.ua:
headers["User-Agent"] = params.ua
rss_items = self.rsshelper.parse(url=params.url,
proxy=settings.PROXY if params.proxy else None,
timeout=params.timeout,
headers=headers)
if not rss_items:
logger.error(f'RSS地址 {params.url} 未获取到RSS数据')
return context
# 组装种子
for item in rss_items:
if not item.get("title"):
continue
torrentinfo = TorrentInfo(
title=item.get("title"),
enclosure=item.get("enclosure"),
page_url=item.get("link"),
size=item.get("size"),
pubdate=item["pubdate"].strftime("%Y-%m-%d %H:%M:%S") if item.get("pubdate") else None,
)
meta, mediainfo = None, None
if params.recognize:
meta = MetaInfo(title=torrentinfo.title, subtitle=torrentinfo.description)
mediainfo = self.mediachain.recognize_media(meta)
if not mediainfo:
logger.warning(f"{torrentinfo.title} 未识别到媒体信息")
continue
self._rss_torrents.append(Context(meta_info=meta, media_info=mediainfo, torrent_info=torrentinfo))
if self._rss_torrents:
logger.info(f"已获取 {len(self._rss_torrents)} 个RSS资源")
context.torrents.extend(self._rss_torrents)
self.job_done()
return context

View File

@@ -1,7 +1,6 @@
from time import sleep
from typing import Dict, Any, Tuple
from app.actions import BaseAction
from app.helper.module import ModuleHelper
from app.log import logger
from app.schemas import Action, ActionContext
@@ -14,7 +13,7 @@ class WorkFlowManager(metaclass=Singleton):
"""
# 所有动作定义
_actions: Dict[str, BaseAction] = {}
_actions: Dict[str, Any] = {}
def __init__(self):
self.init()
@@ -59,14 +58,18 @@ class WorkFlowManager(metaclass=Singleton):
if not context:
context = ActionContext()
if action.id in self._actions:
action_obj = self._actions[action.id]
# 实例化
action_obj = self._actions[action.id]()
# 执行
logger.info(f"执行动作: {action.id} - {action.name}")
result_context = action_obj.execute(action.params, context)
logger.info(f"{action.name} 执行结果: {action_obj.success}")
if action.loop and action.loop_interval:
while not action_obj.done:
# 等待
logger.info(f"{action.name} 等待 {action.loop_interval} 秒后继续执行")
sleep(action.loop_interval)
# 执行
logger.info(f"继续执行动作: {action.id} - {action.name}")
result_context = action_obj.execute(action.params, result_context)
logger.info(f"{action.name} 执行结果: {action_obj.success}")

View File

@@ -239,7 +239,9 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]):
path=torrent_path,
hash=torrent.get('hash'),
size=torrent.get('total_size'),
tags=torrent.get('tags')
tags=torrent.get('tags'),
progress=torrent.get('progress') * 100,
state="paused" if torrent.get('state') in ("paused", "pausedDL") else "downloading",
))
elif status == TorrentStatus.TRANSFER:
# 获取已完成且未整理的

View File

@@ -246,7 +246,9 @@ class TransmissionModule(_ModuleBase, _DownloaderBase[Transmission]):
title=torrent.name,
path=Path(torrent.download_dir) / torrent.name,
hash=torrent.hashString,
tags=",".join(torrent.labels or [])
tags=",".join(torrent.labels or []),
progress=torrent.progress,
state="paused" if torrent.status == "stopped" else "downloading",
))
elif status == TorrentStatus.DOWNLOADING:
# 获取正在下载的任务

View File

@@ -21,6 +21,8 @@ class TransferTorrent(BaseModel):
tags: Optional[str] = None
size: Optional[int] = 0
userid: Optional[str] = None
progress: Optional[float] = 0
state: Optional[str] = None
class DownloadingTorrent(BaseModel):