nas-tools/app/brushtask.py
2023-02-11 22:42:12 +08:00

860 lines
42 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import re
import sys
import time
from datetime import datetime
import pytz
from apscheduler.schedulers.background import BackgroundScheduler
import log
from app.downloader.client import Qbittorrent, Transmission
from app.filter import Filter
from app.helper import DbHelper
from app.message import Message
from app.rss import Rss
from app.sites import Sites
from app.utils import StringUtils, Torrent, ExceptionUtils
from app.utils.commons import singleton
from app.utils.types import BrushDeleteType
from config import BRUSH_REMOVE_TORRENTS_INTERVAL, Config
@singleton
class BrushTask(object):
message = None
sites = None
filter = None
dbhelper = None
_scheduler = None
_brush_tasks = []
_torrents_cache = []
_downloader_infos = []
_qb_client = "qbittorrent"
_tr_client = "transmission"
def __init__(self):
self.init_config()
def init_config(self):
self.dbhelper = DbHelper()
self.message = Message()
self.sites = Sites()
self.filter = Filter()
# 移除现有任务
try:
if self._scheduler:
self._scheduler.remove_all_jobs()
if self._scheduler.running:
self._scheduler.shutdown()
self._scheduler = None
except Exception as e:
ExceptionUtils.exception_traceback(e)
# 读取下载器列表
downloaders = self.dbhelper.get_user_downloaders()
self._downloader_infos = []
for downloader_info in downloaders:
self._downloader_infos.append(
{
"id": downloader_info.ID,
"name": downloader_info.NAME,
"type": downloader_info.TYPE,
"host": downloader_info.HOST,
"port": downloader_info.PORT,
"username": downloader_info.USERNAME,
"password": downloader_info.PASSWORD,
"save_dir": downloader_info.SAVE_DIR
}
)
# 读取刷流任务列表
self._brush_tasks = self.get_brushtask_info()
if not self._brush_tasks:
return
# 启动RSS任务
task_flag = False
self._scheduler = BackgroundScheduler(timezone=Config().get_timezone())
for task in self._brush_tasks:
if task.get("state") == "Y" and task.get("interval") and str(task.get("interval")).isdigit():
task_flag = True
self._scheduler.add_job(func=self.check_task_rss,
args=[task.get("id")],
trigger='interval',
seconds=int(task.get("interval")) * 60)
# 启动删种任务
if task_flag:
self._scheduler.add_job(func=self.remove_tasks_torrents,
trigger='interval',
seconds=BRUSH_REMOVE_TORRENTS_INTERVAL)
# 启动
self._scheduler.print_jobs()
self._scheduler.start()
log.info("刷流服务启动")
def get_brushtask_info(self, taskid=None):
"""
读取刷流任务列表
"""
brushtasks = self.dbhelper.get_brushtasks()
_brush_tasks = []
for task in brushtasks:
site_info = self.sites.get_sites(siteid=task.SITE)
if site_info:
site_url = StringUtils.get_base_url(site_info.get("signurl") or site_info.get("rssurl"))
else:
site_url = ""
downloader_info = self.get_downloader_info(task.DOWNLOADER)
_brush_tasks.append({
"id": task.ID,
"name": task.NAME,
"site": site_info.get("name"),
"site_id": task.SITE,
"interval": task.INTEVAL,
"state": task.STATE,
"downloader": task.DOWNLOADER,
"downloader_name": downloader_info.get("name"),
"transfer": task.TRANSFER,
"free": task.FREELEECH,
"rss_rule": eval(task.RSS_RULE),
"remove_rule": eval(task.REMOVE_RULE),
"seed_size": task.SEED_SIZE,
"rss_url": site_info.get("rssurl"),
"cookie": site_info.get("cookie"),
"sendmessage": task.SENDMESSAGE,
"forceupload": task.FORCEUPLOAD,
"ua": site_info.get("ua"),
"download_count": task.DOWNLOAD_COUNT,
"remove_count": task.REMOVE_COUNT,
"download_size": StringUtils.str_filesize(task.DOWNLOAD_SIZE),
"upload_size": StringUtils.str_filesize(task.UPLOAD_SIZE),
"lst_mod_date": task.LST_MOD_DATE,
"site_url": site_url
})
if taskid:
for task in _brush_tasks:
if task.get("id") == int(taskid):
return task
return {}
else:
return _brush_tasks
def check_task_rss(self, taskid):
"""
检查RSS并添加下载由定时服务调用
:param taskid: 刷流任务的ID
"""
if not taskid:
return
# 任务信息
taskinfo = self.get_brushtask_info(taskid)
if not taskinfo:
return
# 任务属性
seed_size = taskinfo.get("seed_size")
task_name = taskinfo.get("name")
site_id = taskinfo.get("site_id")
rss_url = taskinfo.get("rss_url")
rss_rule = taskinfo.get("rss_rule")
cookie = taskinfo.get("cookie")
rss_free = taskinfo.get("free")
ua = taskinfo.get("ua")
# 查询站点信息
site_info = self.sites.get_sites(siteid=site_id)
if not site_info:
log.error("【Brush】刷流任务 %s 的站点已不存在,无法刷流!" % task_name)
return
site_name = site_info.get("name")
site_proxy = site_info.get("proxy")
if not rss_url:
log.error("【Brush】站点 %s 未配置RSS订阅地址无法刷流" % site_name)
return
if rss_free and not cookie:
log.warn("【Brush】站点 %s 未配置Cookie无法开启促销刷流" % site_name)
return
# 下载器参数
downloader_cfg = self.get_downloader_info(taskinfo.get("downloader"))
if not downloader_cfg:
log.error("【Brush】任务 %s 下载器不存在,无法刷流!" % task_name)
return
log.info("【Brush】开始站点 %s 的刷流任务:%s..." % (site_name, task_name))
# 检查是否达到保种体积
if not self.__is_allow_new_torrent(taskid=taskid,
taskname=task_name,
seedsize=seed_size,
downloadercfg=downloader_cfg,
dlcount=rss_rule.get("dlcount")):
return
rss_result = Rss.parse_rssxml(rss_url)
if len(rss_result) == 0:
log.warn("【Brush】%s RSS未下载到数据" % site_name)
return
else:
log.info("【Brush】%s RSS获取数据%s" % (site_name, len(rss_result)))
max_dlcount = rss_rule.get("dlcount")
success_count = 0
if max_dlcount:
downloading_count = self.__get_downloading_count(downloader_cfg) or 0
new_torrent_count = int(max_dlcount) - int(downloading_count)
for res in rss_result:
try:
# 种子名
torrent_name = res.get('title')
# 种子链接
enclosure = res.get('enclosure')
# 种子页面
page_url = res.get('link')
# 种子大小
size = res.get('size')
# 发布时间
pubdate = res.get('pubdate')
if enclosure not in self._torrents_cache:
self._torrents_cache.append(enclosure)
else:
log.debug("【Brush】%s 已处理过" % torrent_name)
continue
# 检查种子是否符合选种规则
if not self.__check_rss_rule(rss_rule=rss_rule,
title=torrent_name,
torrent_url=page_url,
torrent_size=size,
pubdate=pubdate,
cookie=cookie,
ua=ua,
proxy=site_proxy):
continue
# 开始下载
log.debug("【Brush】%s 符合条件,开始下载..." % torrent_name)
if self.__download_torrent(downloadercfg=downloader_cfg,
title=torrent_name,
enclosure=enclosure,
size=size,
taskid=taskid,
transfer=True if taskinfo.get("transfer") == 'Y' else False,
sendmessage=True if taskinfo.get("sendmessage") == 'Y' else False,
forceupload=True if taskinfo.get("forceupload") == 'Y' else False,
upspeed=rss_rule.get("upspeed"),
downspeed=rss_rule.get("downspeed"),
taskname=task_name,
site_info=site_info):
# 计数
success_count += 1
# 添加种子后不能超过最大下载数量
if max_dlcount and success_count >= new_torrent_count:
break
# 再判断一次
if not self.__is_allow_new_torrent(taskid=taskid,
taskname=task_name,
seedsize=seed_size,
dlcount=rss_rule.get("dlcount"),
downloadercfg=downloader_cfg):
break
except Exception as err:
ExceptionUtils.exception_traceback(err)
continue
log.info("【Brush】任务 %s 本次添加了 %s 个下载" % (task_name, success_count))
def remove_tasks_torrents(self):
"""
根据条件检查所有任务下载完成的种子,按条件进行删除,并更新任务数据
由定时服务调用
"""
def __send_message(_task_name, _delete_type, _torrent_name):
"""
发送删种消息
"""
_msg_title = "【刷流任务 {} 删除做种】".format(_task_name)
_msg_text = "删除原因:{}\n种子名称:{}".format(_delete_type.value, _torrent_name)
self.message.send_brushtask_remove_message(title=_msg_title, text=_msg_text)
# 遍历所有任务
for taskinfo in self._brush_tasks:
if taskinfo.get("state") != "Y":
continue
try:
# 总上传量
total_uploaded = 0
# 总下载量
total_downloaded = 0
# 可以删种的种子
delete_ids = []
# 需要更新状态的种子
update_torrents = []
# 任务信息
taskid = taskinfo.get("id")
task_name = taskinfo.get("name")
download_id = taskinfo.get("downloader")
remove_rule = taskinfo.get("remove_rule")
sendmessage = True if taskinfo.get("sendmessage") == "Y" else False
# 当前任务种子详情
task_torrents = self.dbhelper.get_brushtask_torrents(taskid)
torrent_ids = [item.DOWNLOAD_ID for item in task_torrents if item.DOWNLOAD_ID]
if not torrent_ids:
continue
# 下载器参数
downloader_cfg = self.get_downloader_info(download_id)
if not downloader_cfg:
log.warn("【Brush】任务 %s 下载器不存在" % task_name)
continue
# 下载器类型
client_type = downloader_cfg.get("type")
# qbittorrent
if client_type == self._qb_client:
downloader = Qbittorrent(config=downloader_cfg)
# 检查完成状态的
torrents, has_err = downloader.get_torrents(ids=torrent_ids, status=["completed"])
# 看看是否有错误, 有错误的话就不处理了
if has_err:
log.warn("【BRUSH】任务 %s 获取种子状态失败" % task_name)
continue
remove_torrent_ids = list(
set(torrent_ids).difference(set([torrent.get("hash") for torrent in torrents])))
for torrent in torrents:
# ID
torrent_id = torrent.get("hash")
# 已开始时间 秒
dltime = int(time.time() - torrent.get("added_on"))
# 已做种时间 秒
date_done = torrent.completion_on if torrent.completion_on > 0 else torrent.added_on
date_now = int(time.mktime(datetime.now().timetuple()))
seeding_time = date_now - date_done if date_done else 0
# 分享率
ratio = torrent.get("ratio") or 0
# 上传量
uploaded = torrent.get("uploaded") or 0
total_uploaded += uploaded
# 平均上传速度 Byte/s
avg_upspeed = int(uploaded / dltime)
# 已未活动 秒
last_activity = int(torrent.get("last_activity", 0))
iatime = date_now - last_activity if last_activity else 0
# 下载量
downloaded = torrent.get("downloaded")
total_downloaded += downloaded
need_delete, delete_type = self.__check_remove_rule(remove_rule=remove_rule,
seeding_time=seeding_time,
ratio=ratio,
uploaded=uploaded,
avg_upspeed=avg_upspeed,
iatime=iatime)
if need_delete:
log.info(
"【Brush】%s 做种达到删种条件:%s,删除任务..." % (torrent.get('name'), delete_type.value))
if sendmessage:
__send_message(task_name, delete_type, torrent.get('name'))
if torrent_id not in delete_ids:
delete_ids.append(torrent_id)
update_torrents.append(("%s,%s" % (uploaded, downloaded), taskid, torrent_id))
# 检查下载中状态的
torrents, has_err = downloader.get_torrents(ids=torrent_ids, status=["downloading"])
# 看看是否有错误, 有错误的话就不处理了
if has_err:
log.warn("【BRUSH】任务 %s 获取种子状态失败" % task_name)
continue
remove_torrent_ids = list(
set(remove_torrent_ids).difference(set([torrent.get("hash") for torrent in torrents])))
for torrent in torrents:
# ID
torrent_id = torrent.get("hash")
# 下载耗时 秒
dltime = int(time.time() - torrent.get("added_on"))
# 上传量 Byte
uploaded = torrent.get("uploaded") or 0
total_uploaded += uploaded
# 平均上传速度 Byte/s
avg_upspeed = int(uploaded / dltime)
# 已未活动 秒
date_now = int(time.mktime(datetime.now().timetuple()))
last_activity = int(torrent.get("last_activity", 0))
iatime = date_now - last_activity if last_activity else 0
# 下载量
downloaded = torrent.get("downloaded")
total_downloaded += downloaded
need_delete, delete_type = self.__check_remove_rule(remove_rule=remove_rule,
dltime=dltime,
avg_upspeed=avg_upspeed,
iatime=iatime)
if need_delete:
log.info(
"【Brush】%s 达到删种条件:%s,删除下载任务..." % (torrent.get('name'), delete_type.value))
if sendmessage:
__send_message(task_name, delete_type, torrent.get('name'))
if torrent_id not in delete_ids:
delete_ids.append(torrent_id)
update_torrents.append(("%s,%s" % (uploaded, downloaded), taskid, torrent_id))
# transmission
else:
# 将查询的torrent_ids转为数字型
torrent_ids = [int(x) for x in torrent_ids if str(x).isdigit()]
# 检查完成状态
downloader = Transmission(config=downloader_cfg)
torrents, has_err = downloader.get_torrents(ids=torrent_ids, status=["seeding", "seed_pending"])
# 看看是否有错误, 有错误的话就不处理了
if has_err:
log.warn("【BRUSH】任务 %s 获取种子状态失败" % task_name)
continue
remove_torrent_ids = list(set(torrent_ids).difference(set([torrent.id for torrent in torrents])))
for torrent in torrents:
# ID
torrent_id = torrent.id
# 做种时间
date_done = torrent.date_done or torrent.date_added
date_now = int(time.mktime(datetime.now().timetuple()))
dltime = date_now - int(time.mktime(torrent.date_added.timetuple()))
seeding_time = date_now - int(time.mktime(date_done.timetuple()))
# 下载量
downloaded = int(torrent.total_size * torrent.progress / 100)
total_downloaded += downloaded
# 分享率
ratio = torrent.ratio or 0
# 上传量
uploaded = int(downloaded * torrent.ratio)
total_uploaded += uploaded
# 平均上传速度
avg_upspeed = int(uploaded / dltime)
need_delete, delete_type = self.__check_remove_rule(remove_rule=remove_rule,
seeding_time=seeding_time,
ratio=ratio,
uploaded=uploaded,
avg_upspeed=avg_upspeed)
if need_delete:
log.info("【Brush】%s 做种达到删种条件:%s,删除任务..." % (torrent.name, delete_type.value))
if sendmessage:
__send_message(task_name, delete_type, torrent.name)
if torrent_id not in delete_ids:
delete_ids.append(torrent_id)
update_torrents.append(("%s,%s" % (uploaded, downloaded), taskid, torrent_id))
# 检查下载状态
torrents, has_err = downloader.get_torrents(ids=torrent_ids,
status=["downloading", "download_pending", "stopped"])
# 看看是否有错误, 有错误的话就不处理了
if has_err:
log.warn("【BRUSH】任务 %s 获取种子状态失败" % task_name)
continue
remove_torrent_ids = list(
set(remove_torrent_ids).difference(set([torrent.id for torrent in torrents])))
for torrent in torrents:
# ID
torrent_id = torrent.id
# 下载耗时
dltime = (datetime.now().astimezone() - torrent.date_added).seconds
# 下载量
downloaded = int(torrent.total_size * torrent.progress / 100)
total_downloaded += downloaded
# 上传量
uploaded = int(downloaded * torrent.ratio)
total_uploaded += uploaded
# 平均上传速度
avg_upspeed = int(uploaded / dltime)
need_delete, delete_type = self.__check_remove_rule(remove_rule=remove_rule,
dltime=dltime,
avg_upspeed=avg_upspeed)
if need_delete:
log.info("【Brush】%s 达到删种条件:%s,删除下载任务..." % (torrent.name, delete_type.value))
if sendmessage:
__send_message(task_name, delete_type, torrent.name)
if torrent_id not in delete_ids:
delete_ids.append(torrent_id)
update_torrents.append(("%s,%s" % (uploaded, downloaded), taskid, torrent_id))
# 手工删除的种子,清除对应记录
if remove_torrent_ids:
log.info("【Brush】任务 %s 的这些下载任务在下载器中不存在,将删除任务记录:%s" % (
task_name, remove_torrent_ids))
for remove_torrent_id in remove_torrent_ids:
self.dbhelper.delete_brushtask_torrent(taskid, remove_torrent_id)
# 更新种子状态为已删除
self.dbhelper.update_brushtask_torrent_state(update_torrents)
# 删除下载器种子
if delete_ids:
downloader.delete_torrents(delete_file=True, ids=delete_ids)
log.info("【Brush】任务 %s 共删除 %s 个刷流下载任务" % (task_name, len(delete_ids)))
else:
log.info("【Brush】任务 %s 本次检查未删除下载任务" % task_name)
# 更新上传下载量和删除种子数
self.dbhelper.add_brushtask_upload_count(brush_id=taskid,
upload_size=total_uploaded,
download_size=total_downloaded,
remove_count=len(delete_ids) + len(remove_torrent_ids))
except Exception as e:
ExceptionUtils.exception_traceback(e)
def __is_allow_new_torrent(self, taskid, taskname, downloadercfg, seedsize, dlcount):
"""
检查是否还能添加新的下载
"""
if not taskid:
return False
# 判断大小
total_size = self.dbhelper.get_brushtask_totalsize(taskid)
if seedsize:
if float(seedsize) * 1024 ** 3 <= int(total_size):
log.warn("【Brush】刷流任务 %s 当前保种体积 %sGB不再新增下载"
% (taskname, round(int(total_size) / 1024 / 1024 / 1024, 1)))
return False
# 检查正在下载的任务数
if dlcount:
downloading_count = self.__get_downloading_count(downloadercfg)
if downloading_count is None:
log.error("【Brush】任务 %s 下载器 %s 无法连接" % (taskname, downloadercfg.get("name")))
return False
if int(downloading_count) >= int(dlcount):
log.warn("【Brush】下载器 %s 正在下载任务数:%s,超过设定上限,暂不添加下载" % (
downloadercfg.get("name"), downloading_count))
return False
return True
def get_downloader_info(self, dlid=None):
"""
获取下载器的参数
"""
if dlid:
for downloader in self._downloader_infos:
if downloader.get('id') == int(dlid):
if downloader.get('type') == self._qb_client:
return {
"id": downloader.get("id"),
"name": downloader.get("name"),
"type": downloader.get("type"),
"save_dir": downloader.get("save_dir"),
"qbhost": downloader.get("host"),
"qbport": downloader.get("port"),
"qbusername": downloader.get("username"),
"qbpassword": downloader.get("password")
}
elif downloader.get('type') == self._tr_client:
return {
"id": downloader.get("id"),
"name": downloader.get("name"),
"type": downloader.get("type"),
"save_dir": downloader.get("save_dir"),
"trhost": downloader.get("host"),
"trport": downloader.get("port"),
"trusername": downloader.get("username"),
"trpassword": downloader.get("password")
}
return downloader
return {}
else:
return self._downloader_infos
def __get_downloading_count(self, downloadercfg):
"""
查询当前正在下载的任务数
"""
if not downloadercfg:
return 0
if downloadercfg.get("type") == self._qb_client:
downloader = Qbittorrent(config=downloadercfg)
if not downloader.qbc:
return None
dlitems = downloader.get_downloading_torrents()
if dlitems is not None:
return int(len(dlitems))
else:
downloader = Transmission(config=downloadercfg)
if not downloader.trc:
return None
dlitems = downloader.get_downloading_torrents()
if dlitems is not None:
return int(len(dlitems))
return None
def __download_torrent(self,
downloadercfg,
title,
enclosure,
size,
taskid,
transfer,
sendmessage,
forceupload,
upspeed,
downspeed,
taskname,
site_info):
"""
添加下载任务,更新任务数据
:param downloadercfg: 下载器的所有参数
:param title: 种子名称
:param enclosure: 种子地址
:param size: 种子大小
:param taskid: 任务ID
:param transfer: 是否要转移为False时直接添加已整理的标签
:param sendmessage: 是否需要消息推送
:param forceupload: 是否需要将添加的刷流任务设置为强制做种(仅针对qBittorrent)
:param upspeed: 上传限速
:param downspeed: 下载限速
:param taskname: 任务名称
:param site_info: 站点信息
"""
if not downloadercfg or not enclosure:
return False
# 标签
tag = "已整理" if not transfer else None
# 下载任务ID
download_id = None
# 下载种子文件
_, content, _, _, retmsg = Torrent().get_torrent_info(
url=enclosure,
cookie=site_info.get("cookie"),
ua=site_info.get("ua"),
proxy=site_info.get("proxy"))
if content:
# 添加下载
if downloadercfg.get("type") == self._qb_client:
# 初始化下载器
downloader = Qbittorrent(config=downloadercfg)
if not downloader.qbc:
log.error("【Brush】任务 %s 下载器 %s 无法连接" % (taskname, downloadercfg.get("name")))
return False
torrent_tag = "NT" + StringUtils.generate_random_str(5)
if tag:
tags = [tag, torrent_tag]
else:
tags = torrent_tag
ret = downloader.add_torrent(content=content,
tag=tags,
download_dir=downloadercfg.get("save_dir"),
upload_limit=upspeed,
download_limit=downspeed)
if ret:
# QB添加下载后需要时间重试5次每次等待5秒
download_id = downloader.get_torrent_id_by_tag(torrent_tag)
if download_id:
# 开始下载
downloader.start_torrents(download_id)
# 强制做种
if forceupload:
downloader.torrents_set_force_start(download_id)
else:
# 初始化下载器
downloader = Transmission(config=downloadercfg)
if not downloader.trc:
log.error("【Brush】任务 %s 下载器 %s 无法连接" % (taskname, downloadercfg.get("name")))
return False
ret = downloader.add_torrent(content=content,
download_dir=downloadercfg.get("save_dir"),
upload_limit=upspeed,
download_limit=downspeed
)
if ret:
download_id = ret.id
# 设置标签
if download_id and tag:
downloader.set_torrent_tag(tid=download_id, tag=tag)
if not download_id:
# 下载失败
log.warn(f"【Brush】{taskname} 添加下载任务出错:{title}"
f"错误原因:{retmsg or '下载器添加任务失败'}"
f"种子链接:{enclosure}")
return False
else:
# 下载成功
log.info("【Brush】成功添加下载%s" % title)
if sendmessage:
msg_title = "【刷流任务 {} 新增下载】".format(taskname)
msg_text = "种子名称:{}\n种子大小:{}".format(title, StringUtils.str_filesize(size))
self.message.send_brushtask_added_message(title=msg_title, text=msg_text)
# 插入种子数据
if self.dbhelper.insert_brushtask_torrent(brush_id=taskid,
title=title,
enclosure=enclosure,
downloader=downloadercfg.get("id"),
download_id=download_id,
size=size):
# 更新下载次数
self.dbhelper.add_brushtask_download_count(brush_id=taskid)
else:
log.info("【Brush】%s 已下载过" % title)
return True
def __check_rss_rule(self,
rss_rule,
title,
torrent_url,
torrent_size,
pubdate,
cookie,
ua,
proxy):
"""
检查种子是否符合刷流过滤条件
:param rss_rule: 过滤条件字典
:param title: 种子名称
:param torrent_url: 种子页面地址
:param torrent_size: 种子大小
:param pubdate: 发布时间
:param cookie: Cookie
:param ua: User-Agent
:return: 是否命中
"""
if not rss_rule:
return True
# 检查种子大小
try:
if rss_rule.get("size"):
rule_sizes = rss_rule.get("size").split("#")
if rule_sizes[0]:
if len(rule_sizes) > 1 and rule_sizes[1]:
min_max_size = rule_sizes[1].split(',')
min_size = min_max_size[0]
if len(min_max_size) > 1:
max_size = min_max_size[1]
else:
max_size = 0
if rule_sizes[0] == "gt" and float(torrent_size) < float(min_size) * 1024 ** 3:
return False
if rule_sizes[0] == "lt" and float(torrent_size) > float(min_size) * 1024 ** 3:
return False
if rule_sizes[0] == "bw" and not float(min_size) * 1024 ** 3 < float(torrent_size) < float(
max_size) * 1024 ** 3:
return False
# 检查包含规则
if rss_rule.get("include"):
if not re.search(r"%s" % rss_rule.get("include"), title):
return False
# 检查排除规则
if rss_rule.get("exclude"):
if re.search(r"%s" % rss_rule.get("exclude"), title):
return False
torrent_attr = self.sites.check_torrent_attr(torrent_url=torrent_url,
cookie=cookie,
ua=ua,
proxy=proxy)
torrent_peer_count = torrent_attr.get("peer_count")
log.debug("【Brush】%s 解析详情, %s" % (title, torrent_attr))
# 检查免费状态
if rss_rule.get("free") == "FREE":
if not torrent_attr.get("free"):
log.debug("【Brush】不是一个FREE资源跳过")
return False
elif rss_rule.get("free") == "2XFREE":
if not torrent_attr.get("2xfree"):
log.debug("【Brush】不是一个2XFREE资源跳过")
return False
# 检查HR状态
if rss_rule.get("hr"):
if torrent_attr.get("hr"):
log.debug("【Brush】这是一个H&R资源跳过")
return False
# 检查做种人数
if rss_rule.get("peercount"):
# 兼容旧版本
peercount_str = rss_rule.get("peercount")
if not peercount_str:
peercount_str = "#"
elif "#" not in peercount_str:
peercount_str = "lt#" + peercount_str
else:
pass
peer_counts = peercount_str.split("#")
if len(peer_counts) >= 2 and peer_counts[1]:
min_max_count = peer_counts[1].split(',')
min_count = int(min_max_count[0])
if len(min_max_count) > 1:
max_count = int(min_max_count[1])
else:
max_count = sys.maxsize
if peer_counts[0] == "gt" and torrent_peer_count <= min_count:
log.debug("【Brush】%s `判断做种数, 判断条件: peer_count:%d %s threshold:%d" % (
title, torrent_peer_count, peer_counts[0], min_count))
return False
if peer_counts[0] == "lt" and torrent_peer_count >= min_count:
log.debug("【Brush】%s `判断做种数, 判断条件: peer_count:%d %s threshold:%d" % (
title, torrent_peer_count, peer_counts[0], min_count))
return False
if peer_counts[0] == "bw" and not (min_count <= torrent_peer_count <= max_count):
log.debug("【Brush】%s `判断做种数, 判断条件: left:%d %s peer_count:%d %s right:%d" % (
title, min_count, peer_counts[0], torrent_peer_count, peer_counts[0], max_count))
return False
# 检查发布时间
if rss_rule.get("pubdate") and pubdate:
rule_pubdates = rss_rule.get("pubdate").split("#")
if len(rule_pubdates) >= 2 and rule_pubdates[1]:
localtz = pytz.timezone(Config().get_timezone())
localnowtime = datetime.now().astimezone(localtz)
localpubdate = pubdate.astimezone(localtz)
log.debug('【Brush】发布时间%s,当前时间:%s' % (localpubdate.isoformat(), localnowtime.isoformat()))
if (localnowtime - localpubdate).seconds / 3600 > float(rule_pubdates[1]):
log.debug("【Brush】发布时间不符合条件。")
return False
except Exception as err:
ExceptionUtils.exception_traceback(err)
return True
@staticmethod
def __check_remove_rule(remove_rule, seeding_time=None, ratio=None, uploaded=None, dltime=None, avg_upspeed=None, iatime=None):
"""
检查是否符合删种规则
:param remove_rule: 删种规则
:param seeding_time: 做种时间
:param ratio: 分享率
:param uploaded: 上传量
:param dltime: 下载耗时
:param avg_upspeed: 上传平均速度
:param iatime: 未活动时间
"""
if not remove_rule:
return False
try:
if remove_rule.get("time") and seeding_time:
rule_times = remove_rule.get("time").split("#")
if rule_times[0]:
if len(rule_times) > 1 and rule_times[1]:
if float(seeding_time) > float(rule_times[1]) * 3600:
return True, BrushDeleteType.SEEDTIME
if remove_rule.get("ratio") and ratio:
rule_ratios = remove_rule.get("ratio").split("#")
if rule_ratios[0]:
if len(rule_ratios) > 1 and rule_ratios[1]:
if float(ratio) > float(rule_ratios[1]):
return True, BrushDeleteType.RATIO
if remove_rule.get("uploadsize") and uploaded:
rule_uploadsizes = remove_rule.get("uploadsize").split("#")
if rule_uploadsizes[0]:
if len(rule_uploadsizes) > 1 and rule_uploadsizes[1]:
if float(uploaded) > float(rule_uploadsizes[1]) * 1024 ** 3:
return True, BrushDeleteType.UPLOADSIZE
if remove_rule.get("dltime") and dltime:
rule_times = remove_rule.get("dltime").split("#")
if rule_times[0]:
if len(rule_times) > 1 and rule_times[1]:
if float(dltime) > float(rule_times[1]) * 3600:
return True, BrushDeleteType.DLTIME
if remove_rule.get("avg_upspeed") and avg_upspeed:
rule_avg_upspeeds = remove_rule.get("avg_upspeed").split("#")
if rule_avg_upspeeds[0]:
if len(rule_avg_upspeeds) > 1 and rule_avg_upspeeds[1]:
if float(avg_upspeed) < float(rule_avg_upspeeds[1]) * 1024:
return True, BrushDeleteType.AVGUPSPEED
if remove_rule.get("iatime") and iatime:
rule_times = remove_rule.get("iatime").split("#")
if rule_times[0]:
if len(rule_times) > 1 and rule_times[1]:
if float(iatime) > float(rule_times[1]) * 3600:
return True, BrushDeleteType.IATIME
except Exception as err:
ExceptionUtils.exception_traceback(err)
return False, BrushDeleteType.NOTDELETE