From 0a7ee202b4e8d063d22ff563eecc821735e8eda4 Mon Sep 17 00:00:00 2001 From: Xu <692360102@qq.com> Date: Wed, 13 Nov 2024 09:22:40 +0800 Subject: [PATCH 01/11] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=A7=8D=E5=AD=90?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E5=85=BC=E5=AE=B9v2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 - package.v2.json | 14 ++ plugins.v2/downloadtorrent/__init__.py | 314 +++++++++++++++++++++++++ 3 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 plugins.v2/downloadtorrent/__init__.py diff --git a/package.json b/package.json index 93c2bc9..c4876ba 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,6 @@ "icon": "download.png", "author": "thsrite", "level": 1, - "v2": true, "history": { "v1.1": "支持选择MoviePilot配置的下载路径", "v1.0": "删除下载器中该站点辅种,保留该站点没有辅种的种子" diff --git a/package.v2.json b/package.v2.json index 4c5a62e..e6818bb 100644 --- a/package.v2.json +++ b/package.v2.json @@ -425,5 +425,19 @@ "history": { "v1.0": "重写Strm文件内容" } + }, + "DownloadTorrent": { + "name": "添加种子下载", + "description": "选择下载器,添加种子任务。", + "labels": "站点", + "version": "2.0", + "icon": "download.png", + "author": "thsrite", + "level": 1, + "history": { + "v2.0": "兼容V2版本", + "v1.1": "支持选择MoviePilot配置的下载路径", + "v1.0": "删除下载器中该站点辅种,保留该站点没有辅种的种子" + } } } diff --git a/plugins.v2/downloadtorrent/__init__.py b/plugins.v2/downloadtorrent/__init__.py new file mode 100644 index 0000000..c42042f --- /dev/null +++ b/plugins.v2/downloadtorrent/__init__.py @@ -0,0 +1,314 @@ +from typing import Any, List, Dict, Tuple, Optional +from app.db.site_oper import SiteOper +from app.plugins import _PluginBase +from app.log import logger +from app.utils.string import StringUtils +from app.schemas import ServiceInfo +from app.helper.downloader import DownloaderHelper +from app.helper.directory import DirectoryHelper + + + +class DownloadTorrent(_PluginBase): + # 插件名称 + plugin_name = "添加种子下载" + # 插件描述 + plugin_desc = "选择下载器,添加种子任务。" + # 插件图标 + plugin_icon = "download.png" + # 插件版本 + plugin_version = "2.0" + # 插件作者 + plugin_author = "thsrite" + # 作者主页 + author_url = "https://github.com/thsrite" + # 插件配置项ID前缀 + plugin_config_prefix = "downloadtorrent_" + # 加载顺序 + plugin_order = 28 + # 可使用的用户级别 + auth_level = 1 + + # 私有属性 + _is_paused = False + _save_path = None + _mp_path = None + _downloader = None + site = None + torrent_helper = None + downloader_helper = None + directory_helper = None + + def init_plugin(self, config: dict = None): + self.downloader_helper = DownloaderHelper() + self.directory_helper = DirectoryHelper() + self.site = SiteOper() + + if config: + self._is_paused = config.get("is_paused") + self._save_path = config.get("save_path") + self._mp_path = config.get("mp_path") + self._torrent_urls = config.get("torrent_urls") + self._downloader = config.get("downloader") + + # 下载种子 + if self._torrent_urls: + for torrent_url in str(self._torrent_urls).split("\n"): + # 获取种子对应站点cookie + domain = StringUtils.get_url_domain(torrent_url) + if not domain: + logger.error(f"种子 {torrent_url} 获取站点域名失败,跳过处理") + continue + + # 查询站点 + site = self.site.get_by_domain(domain) + if not site or not site.cookie: + logger.error(f"种子 {torrent_url} 获取站点cookie失败,跳过处理") + continue + + service = self.service_info(self._downloader) + download_id = self.__download(service=service, + content=torrent_url, + save_path=self._save_path or self._mp_path, + cookie=site.cookie) + + if download_id: + logger.info(f"种子添加下载成功 {torrent_url} 保存位置 {self._save_path or self._mp_path}") + else: + logger.error(f"种子添加下载失败 {torrent_url} 保存位置 {self._save_path or self._mp_path}") + + self.update_config({ + "downloader": self._downloader, + "save_path": self._save_path, + "mp_path": self._mp_path, + "is_paused": self._is_paused + }) + + def service_info(self, name: str) -> Optional[ServiceInfo]: + """ + 服务信息 + """ + if not name: + logger.warning("尚未配置下载器,请检查配置") + return None + + service = self.downloader_helper.get_service(name) + if not service or not service.instance: + logger.warning(f"获取下载器 {name} 实例失败,请检查配置") + return None + + if service.instance.is_inactive(): + logger.warning(f"下载器 {name} 未连接,请检查配置") + return None + return service + + def __download(self, service: ServiceInfo, content: bytes, + save_path: str, cookie: str) -> Optional[str]: + """ + 添加下载任务 + """ + if not service or not service.instance: + return + downloader = service.instance + if self.downloader_helper.is_downloader("qbittorrent", service=service): + torrent = downloader.add_torrent(content=content, + download_dir=save_path, + is_paused=self._is_paused, + cookie=cookie) + if not torrent: + return None + else: + return torrent + elif self.downloader_helper.is_downloader("transmission", service=service): + # 添加任务 + torrent = downloader.add_torrent(content=content, + download_dir=save_path, + is_paused=self._is_paused, + cookie=cookie) + if not torrent: + return None + else: + return torrent.hashString + + logger.error(f"不支持的下载器类型") + return None + + + def get_state(self) -> bool: + return False + + @staticmethod + def get_command() -> List[Dict[str, Any]]: + pass + + def get_api(self) -> List[Dict[str, Any]]: + pass + + def get_form(self) -> Tuple[List[dict], Dict[str, Any]]: + """ + 拼装插件配置页面,需要返回两块数据:1、页面配置;2、数据结构 + """ + dir_conf = [{'title': d.name, 'value': d.download_path} for d in self.directory_helper.get_local_download_dirs()] + downloader_options = [{"title": config.name, "value": config.name} for config in self.downloader_helper.get_configs().values()] + return [ + { + 'component': 'VForm', + 'content': [ + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 3 + }, + 'content': [ + { + 'component': 'VSelect', + 'props': { + 'model': 'downloader', + 'label': '下载器', + 'items': downloader_options + } + } + ] + }, + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 3 + }, + 'content': [ + { + 'component': 'VSelect', + 'props': { + 'model': 'is_paused', + 'label': '暂停种子', + 'items': [ + {'title': '开启', 'value': True}, + {'title': '不开启', 'value': False} + ] + } + } + ] + }, + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 3 + }, + 'content': [ + { + 'component': 'VSelect', + 'props': { + 'model': 'mp_path', + 'label': 'MoviePilot保存路径', + 'items': dir_conf + } + } + ] + }, + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 3 + }, + 'content': [ + { + 'component': 'VTextField', + 'props': { + 'model': 'save_path', + 'label': '自定义保存路径' + } + } + ] + }, + ] + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12, + }, + 'content': [ + { + 'component': 'VTextarea', + 'props': { + 'model': 'torrent_urls', + 'rows': '3', + 'label': '种子链接', + 'placeholder': '种子链接,一行一个' + } + } + ] + } + ] + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12, + }, + 'content': [ + { + 'component': 'VAlert', + 'props': { + 'type': 'info', + 'variant': 'tonal', + 'text': '自定义保存路径优先级高于MoviePilot保存路径。' + } + } + ] + } + ] + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12, + }, + 'content': [ + { + 'component': 'VAlert', + 'props': { + 'type': 'info', + 'variant': 'tonal', + 'text': '保存路径为下载器保存路径,种子链接一行一个。' + '添加的种子链接需站点已在站点管理维护或公共站点。' + } + } + ] + } + ] + } + ] + } + ], { + "downloader": "qb", + "is_paused": False, + "save_path": "", + "mp_path": "", + "torrent_urls": "" + } + + def get_page(self) -> List[dict]: + pass + + def stop_service(self): + """ + 退出插件 + """ + pass \ No newline at end of file From a8bb889ae04dd6c4792cbbfda149d91fabf37b1e Mon Sep 17 00:00:00 2001 From: thsrite Date: Wed, 13 Nov 2024 15:59:23 +0800 Subject: [PATCH 02/11] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E4=B8=8B=E8=BD=BD=E5=99=A8=E7=A7=8D=E5=AD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.v2.json | 3 ++- plugins.v2/syncdownloadfiles/__init__.py | 18 +++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/package.v2.json b/package.v2.json index 5174025..8de7189 100644 --- a/package.v2.json +++ b/package.v2.json @@ -193,11 +193,12 @@ "name": "下载器文件同步", "description": "同步下载器的文件信息到数据库,删除文件时联动删除下载任务。", "labels": "下载管理", - "version": "1.1.3", + "version": "1.1.4", "icon": "Youtube-dl_A.png", "author": "thsrite", "level": 1, "history": { + "v1.1.4": "修复同步下载器种子", "v1.1.3": "支持v2", "v1.1.1": "修复时区问题导致的上次同步后8h内的种子不同步的问题" } diff --git a/plugins.v2/syncdownloadfiles/__init__.py b/plugins.v2/syncdownloadfiles/__init__.py index 04959f9..30fe04c 100644 --- a/plugins.v2/syncdownloadfiles/__init__.py +++ b/plugins.v2/syncdownloadfiles/__init__.py @@ -22,7 +22,7 @@ class SyncDownloadFiles(_PluginBase): # 插件图标 plugin_icon = "Youtube-dl_A.png" # 插件版本 - plugin_version = "1.1.3" + plugin_version = "1.1.4" # 插件作者 plugin_author = "thsrite" # 作者主页 @@ -224,7 +224,7 @@ class SyncDownloadFiles(_PluginBase): grouped_data = {} # 排序种子,根据种子添加时间倒序 - if dl_tpe == "qbittorrent": + if dl_tpe == "Qbittorrent": torrents = sorted(torrents, key=lambda x: x.get("added_on"), reverse=True) # 遍历原始数组,按照size和name进行分组 for torrent in torrents: @@ -262,7 +262,7 @@ class SyncDownloadFiles(_PluginBase): def __compare_time(torrent: Any, dl_tpe: str, last_sync_time: str = None): if last_sync_time: # 获取种子时间 - if dl_tpe == "qbittorrent": + if dl_tpe == "Qbittorrent": torrent_date = time.localtime(torrent.get("added_on")) # 将时间戳转换为时间元组 torrent_date = time.strftime("%Y-%m-%d %H:%M:%S", torrent_date) # 格式化时间 else: @@ -280,7 +280,7 @@ class SyncDownloadFiles(_PluginBase): 判断文件是否被下载 """ try: - if dl_type == "qbittorrent": + if dl_type == "Qbittorrent": return True else: return file.completed and file.completed > 0 @@ -294,7 +294,7 @@ class SyncDownloadFiles(_PluginBase): 获取文件路径 """ try: - return file.get("name") if dl_type == "qbittorrent" else file.name + return file.get("name") if dl_type == "Qbittorrent" else file.name except Exception as e: print(str(e)) return "" @@ -305,7 +305,7 @@ class SyncDownloadFiles(_PluginBase): 获取种子文件 """ try: - return torrent.files if dl_type == "qbittorrent" else downloader_obj.get_files(tid=torrent.id) + return torrent.files if dl_type == "Qbittorrent" else downloader_obj.get_files(tid=torrent.id) except Exception as e: print(str(e)) return "" @@ -316,7 +316,7 @@ class SyncDownloadFiles(_PluginBase): 获取种子name """ try: - return torrent.get("name") if dl_type == "qbittorrent" else torrent.name + return torrent.get("name") if dl_type == "Qbittorrent" else torrent.name except Exception as e: print(str(e)) return "" @@ -327,7 +327,7 @@ class SyncDownloadFiles(_PluginBase): 获取种子download_dir """ try: - return torrent.get("save_path") if dl_type == "qbittorrent" else torrent.download_dir + return torrent.get("save_path") if dl_type == "Qbittorrent" else torrent.download_dir except Exception as e: print(str(e)) return "" @@ -338,7 +338,7 @@ class SyncDownloadFiles(_PluginBase): 获取种子hash """ try: - return torrent.get("hash") if dl_type == "qbittorrent" else torrent.hashString + return torrent.get("hash") if dl_type == "Qbittorrent" else torrent.hashString except Exception as e: print(str(e)) return "" From 3b1957e6da834631fda3d7410f1918fee3dfbb9c Mon Sep 17 00:00:00 2001 From: thsrite Date: Thu, 14 Nov 2024 10:44:14 +0800 Subject: [PATCH 03/11] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E4=B8=8B=E8=BD=BD=E5=99=A8=E7=A7=8D=E5=AD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.v2.json | 2 +- plugins.v2/syncdownloadfiles/__init__.py | 35 ++++++++++++------------ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/package.v2.json b/package.v2.json index 42def63..bfb669f 100644 --- a/package.v2.json +++ b/package.v2.json @@ -198,7 +198,7 @@ "author": "thsrite", "level": 1, "history": { - "v1.1.4": "修复同步下载器种子", + "v1.1.5": "修复同步下载器种子", "v1.1.3": "支持v2", "v1.1.1": "修复时区问题导致的上次同步后8h内的种子不同步的问题" } diff --git a/plugins.v2/syncdownloadfiles/__init__.py b/plugins.v2/syncdownloadfiles/__init__.py index 30fe04c..800120f 100644 --- a/plugins.v2/syncdownloadfiles/__init__.py +++ b/plugins.v2/syncdownloadfiles/__init__.py @@ -22,7 +22,7 @@ class SyncDownloadFiles(_PluginBase): # 插件图标 plugin_icon = "Youtube-dl_A.png" # 插件版本 - plugin_version = "1.1.4" + plugin_version = "1.1.5" # 插件作者 plugin_author = "thsrite" # 作者主页 @@ -113,19 +113,20 @@ class SyncDownloadFiles(_PluginBase): continue # 把种子按照名称和种子大小分组,获取添加时间最早的一个,认定为是源种子,其余为辅种 - torrents = self.__get_origin_torrents(torrents, downloader) + downloader_config = self.__get_downloader_config(downloader) + torrents = self.__get_origin_torrents(torrents, downloader_config.type) logger.info(f"下载器 {downloader} 去除辅种,获取到源种子数:{len(torrents)}") for torrent in torrents: # 返回false,标识后续种子已被同步 - sync_flag = self.__compare_time(torrent, downloader, last_sync_time) + sync_flag = self.__compare_time(torrent, downloader_config.type, last_sync_time) if not sync_flag: logger.info(f"最后同步时间{last_sync_time}, 之前种子已被同步,结束当前下载器 {downloader} 任务") break # 获取种子hash - hash_str = self.__get_hash(torrent, downloader) + hash_str = self.__get_hash(torrent, downloader_config.type) # 判断是否是mp下载,判断download_hash是否在downloadhistory表中,是则不处理 downloadhis = self.downloadhis.get_by_hash(hash_str) @@ -136,7 +137,7 @@ class SyncDownloadFiles(_PluginBase): continue # 获取种子download_dir - download_dir = self.__get_download_dir(torrent, downloader) + download_dir = self.__get_download_dir(torrent, downloader_config.type) # 处理路径映射 if self._dirs: @@ -146,20 +147,20 @@ class SyncDownloadFiles(_PluginBase): download_dir = download_dir.replace(sub_paths[0], sub_paths[1]).replace('\\', '/') # 获取种子name - torrent_name = self.__get_torrent_name(torrent, downloader) + torrent_name = self.__get_torrent_name(torrent, downloader_config.type) # 种子保存目录 save_path = Path(download_dir).joinpath(torrent_name) # 获取种子文件 - torrent_files = self.__get_torrent_files(torrent, downloader, downloader_obj) + torrent_files = self.__get_torrent_files(torrent, downloader_config.type, downloader_obj) logger.info(f"开始同步种子 {hash_str}, 文件数 {len(torrent_files)}") download_files = [] for file in torrent_files: # 过滤掉没下载的文件 - if not self.__is_download(file, downloader): + if not self.__is_download(file, downloader_config.type): continue # 种子文件路径 - file_path_str = self.__get_file_path(file, downloader) + file_path_str = self.__get_file_path(file, downloader_config.type) file_path = Path(file_path_str) # 只处理视频格式 if not file_path.suffix \ @@ -224,7 +225,7 @@ class SyncDownloadFiles(_PluginBase): grouped_data = {} # 排序种子,根据种子添加时间倒序 - if dl_tpe == "Qbittorrent": + if dl_tpe == "qbittorrent": torrents = sorted(torrents, key=lambda x: x.get("added_on"), reverse=True) # 遍历原始数组,按照size和name进行分组 for torrent in torrents: @@ -262,7 +263,7 @@ class SyncDownloadFiles(_PluginBase): def __compare_time(torrent: Any, dl_tpe: str, last_sync_time: str = None): if last_sync_time: # 获取种子时间 - if dl_tpe == "Qbittorrent": + if dl_tpe == "qbittorrent": torrent_date = time.localtime(torrent.get("added_on")) # 将时间戳转换为时间元组 torrent_date = time.strftime("%Y-%m-%d %H:%M:%S", torrent_date) # 格式化时间 else: @@ -280,7 +281,7 @@ class SyncDownloadFiles(_PluginBase): 判断文件是否被下载 """ try: - if dl_type == "Qbittorrent": + if dl_type == "qbittorrent": return True else: return file.completed and file.completed > 0 @@ -294,7 +295,7 @@ class SyncDownloadFiles(_PluginBase): 获取文件路径 """ try: - return file.get("name") if dl_type == "Qbittorrent" else file.name + return file.get("name") if dl_type == "qbittorrent" else file.name except Exception as e: print(str(e)) return "" @@ -305,7 +306,7 @@ class SyncDownloadFiles(_PluginBase): 获取种子文件 """ try: - return torrent.files if dl_type == "Qbittorrent" else downloader_obj.get_files(tid=torrent.id) + return torrent.files if dl_type == "qbittorrent" else downloader_obj.get_files(tid=torrent.id) except Exception as e: print(str(e)) return "" @@ -316,7 +317,7 @@ class SyncDownloadFiles(_PluginBase): 获取种子name """ try: - return torrent.get("name") if dl_type == "Qbittorrent" else torrent.name + return torrent.get("name") if dl_type == "qbittorrent" else torrent.name except Exception as e: print(str(e)) return "" @@ -327,7 +328,7 @@ class SyncDownloadFiles(_PluginBase): 获取种子download_dir """ try: - return torrent.get("save_path") if dl_type == "Qbittorrent" else torrent.download_dir + return torrent.get("save_path") if dl_type == "qbittorrent" else torrent.download_dir except Exception as e: print(str(e)) return "" @@ -338,7 +339,7 @@ class SyncDownloadFiles(_PluginBase): 获取种子hash """ try: - return torrent.get("hash") if dl_type == "Qbittorrent" else torrent.hashString + return torrent.get("hash") if dl_type == "qbittorrent" else torrent.hashString except Exception as e: print(str(e)) return "" From 518d234be19f88820790bbc77cf5970829696221 Mon Sep 17 00:00:00 2001 From: thsrite Date: Thu, 14 Nov 2024 13:37:56 +0800 Subject: [PATCH 04/11] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=E5=A4=8D?= =?UTF-8?q?=E5=88=B6=E9=9D=9E=E5=AA=92=E4=BD=93=E6=96=87=E4=BB=B6=E9=80=89?= =?UTF-8?q?=E9=A1=B9=E6=97=B6=E7=88=B6=E7=9B=AE=E5=BD=95=E4=B8=8D=E5=AD=98?= =?UTF-8?q?=E5=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.v2.json | 3 ++- plugins.v2/cloudstrmcompanion/__init__.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/package.v2.json b/package.v2.json index bfb669f..100a6e3 100644 --- a/package.v2.json +++ b/package.v2.json @@ -401,11 +401,12 @@ "name": "云盘Strm助手", "description": "实时监控、定时全量增量生成strm文件。", "labels": "云盘", - "version": "1.0.6", + "version": "1.0.7", "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/cloudcompanion.png", "author": "thsrite", "level": 1, "history": { + "v1.0.7": "修复复制非媒体文件选项时父目录不存在", "v1.0.6": "支持[目录实时监控]插件联动", "v1.0.5": "增加复制非媒体文件选项", "v1.0.4": "修复实时监控,只处理指定类型的文件", diff --git a/plugins.v2/cloudstrmcompanion/__init__.py b/plugins.v2/cloudstrmcompanion/__init__.py index 5617d5d..8485655 100644 --- a/plugins.v2/cloudstrmcompanion/__init__.py +++ b/plugins.v2/cloudstrmcompanion/__init__.py @@ -58,7 +58,7 @@ class CloudStrmCompanion(_PluginBase): # 插件图标 plugin_icon = "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/cloudcompanion.png" # 插件版本 - plugin_version = "1.0.6" + plugin_version = "1.0.7" # 插件作者 plugin_author = "thsrite" # 作者主页 @@ -396,6 +396,8 @@ class CloudStrmCompanion(_PluginBase): strm_content=strm_content) else: if self._copy_files: + # 确保目标文件的父目录存在 + os.makedirs(os.path.dirname(target_file), exist_ok=True) # 其他nfo、jpg等复制文件 shutil.copy2(str(event_path), target_file) logger.info(f"复制其他文件 {str(event_path)} 到 {target_file}") From 65355880f8593fcd3ecf602e984497a17568cc28 Mon Sep 17 00:00:00 2001 From: thsrite Date: Fri, 15 Nov 2024 09:18:51 +0800 Subject: [PATCH 05/11] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=E9=87=8D?= =?UTF-8?q?=E5=BB=BA=E7=BC=93=E5=AD=98=E4=B8=8D=E7=94=9F=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.v2.json | 5 +++-- plugins.v2/cloudstrmcompanion/__init__.py | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/package.v2.json b/package.v2.json index 100a6e3..8bca34f 100644 --- a/package.v2.json +++ b/package.v2.json @@ -401,12 +401,13 @@ "name": "云盘Strm助手", "description": "实时监控、定时全量增量生成strm文件。", "labels": "云盘", - "version": "1.0.7", + "version": "1.0.8", "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/cloudcompanion.png", "author": "thsrite", "level": 1, "history": { - "v1.0.7": "修复复制非媒体文件选项时父目录不存在", + "v1.0.8": "修复重建缓存不生效", + "v1.0.7": "修复复制非媒体文件时父目录不存在", "v1.0.6": "支持[目录实时监控]插件联动", "v1.0.5": "增加复制非媒体文件选项", "v1.0.4": "修复实时监控,只处理指定类型的文件", diff --git a/plugins.v2/cloudstrmcompanion/__init__.py b/plugins.v2/cloudstrmcompanion/__init__.py index 8485655..35b72a2 100644 --- a/plugins.v2/cloudstrmcompanion/__init__.py +++ b/plugins.v2/cloudstrmcompanion/__init__.py @@ -58,7 +58,7 @@ class CloudStrmCompanion(_PluginBase): # 插件图标 plugin_icon = "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/cloudcompanion.png" # 插件版本 - plugin_version = "1.0.7" + plugin_version = "1.0.8" # 插件作者 plugin_author = "thsrite" # 作者主页 @@ -131,6 +131,9 @@ class CloudStrmCompanion(_PluginBase): logger.info("开始清理旧数据索引") self._rebuild = False self._cloud_files = [] + if Path(self._cloud_files_json).exists(): + Path(self._cloud_files_json).unlink() + logger.info("旧数据索引清理完成") self.__update_config() # 停止现有任务 From f10025728b9553aa9079cbc962cd2a602a927cdb Mon Sep 17 00:00:00 2001 From: thsrite Date: Fri, 15 Nov 2024 10:39:27 +0800 Subject: [PATCH 06/11] =?UTF-8?q?fix=20=E7=9B=AE=E5=BD=95=E6=A0=91?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=A4=9A=E7=BA=A7=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.v2.json | 3 ++- plugins.v2/cloudstrmcompanion/__init__.py | 20 +++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/package.v2.json b/package.v2.json index 8bca34f..d3e15d1 100644 --- a/package.v2.json +++ b/package.v2.json @@ -401,11 +401,12 @@ "name": "云盘Strm助手", "description": "实时监控、定时全量增量生成strm文件。", "labels": "云盘", - "version": "1.0.8", + "version": "1.0.9", "icon": "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/cloudcompanion.png", "author": "thsrite", "level": 1, "history": { + "v1.0.9": "目录树支持多级结构", "v1.0.8": "修复重建缓存不生效", "v1.0.7": "修复复制非媒体文件时父目录不存在", "v1.0.6": "支持[目录实时监控]插件联动", diff --git a/plugins.v2/cloudstrmcompanion/__init__.py b/plugins.v2/cloudstrmcompanion/__init__.py index 35b72a2..eaa3483 100644 --- a/plugins.v2/cloudstrmcompanion/__init__.py +++ b/plugins.v2/cloudstrmcompanion/__init__.py @@ -58,7 +58,7 @@ class CloudStrmCompanion(_PluginBase): # 插件图标 plugin_icon = "https://raw.githubusercontent.com/thsrite/MoviePilot-Plugins/main/icons/cloudcompanion.png" # 插件版本 - plugin_version = "1.0.8" + plugin_version = "1.0.9" # 插件作者 plugin_author = "thsrite" # 作者主页 @@ -308,9 +308,9 @@ class CloudStrmCompanion(_PluginBase): if not tree_content: continue # 遍历云盘树形结构文件 - for cloud_file in self.parse_tree_structure(tree_content): + for cloud_file in self.parse_tree_structure(content=tree_content, dir_path=cloud_dir): try: - if Path(cloud_file).is_dir(): + if Path(str(cloud_file)).is_dir(): continue # 本地挂载路径 local_file = str(cloud_file).replace(cloud_dir, local_dir) @@ -544,24 +544,26 @@ class CloudStrmCompanion(_PluginBase): return None @staticmethod - def parse_tree_structure(content: str): + def parse_tree_structure(content: str, dir_path: str): """ 解析目录树内容并生成每个路径 """ tree_pattern = re_compile(r"^(?:\| )+\|-") - current_path = ["/"] # 初始化当前路径为根目录 + dir_path = Path(dir_path) + current_path = [str(dir_path.parent)] if dir_path.parent != Path("/") or (dir_path.parent == dir_path and ( + dir_path.is_absolute() or ':' in dir_path.name)) else ["/"] # 初始化当前路径为根目录 for line in content.splitlines(): # 匹配目录树的每一行 match = tree_pattern.match(line) - if not match or "根目录" in line: + if not match: continue # 跳过不符合格式的行 # 计算当前行的深度 level_indicator = match.group(0) depth = (len(level_indicator) // 2) - 1 - # 获取当前行的目录名称 - item_name = escape(line.strip()[len(level_indicator):]) + # 获取当前行的目录名称,去掉前面的 '| ' 或 '- ' + item_name = escape(line.strip()[len(level_indicator):].strip()) # 根据深度更新当前路径 if depth < len(current_path): @@ -570,7 +572,7 @@ class CloudStrmCompanion(_PluginBase): current_path.append(item_name) # 添加新的深度名称 # 生成并返回当前深度的完整路径 - yield join_path(*current_path[:depth + 1]) + yield join_path(*current_path[:depth + 1]).replace('\\', '/') @eventmanager.register(EventType.PluginAction) def remote_sync_one(self, event: Event = None): From eba8c3a6a51647302d0e413cbdda5b46604fc468 Mon Sep 17 00:00:00 2001 From: thsrite Date: Fri, 15 Nov 2024 12:41:34 +0800 Subject: [PATCH 07/11] =?UTF-8?q?fix=20=E4=B8=8B=E8=BD=BD=E5=99=A8?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=90=8C=E6=AD=A5=E6=B7=BB=E5=8A=A0=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E9=BB=98=E8=AE=A4=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.v2.json | 3 ++- plugins.v2/mediasyncdel/__init__.py | 1 - plugins.v2/syncdownloadfiles/__init__.py | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/package.v2.json b/package.v2.json index d3e15d1..1fbbead 100644 --- a/package.v2.json +++ b/package.v2.json @@ -193,11 +193,12 @@ "name": "下载器文件同步", "description": "同步下载器的文件信息到数据库,删除文件时联动删除下载任务。", "labels": "下载管理", - "version": "1.1.4", + "version": "1.1.6", "icon": "Youtube-dl_A.png", "author": "thsrite", "level": 1, "history": { + "v1.1.6": "添加记录默认状态", "v1.1.5": "修复同步下载器种子", "v1.1.3": "支持v2", "v1.1.1": "修复时区问题导致的上次同步后8h内的种子不同步的问题" diff --git a/plugins.v2/mediasyncdel/__init__.py b/plugins.v2/mediasyncdel/__init__.py index aec45e2..321e686 100644 --- a/plugins.v2/mediasyncdel/__init__.py +++ b/plugins.v2/mediasyncdel/__init__.py @@ -656,7 +656,6 @@ class MediaSyncDel(_PluginBase): "exclude_path": self._exclude_path, "library_path": self._library_path, "notify": self._notify, - "cron": self._cron, "sync_type": self._sync_type, }) return diff --git a/plugins.v2/syncdownloadfiles/__init__.py b/plugins.v2/syncdownloadfiles/__init__.py index 800120f..ce483d8 100644 --- a/plugins.v2/syncdownloadfiles/__init__.py +++ b/plugins.v2/syncdownloadfiles/__init__.py @@ -22,7 +22,7 @@ class SyncDownloadFiles(_PluginBase): # 插件图标 plugin_icon = "Youtube-dl_A.png" # 插件版本 - plugin_version = "1.1.5" + plugin_version = "1.1.6" # 插件作者 plugin_author = "thsrite" # 作者主页 @@ -191,6 +191,7 @@ class SyncDownloadFiles(_PluginBase): "savepath": str(save_path), "filepath": rel_path, "torrentname": torrent_name, + "state": 1 } ) From 996f10cebef4773cc02f981ee652ecd8425f2548 Mon Sep 17 00:00:00 2001 From: thsrite Date: Fri, 15 Nov 2024 12:47:35 +0800 Subject: [PATCH 08/11] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=BA=90=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.v2.json | 3 ++- plugins.v2/mediasyncdel/__init__.py | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/package.v2.json b/package.v2.json index 1fbbead..bb9448a 100644 --- a/package.v2.json +++ b/package.v2.json @@ -176,11 +176,12 @@ "name": "媒体文件同步删除", "description": "同步删除历史记录、源文件和下载任务。", "labels": "媒体库,文件整理", - "version": "1.8.4", + "version": "1.8.5", "icon": "mediasyncdel.png", "author": "thsrite", "level": 1, "history": { + "v1.8.5": "修复删除源文件", "v1.8.4": "修复暂停种子失败", "v1.8.3": "修复源文件删除", "v1.8.1": "适配v2多媒体服务器,移除日志方式", diff --git a/plugins.v2/mediasyncdel/__init__.py b/plugins.v2/mediasyncdel/__init__.py index 321e686..f37addc 100644 --- a/plugins.v2/mediasyncdel/__init__.py +++ b/plugins.v2/mediasyncdel/__init__.py @@ -26,7 +26,7 @@ class MediaSyncDel(_PluginBase): # 插件图标 plugin_icon = "mediasyncdel.png" # 插件版本 - plugin_version = "1.8.4" + plugin_version = "1.8.5" # 插件作者 plugin_author = "thsrite" # 作者主页 @@ -766,8 +766,8 @@ class MediaSyncDel(_PluginBase): if self._del_source: # 1、直接删除源文件 if transferhis.src and Path(transferhis.src).suffix in settings.RMT_MEDIAEXT: - dest_fileitem = schemas.FileItem(**transferhis.dest_fileitem) - state = StorageChain().delete_file(dest_fileitem) + StorageChain().delete_file(schemas.FileItem(**transferhis.dest_fileitem)) + state = StorageChain().delete_file(schemas.FileItem(**transferhis.src_fileitem)) if state and transferhis.download_hash: try: # 2、判断种子是否被删除完 From 0d6836df6c0b99dc9a3b293ef2bf2f7c0386a3ab Mon Sep 17 00:00:00 2001 From: thsrite Date: Fri, 15 Nov 2024 12:48:41 +0800 Subject: [PATCH 09/11] fix log --- plugins.v2/mediasyncdel/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins.v2/mediasyncdel/__init__.py b/plugins.v2/mediasyncdel/__init__.py index f37addc..d95823b 100644 --- a/plugins.v2/mediasyncdel/__init__.py +++ b/plugins.v2/mediasyncdel/__init__.py @@ -1,4 +1,3 @@ -import json import os import time from pathlib import Path @@ -767,7 +766,9 @@ class MediaSyncDel(_PluginBase): # 1、直接删除源文件 if transferhis.src and Path(transferhis.src).suffix in settings.RMT_MEDIAEXT: StorageChain().delete_file(schemas.FileItem(**transferhis.dest_fileitem)) - state = StorageChain().delete_file(schemas.FileItem(**transferhis.src_fileitem)) + src_fileitem = schemas.FileItem(**transferhis.src_fileitem) + logger.info(f"开始删除源文件 {src_fileitem.path}") + state = StorageChain().delete_file(src_fileitem) if state and transferhis.download_hash: try: # 2、判断种子是否被删除完 From 3140ff293bd54ea97ebf45b2dd687113e287f6ff Mon Sep 17 00:00:00 2001 From: thsrite Date: Fri, 15 Nov 2024 13:19:40 +0800 Subject: [PATCH 10/11] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=BA=90=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.v2.json | 4 ++-- plugins.v2/mediasyncdel/__init__.py | 14 +++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/package.v2.json b/package.v2.json index bb9448a..c8c418a 100644 --- a/package.v2.json +++ b/package.v2.json @@ -176,12 +176,12 @@ "name": "媒体文件同步删除", "description": "同步删除历史记录、源文件和下载任务。", "labels": "媒体库,文件整理", - "version": "1.8.5", + "version": "1.8.6", "icon": "mediasyncdel.png", "author": "thsrite", "level": 1, "history": { - "v1.8.5": "修复删除源文件", + "v1.8.6": "修复删除源文件", "v1.8.4": "修复暂停种子失败", "v1.8.3": "修复源文件删除", "v1.8.1": "适配v2多媒体服务器,移除日志方式", diff --git a/plugins.v2/mediasyncdel/__init__.py b/plugins.v2/mediasyncdel/__init__.py index d95823b..e679484 100644 --- a/plugins.v2/mediasyncdel/__init__.py +++ b/plugins.v2/mediasyncdel/__init__.py @@ -25,7 +25,7 @@ class MediaSyncDel(_PluginBase): # 插件图标 plugin_icon = "mediasyncdel.png" # 插件版本 - plugin_version = "1.8.5" + plugin_version = "1.8.6" # 插件作者 plugin_author = "thsrite" # 作者主页 @@ -50,12 +50,14 @@ class MediaSyncDel(_PluginBase): _transferhis = None _downloadhis = None _default_downloader = None + _storagechain = None def init_plugin(self, config: dict = None): self._transferchain = TransferChain() self._downloader_helper = DownloaderHelper() self._transferhis = self._transferchain.transferhis self._downloadhis = self._transferchain.downloadhis + self._storagechain = StorageChain() # 读取配置 if config: @@ -765,11 +767,17 @@ class MediaSyncDel(_PluginBase): if self._del_source: # 1、直接删除源文件 if transferhis.src and Path(transferhis.src).suffix in settings.RMT_MEDIAEXT: - StorageChain().delete_file(schemas.FileItem(**transferhis.dest_fileitem)) + self._storagechain.delete_file(schemas.FileItem(**transferhis.dest_fileitem)) src_fileitem = schemas.FileItem(**transferhis.src_fileitem) logger.info(f"开始删除源文件 {src_fileitem.path}") - state = StorageChain().delete_file(src_fileitem) + state = self._storagechain.delete_file(src_fileitem) if state and transferhis.download_hash: + folder_item = self._storagechain.get_parent_item(src_fileitem) + if folder_item and not self._storagechain.any_files(folder_item, + extensions=settings.RMT_MEDIAEXT): + logger.warn(f"删除残留空文件夹:【{folder_item.storage}】{folder_item.path}") + self._storagechain.delete_file(folder_item) + try: # 2、判断种子是否被删除完 delete_flag, success_flag, handle_torrent_hashs = self.handle_torrent( From cfbc5efc2416d3087cde1b4597526cc89301a0c8 Mon Sep 17 00:00:00 2001 From: thsrite Date: Fri, 15 Nov 2024 13:21:08 +0800 Subject: [PATCH 11/11] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=BA=90=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins.v2/mediasyncdel/__init__.py | 32 ++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/plugins.v2/mediasyncdel/__init__.py b/plugins.v2/mediasyncdel/__init__.py index e679484..3171ac6 100644 --- a/plugins.v2/mediasyncdel/__init__.py +++ b/plugins.v2/mediasyncdel/__init__.py @@ -771,28 +771,28 @@ class MediaSyncDel(_PluginBase): src_fileitem = schemas.FileItem(**transferhis.src_fileitem) logger.info(f"开始删除源文件 {src_fileitem.path}") state = self._storagechain.delete_file(src_fileitem) - if state and transferhis.download_hash: + if state: folder_item = self._storagechain.get_parent_item(src_fileitem) if folder_item and not self._storagechain.any_files(folder_item, extensions=settings.RMT_MEDIAEXT): logger.warn(f"删除残留空文件夹:【{folder_item.storage}】{folder_item.path}") self._storagechain.delete_file(folder_item) - - try: - # 2、判断种子是否被删除完 - delete_flag, success_flag, handle_torrent_hashs = self.handle_torrent( - type=transferhis.type, - src=transferhis.src, - torrent_hash=transferhis.download_hash) - if not success_flag: - error_cnt += 1 - else: - if delete_flag: - del_torrent_hashs += handle_torrent_hashs + if transferhis.download_hash: + try: + # 2、判断种子是否被删除完 + delete_flag, success_flag, handle_torrent_hashs = self.handle_torrent( + type=transferhis.type, + src=transferhis.src, + torrent_hash=transferhis.download_hash) + if not success_flag: + error_cnt += 1 else: - stop_torrent_hashs += handle_torrent_hashs - except Exception as e: - logger.error("删除种子失败:%s" % str(e)) + if delete_flag: + del_torrent_hashs += handle_torrent_hashs + else: + stop_torrent_hashs += handle_torrent_hashs + except Exception as e: + logger.error("删除种子失败:%s" % str(e)) logger.info(f"同步删除 {msg} 完成!")