From 3be445b409e1318e4e15b098ee15bdd17758816f Mon Sep 17 00:00:00 2001 From: jxxghp Date: Fri, 21 Jul 2023 07:25:29 +0800 Subject: [PATCH] =?UTF-8?q?feat=20=E4=B8=8B=E8=BD=BD=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E4=BA=8C=E7=BA=A7=E5=88=86=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 5 ++++- README.md | 8 +++----- app/chain/__init__.py | 15 ++++++++++----- app/chain/download.py | 11 +++++++++-- app/core/config.py | 2 ++ app/modules/qbittorrent/__init__.py | 5 +++-- app/modules/subtitle/__init__.py | 6 ++++-- app/modules/transmission/__init__.py | 5 +++-- 8 files changed, 38 insertions(+), 19 deletions(-) diff --git a/Dockerfile b/Dockerfile index ded1264f..97005013 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,8 +7,11 @@ ENV LANG="C.UTF-8" \ CONFIG_DIR="/config" \ API_TOKEN="moviepilot" \ AUTH_SITE="iyuu" \ - LIBRARY_PATH="" \ DOWNLOAD_PATH="/downloads" \ + DOWNLOAD_CATEGORY="false" \ + TORRENT_TAG="MOVIEPILOT" \ + LIBRARY_PATH="" \ + LIBRARY_CATEGORY="false" \ TRANSFER_TYPE="copy" \ COOKIECLOUD_HOST="https://nastool.org/cookiecloud" \ COOKIECLOUD_KEY="" \ diff --git a/README.md b/README.md index d6c3eedb..7b83084a 100644 --- a/README.md +++ b/README.md @@ -49,16 +49,17 @@ docker pull jxxghp/moviepilot:latest - **PROXY_HOST:** 网络代理(可选),访问themoviedb需要使用代理访问,格式为`http(s)://ip:port` - **TMDB_API_DOMAIN:** TMDB API地址,默认`api.themoviedb.org`,也可配置为`api.tmdb.org`或其它中转代理服务地址,能连通即可 - **DOWNLOAD_PATH:** 下载保存目录,**注意:需要将`moviepilot`及`下载器`的映射路径与宿主机`真实路径`保持一致**,例如群晖中下载路程径为`/volume1/downloads`,则需要将`moviepilot`及`下载器`的映射路径均设置为`/volume1/downloads`,否则会导致下载文件无法转移 +- **DOWNLOAD_CATEGORY:** 下载二级分类开关,`true`/`false`,默认`false`,开启后会根据配置`category.yaml`自动在下载目录下建立二级目录分类 - **TORRENT_TAG:** 种子标签,默认为`MOVIEPILOT`,设置后只有MoviePilot添加的下载才会处理,留空所有下载器中的任务均会处理 - **LIBRARY_PATH:** 媒体库目录,**注意:需要将`moviepilot`的映射路径与宿主机`真实路径`保持一致**,多个目录使用`,`分隔 -- **LIBRARY_CATEGORY:** 二级分类开关,`true`/`false`,开启后会根据配置自动在媒体库目录下建立二级目录分类 +- **LIBRARY_CATEGORY:** 媒体库二级分类开关,`true`/`false`,默认`false`,开启后会根据配置`category.yaml`自动在媒体库目录下建立二级目录分类 - **DOUBAN_USER_IDS:** 豆瓣用户ID,用于同步豆瓣标记的`想看`数据,自动添加订阅,多个用户使用,分隔 - **TRANSFER_TYPE:** 转移方式,支持`link`/`copy`/`move`/`softlink` - **COOKIECLOUD_HOST:** CookieCloud服务器地址,格式:`http://ip:port`,必须配置,否则无法添加站点 - **COOKIECLOUD_KEY:** CookieCloud用户KEY - **COOKIECLOUD_PASSWORD:** CookieCloud端对端加密密码 - **COOKIECLOUD_INTERVAL:** CookieCloud同步间隔(分钟) -- **USER_AGENT:** CookieCloud对应的浏览器UA,可选,同步站点后可以在管理界面中修改 +- **USER_AGENT:** CookieCloud对应的浏览器UA,可选,设置后可增加连接站点的成功率,同步站点后可以在管理界面中修改 **MESSAGER:** 消息通知渠道,支持 `telegram`/`wechat`/`slack`,开启多个渠道时使用`,`分隔。同时还需要配置对应渠道的环境变量,非对应渠道的变量可删除,推荐使用`telegram` @@ -188,12 +189,9 @@ docker pull jxxghp/moviepilot:latest 在`设定`-`规则`中设定,规则说明: - 仅支持使用内置规则进行排列组合,内置规则有:`蓝光原盘`、`4K`、`1080P`、`中文字幕`、`特效字幕`、`H265`、`H264`、`杜比`、`HDR`、`REMUX`、`WEB-DL`、`免费`、`国语配音` 等 -- `&`表示与,`|`表示或,`!`表示非,`>`表示优先级层级 - 符合任一层级规则的资源将被标识选中,匹配成功的层级做为该资源的优先级,排越前面优先级超高 - 不符合过滤规则所有层级规则的资源将不会被选中 -`!BLU & 4K & CNSUB > !BLU & 1080P & CNSUB > !BLU & 4K > !BLU & 1080P` 表示优先中文字幕非蓝光4K,然后中文字幕非蓝光1080P,然后非蓝光4K,最后非蓝光1080P - ## 使用 diff --git a/app/chain/__init__.py b/app/chain/__init__.py index 034d90fc..adf1e986 100644 --- a/app/chain/__init__.py +++ b/app/chain/__init__.py @@ -202,25 +202,30 @@ class ChainBase(AbstractSingleton, metaclass=Singleton): return self.run_module("filter_torrents", rule_string=rule_string, torrent_list=torrent_list, season_episodes=season_episodes) - def download(self, torrent_path: Path, cookie: str, - episodes: Set[int] = None) -> Optional[Tuple[Optional[str], str]]: + def download(self, torrent_path: Path, download_dir: Path, cookie: str, + episodes: Set[int] = None, + ) -> Optional[Tuple[Optional[str], str]]: """ 根据种子文件,选择并添加下载任务 :param torrent_path: 种子文件地址 + :param download_dir: 下载目录 :param cookie: cookie :param episodes: 需要下载的集数 :return: 种子Hash,错误信息 """ - return self.run_module("download", torrent_path=torrent_path, cookie=cookie, episodes=episodes) + return self.run_module("download", torrent_path=torrent_path, download_dir=download_dir, + cookie=cookie, episodes=episodes, ) - def download_added(self, context: Context, torrent_path: Path) -> None: + def download_added(self, context: Context, torrent_path: Path, download_dir: Path) -> None: """ 添加下载任务成功后,从站点下载字幕,保存到下载目录 :param context: 上下文,包括识别信息、媒体信息、种子信息 :param torrent_path: 种子文件地址 + :param download_dir: 下载目录 :return: None,该方法可被多个模块同时处理 """ - return self.run_module("download_added", context=context, torrent_path=torrent_path) + return self.run_module("download_added", context=context, torrent_path=torrent_path, + download_dir=download_dir) def list_torrents(self, status: TorrentStatus = None, hashs: Union[list, str] = None) -> Optional[List[Union[TransferTorrent, DownloadingTorrent]]]: diff --git a/app/chain/download.py b/app/chain/download.py index 645ceae5..83ec5133 100644 --- a/app/chain/download.py +++ b/app/chain/download.py @@ -3,6 +3,7 @@ from pathlib import Path from typing import List, Optional, Tuple, Set, Dict, Union from app.chain import ChainBase +from app.core.config import settings from app.core.context import MediaInfo, TorrentInfo, Context from app.core.meta import MetaBase from app.db.downloadhistory_oper import DownloadHistoryOper @@ -101,10 +102,16 @@ class DownloadChain(ChainBase): torrent_file, _folder_name, _ = self.download_torrent(_torrent, userid=userid) if not torrent_file: return + # 下载目录 + if settings.DOWNLOAD_CATEGORY and _media and _media.category: + download_dir = Path(settings.DOWNLOAD_PATH) / _media.category + else: + download_dir = Path(settings.DOWNLOAD_PATH) # 添加下载 result: Optional[tuple] = self.download(torrent_path=torrent_file, cookie=_torrent.site_cookie, - episodes=episodes) + episodes=episodes, + download_dir=download_dir) if result: _hash, error_msg = result else: @@ -133,7 +140,7 @@ class DownloadChain(ChainBase): self.post_download_message(meta=_meta, mediainfo=_media, torrent=_torrent, channel=channel, userid=userid) # 下载成功后处理 - self.download_added(context=context, torrent_path=torrent_file) + self.download_added(context=context, torrent_path=torrent_file, download_dir=download_dir) # 广播事件 self.eventmanager.send_event(EventType.DownloadAdded, { "hash": _hash, diff --git a/app/core/config.py b/app/core/config.py index 3b53fea5..1dd69075 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -109,6 +109,8 @@ class Settings(BaseSettings): TORRENT_TAG: str = "MOVIEPILOT" # 下载保存目录,容器内映射路径需要一致 DOWNLOAD_PATH: str = "/downloads" + # 下载目录二级分类 + DOWNLOAD_CATEGORY: bool = False # 媒体服务器 emby/jellyfin/plex MEDIASERVER: str = "emby" # EMBY服务器地址,IP:PORT diff --git a/app/modules/qbittorrent/__init__.py b/app/modules/qbittorrent/__init__.py index ea22ad5f..6a6b649b 100644 --- a/app/modules/qbittorrent/__init__.py +++ b/app/modules/qbittorrent/__init__.py @@ -24,11 +24,12 @@ class QbittorrentModule(_ModuleBase): def init_setting(self) -> Tuple[str, Union[str, bool]]: return "DOWNLOADER", "qbittorrent" - def download(self, torrent_path: Path, cookie: str, + def download(self, torrent_path: Path, download_dir: Path, cookie: str, episodes: Set[int] = None) -> Optional[Tuple[Optional[str], str]]: """ 根据种子文件,选择并添加下载任务 :param torrent_path: 种子文件地址 + :param download_dir: 下载目录 :param cookie: cookie :param episodes: 需要下载的集数 :return: 种子Hash,错误信息 @@ -45,7 +46,7 @@ class QbittorrentModule(_ModuleBase): is_paused = True if episodes else False # 添加任务 state = self.qbittorrent.add_torrent(content=torrent_path.read_bytes(), - download_dir=settings.DOWNLOAD_PATH, + download_dir=str(download_dir), is_paused=is_paused, tag=tags, cookie=cookie) diff --git a/app/modules/subtitle/__init__.py b/app/modules/subtitle/__init__.py index c934cd2c..19a4fd03 100644 --- a/app/modules/subtitle/__init__.py +++ b/app/modules/subtitle/__init__.py @@ -34,11 +34,12 @@ class SubtitleModule(_ModuleBase): def stop(self) -> None: pass - def download_added(self, context: Context, torrent_path: Path) -> None: + def download_added(self, context: Context, torrent_path: Path, download_dir: Path) -> None: """ 添加下载任务成功后,从站点下载字幕,保存到下载目录 :param context: 上下文,包括识别信息、媒体信息、种子信息 :param torrent_path: 种子文件地址 + :param download_dir: 下载目录 :return: None,该方法可被多个模块同时处理 """ # 种子信息 @@ -49,7 +50,8 @@ class SubtitleModule(_ModuleBase): logger.info("开始从站点下载字幕:%s" % torrent.page_url) # 获取种子信息 folder_name, _ = TorrentHelper.get_torrent_info(torrent_path) - download_dir = Path(settings.DOWNLOAD_PATH) / folder_name + + download_dir = download_dir / (folder_name or "") # 等待文件或者目录存在 for _ in range(10): if download_dir.exists(): diff --git a/app/modules/transmission/__init__.py b/app/modules/transmission/__init__.py index 47bbee50..e05939d9 100644 --- a/app/modules/transmission/__init__.py +++ b/app/modules/transmission/__init__.py @@ -24,11 +24,12 @@ class TransmissionModule(_ModuleBase): def init_setting(self) -> Tuple[str, Union[str, bool]]: return "DOWNLOADER", "transmission" - def download(self, torrent_path: Path, cookie: str, + def download(self, torrent_path: Path, download_dir: Path, cookie: str, episodes: Set[int] = None) -> Optional[Tuple[Optional[str], str]]: """ 根据种子文件,选择并添加下载任务 :param torrent_path: 种子文件地址 + :param download_dir: 下载目录 :param cookie: cookie :param episodes: 需要下载的集数 :return: 种子Hash @@ -42,7 +43,7 @@ class TransmissionModule(_ModuleBase): labels = None # 添加任务 torrent = self.transmission.add_torrent(content=torrent_path.read_bytes(), - download_dir=settings.DOWNLOAD_PATH, + download_dir=str(download_dir), is_paused=is_paused, labels=labels, cookie=cookie)