Merge pull request #929 from thsrite/main

This commit is contained in:
jxxghp
2023-10-20 14:33:27 +08:00
committed by GitHub
22 changed files with 388 additions and 74 deletions

View File

@ -0,0 +1,224 @@
from typing import Any, List, Dict, Tuple
from app.chain.site import SiteChain
from app.core.event import eventmanager
from app.db.site_oper import SiteOper
from app.log import logger
from app.plugins import _PluginBase
from app.schemas.types import EventType, NotificationType
from app.utils.string import StringUtils
class AutoLogin(_PluginBase):
# 插件名称
plugin_name = "自动登录"
# 插件描述
plugin_desc = "配置站点用户名和密码、Cookie过期自动登录刷新Cookie和Ua。"
# 插件图标
plugin_icon = "login.png"
# 主题色
plugin_color = "#99b3ff"
# 插件版本
plugin_version = "1.0"
# 插件作者
plugin_author = "thsrite"
# 作者主页
author_url = "https://github.com/thsrite"
# 插件配置项ID前缀
plugin_config_prefix = "autologin_"
# 加载顺序
plugin_order = 2
# 可使用的用户级别
auth_level = 2
# 私有属性
siteoper: SiteOper = None
# 配置属性
_enabled: bool = False
_notify: bool = False
"""
格式
站点domain|用户名|用户密码
"""
_siteconf: list = []
def init_plugin(self, config: dict = None):
self.siteoper = SiteOper()
# 配置
if config:
self._enabled = config.get("enabled")
self._notify = config.get("notify")
self._siteconf = str(config.get("siteconf")).split('\n')
def get_state(self) -> bool:
return self._enabled
@eventmanager.register(EventType.SiteLogin)
def site_login(self, event):
"""
开始站点登录
"""
if not self.get_state():
return
# 站点id
site_id = event.event_data.get("site_id")
if not site_id:
logger.error(f"未获取到site_id")
return
site = self.siteoper.get(site_id)
if not site:
logger.error(f"未获取到site_id {site_id} 对应的站点数据")
return
site_name = site.name
logger.info(f"开始尝试登录站点 {site_name}")
siteurl, siteuser, sitepwd = None, None, None
# 判断site是否已配置用户名密码
for site_conf in self._siteconf:
if not site_conf:
continue
site_confs = str(site_conf).split("|")
if len(site_confs) == 3:
siteurl = site_confs[0]
siteuser = site_confs[1]
sitepwd = site_confs[2]
else:
logger.error(f"{site_conf}配置有误,已跳过")
continue
# 判断是否是目标域名
if str(siteurl) in StringUtils.get_url_domain(site.url):
# 找到目标域名配置,跳出循环
break
# 开始登录更新cookie和ua
if siteurl and siteuser and sitepwd:
state, messages = SiteChain().update_cookie(site_info=site,
username=siteuser,
password=sitepwd)
if state:
logger.info(f"站点{site_name}自动更新Cookie和Ua成功")
else:
logger.error(f"站点{site_name}自动更新Cookie和Ua失败")
if self._notify:
self.post_message(mtype=NotificationType.SiteMessage,
title=f"站点 {site_name} 自动更新Cookie和Ua{'成功' if state else '失败'}")
else:
logger.error(f"未获取到站点{site_name}配置,已跳过")
@staticmethod
def get_command() -> List[Dict[str, Any]]:
pass
def get_api(self) -> List[Dict[str, Any]]:
pass
def get_form(self) -> Tuple[List[dict], Dict[str, Any]]:
"""
拼装插件配置页面需要返回两块数据1、页面配置2、数据结构
"""
return [
{
'component': 'VForm',
'content': [
{
'component': 'VRow',
'content': [
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 6
},
'content': [
{
'component': 'VSwitch',
'props': {
'model': 'enabled',
'label': '启用插件',
}
}
]
},
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 6
},
'content': [
{
'component': 'VSwitch',
'props': {
'model': 'notify',
'label': '开启通知',
}
}
]
}
]
},
{
'component': 'VRow',
'content': [
{
'component': 'VCol',
'props': {
'cols': 12
},
'content': [
{
'component': 'VTextarea',
'props': {
'model': 'siteconf',
'label': '站点配置',
'rows': 5,
'placeholder': '每一行一个站点,配置方式:\n'
'域名domain|用户名|用户密码\n'
}
}
]
}
]
},
{
'component': 'VRow',
'content': [
{
'component': 'VCol',
'props': {
'cols': 12,
},
'content': [
{
'component': 'VAlert',
'props': {
'text': '站点签到提示Cookie过期时自动触发。'
'不支持开启两步认证的站点。'
'不是所有站点都支持,失败请手动更新。'
}
}
]
}
]
}
]
}
], {
"enabled": False,
"notify": False,
"siteconf": ""
}
def get_page(self) -> List[dict]:
pass
def stop_service(self):
"""
退出插件
"""
pass

