fix brushflow 增加H&R做种时间、下载器监控配置项,刷流前置条件逻辑调整,代理下载种子默认为关闭

This commit is contained in:
InfinityPacer
2024-04-04 14:54:24 +08:00
parent 551a651707
commit 786de1d8b0
2 changed files with 164 additions and 47 deletions

View File

@@ -226,7 +226,7 @@
"BrushFlow": {
"name": "站点刷流",
"description": "自动托管刷流,将会提高对应站点的访问频率。",
"version": "2.4",
"version": "2.5",
"icon": "brush.jpg",
"author": "jxxghp,InfinityPacer",
"level": 2

View File

@@ -51,6 +51,7 @@ class BrushConfig:
self.seeder = config.get("seeder")
self.pubtime = config.get("pubtime")
self.seed_time = self.__parse_number(config.get("seed_time"))
self.hr_seed_time = self.__parse_number(config.get("hr_seed_time"))
self.seed_ratio = self.__parse_number(config.get("seed_ratio"))
self.seed_size = self.__parse_number(config.get("seed_size"))
self.download_time = self.__parse_number(config.get("download_time"))
@@ -65,12 +66,15 @@ class BrushConfig:
self.except_tags = config.get("except_tags", True)
self.except_subscribe = config.get("except_subscribe", True)
self.brush_sequential = config.get("brush_sequential", False)
self.proxy_download = config.get("proxy_download", True)
self.proxy_download = config.get("proxy_download", False)
self.proxy_delete = config.get("proxy_delete", False)
self.log_more = config.get("log_more", False)
self.active_time_range = config.get("active_time_range")
self.enable_site_config = config.get("enable_site_config", False)
self.downloader_monitor = config.get("downloader_monitor")
self.brush_tag = "刷流"
# 站点独立配置
self.enable_site_config = config.get("enable_site_config", False)
self.site_config = config.get("site_config", "[]")
self.group_site_configs = {}
@@ -91,6 +95,7 @@ class BrushConfig:
"seeder",
"pubtime",
"seed_time",
"hr_seed_time",
"seed_ratio",
"seed_size",
"download_time",
@@ -185,7 +190,7 @@ class BrushFlow(_PluginBase):
# 插件图标
plugin_icon = "brush.jpg"
# 插件版本
plugin_version = "2.4"
plugin_version = "2.5"
# 插件作者
plugin_author = "jxxghp,InfinityPacer"
# 作者主页
@@ -701,6 +706,23 @@ class BrushFlow(_PluginBase):
}
]
},
{
'component': 'VCol',
'props': {
"cols": 12,
"md": 4
},
'content': [
{
'component': 'VTextField',
'props': {
'model': 'hr_seed_time',
'label': 'H&R做种时间小时',
'placeholder': '达到后删除任务'
}
}
]
},
{
'component': 'VCol',
'props': {
@@ -1042,6 +1064,22 @@ class BrushFlow(_PluginBase):
{
'component': 'VRow',
"content": [
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 4
},
'content': [
{
'component': 'VSwitch',
'props': {
'model': 'downloader_monitor',
'label': '下载器监控',
}
}
]
},
{
'component': 'VCol',
'props': {
@@ -1182,12 +1220,13 @@ class BrushFlow(_PluginBase):
"except_tags": True,
"except_subscribe": True,
"brush_sequential": False,
"proxy_download": True,
"proxy_download": False,
"proxy_delete": False,
"freeleech": "free",
"hr": "yes",
"enable_site_config": False,
"log_more": False
"log_more": False,
"downloader_monitor": False,
}
def get_page(self) -> List[dict]:
@@ -1781,7 +1820,7 @@ class BrushFlow(_PluginBase):
# 判断能否通过保种体积刷流条件
size_condition_passed, reason = self.__evaluate_size_condition_for_brush(torrents_size=torrents_size,
brush_torrent_size=torrent.size)
add_torrent_size=torrent.size)
self.__log_brush_conditions(passed=size_condition_passed, reason=reason, torrent=torrent)
if not size_condition_passed:
continue
@@ -1844,26 +1883,42 @@ class BrushFlow(_PluginBase):
return True
def __evaluate_size_condition_for_brush(self, torrents_size: float,
brush_torrent_size: float = 0.0) -> Tuple[bool, Optional[str]]:
add_torrent_size: float = 0.0) -> Tuple[bool, Optional[str]]:
"""
过滤体积不符合条件的种子
"""
total_size = self.__bytes_to_gb(torrents_size + brush_torrent_size) # 预计总做种体积
brush_config = self.__get_brush_config()
# 如果没有明确指定增加的种子大小,则检查配置中是否有种子大小下限,如果有,使用这个大小作为增加的种子大小
preset_condition = False
if not add_torrent_size and brush_config.size:
size_limits = [float(size) * 1024 ** 3 for size in brush_config.size.split("-")]
add_torrent_size = size_limits[0] # 使用配置的种子大小下限
preset_condition = True
total_size = self.__bytes_to_gb(torrents_size + add_torrent_size) # 预计总做种体积
def generate_message(config):
if brush_torrent_size > 0:
return (f"当前做种体积 {self.__bytes_to_gb(torrents_size):.1f} GB"
f"刷流种子 {self.__bytes_to_gb(brush_torrent_size):.1f} GB"
f"预计做种体积 {total_size:.1f} GB已超过做种体积 {config} GB")
if add_torrent_size:
if preset_condition:
return (f"当前做种体积 {self.__bytes_to_gb(torrents_size):.1f} GB"
f"刷流种子下限 {self.__bytes_to_gb(add_torrent_size):.1f} GB"
f"预计做种体积 {total_size:.1f} GB"
f"超过设定的保种体积 {config} GB暂时停止新增任务")
else:
return (f"当前做种体积 {self.__bytes_to_gb(torrents_size):.1f} GB"
f"刷流种子大小 {self.__bytes_to_gb(add_torrent_size):.1f} GB"
f"预计做种体积 {total_size:.1f} GB"
f"超过设定的保种体积 {config} GB")
else:
return f"当前做种体积 {self.__bytes_to_gb(torrents_size):.1f} GB已超过做种体积 {config} GB暂时停止新增任务"
return (f"当前做种体积 {self.__bytes_to_gb(torrents_size):.1f} GB"
f"超过设定的保种体积 {config} GB暂时停止新增任务")
reasons = [
("disksize",
lambda config: torrents_size + brush_torrent_size > float(config) * 1024 ** 3, generate_message)
lambda config: torrents_size + add_torrent_size > float(config) * 1024 ** 3, generate_message)
]
brush_config = self.__get_brush_config()
for condition, check, message in reasons:
config_value = getattr(brush_config, condition, None)
if config_value and check(config_value):
@@ -2021,6 +2076,7 @@ class BrushFlow(_PluginBase):
seeding_torrents_dict = {self.__get_hash(torrent): torrent for torrent in seeding_torrents}
# 检查种子刷流标签变更情况
self.__update_seeding_tasks_based_on_tags(torrent_tasks=torrent_tasks, unmanaged_tasks=unmanaged_tasks,
seeding_torrents_dict=seeding_torrents_dict)
@@ -2096,7 +2152,14 @@ class BrushFlow(_PluginBase):
seeding_torrents_dict: Dict[str, Any]):
brush_config = self.__get_brush_config()
if brush_config.downloader_monitor:
logger.info("已开启下载器监控,开始同步种子刷流标签记录")
else:
logger.info("没有开启下载器监控,取消同步种子刷流标签记录")
return
if not brush_config.downloader == "qbittorrent":
logger.info("同步种子刷流标签记录目前仅支持qbittorrent")
return
# 初始化汇总信息
@@ -2116,15 +2179,15 @@ class BrushFlow(_PluginBase):
torrent_task = unmanaged_tasks.pop(torrent_hash)
torrent_tasks[torrent_hash] = torrent_task
added_tasks.append(torrent_task)
logger.info(
f"站点 {torrent_task.get('site_name')}刷流任务种子再次加入:{torrent_task.get('title')}|{torrent_task.get('description')}")
logger.info(f"站点 {torrent_task.get('site_name')}"
f"刷流任务种子再次加入:{torrent_task.get('title')}|{torrent_task.get('description')}")
else:
# 否则,创建一个新的任务
torrent_task = self.__convert_torrent_info_to_task(torrent)
torrent_tasks[torrent_hash] = torrent_task
added_tasks.append(torrent_task)
logger.info(
f"站点 {torrent_task.get('site_name')}刷流任务种子加入:{torrent_task.get('title')}|{torrent_task.get('description')}")
logger.info(f"站点 {torrent_task.get('site_name')}"
f"刷流任务种子加入:{torrent_task.get('title')}|{torrent_task.get('description')}")
# 包含刷流标签又在刷流任务中,这里额外处理一个特殊逻辑,就是种子在刷流任务中可能被标记删除但实际上又还在下载器中,这里进行重置
else:
torrent_task = torrent_tasks[torrent_hash]
@@ -2132,7 +2195,8 @@ class BrushFlow(_PluginBase):
torrent_task["deleted"] = False
reset_tasks.append(torrent_task)
logger.info(
f"站点 {torrent_task.get('site_name')},在下载器中找到已标记删除的刷流任务对应的种子信息,更新刷流任务状态为正常:{torrent_task.get('title')}|{torrent_task.get('description')}")
f"站点 {torrent_task.get('site_name')},在下载器中找到已标记删除的刷流任务对应的种子信息,"
f"更新刷流任务状态为正常:{torrent_task.get('title')}|{torrent_task.get('description')}")
else:
# 不包含刷流标签但又在刷流任务中,则移除管理
if torrent_hash in torrent_tasks:
@@ -2140,8 +2204,8 @@ class BrushFlow(_PluginBase):
torrent_task = torrent_tasks.pop(torrent_hash)
unmanaged_tasks[torrent_hash] = torrent_task
removed_tasks.append(torrent_task)
logger.info(
f"站点 {torrent_task.get('site_name')}刷流任务种子移除:{torrent_task.get('title')}|{torrent_task.get('description')}")
logger.info(f"站点 {torrent_task.get('site_name')}"
f"刷流任务种子移除:{torrent_task.get('title')}|{torrent_task.get('description')}")
self.save_data("torrents", torrent_tasks)
self.save_data("unmanaged", unmanaged_tasks)
@@ -2183,12 +2247,30 @@ class BrushFlow(_PluginBase):
return proxy_delete_torrents, not_proxy_delete_torrents
def __evaluate_conditions_for_delete(self, site_name: str, torrent_info: dict) -> Tuple[bool, str]:
def __evaluate_conditions_for_delete(self, site_name: str, torrent_info: dict, torrent_task: dict) \
-> Tuple[bool, str]:
"""
评估删除条件并返回是否应删除种子及其原因
"""
brush_config = self.__get_brush_config(sitename=site_name)
reason = "未能满足设置的删除条件"
# 当配置了H&R做种时间/分享率时则H&R种子只有达到预期行为时才会进行删除如果没有配置H&R做种时间/分享率则普通种子的删除规则也适用于H&R种子
# 判断是否为H&R种子并且是否配置了特定的H&R条件
hit_and_run = torrent_task.get("hit_and_run", False)
hr_specific_conditions_configured = hit_and_run and (brush_config.hr_seed_time or brush_config.seed_ratio)
if hr_specific_conditions_configured:
if (brush_config.hr_seed_time and torrent_info.get("seeding_time")
>= float(brush_config.hr_seed_time) * 3600):
return True, (f"H&R种子做种时间 {torrent_info.get('seeding_time') / 3600:.1f} 小时,"
f"大于 {brush_config.hr_seed_time} 小时")
if brush_config.seed_ratio and torrent_info.get("ratio") >= float(brush_config.seed_ratio):
return True, f"H&R种子分享率 {torrent_info.get('ratio'):.2f},大于 {brush_config.seed_ratio}"
return False, "H&R种子未能满足设置的H&R删除条件"
# 处理其他场景1. 不是H&R种子2. 是H&R种子但没有特定条件配置
reason = reason if not hit_and_run else "H&R种子未设置H&R条件未能满足设置的删除条件"
if brush_config.seed_time and torrent_info.get("seeding_time") >= float(brush_config.seed_time) * 3600:
reason = f"做种时间 {torrent_info.get('seeding_time') / 3600:.1f} 小时,大于 {brush_config.seed_time} 小时"
elif brush_config.seed_ratio and torrent_info.get("ratio") >= float(brush_config.seed_ratio):
@@ -2205,15 +2287,16 @@ class BrushFlow(_PluginBase):
brush_config.seed_inactivetime) * 60:
reason = f"未活动时间 {torrent_info.get('iatime') / 60:.0f} 分钟,大于 {brush_config.seed_inactivetime} 分钟"
else:
return False, ""
return False, reason
return True, reason
return True, reason if not hit_and_run else "H&R种子未设置H&R条件" + reason
def __delete_torrent_for_evaluate_conditions(self, torrents: List[Any], torrent_tasks: Dict[str, dict],
proxy_delete: bool = False) -> List:
"""
根据条件删除种子并获取已删除列表
"""
brush_config = self.__get_brush_config()
delete_hashs = []
for torrent in torrents:
@@ -2230,13 +2313,17 @@ class BrushFlow(_PluginBase):
# 删除种子的具体实现可能会根据实际情况略有不同
should_delete, reason = self.__evaluate_conditions_for_delete(site_name=site_name,
torrent_info=torrent_info)
torrent_info=torrent_info,
torrent_task=torrent_task)
if should_delete:
delete_hashs.append(torrent_hash)
reason = "触发动态删除," + reason if proxy_delete else 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}")
else:
if brush_config.log_more:
logger.info(f"站点:{site_name}{reason},不删除种子:{torrent_title}|{torrent_desc}")
return delete_hashs
@@ -2266,11 +2353,13 @@ class BrushFlow(_PluginBase):
# 当总体积未超过最大阈值时,不需要执行删除操作
if total_torrent_size < max_size:
logger.info(
f"当前做种体积 {self.__bytes_to_gb(total_torrent_size):.1f} GB上限 {self.__bytes_to_gb(max_size):.1f} GB下限 {self.__bytes_to_gb(min_size):.1f} GB未触发动态删除")
f"当前做种体积 {self.__bytes_to_gb(total_torrent_size):.1f} GB上限 {self.__bytes_to_gb(max_size):.1f} GB"
f"下限 {self.__bytes_to_gb(min_size):.1f} GB未触发动态删除")
return []
else:
logger.info(
f"当前做种体积 {self.__bytes_to_gb(total_torrent_size):.1f} GB上限 {self.__bytes_to_gb(max_size):.1f} GB下限 {self.__bytes_to_gb(min_size):.1f} GB触发动态删除")
f"当前做种体积 {self.__bytes_to_gb(total_torrent_size):.1f} GB上限 {self.__bytes_to_gb(max_size):.1f} GB"
f"下限 {self.__bytes_to_gb(min_size):.1f} GB触发动态删除")
need_delete_hashes = []
@@ -2337,7 +2426,8 @@ class BrushFlow(_PluginBase):
reason=reason)
logger.info(f"站点:{site_name}{reason},删除种子:{torrent_title}|{torrent_desc}")
msg = f"站点:{''.join(sites_names)}\n内容:已完成 {len(need_delete_hashes)} 个种子删除,当前做种体积 {self.__bytes_to_gb(total_torrent_size):.1f} GB\n原因:触发动态删除"
msg = (f"站点:{''.join(sites_names)}\n内容:已完成 {len(need_delete_hashes)} 个种子删除,"
f"当前做种体积 {self.__bytes_to_gb(total_torrent_size):.1f} GB\n原因:触发动态删除")
logger.info(msg)
self.__send_message(title="【刷流任务状态更新】", text=msg)
@@ -2348,6 +2438,14 @@ class BrushFlow(_PluginBase):
"""
处理已经被删除,但是任务记录中还没有被标记删除的种子
"""
brush_config = self.__get_brush_config()
if brush_config.downloader_monitor:
logger.info("已开启下载器监控,开始同步刷流任务删除记录")
else:
logger.info("没有开启下载器监控,取消同步刷流任务删除记录")
return
# 先通过获取的全量种子,判断已经被删除,但是任务记录中还没有被标记删除的种子
torrent_all_hashes = self.__get_all_hashes(torrents)
missing_hashes = [hash_value for hash_value in torrent_check_hashes if hash_value not in torrent_all_hashes]
@@ -2481,6 +2579,7 @@ class BrushFlow(_PluginBase):
"maxdlspeed": "总下载带宽",
"maxdlcount": "同时下载任务数",
"seed_time": "做种时间",
"hr_seed_time": "H&R做种时间",
"seed_ratio": "分享率",
"seed_size": "上传量",
"download_time": "下载超时时间",
@@ -2550,6 +2649,7 @@ class BrushFlow(_PluginBase):
"seeder": brush_config.seeder,
"pubtime": brush_config.pubtime,
"seed_time": brush_config.seed_time,
"hr_seed_time": brush_config.hr_seed_time,
"seed_ratio": brush_config.seed_ratio,
"seed_size": brush_config.seed_size,
"download_time": brush_config.download_time,
@@ -2568,6 +2668,7 @@ class BrushFlow(_PluginBase):
"proxy_delete": brush_config.proxy_delete,
"log_more": brush_config.log_more,
"active_time_range": brush_config.active_time_range,
"downloader_monitor": brush_config.downloader_monitor,
"enable_site_config": brush_config.enable_site_config,
"site_config": brush_config.site_config
}
@@ -3301,23 +3402,39 @@ class BrushFlow(_PluginBase):
"https://github.com/InfinityPacer/MoviePilot-Plugins/blob/main/README.md "
"进行配置,请注意,只需要保留实际配置内容(删除这段)\n")
config = """[{
"sitename": "测试站点",
"freeleech": "free",
"hr": "no",
"include": "",
"exclude": "",
"size": "10-500",
"seeder": "1",
"pubtime": "5-120",
"seed_time": 120,
"seed_ratio": "",
"seed_size": "",
"download_time": "",
"seed_avgspeed": "",
"seed_inactivetime": "",
"save_path": "/downloads/site1",
"proxy_download": false
}]"""
"sitename": "站点1",
"seed_time": 96,
"hr_seed_time": 144
}, {
"sitename": "站点2",
"hr": "yes",
"size": "10-500",
"seeder": "5-10",
"pubtime": "5-120",
"seed_time": 96,
"save_path": "/downloads/site2",
"proxy_download": true,
"hr_seed_time": 144
}, {
"sitename": "站点3",
"freeleech": "free",
"hr": "yes",
"include": "",
"exclude": "",
"size": "10-500",
"seeder": "1",
"pubtime": "5-120",
"seed_time": 120,
"hr_seed_time": 144,
"seed_ratio": "",
"seed_size": "",
"download_time": "",
"seed_avgspeed": "",
"seed_inactivetime": "",
"save_path": "/downloads/site1",
"proxy_download": false,
"proxy_delete": false,
}]"""
return desc + config
@staticmethod