diff --git a/app/chain/__init__.py b/app/chain/__init__.py index 11e6b3ed..5a2bdc6f 100644 --- a/app/chain/__init__.py +++ b/app/chain/__init__.py @@ -342,7 +342,7 @@ class ChainBase(metaclass=ABCMeta): def download(self, content: Union[Path, str], download_dir: Path, cookie: str, episodes: Set[int] = None, category: str = None, downloader: str = None - ) -> Optional[Tuple[Optional[str], Optional[str], str]]: + ) -> Optional[Tuple[Optional[str], Optional[str], Optional[str], str]]: """ 根据种子文件,选择并添加下载任务 :param content: 种子文件地址或者磁力链接 @@ -351,7 +351,7 @@ class ChainBase(metaclass=ABCMeta): :param episodes: 需要下载的集数 :param category: 种子分类 :param downloader: 下载器 - :return: 下载器名称、种子Hash、错误信息 + :return: 下载器名称、种子Hash、种子文件布局、错误原因 """ return self.run_module("download", content=content, download_dir=download_dir, cookie=cookie, episodes=episodes, category=category, diff --git a/app/chain/download.py b/app/chain/download.py index 54dd8660..c3f9ac03 100644 --- a/app/chain/download.py +++ b/app/chain/download.py @@ -313,16 +313,21 @@ class DownloadChain(ChainBase): category=_media.category, downloader=downloader or _site_downloader) if result: - _downloader, _hash, error_msg = result + _downloader, _hash, _layout, error_msg = result else: - _downloader, _hash, error_msg = None, None, "未找到下载器" + _downloader, _hash, _layout, error_msg = None, None, None, "未找到下载器" if _hash: # 下载文件路径 - if _folder_name: + if _layout == "NoSubfolder" or not _folder_name: + # `不创建子文件夹` 或 `不存在子文件夹` 则记录至文件 + download_path = download_dir / _file_list[0] if _file_list else download_dir + elif _folder_name: + # 原始布局 download_path = download_dir / _folder_name else: - download_path = download_dir / _file_list[0] if _file_list else download_dir + # 创建子文件夹 + download_path = download_dir / Path(_file_list[0]).stem if _file_list else download_dir # 登记下载记录 self.downloadhis.add( @@ -362,11 +367,23 @@ class DownloadChain(ChainBase): if not Path(file).suffix \ or Path(file).suffix.lower() not in settings.RMT_MEDIAEXT: continue + + # savepath 包含子文件夹, 不含文件 + if _layout == "NoSubfolder" or not _folder_name: + # `不创建子文件夹` 或 `不存在子文件夹` 则记录至文件 + _save_path = download_dir + elif _folder_name: + # 原始布局 + _save_path = download_dir / _folder_name + else: + # 创建子文件夹 + _save_path = download_dir / Path(_file_list[0]).stem if _file_list else download_dir + files_to_add.append({ "download_hash": _hash, "downloader": _downloader, - "fullpath": str(download_dir / _folder_name / file), - "savepath": str(download_dir / _folder_name), + "fullpath": str(_save_path / file), + "savepath": str(_save_path), "filepath": file, "torrentname": _meta.org_string, }) diff --git a/app/modules/qbittorrent/__init__.py b/app/modules/qbittorrent/__init__.py index 8987eae9..2b829838 100644 --- a/app/modules/qbittorrent/__init__.py +++ b/app/modules/qbittorrent/__init__.py @@ -79,7 +79,7 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]): def download(self, content: Union[Path, str], download_dir: Path, cookie: str, episodes: Set[int] = None, category: str = None, - downloader: str = None) -> Optional[Tuple[Optional[str], Optional[str], str]]: + downloader: str = None) -> Optional[Tuple[Optional[str], Optional[str], Optional[str], str]]: """ 根据种子文件,选择并添加下载任务 :param content: 种子文件地址或者磁力链接 @@ -88,7 +88,7 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]): :param episodes: 需要下载的集数 :param category: 分类 :param downloader: 下载器 - :return: 种子Hash,错误信息 + :return: 下载器名称、种子Hash、种子文件布局、错误原因 """ def __get_torrent_info() -> Tuple[str, int]: @@ -106,10 +106,10 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]): return "", 0 if not content: - return None, None, "下载内容为空" + return None, None, None, "下载内容为空" if isinstance(content, Path) and not content.exists(): logger.error(f"种子文件不存在:{content}") - return None, None, f"种子文件不存在:{content}" + return None, None, None, f"种子文件不存在:{content}" # 获取下载器 server: Qbittorrent = self.get_instance(downloader) @@ -134,15 +134,20 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]): category=category, ignore_category_check=False ) + # 获取下载器全局设置 + application = server.qbc.application.preferences + # 获取种子内容布局: `Original: 原始, Subfolder: 创建子文件夹, NoSubfolder: 不创建子文件夹` + torrent_layout = application.get("torrent_content_layout", "Original") + if not state: # 读取种子的名称 torrent_name, torrent_size = __get_torrent_info() if not torrent_name: - return None, None, f"添加种子任务失败:无法读取种子文件" + return None, None, None, f"添加种子任务失败:无法读取种子文件" # 查询所有下载器的种子 torrents, error = server.get_torrents() if error: - return None, None, "无法连接qbittorrent下载器" + return None, None, None, "无法连接qbittorrent下载器" if torrents: for torrent in torrents: # 名称与大小相等则认为是同一个种子 @@ -156,19 +161,19 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]): if settings.TORRENT_TAG and settings.TORRENT_TAG not in torrent_tags: logger.info(f"给种子 {torrent_hash} 打上标签:{settings.TORRENT_TAG}") server.set_torrents_tag(ids=torrent_hash, tags=[settings.TORRENT_TAG]) - return downloader or self.get_default_config_name(), torrent_hash, f"下载任务已存在" - return None, None, f"添加种子任务失败:{content}" + return downloader or self.get_default_config_name(), torrent_hash, torrent_layout, f"下载任务已存在" + return None, None, None, f"添加种子任务失败:{content}" else: # 获取种子Hash torrent_hash = server.get_torrent_id_by_tag(tags=tag) if not torrent_hash: - return None, None, f"下载任务添加成功,但获取Qbittorrent任务信息失败:{content}" + return None, None, None, f"下载任务添加成功,但获取Qbittorrent任务信息失败:{content}" else: if is_paused: # 种子文件 torrent_files = server.get_files(torrent_hash) if not torrent_files: - return downloader or self.get_default_config_name(), torrent_hash, "获取种子文件失败,下载任务可能在暂停状态" + return downloader or self.get_default_config_name(), torrent_hash, torrent_layout, "获取种子文件失败,下载任务可能在暂停状态" # 不需要的文件ID file_ids = [] @@ -193,11 +198,11 @@ class QbittorrentModule(_ModuleBase, _DownloaderBase[Qbittorrent]): server.torrents_set_force_start(torrent_hash) else: server.start_torrents(torrent_hash) - return downloader or self.get_default_config_name(), torrent_hash, f"添加下载成功,已选择集数:{sucess_epidised}" + return downloader or self.get_default_config_name(), torrent_hash, torrent_layout, f"添加下载成功,已选择集数:{sucess_epidised}" else: if server.is_force_resume(): server.torrents_set_force_start(torrent_hash) - return downloader or self.get_default_config_name(), torrent_hash, "添加下载成功" + return downloader or self.get_default_config_name(), torrent_hash, torrent_layout, "添加下载成功" def list_torrents(self, status: TorrentStatus = None, hashs: Union[list, str] = None, diff --git a/app/modules/transmission/__init__.py b/app/modules/transmission/__init__.py index 71734a7b..eb6b967d 100644 --- a/app/modules/transmission/__init__.py +++ b/app/modules/transmission/__init__.py @@ -80,7 +80,7 @@ class TransmissionModule(_ModuleBase, _DownloaderBase[Transmission]): def download(self, content: Union[Path, str], download_dir: Path, cookie: str, episodes: Set[int] = None, category: str = None, - downloader: str = None) -> Optional[Tuple[Optional[str], Optional[str], str]]: + downloader: str = None) -> Optional[Tuple[Optional[str], Optional[str], Optional[str], str]]: """ 根据种子文件,选择并添加下载任务 :param content: 种子文件地址或者磁力链接 @@ -89,7 +89,7 @@ class TransmissionModule(_ModuleBase, _DownloaderBase[Transmission]): :param episodes: 需要下载的集数 :param category: 分类,TR中未使用 :param downloader: 下载器 - :return: 下载器名称、种子Hash、错误原因 + :return: 下载器名称、种子Hash、种子文件布局、错误原因 """ def __get_torrent_info() -> Tuple[str, int]: @@ -107,9 +107,9 @@ class TransmissionModule(_ModuleBase, _DownloaderBase[Transmission]): return "", 0 if not content: - return None, None, "下载内容为空" + return None, None, None, "下载内容为空" if isinstance(content, Path) and not content.exists(): - return None, None, f"种子文件不存在:{content}" + return None, None, None, f"种子文件不存在:{content}" # 获取下载器 server: Transmission = self.get_instance(downloader) @@ -131,15 +131,18 @@ class TransmissionModule(_ModuleBase, _DownloaderBase[Transmission]): labels=labels, cookie=cookie ) + # TR 始终使用原始种子布局, 返回"Original" + torrent_layout = "Original" + if not torrent: # 读取种子的名称 torrent_name, torrent_size = __get_torrent_info() if not torrent_name: - return None, None, f"添加种子任务失败:无法读取种子文件" + return None, None, None, f"添加种子任务失败:无法读取种子文件" # 查询所有下载器的种子 torrents, error = server.get_torrents() if error: - return None, None, "无法连接transmission下载器" + return None, None, None, "无法连接transmission下载器" if torrents: for torrent in torrents: # 名称与大小相等则认为是同一个种子 @@ -158,15 +161,15 @@ class TransmissionModule(_ModuleBase, _DownloaderBase[Transmission]): if settings.TORRENT_TAG and settings.TORRENT_TAG not in labels: labels.append(settings.TORRENT_TAG) server.set_torrent_tag(ids=torrent_hash, tags=labels) - return downloader or self.get_default_config_name(), torrent_hash, f"下载任务已存在" - return None, None, f"添加种子任务失败:{content}" + return downloader or self.get_default_config_name(), torrent_hash, torrent_layout, f"下载任务已存在" + return None, None, None, f"添加种子任务失败:{content}" else: torrent_hash = torrent.hashString if is_paused: # 选择文件 torrent_files = server.get_files(torrent_hash) if not torrent_files: - return downloader or self.get_default_config_name(), torrent_hash, "获取种子文件失败,下载任务可能在暂停状态" + return downloader or self.get_default_config_name(), torrent_hash, torrent_layout, "获取种子文件失败,下载任务可能在暂停状态" # 需要的文件信息 file_ids = [] unwanted_file_ids = [] @@ -187,9 +190,9 @@ class TransmissionModule(_ModuleBase, _DownloaderBase[Transmission]): server.set_unwanted_files(torrent_hash, unwanted_file_ids) # 开始任务 server.start_torrents(torrent_hash) - return downloader or self.get_default_config_name(), torrent_hash, "添加下载任务成功" + return downloader or self.get_default_config_name(), torrent_hash, torrent_layout, "添加下载任务成功" else: - return downloader or self.get_default_config_name(), torrent_hash, "添加下载任务成功" + return downloader or self.get_default_config_name(), torrent_hash, torrent_layout, "添加下载任务成功" def list_torrents(self, status: TorrentStatus = None, hashs: Union[list, str] = None,