View File

@ -72,6 +72,7 @@ class AutoSignIn(_PluginBase):
_clean: bool = False _clean: bool = False
_start_time: int = None _start_time: int = None
_end_time: int = None _end_time: int = None
_auto_cf: int = 0
def init_plugin(self, config: dict = None): def init_plugin(self, config: dict = None):
self.sites = SitesHelper() self.sites = SitesHelper()
@ -91,6 +92,7 @@ class AutoSignIn(_PluginBase):
self._sign_sites = config.get("sign_sites") or [] self._sign_sites = config.get("sign_sites") or []
self._login_sites = config.get("login_sites") or [] self._login_sites = config.get("login_sites") or []
self._retry_keyword = config.get("retry_keyword") self._retry_keyword = config.get("retry_keyword")
self._auto_cf = config.get("auto_cf")
self._clean = config.get("clean") self._clean = config.get("clean")
# 过滤掉已删除的站点 # 过滤掉已删除的站点
@ -206,6 +208,7 @@ class AutoSignIn(_PluginBase):
"sign_sites": self._sign_sites, "sign_sites": self._sign_sites,
"login_sites": self._login_sites, "login_sites": self._login_sites,
"retry_keyword": self._retry_keyword, "retry_keyword": self._retry_keyword,
"auto_cf": self._auto_cf,
"clean": self._clean, "clean": self._clean,
} }
) )
@ -333,7 +336,7 @@ class AutoSignIn(_PluginBase):
'component': 'VCol', 'component': 'VCol',
'props': { 'props': {
'cols': 12, 'cols': 12,
'md': 4 'md': 3
}, },
'content': [ 'content': [
{ {
@ -350,7 +353,7 @@ class AutoSignIn(_PluginBase):
'component': 'VCol', 'component': 'VCol',
'props': { 'props': {
'cols': 12, 'cols': 12,
'md': 4 'md': 3
}, },
'content': [ 'content': [
{ {
@ -366,7 +369,7 @@ class AutoSignIn(_PluginBase):
'component': 'VCol', 'component': 'VCol',
'props': { 'props': {
'cols': 12, 'cols': 12,
'md': 4 'md': 3
}, },
'content': [ 'content': [
{ {
@ -378,6 +381,23 @@ class AutoSignIn(_PluginBase):
} }
} }
] ]
},
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 3
},
'content': [
{
'component': 'VTextField',
'props': {
'model': 'auto_cf',
'label': '自动优选',
'placeholder': '0为不开启命中重试关键词达到数量自动进行Cloudflare IP优选'
}
}
]
} }
] ]
}, },
@ -443,6 +463,25 @@ class AutoSignIn(_PluginBase):
] ]
} }
] ]
},
{
'component': 'VRow',
'content': [
{
'component': 'VCol',
'props': {
'cols': 12,
},
'content': [
{
'component': 'VAlert',
'props': {
'text': '自动Cloudflare IP优选0=不开启命中重试关键词数量大于该数量时自动执行Cloudflare IP优选。需要开启且则正确配置Cloudflare IP优选插件和自定义Hosts插件'
}
}
]
}
]
} }
] ]
} }
@ -450,6 +489,7 @@ class AutoSignIn(_PluginBase):
"enabled": False, "enabled": False,
"notify": True, "notify": True,
"cron": "", "cron": "",
"auto_cf": 0,
"onlyonce": False, "onlyonce": False,
"clean": False, "clean": False,
"queue_cnt": 5, "queue_cnt": 5,
@ -710,6 +750,15 @@ class AutoSignIn(_PluginBase):
elif '已签到' in s: elif '已签到' in s:
already_sign_msg.append(s) already_sign_msg.append(s)
else: else:
if 'Cookie已失效' in s and site_id:
# 触发自动登录插件登录
autologin = self.get_config("AutoLogin")
if autologin and autologin.get("enabled") and autologin.get("siteconf"):
logger.info(f"触发站点 {site_name} 自动登录更新Cookie和Ua")
self.eventmanager.send_event(EventType.SiteLogin,
{
"site_id": site_id
})
failed_msg.append(s) failed_msg.append(s)
if not self._retry_keyword: if not self._retry_keyword:
@ -724,6 +773,10 @@ class AutoSignIn(_PluginBase):
"retry": retry_sites "retry": retry_sites
}) })
# 自动Cloudflare IP优选
if self._auto_cf and self._auto_cf > 0 and retry_msg and len(retry_msg) > self._auto_cf:
EventManager().send_event(EventType.CloudFlareSpeedTest, {})
# 发送通知 # 发送通知
if self._notify: if self._notify:
# 签到详细信息 登录成功、签到成功、已签到、仿真签到成功、失败--命中重试 # 签到详细信息 登录成功、签到成功、已签到、仿真签到成功、失败--命中重试

