From 67e29be7d0078ec49f2a3c5be5074f56d297d4bf Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 3 Jun 2024 14:29:07 +0800 Subject: [PATCH 01/10] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=AA=E8=A1=A8?= =?UTF-8?q?=E6=9D=BF=E7=BB=84=E4=BB=B6=E7=9A=84=E9=AB=98=E5=BA=A6=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/downloaderhelper/__init__.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/plugins/downloaderhelper/__init__.py b/plugins/downloaderhelper/__init__.py index 5c69377..961cb94 100644 --- a/plugins/downloaderhelper/__init__.py +++ b/plugins/downloaderhelper/__init__.py @@ -2504,7 +2504,7 @@ class DownloaderHelper(_PluginBase): 'fixed-header': True, 'density': 'compact', 'style': { - 'height': '230px' + 'height': '242px' } }, 'content': [ @@ -2627,21 +2627,24 @@ class DownloaderHelper(_PluginBase): }] } - def __build_dashboard_speed_widget_list_item_element(self, mdi_icon: str, label: str, value: str) -> dict: + def __build_dashboard_speed_widget_list_item_element(self, mdi_icon: str, label: str, value: str, is_last: bool = False) -> dict: """ 构造仪表板实时速率组件列表item元素 """ if not mdi_icon or not label or not value: return None + div_style = { + 'display': 'grid', + 'grid-template-areas': '"prepend content append"', + 'grid-template-columns': 'max-content 1fr auto', + 'padding-bottom': '16px' + } + if is_last: + del div_style['padding-bottom'] return { 'component': 'div', 'props': { - 'style': { - 'display': 'grid', - 'grid-template-areas': '"prepend content append"', - 'grid-template-columns': 'max-content 1fr auto', - 'padding-bottom': '16px' - } + 'style': div_style }, 'content': [{ 'component': 'div', @@ -2700,13 +2703,13 @@ class DownloaderHelper(_PluginBase): list_items = [ self.__build_dashboard_speed_widget_list_item_element(mdi_icon='mdi-cloud-upload', label='总上传量', value=data.upload_size), self.__build_dashboard_speed_widget_list_item_element(mdi_icon='mdi-download-box', label='总下载量', value=data.download_size), - self.__build_dashboard_speed_widget_list_item_element(mdi_icon='mdi-content-save', label='磁盘剩余空间', value=data.free_space), + self.__build_dashboard_speed_widget_list_item_element(mdi_icon='mdi-content-save', label='磁盘剩余空间', value=data.free_space, is_last=True), ] return [{ 'component': 'div', 'props': { 'style': { - 'padding': '16px 0 20px 0' + 'padding': '16px 0 0 0' } }, 'content': [{ From ae1ee0895c8b4e105f2f6798e83801d2343a98f0 Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 3 Jun 2024 14:32:24 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=B4=BB=E5=8A=A8?= =?UTF-8?q?=E7=A7=8D=E5=AD=90=E7=8A=B6=E6=80=81=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/downloaderhelper/convertor.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/downloaderhelper/convertor.py b/plugins/downloaderhelper/convertor.py index d062571..b85d586 100644 --- a/plugins/downloaderhelper/convertor.py +++ b/plugins/downloaderhelper/convertor.py @@ -69,6 +69,8 @@ class StateConvertor(IConvertor, metaclass=Singleton): return '等待' if data == TorrentState.CHECKING_DOWNLOAD.value: return '校验' + if data == TorrentState.QUEUED_DOWNLOAD.value: + return '排队' # tr if data == 6: return '做种' From e1260714cd16cd03388eb494c49d9a1998686024 Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 3 Jun 2024 14:45:34 +0800 Subject: [PATCH 03/10] =?UTF-8?q?=E9=85=8D=E7=BD=AE=E8=A1=A8=E5=8D=95?= =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/downloaderhelper/__init__.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/plugins/downloaderhelper/__init__.py b/plugins/downloaderhelper/__init__.py index 961cb94..93ec4b0 100644 --- a/plugins/downloaderhelper/__init__.py +++ b/plugins/downloaderhelper/__init__.py @@ -32,7 +32,7 @@ class DownloaderHelper(_PluginBase): # 插件名称 plugin_name = "下载器助手" # 插件描述 - plugin_desc = "自动做种、站点标签、自动删种。" + plugin_desc = "站点标签、自动做种、自动删种。" # 插件图标 plugin_icon = "DownloaderHelper.png" # 插件版本 @@ -221,6 +221,11 @@ class DownloaderHelper(_PluginBase): }, 'content': [{ 'component': 'VRow', + 'props': { + 'style': { + 'margin-top': '0' + } + }, 'content': [{ 'component': 'VCol', 'props': { @@ -244,9 +249,9 @@ class DownloaderHelper(_PluginBase): 'content': [{ 'component': 'VSwitch', 'props': { - 'model': f'{d.short_id}_enable_seeding', - 'label': '自动做种', - 'hint': '是否开启自动做种功能' + 'model': f'{d.short_id}_enable_tagging', + 'label': '站点标签', + 'hint': '是否开启站点标签功能' } }] }, { @@ -258,9 +263,9 @@ class DownloaderHelper(_PluginBase): 'content': [{ 'component': 'VSwitch', 'props': { - 'model': f'{d.short_id}_enable_tagging', - 'label': '站点标签', - 'hint': '是否开启站点标签功能' + 'model': f'{d.short_id}_enable_seeding', + 'label': '自动做种', + 'hint': '是否开启自动做种功能' } }] }, { From 9fe73a753ca726868294623e6f0865b4023791a4 Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 3 Jun 2024 15:59:39 +0800 Subject: [PATCH 04/10] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=AB=99=E7=82=B9?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E7=AD=89=E9=80=BB=E8=BE=91=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/downloaderhelper/__init__.py | 136 ++++++++++++++++++--------- 1 file changed, 89 insertions(+), 47 deletions(-) diff --git a/plugins/downloaderhelper/__init__.py b/plugins/downloaderhelper/__init__.py index 93ec4b0..e16c985 100644 --- a/plugins/downloaderhelper/__init__.py +++ b/plugins/downloaderhelper/__init__.py @@ -202,6 +202,7 @@ class DownloaderHelper(_PluginBase): 'cron': '0/30 * * * *', 'exclude_tags': 'BT,刷流', 'dashboard_widget_refresh': 5, + 'dashboard_speed_widget_refresh': 5, } # 合并默认配置 config_suggest.update(self.__config_default) @@ -1673,19 +1674,19 @@ class DownloaderHelper(_PluginBase): logger.info( f'子任务执行状态: 自动做种={enable_seeding}, 自动打标={enable_tagging}, 自动删种={enable_delete}') - # 做种 - if enable_seeding: - result.set_seeding(self.__seeding_batch_for_qbittorrent(torrents=torrents)) - if self.__exit_event.is_set(): - logger.warn(f'插件服务正在退出,任务终止[{downloader_name}]') - return context - # 打标 + # 站点标签 if enable_tagging: result.set_tagging(self.__tagging_batch_for_qbittorrent(torrents=torrents)) if self.__exit_event.is_set(): logger.warn(f'插件服务正在退出,任务终止[{downloader_name}]') return context - # 删种 + # 自动做种 + if enable_seeding: + result.set_seeding(self.__seeding_batch_for_qbittorrent(torrents=torrents)) + if self.__exit_event.is_set(): + logger.warn(f'插件服务正在退出,任务终止[{downloader_name}]') + return context + # 自动删种 if enable_delete: result.set_delete(self.__delete_batch_for_qbittorrent(qbittorrent=qbittorrent, torrents=torrents, deleted_event_data=context.get_deleted_event_data())) @@ -1701,10 +1702,10 @@ class DownloaderHelper(_PluginBase): def __seeding_batch_for_qbittorrent(self, torrents: List[TorrentDictionary]) -> int: """ - qb批量做种 + qb批量自动做种 :return: 做种数 """ - logger.info('[QB]批量做种开始...') + logger.info('[QB]批量自动做种开始...') count = 0 if not torrents: return count @@ -1714,12 +1715,12 @@ class DownloaderHelper(_PluginBase): return count if self.__seeding_single_for_qbittorrent(torrent=torrent): count += 1 - logger.info('[QB]批量做种结束') + logger.info('[QB]批量自动做种结束') return count def __seeding_single_for_qbittorrent(self, torrent: TorrentDictionary) -> bool: """ - qb单个做种 + qb单个自动做种 :return: 是否执行 """ if not torrent: @@ -1733,15 +1734,15 @@ class DownloaderHelper(_PluginBase): if not need_seeding: return False torrent.resume() - logger.info(f"[QB]单个做种完成: hash = {torrent.get('hash')}, name = {torrent.get('name')}") + logger.info(f"[QB]单个自动做种完成: hash = {torrent.get('hash')}, name = {torrent.get('name')}") return True def __tagging_batch_for_qbittorrent(self, torrents: List[TorrentDictionary]) -> int: """ - qb批量打标 + qb批量站点标签 :return: 打标数 """ - logger.info('[QB]批量打标开始...') + logger.info('[QB]批量站点标签开始...') count = 0 if not torrents: return count @@ -1751,12 +1752,12 @@ class DownloaderHelper(_PluginBase): return count if self.__tagging_single_for_qbittorrent(torrent=torrent): count += 1 - logger.info('[QB]批量打标结束') + logger.info('[QB]批量站点标签结束') return count def __tagging_single_for_qbittorrent(self, torrent: TorrentDictionary) -> bool: """ - qb单个打标签 + qb单个站点标签 :return: 是否执行 """ if not torrent: @@ -1766,6 +1767,9 @@ class DownloaderHelper(_PluginBase): # 判断种子中是否存在排除的标签 if self.__exists_exclude_tag(torrent_tags): return False + # BT种子与站点无关,故排除BT标签 + #if "BT" in torrent_tags: + # return False # 种子的tracker地址 tracker_url = self.__parse_tracker_for_qbittorrent(torrent=torrent) if not tracker_url: @@ -1782,16 +1786,34 @@ class DownloaderHelper(_PluginBase): return False # 打标签 torrent.add_tags(site_tag) - logger.info(f"[QB]单个打标成功: hash = {torrent.get('hash')}, name = {torrent.get('name')}") + logger.info(f"[QB]单个站点标签成功: hash = {torrent.get('hash')}, name = {torrent.get('name')}") + # Flush 标签 + self.__flush_torrent_tags_for_qbittorrent(torrent=torrent, tag=site_tag) return True + def __flush_torrent_tags_for_qbittorrent(self, torrent: TorrentDictionary, tag: str): + """ + qb Flush 标签到种子信息中(即更新内存数据) + """ + try: + if not torrent or not tag: + return + torrent_tags = self.__split_tags(torrent.get('tags')) + if tag in torrent_tags: + return + torrent_tags.add(tag) + tag_str = ', '.join(torrent_tags) + torrent.update({'tags': tag_str}) + except Exception as e: + logger.error(f'Flush种子标签异常: {str(e)}', exc_info=True) + def __delete_batch_for_qbittorrent(self, qbittorrent: Qbittorrent, torrents: List[TorrentDictionary], deleted_event_data: dict = None) -> int: """ - qb批量删种 + qb批量自动删种 :return: 删种数 """ - logger.info('[QB]批量删种开始...') + logger.info('[QB]批量自动删种开始...') count = 0 if not torrents: return count @@ -1802,13 +1824,13 @@ class DownloaderHelper(_PluginBase): if (self.__delete_single_for_qbittorrent(qbittorrent=qbittorrent, torrent=torrent, deleted_event_data=deleted_event_data)): count += 1 - logger.info('[QB]批量删种结束') + logger.info('[QB]批量自动删种结束') return count def __delete_single_for_qbittorrent(self, qbittorrent: Qbittorrent, torrent: TorrentDictionary, deleted_event_data: dict = None) -> bool: """ - qb单个删种 + qb单个自动删种 :return: 是否执行 """ if not torrent: @@ -1821,7 +1843,7 @@ class DownloaderHelper(_PluginBase): if not self.__check_need_delete_for_qbittorrent(torrent=torrent, deleted_event_data=deleted_event_data): return False qbittorrent.delete_torrents(True, torrent.get('hash')) - logger.info(f"[QB]单个删种完成: hash = {torrent.get('hash')}, name = {torrent.get('name')}") + logger.info(f"[QB]单个自动删种完成: hash = {torrent.get('hash')}, name = {torrent.get('name')}") return True def __run_for_transmission(self, context: TaskContext = None) -> TaskContext: @@ -1884,19 +1906,19 @@ class DownloaderHelper(_PluginBase): logger.info( f'子任务执行状态: 自动做种={enable_seeding}, 自动打标={enable_tagging}, 自动删种={enable_delete}') - # 做种 - if enable_seeding: - result.set_seeding(self.__seeding_batch_for_transmission(transmission=transmission, torrents=torrents)) - if self.__exit_event.is_set(): - logger.warn(f'插件服务正在退出,任务终止[{downloader_name}]') - return context - # 打标 + # 站点标签 if enable_tagging: result.set_tagging(self.__tagging_batch_for_transmission(transmission=transmission, torrents=torrents)) if self.__exit_event.is_set(): logger.warn(f'插件服务正在退出,任务终止[{downloader_name}]') return context - # 删种 + # 自动做种 + if enable_seeding: + result.set_seeding(self.__seeding_batch_for_transmission(transmission=transmission, torrents=torrents)) + if self.__exit_event.is_set(): + logger.warn(f'插件服务正在退出,任务终止[{downloader_name}]') + return context + # 自动删种 if enable_delete: result.set_delete(self.__delete_batch_for_transmission(transmission=transmission, torrents=torrents, deleted_event_data=context.get_deleted_event_data())) @@ -1912,10 +1934,10 @@ class DownloaderHelper(_PluginBase): def __seeding_batch_for_transmission(self, transmission: Transmission, torrents: List[Torrent]) -> int: """ - tr批量做种 + tr批量自动做种 :return: 做种数 """ - logger.info('[TR]批量做种开始...') + logger.info('[TR]批量自动做种开始...') count = 0 if not torrents: return count @@ -1925,12 +1947,12 @@ class DownloaderHelper(_PluginBase): return count if self.__seeding_single_for_transmission(transmission=transmission, torrent=torrent): count += 1 - logger.info('[TR]批量做种结束') + logger.info('[TR]批量自动做种结束') return count def __seeding_single_for_transmission(self, transmission: Transmission, torrent: Torrent) -> bool: """ - tr单个做种 + tr单个自动做种 :return: 是否执行 """ if not torrent: @@ -1944,15 +1966,15 @@ class DownloaderHelper(_PluginBase): if not need_seeding: return False transmission.start_torrents(torrent.hashString) - logger.info(f"[TR]单个做种完成: hash = {torrent.hashString}, name = {torrent.get('name')}") + logger.info(f"[TR]单个自动做种完成: hash = {torrent.hashString}, name = {torrent.get('name')}") return True def __tagging_batch_for_transmission(self, transmission: Transmission, torrents: List[Torrent]) -> int: """ - tr批量打标 + tr批量站点标签 :return: 打标数 """ - logger.info('[TR]批量打标开始...') + logger.info('[TR]批量站点标签开始...') count = 0 if not torrents: return count @@ -1962,21 +1984,24 @@ class DownloaderHelper(_PluginBase): return count if self.__tagging_single_for_transmission(transmission=transmission, torrent=torrent): count += 1 - logger.info('[TR]批量打标结束') + logger.info('[TR]批量站点标签结束') return count def __tagging_single_for_transmission(self, transmission: Transmission, torrent: Torrent) -> bool: """ - tr单个打标签 + tr单个站点标签 :return: 是否执行 """ if not torrent: return False # 种子当前已经存在的标签 - torrent_tags = torrent.get('labels') + torrent_tags = torrent.get('labels') or [] # 判断种子中是否存在排除的标签 if self.__exists_exclude_tag(torrent_tags): return False + # BT种子与站点无关,故排除BT标签 + #if "BT" in torrent_tags: + # return False # 种子的tracker地址 tracker_url = self.__parse_tracker_for_transmission(torrent=torrent) if not tracker_url: @@ -1998,16 +2023,33 @@ class DownloaderHelper(_PluginBase): return False # 保存标签 transmission.set_torrent_tag(torrent.hashString, torrent_tags_copy) - logger.info(f"[TR]单个打标成功: hash = {torrent.hashString}, name = {torrent.get('name')}") + logger.info(f"[TR]单个站点标签成功: hash = {torrent.hashString}, name = {torrent.get('name')}") + # Flush 标签 + self.__flush_torrent_tags_for_transmission(torrent=torrent, tag=site_tag) return True + def __flush_torrent_tags_for_transmission(self, torrent: Torrent, tag: str): + """ + tr Flush 标签到种子信息中(即更新内存数据) + """ + try: + if not torrent or not tag: + return + torrent_tags = torrent.get('labels') or [] + if tag in torrent_tags: + return + torrent_tags.append(tag) + torrent.fields.update({'labels': torrent_tags}) + except Exception as e: + logger.error(f'Flush种子标签异常: {str(e)}', exc_info=True) + def __delete_batch_for_transmission(self, transmission: Transmission, torrents: List[Torrent], deleted_event_data: dict = None) -> int: """ - tr批量删种 + tr批量自动删种 :return: 删种数 """ - logger.info('[TR]批量删种开始...') + logger.info('[TR]批量自动删种开始...') count = 0 if not torrents: return count @@ -2018,13 +2060,13 @@ class DownloaderHelper(_PluginBase): if (self.__delete_single_for_transmission(transmission=transmission, torrent=torrent, deleted_event_data=deleted_event_data)): count += 1 - logger.info('[TR]批量删种结束') + logger.info('[TR]批量自动删种结束') return count def __delete_single_for_transmission(self, transmission: Transmission, torrent: Torrent, deleted_event_data: dict = None) -> bool: """ - tr单个删种 + tr单个自动删种 :return: 是否执行 """ if not torrent: @@ -2037,7 +2079,7 @@ class DownloaderHelper(_PluginBase): if not self.__check_need_delete_for_transmission(torrent=torrent, deleted_event_data=deleted_event_data): return False transmission.delete_torrents(True, torrent.hashString) - logger.info(f"'[TR]单个删种完成: hash = {torrent.hashString}, name = {torrent.get('name')}") + logger.info(f"'[TR]单个自动删种完成: hash = {torrent.hashString}, name = {torrent.get('name')}") return True @staticmethod From 131ef4d9507ada160267a20e30dca2db8a5e2bf9 Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 3 Jun 2024 16:04:27 +0800 Subject: [PATCH 05/10] =?UTF-8?q?=E5=90=8C=E4=B8=8A=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/downloaderhelper/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/downloaderhelper/__init__.py b/plugins/downloaderhelper/__init__.py index e16c985..810b74e 100644 --- a/plugins/downloaderhelper/__init__.py +++ b/plugins/downloaderhelper/__init__.py @@ -1631,10 +1631,10 @@ class DownloaderHelper(_PluginBase): return context if not context.is_selected_qb_downloader(): return context - enable_seeding = True if self.__get_config_item( - config_key='qb_enable_seeding') and context.is_enabled_seeding() else False enable_tagging = True if self.__get_config_item( config_key='qb_enable_tagging') and context.is_enabled_tagging() else False + enable_seeding = True if self.__get_config_item( + config_key='qb_enable_seeding') and context.is_enabled_seeding() else False enable_delete = True if self.__get_config_item( config_key='qb_enable_delete') and context.is_enabled_delete() else False if not enable_seeding and not enable_tagging and not enable_delete: @@ -1672,7 +1672,7 @@ class DownloaderHelper(_PluginBase): return context logger.info( - f'子任务执行状态: 自动做种={enable_seeding}, 自动打标={enable_tagging}, 自动删种={enable_delete}') + f'子任务执行状态: 站点标签={enable_tagging}, 自动做种={enable_seeding}, 自动删种={enable_delete}') # 站点标签 if enable_tagging: @@ -1861,10 +1861,10 @@ class DownloaderHelper(_PluginBase): return context if not context.is_selected_tr_downloader(): return context - enable_seeding = True if self.__get_config_item( - config_key='tr_enable_seeding') and context.is_enabled_seeding() else False enable_tagging = True if self.__get_config_item( config_key='tr_enable_tagging') and context.is_enabled_tagging() else False + enable_seeding = True if self.__get_config_item( + config_key='tr_enable_seeding') and context.is_enabled_seeding() else False enable_delete = True if self.__get_config_item( config_key='tr_enable_delete') and context.is_enabled_delete() else False if not enable_seeding and not enable_tagging and not enable_delete: @@ -1904,7 +1904,7 @@ class DownloaderHelper(_PluginBase): return context logger.info( - f'子任务执行状态: 自动做种={enable_seeding}, 自动打标={enable_tagging}, 自动删种={enable_delete}') + f'子任务执行状态: 站点标签={enable_tagging}, 自动做种={enable_seeding}, 自动删种={enable_delete}') # 站点标签 if enable_tagging: From 3026f1d3a781119076f8260ed9e78c991b43546f Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 3 Jun 2024 16:15:59 +0800 Subject: [PATCH 06/10] =?UTF-8?q?=E5=90=8C=E4=B8=8A=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/downloaderhelper/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/downloaderhelper/__init__.py b/plugins/downloaderhelper/__init__.py index 810b74e..07da1fc 100644 --- a/plugins/downloaderhelper/__init__.py +++ b/plugins/downloaderhelper/__init__.py @@ -511,7 +511,7 @@ class DownloaderHelper(_PluginBase): ':\n\n' '例如:\n' 'chdbits.xyz:ptchdbits.co', - 'hint': 'Tracker映射。用于在站点打标签时,指定tracker和站点域名不同的种子的域名对应关系;前面为tracker域名(完整域名或者主域名皆可),中间是英文冒号,后面是站点域名。' + 'hint': 'Tracker映射。用于在站点标签时,指定tracker和站点域名不同的种子的域名对应关系;前面为tracker域名(完整域名或者主域名皆可),中间是英文冒号,后面是站点域名。' } }] }] From 266abaccdb9d9cede57312263c8556aac624c95f Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 3 Jun 2024 18:39:19 +0800 Subject: [PATCH 07/10] =?UTF-8?q?=E6=94=AF=E6=8C=81BT/PT=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/downloaderhelper/__init__.py | 238 +++++++++++++++++---------- 1 file changed, 155 insertions(+), 83 deletions(-) diff --git a/plugins/downloaderhelper/__init__.py b/plugins/downloaderhelper/__init__.py index 07da1fc..ec28a6c 100644 --- a/plugins/downloaderhelper/__init__.py +++ b/plugins/downloaderhelper/__init__.py @@ -32,7 +32,7 @@ class DownloaderHelper(_PluginBase): # 插件名称 plugin_name = "下载器助手" # 插件描述 - plugin_desc = "站点标签、自动做种、自动删种。" + plugin_desc = "自动标签、自动做种、自动删种。" # 插件图标 plugin_icon = "DownloaderHelper.png" # 插件版本 @@ -103,6 +103,12 @@ class DownloaderHelper(_PluginBase): 'mdi-download-box': 'M5 3h14a2 2 0 0 1 2 2v14c0 1.11-.89 2-2 2H5a2 2 0 0 1-2-2V5c0-1.1.9-2 2-2m3 14h8v-2H8zm8-7h-2.5V7h-3v3H8l4 4z', 'mdi-content-save': 'M15 9H5V5h10m-3 14a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3a3 3 0 0 1-3 3m5-16H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V7z', } + # 公共 tracker url + __public_tracker_urls = [ + "** [DHT] **", + "** [PeX] **", + "** [LSD] **", + ] def init_plugin(self, config: dict = None): """ @@ -251,8 +257,8 @@ class DownloaderHelper(_PluginBase): 'component': 'VSwitch', 'props': { 'model': f'{d.short_id}_enable_tagging', - 'label': '站点标签', - 'hint': '是否开启站点标签功能' + 'label': '自动标签', + 'hint': '是否开启自动标签功能;包含BT/PT标签和站点标签(仅PT有效);不受【排除种子标签】限制。' } }] }, { @@ -266,7 +272,7 @@ class DownloaderHelper(_PluginBase): 'props': { 'model': f'{d.short_id}_enable_seeding', 'label': '自动做种', - 'hint': '是否开启自动做种功能' + 'hint': '是否开启自动做种功能;受【排除种子标签】限制。' } }] }, { @@ -280,7 +286,7 @@ class DownloaderHelper(_PluginBase): 'props': { 'model': f'{d.short_id}_enable_delete', 'label': '自动删种', - 'hint': '是否开启自动删种功能' + 'hint': '是否开启自动删种功能;受【排除种子标签】限制。' } }] }] @@ -352,7 +358,7 @@ class DownloaderHelper(_PluginBase): 'props': { 'model': 'listen_download_event', 'label': '监听下载事件', - 'hint': '监听下载添加事件。当MoviePilot添加下载任务时,会触发执行本插件进行自动做种和添加站点标签。' + 'hint': '监听下载添加事件。当MoviePilot添加下载任务时,会触发本插件进行自动标签和自动做种。' } }] }, { @@ -366,7 +372,7 @@ class DownloaderHelper(_PluginBase): 'props': { 'model': 'listen_source_file_event', 'label': '监听源文件事件', - 'hint': '监听源文件删除事件。当在【历史记录】中删除源文件时,会自动触发运行本插件任务进行自动删种。' + 'hint': '监听源文件删除事件。当在【历史记录】中删除源文件时,会触发本插件进行自动删种。' } }] }, { @@ -1672,11 +1678,11 @@ class DownloaderHelper(_PluginBase): return context logger.info( - f'子任务执行状态: 站点标签={enable_tagging}, 自动做种={enable_seeding}, 自动删种={enable_delete}') + f'子任务执行状态: 自动标签={enable_tagging}, 自动做种={enable_seeding}, 自动删种={enable_delete}') - # 站点标签 + # 自动标签 if enable_tagging: - result.set_tagging(self.__tagging_batch_for_qbittorrent(torrents=torrents)) + result.set_tagging(self.__tagging_batch_for_qbittorrent(qbittorrent=qbittorrent, torrents=torrents)) if self.__exit_event.is_set(): logger.warn(f'插件服务正在退出,任务终止[{downloader_name}]') return context @@ -1737,12 +1743,14 @@ class DownloaderHelper(_PluginBase): logger.info(f"[QB]单个自动做种完成: hash = {torrent.get('hash')}, name = {torrent.get('name')}") return True - def __tagging_batch_for_qbittorrent(self, torrents: List[TorrentDictionary]) -> int: + def __tagging_batch_for_qbittorrent(self, + qbittorrent: Qbittorrent, + torrents: List[TorrentDictionary]) -> int: """ - qb批量站点标签 + qb批量自动标签 :return: 打标数 """ - logger.info('[QB]批量站点标签开始...') + logger.info('[QB]批量自动标签开始...') count = 0 if not torrents: return count @@ -1750,63 +1758,103 @@ class DownloaderHelper(_PluginBase): if self.__exit_event.is_set(): logger.warn('插件服务正在退出,子任务终止') return count - if self.__tagging_single_for_qbittorrent(torrent=torrent): + if self.__tagging_single_for_qbittorrent(qbittorrent=qbittorrent, torrent=torrent): count += 1 - logger.info('[QB]批量站点标签结束') + logger.info('[QB]批量自动标签结束') return count - def __tagging_single_for_qbittorrent(self, torrent: TorrentDictionary) -> bool: + def __tagging_single_for_qbittorrent(self, + qbittorrent: Qbittorrent, + torrent: TorrentDictionary) -> bool: """ - qb单个站点标签 + qb单个自动标签 :return: 是否执行 """ if not torrent: return False + + hash_str = torrent.get('hash') # 种子当前已经存在的标签 torrent_tags = self.__split_tags(torrent.get('tags')) - # 判断种子中是否存在排除的标签 - if self.__exists_exclude_tag(torrent_tags): - return False + # 需要移除的标签 + remove_tags = None + # 要添加的标签 + add_tags = [] + + # 处理BT/PT标签 + if "BT" not in torrent_tags and "PT" not in torrent_tags: + is_private = self.__check_private_torrent_for_qbittorrent(qbittorrent=qbittorrent, hash_str=hash_str) + btpt_tag = "PT" if is_private else "BT" + add_tags.append(btpt_tag) + + # 处理站点标签 # BT种子与站点无关,故排除BT标签 - #if "BT" in torrent_tags: - # return False - # 种子的tracker地址 - tracker_url = self.__parse_tracker_for_qbittorrent(torrent=torrent) - if not tracker_url: - return False - # 获取标签建议 - site_tag, delete_suggest = self.__consult_site_tag_by_tracker(tracker_url=tracker_url) - # 移除建议删除的标签 - if delete_suggest and len(delete_suggest) > 0: - to_deletes = [to_delete for to_delete in delete_suggest if to_delete in torrent_tags] - if to_deletes and len(to_deletes) > 0: - torrent.remove_tags(to_deletes) - # 如果本次不需要打标签 - if not site_tag or site_tag in torrent_tags: + if "BT" not in torrent_tags and "BT" not in add_tags: + # 种子的tracker地址 + tracker_url = self.__parse_tracker_for_qbittorrent(torrent=torrent) + if tracker_url: + # 获取标签建议 + site_tag, delete_suggest = self.__consult_site_tag_by_tracker(tracker_url=tracker_url) + # 移除建议删除的标签 + if delete_suggest: + remove_tags = [to_delete for to_delete in delete_suggest if to_delete and to_delete in torrent_tags] + # 如果本次需要打标签 + if site_tag and site_tag not in torrent_tags and site_tag not in add_tags: + add_tags.append(site_tag) + + if not remove_tags and not add_tags: return False + if remove_tags: + torrent.remove_tags(tags=remove_tags) # 打标签 - torrent.add_tags(site_tag) - logger.info(f"[QB]单个站点标签成功: hash = {torrent.get('hash')}, name = {torrent.get('name')}") + if add_tags: + torrent.add_tags(tags=add_tags) + logger.info(f"[QB]单个自动标签成功: hash = {hash_str}, name = {torrent.get('name')}") # Flush 标签 - self.__flush_torrent_tags_for_qbittorrent(torrent=torrent, tag=site_tag) + self.__flush_torrent_tags_for_qbittorrent(torrent=torrent, tags=add_tags) return True - def __flush_torrent_tags_for_qbittorrent(self, torrent: TorrentDictionary, tag: str): + def __flush_torrent_tags_for_qbittorrent(self, torrent: TorrentDictionary, remove_tags: List[str], add_tags: List[str]): """ qb Flush 标签到种子信息中(即更新内存数据) """ try: - if not torrent or not tag: + if not torrent: return torrent_tags = self.__split_tags(torrent.get('tags')) - if tag in torrent_tags: - return - torrent_tags.add(tag) + if remove_tags: + for remove_tag in remove_tags: + if remove_tag and remove_tag in torrent_tags: + torrent_tags.remove(remove_tag) + if add_tags: + for add_tag in add_tags: + if add_tag and add_tag not in torrent_tags: + torrent_tags.add(add_tag) tag_str = ', '.join(torrent_tags) torrent.update({'tags': tag_str}) except Exception as e: logger.error(f'Flush种子标签异常: {str(e)}', exc_info=True) + def __check_private_torrent_for_qbittorrent(self, + qbittorrent: Qbittorrent, + hash_str: str) -> bool: + """ + qb检查种子是否是私有种子 + :return: 是否是私有种子 + """ + trackers = qbittorrent.qbc.torrents_trackers(torrent_hash=hash_str) + if not trackers: + return False + for tracker in trackers: + if not tracker: + continue + url = tracker.get("url") + status = tracker.get("status") + tier = tracker.get("tier") + if url in self.__public_tracker_urls and status == 0 and tier == -1: + return True + return False + def __delete_batch_for_qbittorrent(self, qbittorrent: Qbittorrent, torrents: List[TorrentDictionary], deleted_event_data: dict = None) -> int: """ @@ -1886,8 +1934,15 @@ class DownloaderHelper(_PluginBase): context.save_result(result=result) - torrents, error = transmission.get_torrents() - if error: + # 获取全部种子 + # 需要 isPrivate 字段判断是否是私有种子 + arguments = transmission._trarg.copy() + is_private_field = "isPrivate" + if is_private_field not in arguments: + arguments.append(is_private_field) + try: + torrents = transmission.trc.get_torrents(arguments=arguments) + except Exception as e: logger.warn(f'从下载器[{downloader_name}]中获取种子失败,任务终止') return context if not torrents or len(torrents) <= 0: @@ -1904,9 +1959,9 @@ class DownloaderHelper(_PluginBase): return context logger.info( - f'子任务执行状态: 站点标签={enable_tagging}, 自动做种={enable_seeding}, 自动删种={enable_delete}') + f'子任务执行状态: 自动标签={enable_tagging}, 自动做种={enable_seeding}, 自动删种={enable_delete}') - # 站点标签 + # 自动标签 if enable_tagging: result.set_tagging(self.__tagging_batch_for_transmission(transmission=transmission, torrents=torrents)) if self.__exit_event.is_set(): @@ -1971,10 +2026,10 @@ class DownloaderHelper(_PluginBase): def __tagging_batch_for_transmission(self, transmission: Transmission, torrents: List[Torrent]) -> int: """ - tr批量站点标签 + tr批量自动标签 :return: 打标数 """ - logger.info('[TR]批量站点标签开始...') + logger.info('[TR]批量自动标签开始...') count = 0 if not torrents: return count @@ -1984,65 +2039,82 @@ class DownloaderHelper(_PluginBase): return count if self.__tagging_single_for_transmission(transmission=transmission, torrent=torrent): count += 1 - logger.info('[TR]批量站点标签结束') + logger.info('[TR]批量自动标签结束') return count def __tagging_single_for_transmission(self, transmission: Transmission, torrent: Torrent) -> bool: """ - tr单个站点标签 + tr单个自动标签 :return: 是否执行 """ if not torrent: return False + + hash_str = torrent.hashString # 种子当前已经存在的标签 torrent_tags = torrent.get('labels') or [] - # 判断种子中是否存在排除的标签 - if self.__exists_exclude_tag(torrent_tags): - return False + # 需要移除的标签 + remove_tags = None + # 要添加的标签 + add_tags = [] + + # 处理BT/PT标签 + if "BT" not in torrent_tags and "PT" not in torrent_tags: + is_private = self.__check_private_torrent_for_transmission(torrent=torrent) + btpt_tag = "PT" if is_private else "BT" + add_tags.append(btpt_tag) + + # 处理站点标签 # BT种子与站点无关,故排除BT标签 - #if "BT" in torrent_tags: - # return False - # 种子的tracker地址 - tracker_url = self.__parse_tracker_for_transmission(torrent=torrent) - if not tracker_url: - return False - # 获取标签建议 - site_tag, delete_suggest = self.__consult_site_tag_by_tracker(tracker_url=tracker_url) - # 种子标签副本 - torrent_tags_copy = torrent_tags.copy() - # 移除建议删除的标签 - if delete_suggest and len(delete_suggest) > 0: - for to_delete in delete_suggest: - if to_delete and to_delete in torrent_tags_copy: - torrent_tags_copy.remove(to_delete) - # 如果本次需要打标签 - if site_tag and site_tag not in torrent_tags_copy: - torrent_tags_copy.append(site_tag) + if "BT" not in torrent_tags and "BT" not in add_tags: + # 种子的tracker地址 + tracker_url = self.__parse_tracker_for_transmission(torrent=torrent) + if tracker_url: + # 获取标签建议 + site_tag, delete_suggest = self.__consult_site_tag_by_tracker(tracker_url=tracker_url) + # 移除建议删除的标签 + if delete_suggest: + remove_tags = [to_delete for to_delete in delete_suggest if to_delete and to_delete in torrent_tags] + # 如果本次需要打标签 + if site_tag and site_tag not in torrent_tags and site_tag not in add_tags: + add_tags.append(site_tag) + # 如果没有变化就不继续保存 - if torrent_tags_copy == torrent_tags: + if not remove_tags and not add_tags: return False + torrent_tags_copy = torrent_tags.copy() + if remove_tags: + for remove_tag in remove_tags: + torrent_tags_copy.remove(remove_tag) + if add_tags: + for add_tag in add_tags: + torrent_tags_copy.append(add_tag) # 保存标签 - transmission.set_torrent_tag(torrent.hashString, torrent_tags_copy) - logger.info(f"[TR]单个站点标签成功: hash = {torrent.hashString}, name = {torrent.get('name')}") + transmission.set_torrent_tag(hash_str, torrent_tags_copy) + logger.info(f"[TR]单个自动标签成功: hash = {hash_str}, name = {torrent.get('name')}") # Flush 标签 - self.__flush_torrent_tags_for_transmission(torrent=torrent, tag=site_tag) + self.__flush_torrent_tags_for_transmission(torrent=torrent, tags=torrent_tags_copy) return True - def __flush_torrent_tags_for_transmission(self, torrent: Torrent, tag: str): + def __flush_torrent_tags_for_transmission(self, torrent: Torrent, tags: List[str]): """ tr Flush 标签到种子信息中(即更新内存数据) """ try: - if not torrent or not tag: + if not torrent: return - torrent_tags = torrent.get('labels') or [] - if tag in torrent_tags: - return - torrent_tags.append(tag) - torrent.fields.update({'labels': torrent_tags}) + torrent.fields.update({'labels': tags}) except Exception as e: logger.error(f'Flush种子标签异常: {str(e)}', exc_info=True) + def __check_private_torrent_for_transmission(self, + torrent: Torrent) -> bool: + """ + tr检查种子是否是私有种子 + :return: 是否是私有种子 + """ + return torrent.get("isPrivate") + def __delete_batch_for_transmission(self, transmission: Transmission, torrents: List[Torrent], deleted_event_data: dict = None) -> int: """ From 74f0f666d20b56103ec4b3b1c0473b9098f1d9c2 Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 3 Jun 2024 19:41:08 +0800 Subject: [PATCH 08/10] =?UTF-8?q?=E7=9B=91=E5=90=AC=E5=8E=9F=E7=A7=8D?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=BA=8B=E4=BB=B6=E8=A1=A5=E5=85=85=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=88=A0=E7=A7=8D=E9=80=BB=E8=BE=91=EF=BC=9B=E5=8F=AF?= =?UTF-8?q?=E8=83=BD=E9=9C=80=E8=A6=81=E9=87=8D=E5=90=AFMP=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/downloaderhelper/__init__.py | 160 ++++++++++++++++++++------- plugins/downloaderhelper/module.py | 25 ++++- 2 files changed, 143 insertions(+), 42 deletions(-) diff --git a/plugins/downloaderhelper/__init__.py b/plugins/downloaderhelper/__init__.py index ec28a6c..1da69d7 100644 --- a/plugins/downloaderhelper/__init__.py +++ b/plugins/downloaderhelper/__init__.py @@ -372,7 +372,7 @@ class DownloaderHelper(_PluginBase): 'props': { 'model': 'listen_source_file_event', 'label': '监听源文件事件', - 'hint': '监听源文件删除事件。当在【历史记录】中删除源文件时,会触发本插件进行自动删种。' + 'hint': '监听源文件删除事件以及原种删除事件。当在【历史记录】中删除源文件时,会触发本插件进行自动删种。' } }] }, { @@ -1392,46 +1392,78 @@ class DownloaderHelper(_PluginBase): return site_tag, delete_suggest @classmethod - def __check_need_delete_for_qbittorrent(cls, torrent: TorrentDictionary, deleted_event_data: dict = None) -> bool: + def __check_need_delete_for_qbittorrent(cls, torrent: TorrentDictionary, context: TaskContext) -> bool: """ 检查qb种子是否满足删除条件 - :param deleted_event_data: 任务执行伴随的源文件删除事件数据 + :param context: 任务上下文 """ - if not torrent: + if not torrent or not context: return False # 根据种子状态判断是否应该删种:状态为丢失文件时需要删除 if torrent.get('state') == 'missingFiles': return True - # 根据伴随的源文件删除事件判断是否应该删种:如果当前种子和事件匹配并且种子中已经不存在数据文件时就需要删除 - match, torrent_data_path = cls.__check_torrent_match_file_for_qbittorrent(torrent=torrent, - source_file_info=deleted_event_data) - if not match: - return False - # 如果匹配的种子数据路径不存在,说明数据文件已经(全部)被删除了,那么就允许删种 - return not os.path.exists(torrent_data_path) + # 源文件删除事件数据 + download_file_deleted_event_data = context.get_download_file_deleted_event_data() + # 下载任务删除事件数据 + download_deleted_event_data = context.get_download_deleted_event_data() + + # 源文件删除事件触发 + if download_file_deleted_event_data: + # 根据伴随的源文件删除事件判断是否应该删种:如果当前种子和事件匹配并且种子中已经不存在数据文件时就需要删除 + match, torrent_data_path = cls.__check_torrent_match_file_for_qbittorrent(torrent=torrent, + source_file_info=download_file_deleted_event_data) + if not match: + return False + # 如果匹配的种子数据路径不存在,说明数据文件已经(全部)被删除了,那么就允许删种 + return not os.path.exists(torrent_data_path) + # 下载任务删除事件触发 + elif download_deleted_event_data: + torrent_info = download_deleted_event_data + match = cls.__check_torrent_match_torrent_info(torrent_hash=torrent.get('hash'), + torrent_data_file_name=torrent.get('name'), + torrent_size=torrent.get('total_size'), + torrent_info=torrent_info) + return match + return False @classmethod - def __check_need_delete_for_transmission(cls, torrent: Torrent, deleted_event_data: dict = None) -> bool: + def __check_need_delete_for_transmission(cls, torrent: Torrent, context: TaskContext) -> bool: """ 检查tr种子是否满足删除条件 :param deleted_event_data: 任务执行伴随的源文件删除事件数据 """ - if not torrent: + if not torrent or not context: return False # 根据种子状态判断是否应该删种:状态为丢失文件时需要删除 if torrent.error == 3 and torrent.error_string and 'No data found' in torrent.error_string: return True - # 根据伴随的源文件删除事件判断是否应该删种:如果当前种子和事件匹配并且种子中已经不存在数据文件时就需要删除 - match, torrent_data_path = cls.__check_torrent_match_file_for_transmission(torrent=torrent, - source_file_info=deleted_event_data) - if not match: - return False - # 如果匹配的种子数据路径不存在,说明数据文件已经(全部)被删除了,那么就允许删种 - return not os.path.exists(torrent_data_path) + # 源文件删除事件数据 + download_file_deleted_event_data = context.get_download_file_deleted_event_data() + # 下载任务删除事件数据 + download_deleted_event_data = context.get_download_deleted_event_data() + + # 源文件删除事件触发 + if download_file_deleted_event_data: + # 根据伴随的源文件删除事件判断是否应该删种:如果当前种子和事件匹配并且种子中已经不存在数据文件时就需要删除 + match, torrent_data_path = cls.__check_torrent_match_file_for_transmission(torrent=torrent, + source_file_info=download_file_deleted_event_data) + if not match: + return False + # 如果匹配的种子数据路径不存在,说明数据文件已经(全部)被删除了,那么就允许删种 + return not os.path.exists(torrent_data_path) + # 下载任务删除事件触发 + elif download_deleted_event_data: + torrent_info = download_deleted_event_data + match = cls.__check_torrent_match_torrent_info(torrent_hash=torrent.hashString, + torrent_data_file_name=torrent.name, + torrent_size=torrent.total_size, + torrent_info=torrent_info) + return match + return False @classmethod def __check_torrent_match_file_for_qbittorrent(cls, torrent: TorrentDictionary, @@ -1501,6 +1533,25 @@ class DownloaderHelper(_PluginBase): return False, None + @classmethod + def __check_torrent_match_torrent_info(cls, + torrent_hash: str, + torrent_data_file_name: str, + torrent_size: int, + torrent_info: dict) -> bool: + """ + 判断种子是否和种子信息匹配 + :param torrent_hash: 种子hash + :param torrent_data_file_name: 种子数据文件名 + :param torrent_size: 种子大小 + :param torrent_info: 被判断的其它种子信息 + :return: 是否匹配 + """ + if not torrent_hash or not torrent_data_file_name or not torrent_size or not torrent_info: + return False + return torrent_data_file_name == torrent_info.get("title") \ + and torrent_size == torrent_info.get("size") + def __send_notify(self, context: TaskContext): """ 发送通知 @@ -1695,7 +1746,7 @@ class DownloaderHelper(_PluginBase): # 自动删种 if enable_delete: result.set_delete(self.__delete_batch_for_qbittorrent(qbittorrent=qbittorrent, torrents=torrents, - deleted_event_data=context.get_deleted_event_data())) + context=context)) if self.__exit_event.is_set(): logger.warn(f'插件服务正在退出,任务终止[{downloader_name}]') return context @@ -1856,7 +1907,7 @@ class DownloaderHelper(_PluginBase): return False def __delete_batch_for_qbittorrent(self, qbittorrent: Qbittorrent, torrents: List[TorrentDictionary], - deleted_event_data: dict = None) -> int: + context: TaskContext) -> int: """ qb批量自动删种 :return: 删种数 @@ -1870,13 +1921,13 @@ class DownloaderHelper(_PluginBase): logger.warn('插件服务正在退出,子任务终止') return count if (self.__delete_single_for_qbittorrent(qbittorrent=qbittorrent, torrent=torrent, - deleted_event_data=deleted_event_data)): + context=context)): count += 1 logger.info('[QB]批量自动删种结束') return count def __delete_single_for_qbittorrent(self, qbittorrent: Qbittorrent, torrent: TorrentDictionary, - deleted_event_data: dict = None) -> bool: + context: TaskContext) -> bool: """ qb单个自动删种 :return: 是否执行 @@ -1888,7 +1939,7 @@ class DownloaderHelper(_PluginBase): # 判断种子中是否存在排除的标签 if self.__exists_exclude_tag(torrent_tags): return False - if not self.__check_need_delete_for_qbittorrent(torrent=torrent, deleted_event_data=deleted_event_data): + if not self.__check_need_delete_for_qbittorrent(torrent=torrent, context=context): return False qbittorrent.delete_torrents(True, torrent.get('hash')) logger.info(f"[QB]单个自动删种完成: hash = {torrent.get('hash')}, name = {torrent.get('name')}") @@ -1976,7 +2027,7 @@ class DownloaderHelper(_PluginBase): # 自动删种 if enable_delete: result.set_delete(self.__delete_batch_for_transmission(transmission=transmission, torrents=torrents, - deleted_event_data=context.get_deleted_event_data())) + context=context)) if self.__exit_event.is_set(): logger.warn(f'插件服务正在退出,任务终止[{downloader_name}]') return context @@ -2116,7 +2167,7 @@ class DownloaderHelper(_PluginBase): return torrent.get("isPrivate") def __delete_batch_for_transmission(self, transmission: Transmission, torrents: List[Torrent], - deleted_event_data: dict = None) -> int: + context: TaskContext) -> int: """ tr批量自动删种 :return: 删种数 @@ -2130,13 +2181,13 @@ class DownloaderHelper(_PluginBase): logger.warn('插件服务正在退出,子任务终止') return count if (self.__delete_single_for_transmission(transmission=transmission, torrent=torrent, - deleted_event_data=deleted_event_data)): + context=context)): count += 1 logger.info('[TR]批量自动删种结束') return count def __delete_single_for_transmission(self, transmission: Transmission, torrent: Torrent, - deleted_event_data: dict = None) -> bool: + context: TaskContext) -> bool: """ tr单个自动删种 :return: 是否执行 @@ -2148,7 +2199,7 @@ class DownloaderHelper(_PluginBase): # 判断种子中是否存在排除的标签 if self.__exists_exclude_tag(torrent_tags): return False - if not self.__check_need_delete_for_transmission(torrent=torrent, deleted_event_data=deleted_event_data): + if not self.__check_need_delete_for_transmission(torrent=torrent, context=context): return False transmission.delete_torrents(True, torrent.hashString) logger.info(f"'[TR]单个自动删种完成: hash = {torrent.hashString}, name = {torrent.get('name')}") @@ -2861,12 +2912,12 @@ class DownloaderHelper(_PluginBase): 监听下载添加事件 """ logger.info('监听到下载添加事件') - if not event or not event.event_data: - logger.warn('事件信息无效,忽略事件') - return if not self.get_state() or not self.__get_config_item(config_key='listen_download_event'): logger.warn('插件状态无效或未开启监听,忽略事件') return + if not event or not event.event_data: + logger.warn('事件信息无效,忽略事件') + return if self.__exit_event.is_set(): logger.warn('插件服务正在退出,忽略事件') return @@ -2891,12 +2942,12 @@ class DownloaderHelper(_PluginBase): 监听源文件删除事件 """ logger.info('监听到源文件删除事件') - if not event or not event.event_data: - logger.warn('事件信息无效,忽略事件') - return if not self.get_state() or not self.__get_config_item(config_key='listen_source_file_event'): logger.warn('插件状态无效或未开启监听,忽略事件') return + if not event or not event.event_data: + logger.warn('事件信息无效,忽略事件') + return if self.__exit_event.is_set(): logger.warn('插件服务正在退出,忽略事件') return @@ -2906,6 +2957,41 @@ class DownloaderHelper(_PluginBase): context = TaskContext().enable_seeding(False) \ .enable_tagging(False) \ .enable_delete(True) \ - .set_deleted_event_data(event.event_data) + .set_download_file_deleted_event_data(event.event_data) self.__block_run(context=context) logger.info('源文件删除事件监听任务执行结束') + + @eventmanager.register(EventType.DownloadDeleted) + def listen_download_deleted_event(self, event: Event = None): + """ + 监听下载任务删除事件 + """ + logger.info('监听到下载任务删除事件') + if not self.get_state() or not self.__get_config_item(config_key='listen_source_file_event'): + logger.warn('插件状态无效或未开启监听,忽略事件') + return + if not event or not event.event_data: + logger.warn('事件信息无效,忽略事件') + return + torrents = event.event_data.get("torrents") + if not torrents: + logger.warn('事件信息无效,忽略事件') + return + torrents = [torrent for torrent in torrents if torrent] + if not torrents: + logger.warn('事件信息无效,忽略事件') + return + if self.__exit_event.is_set(): + logger.warn('插件服务正在退出,忽略事件') + return + # 执行 + logger.info('下载任务删除事件监听任务执行开始...') + # 针对下载任务删除事件只需要处理删种 + # 删除的种子信息 + torrent_info = torrents[0] + context = TaskContext().enable_seeding(False) \ + .enable_tagging(False) \ + .enable_delete(True) \ + .set_download_deleted_event_data(torrent_info) + self.__block_run(context=context) + logger.info('下载任务删除事件监听任务执行结束') diff --git a/plugins/downloaderhelper/module.py b/plugins/downloaderhelper/module.py index cbabf2d..686b7aa 100644 --- a/plugins/downloaderhelper/module.py +++ b/plugins/downloaderhelper/module.py @@ -95,7 +95,9 @@ class TaskContext: self.__selected_torrents = None # 源文件删除事件数据 - self.__deleted_event_data = None + self.__download_file_deleted_event_data = None + # 下载任务删除事件数据 + self.__download_deleted_event_data = None # 任务结果集 self.__results: Optional[List[TaskResult]] = None @@ -226,18 +228,31 @@ class TaskContext: """ return self.__selected_torrents - def set_deleted_event_data(self, deleted_event_data: dict): + def set_download_file_deleted_event_data(self, download_file_deleted_event_data: dict): """ 设置源文件删除事件数据 """ - self.__deleted_event_data = deleted_event_data + self.__download_file_deleted_event_data = download_file_deleted_event_data return self - def get_deleted_event_data(self) -> dict: + def get_download_file_deleted_event_data(self) -> dict: """ 获取源文件删除事件数据 """ - return self.__deleted_event_data + return self.__download_file_deleted_event_data + + def set_download_deleted_event_data(self, download_deleted_event_data: dict): + """ + 设置下载任务删除事件数据 + """ + self.__download_deleted_event_data = download_deleted_event_data + return self + + def get_download_deleted_event_data(self) -> dict: + """ + 获取下载任务删除事件数据 + """ + return self.__download_deleted_event_data def save_result(self, result: TaskResult): """ From 92748d16ed05d0f738ccff5f0612dcae712e051e Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 3 Jun 2024 19:53:46 +0800 Subject: [PATCH 09/10] fixbug --- plugins/downloaderhelper/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/downloaderhelper/__init__.py b/plugins/downloaderhelper/__init__.py index 1da69d7..7631b7b 100644 --- a/plugins/downloaderhelper/__init__.py +++ b/plugins/downloaderhelper/__init__.py @@ -1862,7 +1862,7 @@ class DownloaderHelper(_PluginBase): torrent.add_tags(tags=add_tags) logger.info(f"[QB]单个自动标签成功: hash = {hash_str}, name = {torrent.get('name')}") # Flush 标签 - self.__flush_torrent_tags_for_qbittorrent(torrent=torrent, tags=add_tags) + self.__flush_torrent_tags_for_qbittorrent(torrent=torrent, remove_tags=remove_tags, add_tags=add_tags) return True def __flush_torrent_tags_for_qbittorrent(self, torrent: TorrentDictionary, remove_tags: List[str], add_tags: List[str]): From 1640047ab8e852654926757142cd3b6d64357023 Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 3 Jun 2024 19:57:37 +0800 Subject: [PATCH 10/10] v2.8 --- package.json | 5 +++-- plugins/downloaderhelper/__init__.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 8e46729..4920fb0 100644 --- a/package.json +++ b/package.json @@ -640,13 +640,14 @@ }, "DownloaderHelper": { "name": "下载器助手", - "description": "自动做种、站点标签、自动删种。", + "description": "自动标签、自动做种、自动删种。", "labels": "下载管理,仪表板", - "version": "2.7", + "version": "2.8", "icon": "DownloaderHelper.png", "author": "hotlcc", "level": 1, "history": { + "v2.8": "优化了仪表板组件高度;优化了活动种子状态;优化了自动标签,优化站点标签,新增BT/PT标签;监听原种删除事件补充删种逻辑。更新后若插件功能异常,请重启一次MP。", "v2.7": "实时速率仪表板样式微调。", "v2.6": "新增仪表板实时速率组件,支持单独展示qb和tr的实时速率(tr未测试,有问题提Issue并@hotlcc)。", "v2.5": "优化通知类型;降低认证级别要求,使MP非认证用户可用,但无法使用【站点名称优先】功能。主程序需升级至v1.9.2及以上版本,否则插件功能异常!", diff --git a/plugins/downloaderhelper/__init__.py b/plugins/downloaderhelper/__init__.py index 7631b7b..9a5af12 100644 --- a/plugins/downloaderhelper/__init__.py +++ b/plugins/downloaderhelper/__init__.py @@ -36,7 +36,7 @@ class DownloaderHelper(_PluginBase): # 插件图标 plugin_icon = "DownloaderHelper.png" # 插件版本 - plugin_version = "2.7" + plugin_version = "2.8" # 插件作者 plugin_author = "hotlcc" # 作者主页