Merge branch 'feature_dev' of https://github.com/InfinityPacer/MoviePilot-Plugins into feature_dev

This commit is contained in:
InfinityPacer
2024-04-24 21:12:24 +08:00
49 changed files with 926 additions and 562 deletions

BIN
icons/Actual_A.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
icons/Apache_webdav_A.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

BIN
icons/Chandao_A.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

BIN
icons/Chandao_B.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
icons/Cloudflare_B.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
icons/Dell_A.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
icons/Docker.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
icons/FileBrowser.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
icons/Flood_A.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
icons/FreshRSS.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
icons/Guacamole_A.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
icons/Homebridge_A.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
icons/Homer_A.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

BIN
icons/Ipw.cn_A.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
icons/Itdog.cn_A.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
icons/Macos_A.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
icons/Macos_Bigsur.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 KiB

BIN
icons/Macos_Catalina.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

BIN
icons/Macos_EI_Capitan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
icons/Macos_High_Sierra.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 KiB

BIN
icons/Macos_Mojave.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 KiB

BIN
icons/Macos_Monterey.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

BIN
icons/Macos_Sierra.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 KiB

BIN
icons/Ombi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
icons/Omnivore_A.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
icons/PVE_B.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
icons/Photoprism_A.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
icons/Photoprism_C.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
icons/Photoprism_D.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
icons/Photoprism_E.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
icons/Photoprism_F.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

BIN
icons/Photostructure_A.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
icons/Qbittorrent_B.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
icons/Readarr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
icons/Rocky_A.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
icons/Shiori_A.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
icons/UnlockMusic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
icons/Verysync.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
icons/Youtube-dl_C.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

View File

