Compare commits

...

12 Commits

Author SHA1 Message Date
jxxghp
397a8a9536 v2.2.1
- 订阅分享支持搜索词,修复了订阅复用人数显示
- 新增`VCronField`前端组件供插件使用,以简化cron表达式的输入
2025-01-13 12:52:58 +08:00
jxxghp
1da0a706a3 fix 订阅匹配缓存问题 2025-01-13 12:41:25 +08:00
jxxghp
4f2a110b5f fix 订阅匹配缓存问题 2025-01-13 12:11:56 +08:00
jxxghp
bb356ffcee Merge pull request #3721 from InfinityPacer/feature/site 2025-01-13 11:41:19 +08:00
jxxghp
6c986416ca fix 订阅分享显示复用人数 2025-01-13 08:55:06 +08:00
jxxghp
951ec138ef Merge pull request #3720 from InfinityPacer/feature/site 2025-01-13 07:09:23 +08:00
InfinityPacer
23e779ed94 fix(site): handle NoneType for userdata.user_level in regex search 2025-01-13 02:02:08 +08:00
InfinityPacer
29fccd3887 fix(site): update regex for unread message matching 2025-01-13 01:30:59 +08:00
jxxghp
1bef723332 Merge pull request #3717 from cddjr/fix_mteam_test 2025-01-12 21:25:16 +08:00
景大侠
3c41fed0ef fix 馒头连通性测试失败 2025-01-12 20:14:30 +08:00
jxxghp
5947d0e6d0 fix transfer 2025-01-09 22:24:01 +08:00
jxxghp
0e4fa86372 更新 transfer.py 2025-01-09 21:34:37 +08:00
6 changed files with 73 additions and 66 deletions

View File

