From 48e77ebb91c855434cfd993b0cf615b9c310c4f5 Mon Sep 17 00:00:00 2001 From: InfinityPacer Date: Tue, 2 Apr 2024 01:24:22 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix=20brushflow=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E9=A1=B5=EF=BC=8C=E8=B0=83=E6=95=B4=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E5=88=A0=E9=99=A4=E7=A7=8D=E5=AD=90=E8=A7=84=E5=88=99?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E5=A4=8DMP=E6=A0=87=E7=AD=BE=E9=97=AE?= =?UTF-8?q?=E9=A2=98=EF=BC=8C=E4=BC=98=E5=8C=96=E6=97=A5=E5=BF=97=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/brushflow/__init__.py | 69 +++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 24 deletions(-) diff --git a/plugins/brushflow/__init__.py b/plugins/brushflow/__init__.py index c9d3d24..20a6ba3 100644 --- a/plugins/brushflow/__init__.py +++ b/plugins/brushflow/__init__.py @@ -1267,6 +1267,10 @@ class BrushFlow(_PluginBase): 'component': 'td', 'text': "是" if data.get("hit_and_run") else "否" }, + { + 'component': 'td', + 'text': f"{data.get('seeding_time') / 3600:.1f}" if data.get('seeding_time') else "N/A" + }, { 'component': 'td', 'props': { @@ -1631,6 +1635,13 @@ class BrushFlow(_PluginBase): }, 'text': 'HR' }, + { + 'component': 'th', + 'props': { + 'class': 'text-start ps-4' + }, + 'text': '做种时间' + }, { 'component': 'th', 'props': { @@ -1818,6 +1829,7 @@ class BrushFlow(_PluginBase): "ratio": 0, "downloaded": 0, "uploaded": 0, + "seeding_time": 0, "deleted": False, "time": time.time() } @@ -1928,9 +1940,9 @@ class BrushFlow(_PluginBase): if brush_config.size: sizes = [float(size) * 1024 ** 3 for size in brush_config.size.split("-")] if len(sizes) == 1 and torrent.size < sizes[0]: - return False, "种子大小不符合条件" + return False, f"种子大小 {self.__bytes_to_gb(torrent.size):.1f} GB,不符合条件" elif len(sizes) > 1 and not sizes[0] <= torrent.size <= sizes[1]: - return False, "种子大小不在指定范围内" + return False, f"种子大小 {self.__bytes_to_gb(torrent.size):.1f} GB,不在指定范围内" # 做种人数 if brush_config.seeder: @@ -1939,12 +1951,12 @@ class BrushFlow(_PluginBase): if len(seeders_range) == 1: # 当做种人数大于该数字时,不符合条件 if torrent.seeders > seeders_range[0]: - return False, "做种人数超过单个指定值" + return False, f"做种人数 {torrent.seeders},超过单个指定值" # 如果指定了一个范围 elif len(seeders_range) > 1: # 检查做种人数是否在指定的范围内(包括边界) if not (seeders_range[0] <= torrent.seeders <= seeders_range[1]): - return False, "做种人数不在指定范围内" + return False, f"做种人数 {torrent.seeders},不在指定范围内" # 发布时间 pubdate_minutes = self.__get_pubminutes(torrent.pubdate) @@ -1954,11 +1966,11 @@ class BrushFlow(_PluginBase): if len(pubtimes) == 1: # 单个值:选择发布时间小于等于该值的种子 if pubdate_minutes > pubtimes[0]: - return False, "发布时间不符合条件" + return False, f"发布时间 {pubdate_minutes:.0f} 分钟前,不符合条件" else: # 范围值:选择发布时间在范围内的种子 if not (pubtimes[0] <= pubdate_minutes <= pubtimes[1]): - return False, "发布时间不在指定范围内" + return False, f"发布时间 {pubdate_minutes:.0f} 分钟前,不在指定范围内" return True, None @@ -2024,20 +2036,22 @@ class BrushFlow(_PluginBase): # 先更新刷流任务的最新状态,上下传,分享率 self.__update_torrent_tasks_state(torrents=check_torrents, torrent_tasks=torrent_tasks) - # 排除MoviePilot种子 - if check_torrents and brush_config.except_tags: - check_torrents = self.__filter_torrents_by_tag(torrents=check_torrents, - exclude_tag=settings.TORRENT_TAG) - # 先通过获取的全量种子,判断已经被删除,但是任务记录中还没有被标记删除的种子 undeleted_hashes = self.__get_undeleted_torrents_missing_in_downloader(torrent_tasks, torrent_check_hashes, check_torrents) or [] + # 这里提前把已经被删除的种子进行标记,避免开启动态删除种子统计体积有时差 if undeleted_hashes: for torrent_hash in undeleted_hashes: torrent_tasks[torrent_hash]["deleted"] = True + # 排除MoviePilot种子 + if check_torrents and brush_config.except_tags: + check_torrents = self.__filter_torrents_by_tag(torrents=check_torrents, + exclude_tag=settings.TORRENT_TAG) + need_delete_hashes = [] + # 如果配置了删种阈值,则根据动态删种进行分组处理 if brush_config.proxy_delete and brush_config.delete_size_range: logger.info("已开启动态删种,按系统默认动态删种条件开始检查任务") @@ -2080,6 +2094,7 @@ class BrushFlow(_PluginBase): "downloaded": torrent_info.get("downloaded"), "uploaded": torrent_info.get("uploaded"), "ratio": torrent_info.get("ratio"), + "seeding_time": torrent_info.get("seeding_time"), }) def __update_seeding_tasks_based_on_tags(self, torrent_tasks: Dict[str, dict], unmanaged_tasks: Dict[str, dict], @@ -2274,7 +2289,7 @@ class BrushFlow(_PluginBase): torrent_info_map[self.__get_hash(torrent)].get("total_size", 0) for torrent in proxy_delete_torrents if self.__get_hash(torrent) in proxy_delete_hashes) - # 在完成初始删除步骤后,如果总体积仍然超过最小阈值,则进一步找到已完成种子并排除HR种子后按加入时间正序进行删除 + # 在完成初始删除步骤后,如果总体积仍然超过最小阈值,则进一步找到已完成种子并排除HR种子后按做种时间正序进行删除 if total_torrent_size > min_size: # 重新计算当前的种子列表,排除已删除的种子 remaining_hashes = list( @@ -2285,10 +2300,10 @@ class BrushFlow(_PluginBase): remaining_hashes = {self.__get_hash(torrent) for torrent in completed_torrents} remaining_torrents = [(_hash, torrent_info_map[_hash]) for _hash in remaining_hashes] - # 准备一个列表,用于存放满足条件的种子,即非HR种子且有明确加入时间 - filtered_torrents = [(_hash, info['add_on']) for _hash, info in remaining_torrents if + # 准备一个列表,用于存放满足条件的种子,即非HR种子且有明确做种时间 + filtered_torrents = [(_hash, info['seeding_time']) for _hash, info in remaining_torrents if not torrent_tasks[_hash].get("hit_and_run", False)] - sorted_torrents = sorted(filtered_torrents, key=lambda x: x[1]) + sorted_torrents = sorted(filtered_torrents, key=lambda x: x[1], reverse=True) # 进行额外的删除操作,直到满足最小阈值或没有更多种子可删除 for torrent_hash, _ in sorted_torrents: @@ -2305,10 +2320,13 @@ class BrushFlow(_PluginBase): site_name = torrent_task.get("site_name", "") torrent_title = torrent_task.get("title", "") torrent_desc = torrent_task.get("description", "") - reason = "触发动态删除,系统自动删除" - self.__send_delete_message(site_name=site_name, torrent_title=torrent_title, torrent_desc=torrent_desc, - reason=reason) - logger.info(f"站点:{site_name},{reason},删除种子:{torrent_title}|{torrent_desc}") + seeding_time = torrent_task.get("seeding_time", 0) + if seeding_time: + reason = f"触发动态删除,做种时间 {seeding_time / 3600:.1f} 小时,系统自动删除" + self.__send_delete_message(site_name=site_name, torrent_title=torrent_title, + torrent_desc=torrent_desc, + reason=reason) + logger.info(f"站点:{site_name},{reason},删除种子:{torrent_title}|{torrent_desc}") msg = f"已完成 {len(need_delete_hashes)} 个种子删除,当前做种体积 {self.__bytes_to_gb(total_torrent_size):.1f} GB" self.post_message(mtype=NotificationType.SiteMessage, title="【刷流任务种子删除】", text=msg) @@ -2627,7 +2645,7 @@ class BrushFlow(_PluginBase): data = data.get(key) if not data: return None - # logger.info(f"获取到下载地址:{data}") + logger.info(f"获取到下载地址:{data}") return data return None @@ -2649,11 +2667,14 @@ class BrushFlow(_PluginBase): download_dir = brush_config.save_path or None # 获取下载链接 torrent_content = torrent.enclosure + # 部分站点下载种子不需要传递Cookie + need_download_cookie = True if torrent_content.startswith("["): torrent_content = self.__get_redict_url(url=torrent_content, proxies=settings.PROXY if torrent.site_proxy else None, ua=torrent.site_ua, cookie=torrent.site_cookie) + need_download_cookie = False if not torrent_content: logger.error(f"获取下载链接失败:{torrent.title}") return None @@ -2668,7 +2689,7 @@ class BrushFlow(_PluginBase): tag = StringUtils.generate_random_str(10) # 如果开启代理下载以及种子地址不是磁力地址,则请求种子到内存再传入下载器 if brush_config.proxy_download and not torrent_content.startswith("magnet"): - response = RequestUtils(cookies=torrent.site_cookie, + response = RequestUtils(cookies=torrent.site_cookie if need_download_cookie else None, proxies=settings.PROXY if torrent.site_proxy else None, ua=torrent.site_ua).get_res(url=torrent_content) if response and response.ok: @@ -2678,7 +2699,7 @@ class BrushFlow(_PluginBase): if torrent_content: state = self.qb.add_torrent(content=torrent_content, download_dir=download_dir, - cookie=torrent.site_cookie, + cookie=torrent.site_cookie if need_download_cookie else None, tag=["已整理", brush_config.brush_tag, tag], upload_limit=up_speed, download_limit=down_speed) @@ -2699,7 +2720,7 @@ class BrushFlow(_PluginBase): return None # 如果开启代理下载以及种子地址不是磁力地址,则请求种子到内存再传入下载器 if brush_config.proxy_download and not torrent_content.startswith("magnet"): - response = RequestUtils(cookies=torrent.site_cookie, + response = RequestUtils(cookies=torrent.site_cookie if need_download_cookie else None, proxies=settings.PROXY if torrent.site_proxy else None, ua=torrent.site_ua).get_res(url=torrent_content) if response and response.ok: @@ -2709,7 +2730,7 @@ class BrushFlow(_PluginBase): if torrent_content: torrent = self.tr.add_torrent(content=torrent_content, download_dir=download_dir, - cookie=torrent.site_cookie, + cookie=torrent.site_cookie if need_download_cookie else None, labels=["已整理", brush_config.brush_tag]) if not torrent: return None From e1dbd910125fa8ea79fa4199d871f0bcec67be8e Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Tue, 2 Apr 2024 17:28:33 +0800 Subject: [PATCH 2/3] fix brushflow tracker mapping --- plugins/brushflow/__init__.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/plugins/brushflow/__init__.py b/plugins/brushflow/__init__.py index 20a6ba3..d6c6b20 100644 --- a/plugins/brushflow/__init__.py +++ b/plugins/brushflow/__init__.py @@ -7,6 +7,7 @@ import time from datetime import datetime, timedelta from threading import Event from typing import Any, List, Dict, Tuple, Optional, Union, Set +from urllib.parse import urlparse, parse_qs, unquote import pytz from app import schemas @@ -2365,11 +2366,7 @@ class BrushFlow(_PluginBase): """ torrent_info = self.__get_torrent_info(torrent=torrent) - trackers = [tracker.get("url") for tracker in (torrent.trackers or []) if - tracker.get("tier", -1) >= 0 and tracker.get("url")] - trackers.append(torrent_info.get("tracker")) - - site_id, site_name = self.__get_site_by_tracker(trackers=trackers) + site_id, site_name = self.__get_site_by_torrent(torrent=torrent) torrent_task = { "site": site_id, @@ -3334,10 +3331,26 @@ class BrushFlow(_PluginBase): # 情况2: 时间段跨越午夜 return now >= start_time or now <= end_time - def __get_site_by_tracker(self, trackers: list[str]) -> Tuple[int, str]: + def __get_site_by_torrent(self, torrent: Any) -> Tuple[int, str]: """ 根据tracker获取站点信息 """ + trackers = [] + try: + tracker_url = torrent.get("tracker") + if tracker_url: + trackers.append(tracker_url) + + magnet_link = torrent.get("magnet_uri") + if magnet_link: + query_params = parse_qs(urlparse(magnet_link).query) + encoded_tracker_urls = query_params.get('tr', []) + # 解码tracker URLs然后扩展到trackers列表中 + decoded_tracker_urls = [unquote(url) for url in encoded_tracker_urls] + trackers.extend(decoded_tracker_urls) + except Exception as e: + logger.error(e) + domain = "未知" if not trackers: return 0, domain @@ -3350,6 +3363,8 @@ class BrushFlow(_PluginBase): } for tracker in trackers: + if not tracker: + continue # 检查tracker是否包含特定的关键字,并进行相应的映射 for key, mapped_domain in tracker_mappings.items(): if key in tracker: From b68fc6bf6ee8957299a9596431a9773daf284e33 Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Tue, 2 Apr 2024 17:47:41 +0800 Subject: [PATCH 3/3] fix brushflow version --- package.json | 2 +- plugins/brushflow/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 79cb097..844f08d 100644 --- a/package.json +++ b/package.json @@ -226,7 +226,7 @@ "BrushFlow": { "name": "站点刷流", "description": "自动托管刷流,将会提高对应站点的访问频率。", - "version": "2.2", + "version": "2.3", "icon": "brush.jpg", "author": "jxxghp,InfinityPacer", "level": 2 diff --git a/plugins/brushflow/__init__.py b/plugins/brushflow/__init__.py index d30505a..e9a5b5e 100644 --- a/plugins/brushflow/__init__.py +++ b/plugins/brushflow/__init__.py @@ -185,7 +185,7 @@ class BrushFlow(_PluginBase): # 插件图标 plugin_icon = "brush.jpg" # 插件版本 - plugin_version = "2.2" + plugin_version = "2.3" # 插件作者 plugin_author = "jxxghp,InfinityPacer" # 作者主页