@@ -1,12 +1,13 @@
{
"AutoSignIn": {
"name": "站点自动签到",
"description": "自动模拟登录站点、签到。",
"version": "1.9",
"description": "自动模拟登录、签到站点。",
"version": "2.0",
"icon": "signin.png",
"author": "thsrite",
"level": 2,
"history": {
"v2.0": "站点签到时更新站点使用统计信息需要主程序升级至v1.8.3+版本",
"v1.9": "支持馒头新架构自动签到"
}
},
@@ -21,11 +22,13 @@
"SiteStatistic": {
"name": "站点数据统计",
"description": "自动统计和展示站点数据。",
"version": "2.6",
"version": "2.8",
"icon": "statistic.png",
"author": "lightolly",
"level": 2,
"history": {
"v2.8": "修复馒头未读消息统计",
"v2.7": "修复憨憨种子信息只统计第一页的问题,增加移除失效统计选项",
"v2.6": "支持馒头新架构数据统计"
}
},
@@ -198,12 +201,13 @@
"CrossSeed": {
"name": "青蛙辅种助手",
"description": "参考ReseedPuppy和IYUU辅种插件实现自动辅种支持站点青蛙、AGSVPT、麒麟、UBits、聆音、憨憨等。",
"version": "2.2",
"version": "2.3",
"icon": "qingwa.png",
"author": "233@qingwa",
"level": 2,
"history": {
"v2.2": "站点停用后会同步暂停对该站点的辅种"
"v2.2": "站点停用后会同步暂停对该站点的辅种",
"v2.3": "站点辅种支持代理"
}
},
"VCBAnimeMonitor": {
@@ -387,11 +391,13 @@
"RemoveLink": {
"name": "清理硬链接",
"description": "监控目录内文件被删除时,同步删除监控目录内所有和它硬链接的文件",
"version": "1.7",
"version": "1.9",
"icon": "Ombi_A.png",
"author": "DzAvril",
"level": 1,
"history": {
"v1.9": "增加清理刮削文件功能beta",
"v1.8": "增加清理空目录功能beta",
"v1.7": "修复因未监测重命名事件导致的清理硬链接失败的问题",
"v1.6": "提升插件性能"
}
@@ -506,10 +512,13 @@
"IyuuAuth": {
"name": "IYUU站点绑定",
"description": "为IYUU账号绑定认证站点以便用于用户认证和辅种。",
"version": "1.0",
"version": "1.1",
"icon": "Iyuu_A.png",
"author": "jxxghp",
"level": 1
"level": 1,
"history": {
"v1.1": "修复IYUU站点绑定失败问题"
}
},
"NtfyMsg": {
"name": "ntfy消息推送",
@@ -522,7 +531,7 @@
"PluginAutoUpgrade": {
"name": "插件自动升级",
"description": "定时检测、升级插件。",
"version": "1.0",
"version": "1.4",
"icon": "PluginAutoUpgrade.png",
"author": "hotlcc",
"level": 1

View File

@@ -16,6 +16,7 @@ from app.chain.site import SiteChain
from app.core.config import settings
from app.core.event import EventManager, eventmanager, Event
from app.db.site_oper import SiteOper
from app.db.sitestatistic_oper import SiteStatisticOper
from app.helper.browser import PlaywrightHelper
from app.helper.cloudflare import under_challenge
from app.helper.module import ModuleHelper
@@ -33,11 +34,11 @@ class AutoSignIn(_PluginBase):
# 插件名称
plugin_name = "站点自动签到"
# 插件描述
plugin_desc = "自动模拟登录站点、签到。"
plugin_desc = "自动模拟登录、签到站点"
# 插件图标
plugin_icon = "signin.png"
# 插件版本
plugin_version = "1.9"
plugin_version = "2.0"
# 插件作者
plugin_author = "thsrite"
# 作者主页
@@ -53,6 +54,7 @@ class AutoSignIn(_PluginBase):
sites: SitesHelper = None
siteoper: SiteOper = None
sitechain: SiteChain = None
sitestatistic: SiteStatisticOper = None
# 事件管理器
event: EventManager = None
# 定时器
@@ -87,6 +89,7 @@ class AutoSignIn(_PluginBase):
self.siteoper = SiteOper()
self.event = EventManager()
self.sitechain = SiteChain()
self.sitestatistic = SiteStatisticOper()
# 停止现有任务
self.stop_service()
@@ -871,26 +874,34 @@ class AutoSignIn(_PluginBase):
签到一个站点
"""
site_module = self.__build_class(site_info.get("url"))
# 开始记时
start_time = datetime.now()
if site_module and hasattr(site_module, "signin"):
try:
_, msg = site_module().signin(site_info)
# 特殊站点直接返回签到信息,防止仿真签到、模拟登录有歧义
return site_info.get("name"), msg or ""
state, message = site_module().signin(site_info)
except Exception as e:
traceback.print_exc()
return site_info.get("name"), f"签到失败:{str(e)}"
state, message = False, f"签到失败:{str(e)}"
else:
return site_info.get("name"), self.__signin_base(site_info)
state, message = self.__signin_base(site_info)
# 统计
seconds = (datetime.now() - start_time).seconds
domain = StringUtils.get_url_domain(site_info.get('url'))
if state:
self.sitestatistic.success(domain=domain, seconds=seconds)
else:
self.sitestatistic.fail(domain)
return site_info.get("name"), message
@staticmethod
def __signin_base(site_info: CommentedMap) -> str:
def __signin_base(site_info: CommentedMap) -> Tuple[bool, str]:
"""
通用签到处理
:param site_info: 站点信息
:return: 签到结果信息
"""
if not site_info:
return ""
return False, ""
site = site_info.get("name")
site_url = site_info.get("url")
site_cookie = site_info.get("cookie")
@@ -900,7 +911,7 @@ class AutoSignIn(_PluginBase):
proxy_server = settings.PROXY_SERVER if site_info.get("proxy") else None
if not site_url or not site_cookie:
logger.warn(f"未配置 {site} 的站点地址或Cookie无法签到")
return ""
return False, ""
# 模拟登录
try:
# 访问链接
@@ -916,14 +927,14 @@ class AutoSignIn(_PluginBase):
proxies=proxy_server)
if not SiteUtils.is_logged_in(page_source):
if under_challenge(page_source):
return f"无法通过Cloudflare"
return f"仿真登录失败Cookie已失效"
return False, f"无法通过Cloudflare"
return False, f"仿真登录失败Cookie已失效"
else:
# 判断是否已签到
if re.search(r'已签|签到已得', page_source, re.IGNORECASE) \
or SiteUtils.is_checkin(page_source):
return f"签到成功"
return "仿真签到成功"
return True, f"签到成功"
return True, "仿真签到成功"
else:
res = RequestUtils(cookies=site_cookie,
ua=ua,
@@ -945,20 +956,20 @@ class AutoSignIn(_PluginBase):
else:
msg = f"状态码:{res.status_code}"
logger.warn(f"{site} 签到失败,{msg}")
return f"签到失败,{msg}"
return False, f"签到失败,{msg}"
else:
logger.info(f"{site} 签到成功")
return f"签到成功"
return True, f"签到成功"
elif res is not None:
logger.warn(f"{site} 签到失败,状态码:{res.status_code}")
return f"签到失败,状态码:{res.status_code}"
return False, f"签到失败,状态码:{res.status_code}"
else:
logger.warn(f"{site} 签到失败,无法打开网站")
return f"签到失败,无法打开网站!"
return False, f"签到失败,无法打开网站!"
except Exception as e:
logger.warn("%s 签到失败:%s" % (site, str(e)))
traceback.print_exc()
return f"签到失败:{str(e)}"
return False, f"签到失败:{str(e)}"
def login_site(self, site_info: CommentedMap) -> Tuple[str, str]:
"""

View File

@@ -154,7 +154,11 @@ class CrossSeedHelper(object):
remote_torrent_infos = []
try:
response = requests.post(
site.get_api_url(), headers=headers, json=data, timeout=10
site.get_api_url(),
headers=headers,
json=data,
timeout=10,
proxies=settings.PROXY if site.proxy else None,
)
response.raise_for_status()
rsp_body = response.json()
@@ -177,7 +181,7 @@ class CrossSeed(_PluginBase):
# 插件图标
plugin_icon = "qingwa.png"
# 插件版本
plugin_version = "2.2"
plugin_version = "2.3"
# 插件作者
plugin_author = "233@qingwa"
# 作者主页

View File

@@ -14,7 +14,7 @@ class IyuuAuth(_PluginBase):
# 插件图标
plugin_icon = "Iyuu_A.png"
# 插件版本
plugin_version = "1.0"
plugin_version = "1.1"
# 插件作者
plugin_author = "jxxghp"
# 作者主页
@@ -85,7 +85,7 @@ class IyuuAuth(_PluginBase):
for item in self.iyuu.get_auth_sites() or []:
SiteOptions.append({
"title": item.get("site"),
"value": item.get("id")
"value": item.get("site")
})
return [
{

File diff suppressed because it is too large Load Diff

View File

@@ -40,7 +40,7 @@ class FileMonitorHandler(FileSystemEventHandler):
# 新增文件记录
with state_lock:
self.sync.state_set[str(file_path)] = file_path.stat().st_ino
def on_moved(self, event):
if event.is_directory:
return
@@ -106,7 +106,7 @@ class RemoveLink(_PluginBase):
# 插件图标
plugin_icon = "Ombi_A.png"
# 插件版本
plugin_version = "1.7"
plugin_version = "1.9"
# 插件作者
plugin_author = "DzAvril"
# 作者主页
@@ -124,6 +124,7 @@ class RemoveLink(_PluginBase):
exclude_keywords = ""
_enabled = False
_notify = False
_delete_scrap_infos = False
_observer = []
# 监控目录的文件列表
state_set: Dict[str, int] = {}
@@ -136,6 +137,7 @@ class RemoveLink(_PluginBase):
self.monitor_dirs = config.get("monitor_dirs")
self.exclude_dirs = config.get("exclude_dirs") or ""
self.exclude_keywords = config.get("exclude_keywords") or ""
self._delete_scrap_infos = config.get("delete_scrap_infos")
# 停止现有任务
self.stop_service()
@@ -224,6 +226,19 @@ class RemoveLink(_PluginBase):
}
],
},
{
"component": "VCol",
"props": {"cols": 12, "md": 4},
"content": [
{
"component": "VSwitch",
"props": {
"model": "delete_scrap_infos",
"label": "清理刮削文件(beta)",
},
}
],
},
],
},
{
@@ -289,32 +304,47 @@ class RemoveLink(_PluginBase):
],
},
{
'component': 'VRow',
'content': [
"component": "VRow",
"content": [
{
'component': 'VCol',
'props': {
'cols': 12,
"component": "VCol",
"props": {
"cols": 12,
},
'content': [
"content": [
{
'component': 'VAlert',
'props': {
'type': 'info',
'variant': 'tonal',
'text': '监控目录如有多个需换行,源目录和硬链接目录都需要添加到监控目录中;如需实现删除硬链接时不删除源文件,可把源文件目录配置到不删除目录中。'
}
"component": "VAlert",
"props": {
"type": "info",
"variant": "tonal",
"text": "监控目录如有多个需换行,源目录和硬链接目录都需要添加到监控目录中;如需实现删除硬链接时不删除源文件,可把源文件目录配置到不删除目录中。",
},
}
]
}
]
}
],
},
{
"component": "VCol",
"props": {
"cols": 12,
},
"content": [
{
"component": "VAlert",
"props": {
"type": "info",
"variant": "tonal",
"text": "清理刮削文件为测试功能,请谨慎开启。",
},
}
],
},
],
},
],
}
], {
"enabled": False,
"notify": False,
"onlyonce": False,
"monitor_dirs": "",
"exclude_keywords": "",
}
@@ -345,12 +375,91 @@ class RemoveLink(_PluginBase):
return True
return False
def scrape_files_left(self, path):
"""
检查path目录是否只包含刮削文件
"""
# 检查path下是否有目录
for dir_path in os.listdir(path):
if os.path.isdir(os.path.join(path, dir_path)):
return False
# 检查path下是否有非刮削文件
for file in path.iterdir():
if not file.suffix.lower() in [
".jpg",
".nfo",
]:
return False
return True
def delete_scrap_infos(self, path):
"""
清理path相关的刮削文件
"""
if not self._delete_scrap_infos:
return
# 文件所在目录已被删除则退出
if not os.path.exists(path.parent):
return
logger.info(f"清理刮削文件: {path}")
if not path.suffix.lower() in [
".jpg",
".nfo",
]:
# 清理与path相关的刮削文件
name_prefix = path.stem
for file in path.parent.iterdir():
if file.name.startswith(name_prefix):
file.unlink()
logger.info(f'删除刮削文件:{file}')
# 清理空目录
self.delete_empty_folders(path)
def delete_empty_folders(self, path):
"""
从指定路径开始,逐级向上层目录检测并删除空目录,直到遇到非空目录或到达指定监控目录为止
"""
logger.info(f"清理空目录: {path}")
while True:
parent_path = path.parent
if self.__is_excluded(parent_path):
break
# parent_path如已被删除则退出检查
if not os.path.exists(parent_path):
break
# 如果当前路径等于监控目录之一,停止向上检查
if parent_path in self.monitor_dirs.split("\n"):
break
# 若目录下只剩刮削文件,则清空文件夹
if self.scrape_files_left(parent_path):
# 清除目录下所有文件
for file in parent_path.iterdir():
file.unlink()
logger.info(f'删除刮削文件:{file}')
if not os.listdir(parent_path):
os.rmdir(parent_path)
logger.info(f"清理空目录:{parent_path}")
if self._notify:
self.post_message(
mtype=NotificationType.SiteMessage,
title=f"【清理硬链接】",
text=f"清理空文件夹:[{parent_path}]\n",
)
else:
break
# 更新路径为父目录,准备下一轮检查
path = parent_path
def handle_deleted(self, file_path: Path):
"""
处理删除事件
"""
# 删除的文件对应的监控信息
with state_lock:
# 清理刮削文件
self.delete_scrap_infos(file_path)
# 删除的文件inode
deleted_inode = self.state_set.get(str(file_path))
if not deleted_inode:
@@ -369,12 +478,16 @@ class RemoveLink(_PluginBase):
# 删除硬链接文件
logger.info(f"删除硬链接文件:{path} inode: {inode}")
file.unlink()
# 清理刮削文件
self.delete_scrap_infos(file_path)
if self._notify:
self.post_message(
mtype=NotificationType.SiteMessage,
title=f"【清理硬链接】",
text=f"监控到删除源文件:[{file_path}]\n"
f"同步删除硬链接文件:[{path}]",
f"同步删除硬链接文件:[{path}]",
)
except Exception as e:
logger.error("删除硬链接文件发生错误:%s - %s" % (str(e), traceback.format_exc()))
logger.error(
"删除硬链接文件发生错误:%s - %s" % (str(e), traceback.format_exc())
)