@@ -1,6 +1,7 @@
import base64 import base64
import re import re
from datetime import datetime from datetime import datetime
from time import time
from typing import Optional, Tuple, Union, Dict from typing import Optional, Tuple, Union, Dict
from urllib.parse import urljoin from urllib.parse import urljoin
@@ -88,7 +89,7 @@ class SiteChain(ChainBase):
)) ))
# 低分享率警告 # 低分享率警告
if userdata.ratio and float(userdata.ratio) < 1 and not bool( if userdata.ratio and float(userdata.ratio) < 1 and not bool(
re.search(r"(贵宾|VIP?)", userdata.user_level, re.IGNORECASE)): re.search(r"(贵宾|VIP?)", userdata.user_level or "", re.IGNORECASE)):
self.post_message(Notification( self.post_message(Notification(
mtype=NotificationType.SiteMessage, mtype=NotificationType.SiteMessage,
title=f"【站点分享率低预警】", title=f"【站点分享率低预警】",
@@ -172,27 +173,37 @@ class SiteChain(ChainBase):
"Content-Type": "application/json", "Content-Type": "application/json",
"User-Agent": user_agent, "User-Agent": user_agent,
"Accept": "application/json, text/plain, */*", "Accept": "application/json, text/plain, */*",
"Authorization": site.token "Authorization": site.token,
"x-api-key": site.apikey,
"ts": str(int(time()))
} }
res = RequestUtils( res = RequestUtils(
headers=headers, headers=headers,
proxies=settings.PROXY if site.proxy else None, proxies=settings.PROXY if site.proxy else None,
timeout=site.timeout or 15 timeout=site.timeout or 15
).post_res(url=url) ).post_res(url=url)
state = False
message = "鉴权已过期或无效"
if res and res.status_code == 200: if res and res.status_code == 200:
user_info = res.json() user_info = res.json() or {}
if user_info and user_info.get("data"): if user_info.get("data"):
# 更新最后访问时间 # 更新最后访问时间
del headers["x-api-key"]
res = RequestUtils(headers=headers, res = RequestUtils(headers=headers,
timeout=site.timeout or 15, timeout=site.timeout or 15,
proxies=settings.PROXY if site.proxy else None, proxies=settings.PROXY if site.proxy else None,
referer=f"{site.url}index" referer=f"{site.url}index"
).post_res(url=f"https://api.{domain}/api/member/updateLastBrowse") ).post_res(url=f"https://api.{domain}/api/member/updateLastBrowse")
if res: state = True
return True, "连接成功" message = "连接成功,但更新状态失败"
else: if res and res.status_code == 200:
return True, f"连接成功,但更新状态失败" update_info = res.json() or {}
return False, "鉴权已过期或无效" if "code" in update_info and int(update_info["code"]) == 0:
message = "连接成功"
elif user_info.get("message"):
# 使用馒头的错误提示
message = user_info.get("message")
return state, message
@staticmethod @staticmethod
def __yema_test(site: Site) -> Tuple[bool, str]: def __yema_test(site: Site) -> Tuple[bool, str]:

View File

@@ -6,8 +6,6 @@ import time
from datetime import datetime from datetime import datetime
from typing import Dict, List, Optional, Union, Tuple from typing import Dict, List, Optional, Union, Tuple
from cachetools import TTLCache
from app.chain import ChainBase from app.chain import ChainBase
from app.chain.download import DownloadChain from app.chain.download import DownloadChain
from app.chain.media import MediaChain from app.chain.media import MediaChain
@@ -509,9 +507,6 @@ class SubscribeChain(ChainBase, metaclass=Singleton):
logger.warn('没有缓存资源,无法匹配订阅') logger.warn('没有缓存资源,无法匹配订阅')
return return
# 记录重新识别过的种子
_recognize_cached = TTLCache(maxsize=1024, ttl=6 * 3600)
with self._rlock: with self._rlock:
logger.debug(f"match lock acquired at {datetime.now()}") logger.debug(f"match lock acquired at {datetime.now()}")
# 所有订阅 # 所有订阅
@@ -552,6 +547,12 @@ class SubscribeChain(ChainBase, metaclass=Singleton):
if exist_flag: if exist_flag:
continue continue
# 订阅识别词
if subscribe.custom_words:
custom_words_list = subscribe.custom_words.split("\n")
else:
custom_words_list = None
# 遍历缓存种子 # 遍历缓存种子
_match_context = [] _match_context = []
for domain, contexts in torrents.items(): for domain, contexts in torrents.items():
@@ -573,8 +574,8 @@ class SubscribeChain(ChainBase, metaclass=Singleton):
continue continue
# 有自定义识别词时,需要判断是否需要重新识别 # 有自定义识别词时,需要判断是否需要重新识别
if subscribe.custom_words: apply_words = None
custom_words_list = subscribe.custom_words.split("\n") if custom_words_list:
_, apply_words = WordsMatcher().prepare(torrent_info.title, _, apply_words = WordsMatcher().prepare(torrent_info.title,
custom_words=custom_words_list) custom_words=custom_words_list)
if apply_words: if apply_words:
@@ -589,30 +590,28 @@ class SubscribeChain(ChainBase, metaclass=Singleton):
# 先判断是否有没识别的种子,否则重新识别 # 先判断是否有没识别的种子,否则重新识别
if not torrent_mediainfo \ if not torrent_mediainfo \
or (not torrent_mediainfo.tmdb_id and not torrent_mediainfo.douban_id): or (not torrent_mediainfo.tmdb_id and not torrent_mediainfo.douban_id):
# 避免重复处理 # 重新识别媒体信息
_cache_key = f"{torrent_meta.org_string}_{torrent_info.description}" torrent_mediainfo = self.recognize_media(meta=torrent_meta)
if not _recognize_cached.get(_cache_key): if torrent_mediainfo:
_recognize_cached[_cache_key] = True # 更新种子缓存
# 重新识别媒体信息 if not apply_words:
torrent_mediainfo = self.recognize_media(meta=torrent_meta)
if torrent_mediainfo:
# 更新种子缓存
context.media_info = torrent_mediainfo context.media_info = torrent_mediainfo
if not torrent_mediainfo: else:
# 通过标题匹配兜底 # 通过标题匹配兜底
logger.warn( logger.warn(
f'{torrent_info.site_name} - {torrent_info.title} 重新识别失败,尝试通过标题匹配...') f'{torrent_info.site_name} - {torrent_info.title} 重新识别失败,尝试通过标题匹配...')
if self.torrenthelper.match_torrent(mediainfo=mediainfo, if self.torrenthelper.match_torrent(mediainfo=mediainfo,
torrent_meta=torrent_meta, torrent_meta=torrent_meta,
torrent=torrent_info): torrent=torrent_info):
# 匹配成功 # 匹配成功
logger.info( logger.info(
f'{mediainfo.title_year} 通过标题匹配到可选资源:{torrent_info.site_name} - {torrent_info.title}') f'{mediainfo.title_year} 通过标题匹配到可选资源:{torrent_info.site_name} - {torrent_info.title}')
# 更新种子缓存 torrent_mediainfo = mediainfo
torrent_mediainfo = mediainfo # 更新种子缓存
if not apply_words:
context.media_info = mediainfo context.media_info = mediainfo
else: else:
continue continue
# 直接比对媒体信息 # 直接比对媒体信息
if torrent_mediainfo and (torrent_mediainfo.tmdb_id or torrent_mediainfo.douban_id): if torrent_mediainfo and (torrent_mediainfo.tmdb_id or torrent_mediainfo.douban_id):

View File

@@ -545,8 +545,6 @@ class TransferChain(ChainBase, metaclass=Singleton):
task = item.task task = item.task
if not task: if not task:
continue continue
# 正在处理
self.jobview.running_task(task)
# 文件信息 # 文件信息
fileitem = task.fileitem fileitem = task.fileitem
# 开始新队列 # 开始新队列
@@ -692,6 +690,9 @@ class TransferChain(ChainBase, metaclass=Singleton):
src_path=Path(task.fileitem.path), src_path=Path(task.fileitem.path),
target_storage=task.target_storage) target_storage=task.target_storage)
# 正在处理
self.jobview.running_task(task)
# 执行整理 # 执行整理
transferinfo: TransferInfo = self.transfer(fileitem=task.fileitem, transferinfo: TransferInfo = self.transfer(fileitem=task.fileitem,
meta=task.meta, meta=task.meta,
@@ -983,23 +984,7 @@ class TransferChain(ChainBase, metaclass=Singleton):
logger.warn(f"{fileitem.path} 没有找到可整理的媒体文件") logger.warn(f"{fileitem.path} 没有找到可整理的媒体文件")
return False, f"{fileitem.name} 没有找到可整理的媒体文件" return False, f"{fileitem.name} 没有找到可整理的媒体文件"
# 总数量 logger.info(f"正在计划整理 {len(file_items)} 个文件...")
total_num = len(file_items)
# 已处理数量
processed_num = 0
# 失败数量
fail_num = 0
logger.info(f"正在计划整理 {total_num} 个文件...")
# 启动进度
if not background:
self.progress.start(ProgressKey.FileTransfer)
__process_msg = f"开始整理,共 {total_num} 个文件 ..."
logger.info(__process_msg)
self.progress.update(value=0,
text=__process_msg,
key=ProgressKey.FileTransfer)
# 整理所有文件 # 整理所有文件
transfer_tasks: List[TransferTask] = [] transfer_tasks: List[TransferTask] = []
@@ -1013,7 +998,6 @@ class TransferChain(ChainBase, metaclass=Singleton):
or file_item.path.find('/.') != -1 \ or file_item.path.find('/.') != -1 \
or file_item.path.find('/@eaDir') != -1: or file_item.path.find('/@eaDir') != -1:
logger.debug(f"{file_item.path} 是回收站或隐藏的文件") logger.debug(f"{file_item.path} 是回收站或隐藏的文件")
fail_num += 1
continue continue
# 整理屏蔽词不处理 # 整理屏蔽词不处理
@@ -1027,7 +1011,6 @@ class TransferChain(ChainBase, metaclass=Singleton):
is_blocked = True is_blocked = True
break break
if is_blocked: if is_blocked:
fail_num += 1
continue continue
# 整理成功的不再处理 # 整理成功的不再处理
@@ -1038,7 +1021,6 @@ class TransferChain(ChainBase, metaclass=Singleton):
all_success = False all_success = False
logger.info(f"{file_item.path} 已整理过,如需重新处理,请删除整理记录。") logger.info(f"{file_item.path} 已整理过,如需重新处理,请删除整理记录。")
err_msgs.append(f"{file_item.name} 已整理过") err_msgs.append(f"{file_item.name} 已整理过")
fail_num += 1
continue continue
if not meta: if not meta:
@@ -1055,7 +1037,6 @@ class TransferChain(ChainBase, metaclass=Singleton):
all_success = False all_success = False
logger.error(f"{file_path.name} 无法识别有效信息") logger.error(f"{file_path.name} 无法识别有效信息")
err_msgs.append(f"{file_path.name} 无法识别有效信息") err_msgs.append(f"{file_path.name} 无法识别有效信息")
fail_num += 1
continue continue
# 自定义识别 # 自定义识别
@@ -1105,14 +1086,28 @@ class TransferChain(ChainBase, metaclass=Singleton):
if background: if background:
self.put_to_queue(task=transfer_task) self.put_to_queue(task=transfer_task)
logger.info(f"{file_path.name} 已添加到整理队列") logger.info(f"{file_path.name} 已添加到整理队列")
processed_num += 1
else: else:
# 加入列表 # 加入列表
self.__put_to_jobview(transfer_task) self.__put_to_jobview(transfer_task)
transfer_tasks.append(transfer_task) transfer_tasks.append(transfer_task)
# 实时整理 # 实时整理
if not background: if transfer_tasks:
# 总数量
total_num = len(transfer_tasks)
# 已处理数量
processed_num = 0
# 失败数量
fail_num = 0
# 启动进度
self.progress.start(ProgressKey.FileTransfer)
__process_msg = f"开始整理,共 {total_num} 个文件 ..."
logger.info(__process_msg)
self.progress.update(value=0,
text=__process_msg,
key=ProgressKey.FileTransfer)
for transfer_task in transfer_tasks: for transfer_task in transfer_tasks:
if global_vars.is_system_stopped: if global_vars.is_system_stopped:
break break

View File

@@ -43,7 +43,7 @@ class NexusPhpSiteUserInfo(SiteParserBase):
message_text = message_labels[0].xpath("string(.)") message_text = message_labels[0].xpath("string(.)")
logger.debug(f"{self._site_name} 消息原始信息 {message_text}") logger.debug(f"{self._site_name} 消息原始信息 {message_text}")
message_unread_match = re.findall(r"[^Date](信息箱\s*|\(|你有\xa0)(\d+)", message_text) message_unread_match = re.findall(r"[^Date](信息箱\s*|\((?![^)]*:)|你有\xa0)(\d+)", message_text)
if message_unread_match and len(message_unread_match[-1]) == 2: if message_unread_match and len(message_unread_match[-1]) == 2:
self.message_unread = StringUtils.str_int(message_unread_match[-1][1]) self.message_unread = StringUtils.str_int(message_unread_match[-1][1])

View File

@@ -127,6 +127,8 @@ class SubscribeShare(BaseModel):
custom_words: Optional[str] = None custom_words: Optional[str] = None
# 自定义媒体类别 # 自定义媒体类别
media_category: Optional[str] = None media_category: Optional[str] = None
# 复用人次
count: Optional[int] = 0
class SubscribeDownloadFileInfo(BaseModel): class SubscribeDownloadFileInfo(BaseModel):

View File

@@ -1,2 +1,2 @@
APP_VERSION = 'v2.2.0' APP_VERSION = 'v2.2.1'
FRONTEND_VERSION = 'v2.2.0' FRONTEND_VERSION = 'v2.2.1'