View File

@ -59,8 +59,8 @@ class Pt52(_ISiteSigninHandler):
return False, '签到失败,请检查站点连通性' return False, '签到失败,请检查站点连通性'
if "login.php" in html_text: if "login.php" in html_text:
logger.error(f"{site} 签到失败Cookie失效") logger.error(f"{site} 签到失败Cookie失效")
return False, '签到失败Cookie失效' return False, '签到失败Cookie失效'
sign_status = self.sign_in_result(html_res=html_text, sign_status = self.sign_in_result(html_res=html_text,
regexs=self._sign_regex) regexs=self._sign_regex)

View File

@ -51,8 +51,8 @@ class BTSchool(_ISiteSigninHandler):
return False, '签到失败,请检查站点连通性' return False, '签到失败,请检查站点连通性'
if "login.php" in html_text: if "login.php" in html_text:
logger.error(f"{site} 签到失败Cookie失效") logger.error(f"{site} 签到失败Cookie失效")
return False, '签到失败Cookie失效' return False, '签到失败Cookie失效'
# 已签到 # 已签到
if self._sign_text not in html_text: if self._sign_text not in html_text:

View File

@ -60,8 +60,8 @@ class CHDBits(_ISiteSigninHandler):
return False, '签到失败,请检查站点连通性' return False, '签到失败,请检查站点连通性'
if "login.php" in html_text: if "login.php" in html_text:
logger.error(f"{site} 签到失败Cookie失效") logger.error(f"{site} 签到失败Cookie失效")
return False, '签到失败Cookie失效' return False, '签到失败Cookie失效'
sign_status = self.sign_in_result(html_res=html_text, sign_status = self.sign_in_result(html_res=html_text,
regexs=self._sign_regex) regexs=self._sign_regex)

View File

@ -49,8 +49,8 @@ class HaiDan(_ISiteSigninHandler):
return False, '签到失败,请检查站点连通性' return False, '签到失败,请检查站点连通性'
if "login.php" in html_text: if "login.php" in html_text:
logger.error(f"{site} 签到失败Cookie失效") logger.error(f"{site} 签到失败Cookie失效")
return False, '签到失败Cookie失效' return False, '签到失败Cookie失效'
sign_status = self.sign_in_result(html_res=html_text, sign_status = self.sign_in_result(html_res=html_text,
regexs=self._succeed_regex) regexs=self._succeed_regex)

View File

@ -53,8 +53,8 @@ class Hares(_ISiteSigninHandler):
return False, '模拟访问失败,请检查站点连通性' return False, '模拟访问失败,请检查站点连通性'
if "login.php" in html_text: if "login.php" in html_text:
logger.error(f"{site} 模拟访问失败Cookie失效") logger.error(f"{site} 模拟访问失败Cookie失效")
return False, '模拟访问失败Cookie失效' return False, '模拟访问失败Cookie失效'
# if self._sign_text in html_res.text: # if self._sign_text in html_res.text:
# logger.info(f"今日已签到") # logger.info(f"今日已签到")

View File

@ -53,8 +53,8 @@ class HD4fans(_ISiteSigninHandler):
return False, '签到失败,请检查站点连通性' return False, '签到失败,请检查站点连通性'
if "login.php" in html_text: if "login.php" in html_text:
logger.error(f"{site} 签到失败,cookie失效") logger.error(f"{site} 签到失败,Cookie失效")
return False, '签到失败,cookie失效' return False, '签到失败,Cookie失效'
# 判断是否已签到 # 判断是否已签到
if self._repeat_text in html_text: if self._repeat_text in html_text:

View File

@ -54,8 +54,8 @@ class HDArea(_ISiteSigninHandler):
return False, '签到失败,请检查站点连通性' return False, '签到失败,请检查站点连通性'
if "login.php" in html_res.text: if "login.php" in html_res.text:
logger.error(f"{site} 签到失败Cookie失效") logger.error(f"{site} 签到失败Cookie失效")
return False, '签到失败Cookie失效' return False, '签到失败Cookie失效'
# 判断是否已签到 # 判断是否已签到
# '已连续签到278天此次签到您获得了100魔力值奖励!' # '已连续签到278天此次签到您获得了100魔力值奖励!'

View File

@ -52,8 +52,8 @@ class HDChina(_ISiteSigninHandler):
cookie += sub_str + ";" cookie += sub_str + ";"
if "hdchina=" not in cookie: if "hdchina=" not in cookie:
logger.error(f"{site} 签到失败Cookie失效") logger.error(f"{site} 签到失败Cookie失效")
return False, '签到失败Cookie失效' return False, '签到失败Cookie失效'
site_cookie = cookie site_cookie = cookie
# 获取页面html # 获取页面html

View File

@ -51,8 +51,8 @@ class HDCity(_ISiteSigninHandler):
return False, '签到失败,请检查站点连通性' return False, '签到失败,请检查站点连通性'
if "login" in html_text: if "login" in html_text:
logger.error(f"{site} 签到失败Cookie失效") logger.error(f"{site} 签到失败Cookie失效")
return False, '签到失败Cookie失效' return False, '签到失败Cookie失效'
# 判断是否已签到 # 判断是否已签到
# '已连续签到278天此次签到您获得了100魔力值奖励!' # '已连续签到278天此次签到您获得了100魔力值奖励!'

View File

@ -54,8 +54,8 @@ class HDSky(_ISiteSigninHandler):
return False, '签到失败,请检查站点连通性' return False, '签到失败,请检查站点连通性'
if "login.php" in html_text: if "login.php" in html_text:
logger.error(f"{site} 签到失败Cookie失效") logger.error(f"{site} 签到失败Cookie失效")
return False, '签到失败Cookie失效' return False, '签到失败Cookie失效'
sign_status = self.sign_in_result(html_res=html_text, sign_status = self.sign_in_result(html_res=html_text,
regexs=self._sign_regex) regexs=self._sign_regex)

View File

@ -53,8 +53,8 @@ class HDUpt(_ISiteSigninHandler):
return False, '签到失败,请检查站点连通性' return False, '签到失败,请检查站点连通性'
if "login.php" in html_text: if "login.php" in html_text:
logger.error(f"{site} 签到失败Cookie失效") logger.error(f"{site} 签到失败Cookie失效")
return False, '签到失败Cookie失效' return False, '签到失败Cookie失效'
sign_status = self.sign_in_result(html_res=html_text, sign_status = self.sign_in_result(html_res=html_text,
regexs=self._sign_regex) regexs=self._sign_regex)

View File

@ -55,8 +55,8 @@ class Opencd(_ISiteSigninHandler):
return False, '签到失败,请检查站点连通性' return False, '签到失败,请检查站点连通性'
if "login.php" in html_text: if "login.php" in html_text:
logger.error(f"{site} 签到失败Cookie失效") logger.error(f"{site} 签到失败Cookie失效")
return False, '签到失败Cookie失效' return False, '签到失败Cookie失效'
if self._repeat_text in html_text: if self._repeat_text in html_text:
logger.info(f"{site} 今日已签到") logger.info(f"{site} 今日已签到")

View File

@ -43,8 +43,12 @@ class PTerClub(_ISiteSigninHandler):
proxy=proxy, proxy=proxy,
render=render) render=render)
if not html_text: if not html_text:
logger.error(f"{site} 签到失败,签到接口请求失败") logger.error(f"{site} 签到失败,请检查站点连通性")
return False, '签到失败,请检查cookie是否失效' return False, '签到失败,请检查站点连通性'
if "login.php" in html_text:
logger.error(f"{site} 签到失败Cookie已失效")
return False, '签到失败Cookie已失效'
try: try:
sign_dict = json.loads(html_text) sign_dict = json.loads(html_text)
except Exception as e: except Exception as e:

View File