View File

@@ -43,7 +43,7 @@ class SiteStatistic(_PluginBase):
# 插件图标
plugin_icon = "statistic.png"
# 插件版本
plugin_version = "2.6"
plugin_version = "2.8"
# 插件作者
plugin_author = "lightolly"
# 作者主页
@@ -70,6 +70,7 @@ class SiteStatistic(_PluginBase):
_cron: str = ""
_notify: bool = False
_queue_cnt: int = 5
_remove_failed: bool = False
_statistic_type: str = None
_statistic_sites: list = []
@@ -87,6 +88,7 @@ class SiteStatistic(_PluginBase):
self._notify = config.get("notify")
self._sitemsg = config.get("sitemsg")
self._queue_cnt = config.get("queue_cnt")
self._remove_failed = config.get("remove_failed")
self._statistic_type = config.get("statistic_type") or "all"
self._statistic_sites = config.get("statistic_sites") or []
@@ -369,7 +371,23 @@ class SiteStatistic(_PluginBase):
}
}
]
}
},
{
'component': 'VCol',
'props': {
'cols': 12,
'md': 4
},
'content': [
{
'component': 'VSwitch',
'props': {
'model': 'remove_failed',
'label': '移除失效站点',
}
}
]
},
]
}
]
@@ -381,6 +399,7 @@ class SiteStatistic(_PluginBase):
"sitemsg": True,
"cron": "5 1 * * *",
"queue_cnt": 5,
"remove_failed": False,
"statistic_type": "all",
"statistic_sites": []
}
@@ -1179,7 +1198,8 @@ class SiteStatistic(_PluginBase):
"bonus": site_user_info.bonus,
"url": site_url,
"err_msg": site_user_info.err_msg,
"message_unread": site_user_info.message_unread
"message_unread": site_user_info.message_unread,
"updated_at": datetime.now().strftime('%Y-%m-%d')
}
})
return site_user_info
@@ -1248,62 +1268,67 @@ class SiteStatistic(_PluginBase):
if not refresh_sites:
return
# 将数据初始化为前一天,筛选站点
yesterday_sites_data = {}
today_date = datetime.now().strftime('%Y-%m-%d')
if self._statistic_type == "add" or not self._remove_failed:
if last_update_time := self.get_data("last_update_time"):
yesterday_sites_data = self.get_data(last_update_time) or {}
if not self._remove_failed and yesterday_sites_data:
site_names = [site.get("name") for site in refresh_sites]
self._sites_data = {k: v for k, v in yesterday_sites_data.items() if k in site_names}
# 并发刷新
with ThreadPool(min(len(refresh_sites), int(self._queue_cnt or 5))) as p:
p.map(self.__refresh_site_data, refresh_sites)
# 通知刷新完成
if self._notify:
yesterday_sites_data = {}
# 增量数据
if self._statistic_type == "add":
last_update_time = self.get_data("last_update_time")
if last_update_time:
yesterday_sites_data = self.get_data(last_update_time) or {}
messages = []
# 按照上传降序排序
sites = self._sites_data.keys()
uploads = [self._sites_data[site].get("upload") or 0 if not yesterday_sites_data.get(site) else
int(self._sites_data[site].get("upload") or 0) - int(
yesterday_sites_data[site].get("upload") or 0) for site in sites]
downloads = [self._sites_data[site].get("download") or 0 if not yesterday_sites_data.get(site) else
int(self._sites_data[site].get("download") or 0) - int(
yesterday_sites_data[site].get("download") or 0) for site in sites]
data_list = sorted(list(zip(sites, uploads, downloads)),
key=lambda x: x[1],
reverse=True)
messages = {}
# 总上传
incUploads = 0
# 总下载
incDownloads = 0
for data in data_list:
site = data[0]
upload = int(data[1])
download = int(data[2])
for rand, site in enumerate(self._sites_data.keys()):
upload = int(self._sites_data[site].get("upload") or 0)
download = int(self._sites_data[site].get("download") or 0)
updated_date = self._sites_data[site].get("updated_at")
if self._statistic_type == "add" and yesterday_sites_data.get(site):
upload -= int(yesterday_sites_data[site].get("upload") or 0)
download -= int(yesterday_sites_data[site].get("download") or 0)
if updated_date and updated_date != today_date:
updated_date = f"{updated_date}"
else:
updated_date = ""
if upload > 0 or download > 0:
incUploads += int(upload)
incDownloads += int(download)
messages.append(f"{site}\n"
f"上传量:{StringUtils.str_filesize(upload)}\n"
f"下载量:{StringUtils.str_filesize(download)}\n"
f"————————————")
incUploads += upload
incDownloads += download
messages[upload + (rand / 1000)] = (
f"{site}{updated_date}\n"
+ f"上传量:{StringUtils.str_filesize(upload)}\n"
+ f"下载量:{StringUtils.str_filesize(download)}\n"
+ "————————————"
)
if incDownloads or incUploads:
messages.insert(0, f"【汇总】\n"
sorted_messages = [messages[key] for key in sorted(messages.keys(), reverse=True)]
sorted_messages.insert(0, f"【汇总】\n"
f"总上传:{StringUtils.str_filesize(incUploads)}\n"
f"总下载:{StringUtils.str_filesize(incDownloads)}\n"
f"————————————")
self.post_message(mtype=NotificationType.SiteMessage,
title="站点数据统计", text="\n".join(messages))
title="站点数据统计", text="\n".join(sorted_messages))
# 获取今天的日期
key = datetime.now().strftime('%Y-%m-%d')
# 保存数据
self.save_data(key, self._sites_data)
self.save_data(today_date, self._sites_data)
# 更新时间
self.save_data("last_update_time", key)
self.save_data("last_update_time", today_date)
logger.info("站点数据刷新完成")
def __custom_sites(self) -> List[Any]:
@@ -1321,6 +1346,7 @@ class SiteStatistic(_PluginBase):
"notify": self._notify,
"sitemsg": self._sitemsg,
"queue_cnt": self._queue_cnt,
"remove_failed": self._remove_failed,
"statistic_type": self._statistic_type,
"statistic_sites": self._statistic_sites,
})

