mirror of
https://github.com/d0zingcat/MoviePilot-Plugins.git
synced 2026-05-13 23:16:47 +00:00
fix brushflow 动态删除种子规则调整,站点独立配置样式优化、日志优化等
This commit is contained in:
@@ -238,11 +238,12 @@
|
||||
"BrushFlow": {
|
||||
"name": "站点刷流",
|
||||
"description": "自动托管刷流,将会提高对应站点的访问频率。",
|
||||
"version": "2.6",
|
||||
"version": "2.7",
|
||||
"icon": "brush.jpg",
|
||||
"author": "jxxghp,InfinityPacer",
|
||||
"level": 2,
|
||||
"history": {
|
||||
"v2.7": "动态删除种子规则调整(请注意查阅插件文档),站点独立配置样式优化、日志优化,修复部分配置项无法配置小数的问题,修复部分场景可能导致重复下载的问题",
|
||||
"v2.6": "修复排除订阅功能",
|
||||
"v2.5": "增加H&R做种时间、下载器监控配置项,刷流前置条件逻辑调整,代理下载种子默认为关闭"
|
||||
}
|
||||
|
||||
@@ -85,7 +85,11 @@ class BrushConfig:
|
||||
|
||||
def __initialize_site_config(self):
|
||||
if not self.site_config:
|
||||
logger.error(f"没有设置站点配置,已关闭站点独立配置并恢复默认配置示例,请检查配置项")
|
||||
self.site_config = self.__get_demo_site_config()
|
||||
self.group_site_configs = {}
|
||||
self.enable_site_config = False
|
||||
return
|
||||
|
||||
# 定义允许覆盖的字段列表
|
||||
allowed_fields = {
|
||||
@@ -130,6 +134,47 @@ class BrushConfig:
|
||||
self.enable_site_config = False
|
||||
self.enabled = False
|
||||
|
||||
@staticmethod
|
||||
def __get_demo_site_config() -> str:
|
||||
desc = ("//以下为配置示例,请参考 "
|
||||
"https://github.com/InfinityPacer/MoviePilot-Plugins/blob/main/README.md "
|
||||
"进行配置,请注意,只需要保留实际配置内容(删除这段)\n")
|
||||
config = """[{
|
||||
"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
|
||||
|
||||
def get_site_config(self, sitename):
|
||||
"""
|
||||
根据站点名称获取特定的BrushConfig实例。如果没有找到站点特定的配置,则返回全局的BrushConfig实例。
|
||||
@@ -192,7 +237,7 @@ class BrushFlow(_PluginBase):
|
||||
# 插件图标
|
||||
plugin_icon = "brush.jpg"
|
||||
# 插件版本
|
||||
plugin_version = "2.6"
|
||||
plugin_version = "2.7"
|
||||
# 插件作者
|
||||
plugin_author = "jxxghp,InfinityPacer"
|
||||
# 作者主页
|
||||
@@ -239,10 +284,6 @@ class BrushFlow(_PluginBase):
|
||||
logger.info("站点刷流任务出错,无法获取插件配置")
|
||||
return False
|
||||
|
||||
# 如果没有站点配置时,增加默认的配置项
|
||||
if not config.get("site_config"):
|
||||
config["site_config"] = self.__get_demo_site_config()
|
||||
|
||||
# 如果配置校验没有通过,那么这里修改配置文件后退出
|
||||
if not self.__validate_and_fix_config(config=config):
|
||||
self._brush_config = BrushConfig(config=config)
|
||||
@@ -941,12 +982,6 @@ class BrushFlow(_PluginBase):
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'component': 'VRow',
|
||||
'content': [
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
'component': 'VRow',
|
||||
'content': [
|
||||
@@ -1148,7 +1183,7 @@ class BrushFlow(_PluginBase):
|
||||
"component": "VDialog",
|
||||
"props": {
|
||||
"model": "dialog_closed",
|
||||
"max-width": "80rem",
|
||||
"max-width": "65rem",
|
||||
"overlay-class": "v-dialog--scrollable v-overlay--scroll-blocked",
|
||||
"content-class": "v-card v-card--density-default v-card--variant-elevated rounded-t"
|
||||
},
|
||||
@@ -1174,12 +1209,12 @@ class BrushFlow(_PluginBase):
|
||||
},
|
||||
'content': [
|
||||
{
|
||||
"component": "VTextarea",
|
||||
"component": "VAceEditor",
|
||||
"props": {
|
||||
"model": "site_config",
|
||||
"placeholder": "请输入站点配置",
|
||||
"label": "站点配置",
|
||||
"rows": 16
|
||||
'modelvalue': 'site_config',
|
||||
'lang': 'json',
|
||||
'theme': 'monokai',
|
||||
'style': 'height: 30rem',
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1747,12 +1782,14 @@ class BrushFlow(_PluginBase):
|
||||
size_condition_passed, reason = self.__evaluate_size_condition_for_brush(torrents_size=torrents_size)
|
||||
self.__log_brush_conditions(passed=size_condition_passed, reason=reason)
|
||||
if not size_condition_passed:
|
||||
logger.info(f"刷流任务执行完成")
|
||||
return
|
||||
|
||||
# 判断能否通过刷流前置条件
|
||||
pre_condition_passed, reason = self.__evaluate_pre_conditions_for_brush()
|
||||
self.__log_brush_conditions(passed=pre_condition_passed, reason=reason)
|
||||
if not pre_condition_passed:
|
||||
logger.info(f"刷流任务执行完成")
|
||||
return
|
||||
|
||||
statistic_info = self.__get_statistic_info()
|
||||
@@ -1823,7 +1860,7 @@ class BrushFlow(_PluginBase):
|
||||
for torrent in torrents:
|
||||
# 判断能否通过刷流前置条件
|
||||
pre_condition_passed, reason = self.__evaluate_pre_conditions_for_brush(include_network_conditions=False)
|
||||
self.__log_brush_conditions(passed=pre_condition_passed, reason=reason, torrent=torrent)
|
||||
self.__log_brush_conditions(passed=pre_condition_passed, reason=reason)
|
||||
if not pre_condition_passed:
|
||||
return False
|
||||
|
||||
@@ -1975,10 +2012,19 @@ class BrushFlow(_PluginBase):
|
||||
"""
|
||||
brush_config = self.__get_brush_config(torrent.site_name)
|
||||
|
||||
# 排除重复种子
|
||||
# 默认根据标题和站点名称进行排除
|
||||
task_key = f"{torrent.site_name}{torrent.title}"
|
||||
if any(task_key == f"{task.get('site_name')}{task.get('title')}" for task in torrent_tasks.values()):
|
||||
return False, "重复种子"
|
||||
|
||||
# 部分站点标题会上新时携带后缀,这里进一步根据种子详情地址进行排除
|
||||
if torrent.page_url:
|
||||
task_page_url = f"{torrent.site_name}{torrent.page_url}"
|
||||
if any(task_page_url == f"{task.get('site_name')}{task.get('page_url')}" for task in
|
||||
torrent_tasks.values()):
|
||||
return False, "重复种子"
|
||||
|
||||
# 促销条件
|
||||
if brush_config.freeleech and torrent.downloadvolumefactor != 0:
|
||||
return False, "非免费种子"
|
||||
@@ -2011,7 +2057,7 @@ class BrushFlow(_PluginBase):
|
||||
|
||||
# 做种人数
|
||||
if brush_config.seeder:
|
||||
seeders_range = [int(n) for n in brush_config.seeder.split("-")]
|
||||
seeders_range = [float(n) for n in brush_config.seeder.split("-")]
|
||||
# 检查是否仅指定了一个数字,即做种人数需要小于等于该数字
|
||||
if len(seeders_range) == 1:
|
||||
# 当做种人数大于该数字时,不符合条件
|
||||
@@ -2027,7 +2073,7 @@ class BrushFlow(_PluginBase):
|
||||
pubdate_minutes = self.__get_pubminutes(torrent.pubdate)
|
||||
pubdate_minutes = self.__adjust_site_pubminutes(pubdate_minutes, torrent)
|
||||
if brush_config.pubtime:
|
||||
pubtimes = [int(n) for n in brush_config.pubtime.split("-")]
|
||||
pubtimes = [float(n) for n in brush_config.pubtime.split("-")]
|
||||
if len(pubtimes) == 1:
|
||||
# 单个值:选择发布时间小于等于该值的种子
|
||||
if pubdate_minutes > pubtimes[0]:
|
||||
@@ -2045,7 +2091,7 @@ class BrushFlow(_PluginBase):
|
||||
"""
|
||||
if not passed:
|
||||
if not torrent:
|
||||
logger.warn(f"种子没有通过前置刷流条件校验,原因:{reason}")
|
||||
logger.warn(f"没有通过前置刷流条件校验,原因:{reason}")
|
||||
else:
|
||||
brush_config = self.__get_brush_config()
|
||||
if brush_config.log_more:
|
||||
@@ -2112,7 +2158,7 @@ class BrushFlow(_PluginBase):
|
||||
|
||||
need_delete_hashes = []
|
||||
|
||||
# 如果配置了删种阈值,则根据动态删种进行分组处理
|
||||
# 如果配置了动态删除以及删种阈值,则根据动态删种进行分组处理
|
||||
if brush_config.proxy_delete and brush_config.delete_size_range:
|
||||
logger.info("已开启动态删种,按系统默认动态删种条件开始检查任务")
|
||||
proxy_delete_hashs = self.__delete_torrent_for_proxy(torrents=check_torrents,
|
||||
@@ -2300,6 +2346,22 @@ class BrushFlow(_PluginBase):
|
||||
|
||||
return True, reason if not hit_and_run else "H&R种子(未设置H&R条件)," + reason
|
||||
|
||||
def __evaluate_proxy_pre_conditions_for_delete(self, site_name: str, torrent_info: dict) -> Tuple[bool, str]:
|
||||
"""
|
||||
评估动态删除前置条件并返回是否应删除种子及其原因
|
||||
"""
|
||||
brush_config = self.__get_brush_config(sitename=site_name)
|
||||
|
||||
reason = "未能满足动态删除设置的前置删除条件"
|
||||
|
||||
if brush_config.download_time and torrent_info.get("downloaded") < torrent_info.get(
|
||||
"total_size") and torrent_info.get("dltime") >= float(brush_config.download_time) * 3600:
|
||||
reason = f"下载耗时 {torrent_info.get('dltime') / 3600:.1f} 小时,大于 {brush_config.download_time} 小时"
|
||||
else:
|
||||
return False, reason
|
||||
|
||||
return True, reason
|
||||
|
||||
def __delete_torrent_for_evaluate_conditions(self, torrents: List[Any], torrent_tasks: Dict[str, dict],
|
||||
proxy_delete: bool = False) -> List:
|
||||
"""
|
||||
@@ -2336,11 +2398,54 @@ class BrushFlow(_PluginBase):
|
||||
|
||||
return delete_hashs
|
||||
|
||||
def __delete_torrent_for_proxy(self, torrents: List[Any], torrent_tasks: Dict[str, dict]) -> List:
|
||||
def __delete_torrent_for_evaluate_proxy_pre_conditions(self, torrents: List[Any],
|
||||
torrent_tasks: Dict[str, dict]) -> List:
|
||||
"""
|
||||
支持动态删除种子,当设置了动态删种(全局)和删除阈值时,当做种体积达到删除阈值时,优先按设置规则进行删除,若还没有达到阈值,则排除HR种子后按加入时间倒序进行删除
|
||||
删除阈值:100,当做种体积 > 100G 时,则开始删除种子,直至降低至 100G
|
||||
删除阈值:50-100,当做种体积 > 100G 时,则开始删除种子,直至降至为 50G
|
||||
根据动态删除前置条件排除H&R种子后删除种子并获取已删除列表
|
||||
"""
|
||||
brush_config = self.__get_brush_config()
|
||||
delete_hashs = []
|
||||
|
||||
for torrent in torrents:
|
||||
torrent_hash = self.__get_hash(torrent)
|
||||
torrent_task = torrent_tasks.get(torrent_hash, None)
|
||||
# 如果找不到种子任务,说明不在管理的种子范围内,直接跳过
|
||||
if not torrent_task:
|
||||
continue
|
||||
|
||||
# 如果是H&R种子,前置条件中不进行处理
|
||||
if torrent_task.get('hit_and_run', False):
|
||||
continue
|
||||
|
||||
site_name = torrent_task.get("site_name", "")
|
||||
torrent_title = torrent_task.get("title", "")
|
||||
torrent_desc = torrent_task.get("description", "")
|
||||
|
||||
torrent_info = self.__get_torrent_info(torrent)
|
||||
|
||||
# 删除种子的具体实现可能会根据实际情况略有不同
|
||||
should_delete, reason = self.__evaluate_proxy_pre_conditions_for_delete(site_name=site_name,
|
||||
torrent_info=torrent_info)
|
||||
if should_delete:
|
||||
delete_hashs.append(torrent_hash)
|
||||
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
|
||||
|
||||
def __delete_torrent_for_proxy(self, torrents: List[Any], torrent_tasks: Dict[str, dict]) -> List:
|
||||
"""
|
||||
动态删除种子,删除规则如下;
|
||||
- 不管做种体积是否超过设定的动态删除阈值,默认优先执行排除H&R种子后满足「下载超时时间」的种子
|
||||
- 上述规则执行完成后,当做种体积依旧超过设定的动态删除阈值时,继续执行下述种子删除规则
|
||||
- 优先删除满足用户设置删除规则的全部种子,即便在删除过程中已经低于了阈值下限,也会继续删除
|
||||
- 若删除后还没有达到阈值,则在已完成种子中排除H&R种子后按做种时间倒序进行删除
|
||||
- 动态删除阈值:100,当做种体积 > 100G 时,则开始删除种子,直至降低至 100G
|
||||
- 动态删除阈值:50-100,当做种体积 > 100G 时,则开始删除种子,直至降至为 50G
|
||||
"""
|
||||
brush_config = self.__get_brush_config()
|
||||
|
||||
@@ -2348,29 +2453,49 @@ class BrushFlow(_PluginBase):
|
||||
if not (brush_config.proxy_delete and brush_config.delete_size_range):
|
||||
return []
|
||||
|
||||
# 获取种子信息Map
|
||||
torrent_info_map = {self.__get_hash(torrent): self.__get_torrent_info(torrent=torrent) for torrent in torrents}
|
||||
|
||||
# 计算当前总做种体积
|
||||
total_torrent_size = self.__calculate_seeding_torrents_size(torrent_tasks=torrent_tasks)
|
||||
|
||||
logger.info(
|
||||
f"当前做种体积 {self.__bytes_to_gb(total_torrent_size):.1f} GB,正在准备计算满足动态前置删除条件的种子")
|
||||
|
||||
# 执行排除H&R种子后满足前置删除条件的种子
|
||||
pre_delete_hashes = self.__delete_torrent_for_evaluate_proxy_pre_conditions(torrents=torrents,
|
||||
torrent_tasks=torrent_tasks) or []
|
||||
|
||||
# 如果存在前置删除种子,这里进行额外判断,总做种体积排除前置删除种子的体积
|
||||
if pre_delete_hashes:
|
||||
pre_delete_total_size = sum(torrent_info_map[self.__get_hash(torrent)].get("total_size", 0)
|
||||
for torrent in torrents if self.__get_hash(torrent) in pre_delete_hashes)
|
||||
total_torrent_size = total_torrent_size - pre_delete_total_size
|
||||
torrents = [torrent for torrent in torrents if self.__get_hash(torrent) not in pre_delete_hashes]
|
||||
logger.info(
|
||||
f"满足动态删除前置条件的种子共 {len(pre_delete_hashes)} 个,体积 {self.__bytes_to_gb(pre_delete_total_size):.1f} GB,"
|
||||
f"删除种子后,当前做种体积 {self.__bytes_to_gb(total_torrent_size):.1f} GB")
|
||||
else:
|
||||
logger.info(f"没有找到任何满足动态删除前置条件的种子")
|
||||
|
||||
# 解析删除阈值范围
|
||||
sizes = [float(size) * 1024 ** 3 for size in brush_config.delete_size_range.split("-")]
|
||||
min_size = sizes[0] # 至少需要达到的做种体积
|
||||
max_size = sizes[1] if len(sizes) > 1 else sizes[0] # 触发删除操作的做种体积上限
|
||||
|
||||
torrent_info_map = {self.__get_hash(torrent): self.__get_torrent_info(torrent=torrent) for torrent in torrents}
|
||||
|
||||
# 计算当前总做种体积
|
||||
# total_torrent_size = sum(info.get("total_size", 0) for info in torrent_info_map.values())
|
||||
total_torrent_size = self.__calculate_seeding_torrents_size(torrent_tasks=torrent_tasks)
|
||||
|
||||
# 当总体积未超过最大阈值时,不需要执行删除操作
|
||||
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,"
|
||||
f"下限 {self.__bytes_to_gb(min_size):.1f} GB,未触发动态删除")
|
||||
return []
|
||||
f"下限 {self.__bytes_to_gb(min_size):.1f} GB,未进一步触发动态删除")
|
||||
return pre_delete_hashes or []
|
||||
else:
|
||||
logger.info(
|
||||
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,触发动态删除")
|
||||
f"下限 {self.__bytes_to_gb(min_size):.1f} GB,进一步触发动态删除")
|
||||
|
||||
need_delete_hashes = []
|
||||
need_delete_hashes.extend(pre_delete_hashes)
|
||||
|
||||
# 即使开了动态删除,但是也有可能部分站点单独设置了关闭,这里根据种子托管进行分组,先处理不需要托管的种子,按设置的规则进行删除
|
||||
proxy_delete_torrents, not_proxy_delete_torrents = self.__group_torrents_by_proxy_delete(torrents=torrents,
|
||||
@@ -2395,7 +2520,6 @@ class BrushFlow(_PluginBase):
|
||||
self.__get_hash(torrent) in proxy_delete_hashes)
|
||||
|
||||
# 在完成初始删除步骤后,如果总体积仍然超过最小阈值,则进一步找到已完成种子并排除HR种子后按做种时间正序进行删除
|
||||
sites_names = set()
|
||||
if total_torrent_size > min_size:
|
||||
# 重新计算当前的种子列表,排除已删除的种子
|
||||
remaining_hashes = list(
|
||||
@@ -2428,14 +2552,15 @@ class BrushFlow(_PluginBase):
|
||||
torrent_desc = torrent_task.get("description", "")
|
||||
seeding_time = torrent_task.get("seeding_time", 0)
|
||||
if seeding_time:
|
||||
sites_names.add(site_name)
|
||||
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"站点:{','.join(sites_names)}\n内容:已完成 {len(need_delete_hashes)} 个种子删除,"
|
||||
delete_sites = {torrent_tasks[hash_key].get('site_name', '') for hash_key in need_delete_hashes if
|
||||
hash_key in torrent_tasks}
|
||||
msg = (f"站点:{','.join(delete_sites)}\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)
|
||||
@@ -2817,7 +2942,7 @@ class BrushFlow(_PluginBase):
|
||||
if response and response.ok:
|
||||
torrent_content = response.content
|
||||
else:
|
||||
logger.error('代理下载种子失败,继续尝试传递种子地址到下载器进行下载')
|
||||
logger.error('尝试通过MP下载种子失败,继续尝试传递种子地址到下载器进行下载')
|
||||
if torrent_content:
|
||||
state = self.qb.add_torrent(content=torrent_content,
|
||||
download_dir=download_dir,
|
||||
@@ -2832,7 +2957,7 @@ class BrushFlow(_PluginBase):
|
||||
torrent_hash = self.qb.get_torrent_id_by_tag(tags=tag)
|
||||
if not torrent_hash:
|
||||
logger.error(f"{brush_config.downloader} 获取种子Hash失败"
|
||||
f"{',请尝试开启代理下载种子' if not brush_config.proxy_download else ''}")
|
||||
f"{',请尝试启用「代理下载种子」配置项' if not brush_config.proxy_download else ''}")
|
||||
return None
|
||||
return torrent_hash
|
||||
return None
|
||||
@@ -2848,7 +2973,7 @@ class BrushFlow(_PluginBase):
|
||||
if response and response.ok:
|
||||
torrent_content = response.content
|
||||
else:
|
||||
logger.error('代理下载种子失败,继续尝试传递种子地址到下载器进行下载')
|
||||
logger.error('尝试通过MP下载种子失败,继续尝试传递种子地址到下载器进行下载')
|
||||
if torrent_content:
|
||||
torrent = self.tr.add_torrent(content=torrent_content,
|
||||
download_dir=download_dir,
|
||||
@@ -3364,9 +3489,9 @@ class BrushFlow(_PluginBase):
|
||||
@staticmethod
|
||||
def __is_number_or_range(value):
|
||||
"""
|
||||
检查字符串是否表示单个数字或数字范围(如'5'或'5-10')
|
||||
检查字符串是否表示单个数字或数字范围(如'5', '5.5', '5-10' 或 '5.5-10.2')
|
||||
"""
|
||||
return bool(re.match(r"^\d+(-\d+)?$", value))
|
||||
return bool(re.match(r"^\d+(\.\d+)?(-\d+(\.\d+)?)?$", value))
|
||||
|
||||
@staticmethod
|
||||
def __is_number(value):
|
||||
@@ -3442,47 +3567,6 @@ class BrushFlow(_PluginBase):
|
||||
}
|
||||
return statistic_info
|
||||
|
||||
@staticmethod
|
||||
def __get_demo_site_config() -> str:
|
||||
desc = ("以下为配置示例,请参考 "
|
||||
"https://github.com/InfinityPacer/MoviePilot-Plugins/blob/main/README.md "
|
||||
"进行配置,请注意,只需要保留实际配置内容(删除这段)\n")
|
||||
config = """[{
|
||||
"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
|
||||
def __is_valid_time_range(time_range: str) -> bool:
|
||||
"""检查时间范围字符串是否有效:格式为"HH:MM-HH:MM",且时间有效"""
|
||||
|
||||
Reference in New Issue
Block a user