@ -75,8 +75,8 @@ class Tjupt(_ISiteSigninHandler):
return False, '签到失败,请检查站点连通性' return False, '签到失败,请检查站点连通性'
if "login.php" in html_text: if "login.php" in html_text:
logger.error(f"{site} 签到失败Cookie失效") logger.error(f"{site} 签到失败Cookie失效")
return False, '签到失败Cookie失效' return False, '签到失败Cookie失效'
sign_status = self.sign_in_result(html_res=html_text, sign_status = self.sign_in_result(html_res=html_text,
regexs=self._sign_regex) regexs=self._sign_regex)

View File

@ -56,8 +56,8 @@ class TTG(_ISiteSigninHandler):
return False, '签到失败,请检查站点连通性' return False, '签到失败,请检查站点连通性'
if "login.php" in html_text: if "login.php" in html_text:
logger.error(f"{site} 签到失败Cookie失效") logger.error(f"{site} 签到失败Cookie失效")
return False, '签到失败Cookie失效' return False, '签到失败Cookie失效'
# 判断是否已签到 # 判断是否已签到
sign_status = self.sign_in_result(html_res=html_text, sign_status = self.sign_in_result(html_res=html_text,

View File

@ -68,8 +68,8 @@ class U2(_ISiteSigninHandler):
return False, '签到失败,请检查站点连通性' return False, '签到失败,请检查站点连通性'
if "login.php" in html_text: if "login.php" in html_text:
logger.error(f"{site} 签到失败Cookie失效") logger.error(f"{site} 签到失败Cookie失效")
return False, '签到失败Cookie失效' return False, '签到失败Cookie失效'
# 判断是否已签到 # 判断是否已签到
sign_status = self.sign_in_result(html_res=html_text, sign_status = self.sign_in_result(html_res=html_text,

View File

@ -50,8 +50,8 @@ class ZhuQue(_ISiteSigninHandler):
return False, '模拟登录失败,请检查站点连通性' return False, '模拟登录失败,请检查站点连通性'
if "login.php" in html_text: if "login.php" in html_text:
logger.error(f"{site} 模拟登录失败Cookie失效") logger.error(f"{site} 模拟登录失败Cookie失效")
return False, '模拟登录失败Cookie失效' return False, '模拟登录失败Cookie失效'
html = etree.HTML(html_text) html = etree.HTML(html_text)

View File

@ -14,6 +14,7 @@ from python_hosts import Hosts, HostsEntry
from requests import Response from requests import Response
from app.core.config import settings from app.core.config import settings
from app.core.event import eventmanager, Event
from app.log import logger from app.log import logger
from app.plugins import _PluginBase from app.plugins import _PluginBase
from app.schemas.types import EventType, NotificationType from app.schemas.types import EventType, NotificationType
@ -109,7 +110,8 @@ class CloudflareSpeedTest(_PluginBase):
self._scheduler.print_jobs() self._scheduler.print_jobs()
self._scheduler.start() self._scheduler.start()
def __cloudflareSpeedTest(self): @eventmanager.register(EventType.CloudFlareSpeedTest)
def __cloudflareSpeedTest(self, event: Event = None):
""" """
CloudflareSpeedTest优选 CloudflareSpeedTest优选
""" """
@ -129,6 +131,12 @@ class CloudflareSpeedTest(_PluginBase):
logger.error("CloudflareSpeedTest加载成功首次运行需要配置优选ip") logger.error("CloudflareSpeedTest加载成功首次运行需要配置优选ip")
return return
if event and event.event_data:
logger.info("收到命令开始Cloudflare IP优选 ...")
self.post_message(channel=event.event_data.get("channel"),
title="开始Cloudflare IP优选 ...",
userid=event.event_data.get("user"))
# ipv4和ipv6必须其一 # ipv4和ipv6必须其一
if not self._ipv4 and not self._ipv6: if not self._ipv4 and not self._ipv6:
self._ipv4 = True self._ipv4 = True
@ -154,7 +162,8 @@ class CloudflareSpeedTest(_PluginBase):
# 执行优选命令,-dd不测速 # 执行优选命令,-dd不测速
if SystemUtils.is_windows(): if SystemUtils.is_windows():
cf_command = f'cd \"{self._cf_path}\" && CloudflareST {self._additional_args} -o \"{self._result_file}\"' + ( cf_command = f'cd \"{self._cf_path}\" && CloudflareST {self._additional_args} -o \"{self._result_file}\"' + (
f' -f \"{self._cf_ipv4}\"' if self._ipv4 else '') + (f' -f \"{self._cf_ipv6}\"' if self._ipv6 else '') f' -f \"{self._cf_ipv4}\"' if self._ipv4 else '') + (
f' -f \"{self._cf_ipv6}\"' if self._ipv6 else '')
else: else:
cf_command = f'cd {self._cf_path} && chmod a+x {self._binary_name} && ./{self._binary_name} {self._additional_args} -o {self._result_file}' + ( cf_command = f'cd {self._cf_path} && chmod a+x {self._binary_name} && ./{self._binary_name} {self._additional_args} -o {self._result_file}' + (
f' -f {self._cf_ipv4}' if self._ipv4 else '') + (f' -f {self._cf_ipv6}' if self._ipv6 else '') f' -f {self._cf_ipv4}' if self._ipv4 else '') + (f' -f {self._cf_ipv6}' if self._ipv6 else '')
@ -313,7 +322,7 @@ class CloudflareSpeedTest(_PluginBase):
# 重装后数据库有版本数据,但是本地没有则重装 # 重装后数据库有版本数据,但是本地没有则重装
if not install_flag and release_version == self._version and not Path( if not install_flag and release_version == self._version and not Path(
f'{self._cf_path}/{self._binary_name}').exists() and not Path( f'{self._cf_path}/{self._binary_name}').exists() and not Path(
f'{self._cf_path}/CloudflareST.exe').exists(): f'{self._cf_path}/CloudflareST.exe').exists():
logger.warn(f"未检测到CloudflareSpeedTest本地版本重新安装") logger.warn(f"未检测到CloudflareSpeedTest本地版本重新安装")
install_flag = True install_flag = True
@ -468,7 +477,16 @@ class CloudflareSpeedTest(_PluginBase):
@staticmethod @staticmethod
def get_command() -> List[Dict[str, Any]]: def get_command() -> List[Dict[str, Any]]:
pass """
定义远程控制命令
:return: 命令关键字、事件、描述、附带数据
"""
return [{
"cmd": "/cloudflare_speedtest",
"event": EventType.CloudFlareSpeedTest,
"desc": "Cloudflare IP优选",
"data": {}
}]
def get_api(self) -> List[Dict[str, Any]]: def get_api(self) -> List[Dict[str, Any]]:
pass pass

View File

@ -567,8 +567,8 @@ class MediaSyncDel(_PluginBase):
# 开始删除 # 开始删除
image = 'https://emby.media/notificationicon.png' image = 'https://emby.media/notificationicon.png'
year = None year = None
del_cnt = 0 del_torrent_hashs = []
stop_cnt = 0 stop_torrent_hashs = []
error_cnt = 0 error_cnt = 0
for transferhis in transfer_history: for transferhis in transfer_history:
title = transferhis.title title = transferhis.title
@ -590,15 +590,16 @@ class MediaSyncDel(_PluginBase):
if transferhis.download_hash: if transferhis.download_hash:
try: try:
# 2、判断种子是否被删除完 # 2、判断种子是否被删除完
delete_flag, success_flag, handle_cnt = self.handle_torrent(src=transferhis.src, delete_flag, success_flag, handle_torrent_hashs = self.handle_torrent(
torrent_hash=transferhis.download_hash) src=transferhis.src,
torrent_hash=transferhis.download_hash)
if not success_flag: if not success_flag:
error_cnt += 1 error_cnt += 1
else: else:
if delete_flag: if delete_flag:
del_cnt += handle_cnt del_torrent_hashs += handle_torrent_hashs
else: else:
stop_cnt += handle_cnt stop_torrent_hashs += handle_torrent_hashs
except Exception as e: except Exception as e:
logger.error("删除种子失败,尝试删除源文件:%s" % str(e)) logger.error("删除种子失败,尝试删除源文件:%s" % str(e))
@ -615,10 +616,16 @@ class MediaSyncDel(_PluginBase):
image = self.get_tmdbimage_url(images[-1].get("file_path"), prefix="original") image = self.get_tmdbimage_url(images[-1].get("file_path"), prefix="original")
torrent_cnt_msg = "" torrent_cnt_msg = ""
if del_cnt: if del_torrent_hashs:
torrent_cnt_msg += f"删除种子{del_cnt}\n" torrent_cnt_msg += f"删除种子{len(set(del_torrent_hashs))}\n"
if stop_cnt: if stop_torrent_hashs:
torrent_cnt_msg += f"暂停种子{stop_cnt}\n" stop_cnt = 0
# 排除已删除
for stop_hash in set(stop_torrent_hashs):
if stop_hash not in set(del_torrent_hashs):
stop_cnt += 1
if stop_cnt > 0:
torrent_cnt_msg += f"暂停种子{stop_cnt}\n"
if error_cnt: if error_cnt:
torrent_cnt_msg += f"删种失败{error_cnt}\n" torrent_cnt_msg += f"删种失败{error_cnt}\n"
# 发送通知 # 发送通知
@ -818,8 +825,8 @@ class MediaSyncDel(_PluginBase):
# 开始删除 # 开始删除
image = 'https://emby.media/notificationicon.png' image = 'https://emby.media/notificationicon.png'
del_cnt = 0 del_torrent_hashs = []
stop_cnt = 0 stop_torrent_hashs = []
error_cnt = 0 error_cnt = 0
for transferhis in transfer_history: for transferhis in transfer_history:
title = transferhis.title title = transferhis.title
@ -839,15 +846,16 @@ class MediaSyncDel(_PluginBase):
if transferhis.download_hash: if transferhis.download_hash:
try: try:
# 2、判断种子是否被删除完 # 2、判断种子是否被删除完
delete_flag, success_flag, handle_cnt = self.handle_torrent(src=transferhis.src, delete_flag, success_flag, handle_torrent_hashs = self.handle_torrent(
torrent_hash=transferhis.download_hash) src=transferhis.src,
torrent_hash=transferhis.download_hash)
if not success_flag: if not success_flag:
error_cnt += 1 error_cnt += 1
else: else:
if delete_flag: if delete_flag:
del_cnt += handle_cnt del_torrent_hashs += handle_torrent_hashs
else: else:
stop_cnt += handle_cnt stop_torrent_hashs += handle_torrent_hashs
except Exception as e: except Exception as e:
logger.error("删除种子失败,尝试删除源文件:%s" % str(e)) logger.error("删除种子失败,尝试删除源文件:%s" % str(e))
@ -856,12 +864,16 @@ class MediaSyncDel(_PluginBase):
# 发送消息 # 发送消息
if self._notify: if self._notify:
torrent_cnt_msg = "" torrent_cnt_msg = ""
if del_cnt: if del_torrent_hashs:
torrent_cnt_msg += f"删除种子{del_cnt}\n" torrent_cnt_msg += f"删除种子{len(set(del_torrent_hashs))}\n"
if stop_cnt: if stop_torrent_hashs:
torrent_cnt_msg += f"暂停种子{stop_cnt}\n" stop_cnt = 0
if error_cnt: # 排除已删除
torrent_cnt_msg += f"删种失败{error_cnt}\n" for stop_hash in set(stop_torrent_hashs):
if stop_hash not in set(del_torrent_hashs):
stop_cnt += 1
if stop_cnt > 0:
torrent_cnt_msg += f"暂停种子{stop_cnt}\n"
self.post_message( self.post_message(
mtype=NotificationType.MediaServer, mtype=NotificationType.MediaServer,
title="媒体库同步删除任务完成", title="媒体库同步删除任务完成",
@ -901,7 +913,7 @@ class MediaSyncDel(_PluginBase):
plugin_id=plugin_id) plugin_id=plugin_id)
logger.info(f"查询到 {history_key} 转种历史 {transfer_history}") logger.info(f"查询到 {history_key} 转种历史 {transfer_history}")
handle_cnt = 0 handle_torrent_hashs = []
try: try:
# 删除本次种子记录 # 删除本次种子记录
self._downloadhis.delete_file_by_fullpath(fullpath=src) self._downloadhis.delete_file_by_fullpath(fullpath=src)
@ -946,7 +958,7 @@ class MediaSyncDel(_PluginBase):
# 删除源种子 # 删除源种子
logger.info(f"删除源下载器下载任务:{settings.DOWNLOADER} - {torrent_hash}") logger.info(f"删除源下载器下载任务:{settings.DOWNLOADER} - {torrent_hash}")
self.chain.remove_torrents(torrent_hash) self.chain.remove_torrents(torrent_hash)
handle_cnt += 1 handle_torrent_hashs.append(torrent_hash)
# 删除转种后任务 # 删除转种后任务
logger.info(f"删除转种后下载任务:{download} - {download_id}") logger.info(f"删除转种后下载任务:{download} - {download_id}")
@ -957,7 +969,7 @@ class MediaSyncDel(_PluginBase):
else: else:
self.qb.delete_torrents(delete_file=True, self.qb.delete_torrents(delete_file=True,
ids=download_id) ids=download_id)
handle_cnt += 1 handle_torrent_hashs.append(download_id)
else: else:
# 暂停种子 # 暂停种子
# 转种后未删除源种时,同步暂停源种 # 转种后未删除源种时,同步暂停源种
@ -967,7 +979,7 @@ class MediaSyncDel(_PluginBase):
# 暂停源种子 # 暂停源种子
logger.info(f"暂停源下载器下载任务:{settings.DOWNLOADER} - {torrent_hash}") logger.info(f"暂停源下载器下载任务:{settings.DOWNLOADER} - {torrent_hash}")
self.chain.stop_torrents(torrent_hash) self.chain.stop_torrents(torrent_hash)
handle_cnt += 1 handle_torrent_hashs.append(torrent_hash)
logger.info(f"暂停转种后下载任务:{download} - {download_id}") logger.info(f"暂停转种后下载任务:{download} - {download_id}")
# 删除转种后下载任务 # 删除转种后下载任务
@ -975,7 +987,7 @@ class MediaSyncDel(_PluginBase):
self.tr.stop_torrents(ids=download_id) self.tr.stop_torrents(ids=download_id)
else: else:
self.qb.stop_torrents(ids=download_id) self.qb.stop_torrents(ids=download_id)
handle_cnt += 1 handle_torrent_hashs.append(download_id)
else: else:
# 未转种de情况 # 未转种de情况
if delete_flag: if delete_flag:
@ -986,20 +998,20 @@ class MediaSyncDel(_PluginBase):
# 暂停源种子 # 暂停源种子
logger.info(f"暂停源下载器下载任务:{download} - {download_id}") logger.info(f"暂停源下载器下载任务:{download} - {download_id}")
self.chain.stop_torrents(download_id) self.chain.stop_torrents(download_id)
handle_cnt += 1 handle_torrent_hashs.append(download_id)
# 处理辅种 # 处理辅种
handle_cnt = self.__del_seed(download=download, handle_cnt = self.__del_seed(download=download,
download_id=download_id, download_id=download_id,
action_flag="del" if delete_flag else 'stop', action_flag="del" if delete_flag else 'stop',
handle_cnt=handle_cnt) handle_torrent_hashs=handle_torrent_hashs)
return delete_flag, True, handle_cnt return delete_flag, True, handle_cnt
except Exception as e: except Exception as e:
logger.error(f"删种失败: {str(e)}") logger.error(f"删种失败: {str(e)}")
return False, False, 0 return False, False, 0
def __del_seed(self, download, download_id, action_flag, handle_cnt): def __del_seed(self, download, download_id, action_flag, handle_torrent_hashs):
""" """
删除辅种 删除辅种
""" """
@ -1022,7 +1034,7 @@ class MediaSyncDel(_PluginBase):
# 删除辅种历史 # 删除辅种历史
for torrent in torrents: for torrent in torrents:
handle_cnt += 1 handle_torrent_hashs.append(torrent)
if str(download) == "qbittorrent": if str(download) == "qbittorrent":
# 删除辅种 # 删除辅种
if action_flag == "del": if action_flag == "del":
@ -1056,7 +1068,7 @@ class MediaSyncDel(_PluginBase):
else: else:
self.del_data(key=history_key, self.del_data(key=history_key,
plugin_id=plugin_id) plugin_id=plugin_id)
return handle_cnt return handle_torrent_hashs
@staticmethod @staticmethod
def parse_emby_log(last_time): def parse_emby_log(last_time):

View File

@ -46,7 +46,10 @@ class EventType(Enum):
NameRecognizeResult = "name.recognize.result" NameRecognizeResult = "name.recognize.result"
# 目录监控同步 # 目录监控同步
DirectorySync = "directory.sync" DirectorySync = "directory.sync"
# Cloudflare IP优选
CloudFlareSpeedTest = "cloudflare.speedtest"
# 站点自动登录更新Cookie、Ua
SiteLogin = "site.login"
# 系统配置Key字典 # 系统配置Key字典
class SystemConfigKey(Enum): class SystemConfigKey(Enum):