View File

@@ -217,6 +217,9 @@ class ISiteUserInfo(metaclass=ABCMeta):
msg_links
)
unread_msg_links.extend(msg_links)
# 重新更新未读消息数99999表示有消息但数量未知
if self.message_unread == 99999:
self.message_unread = len(unread_msg_links)
# 解析未读消息内容
for msg_link in unread_msg_links:
logger.debug(f"{self.site_name} 信息链接 {msg_link}")

View File

@@ -102,7 +102,8 @@ class MTorrentSiteUserInfo(ISiteUserInfo):
self.download = int(user_info.get("memberCount", {}).get("downloaded") or '0')
self.ratio = user_info.get("memberCount", {}).get("shareRate") or 0
self.bonus = user_info.get("memberCount", {}).get("bonus") or 0
self.message_unread = 1
# 需要解析消息,但不确定消息条数
self.message_unread = 99999
self._torrent_seeding_params = {
"pageNumber": 1,

View File

@@ -217,7 +217,7 @@ class NexusPhpSiteUserInfo(ISiteUserInfo):
# 是否存在下页数据
next_page = None
next_page_text = html.xpath('//a[contains(.//text(), "下一页") or contains(.//text(), "下一頁")]/@href')
next_page_text = html.xpath('//a[contains(.//text(), "下一页") or contains(.//text(), "下一頁") or contains(.//text(), ">")]/@href')
if next_page_text:
next_page = next_page_text[-1].strip()
# fix up page url