mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-07-11 15:33:12 +08:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
397a8a9536 | ||
|
|
1da0a706a3 | ||
|
|
4f2a110b5f | ||
|
|
bb356ffcee | ||
|
|
6c986416ca | ||
|
|
951ec138ef | ||
|
|
23e779ed94 | ||
|
|
29fccd3887 | ||
|
|
1bef723332 | ||
|
|
3c41fed0ef | ||
|
|
5947d0e6d0 | ||
|
|
0e4fa86372 |
@@ -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]:
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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])
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
APP_VERSION = 'v2.2.0'
|
APP_VERSION = 'v2.2.1'
|
||||||
FRONTEND_VERSION = 'v2.2.0'
|
FRONTEND_VERSION = 'v2.2.1'
|
||||||
|
|||||||
Reference in New Issue
Block a user