Merge remote-tracking branch 'origin/wlj0909' into wlj0909

This commit is contained in:
mayun110 2023-09-19 18:14:47 +08:00
commit f4633788e9
9 changed files with 130 additions and 23 deletions

View File

@ -223,16 +223,19 @@ class ChainBase(metaclass=ABCMeta):
def filter_torrents(self, rule_string: str, def filter_torrents(self, rule_string: str,
torrent_list: List[TorrentInfo], torrent_list: List[TorrentInfo],
season_episodes: Dict[int, list] = None) -> List[TorrentInfo]: season_episodes: Dict[int, list] = None,
mediainfo: MediaInfo = None) -> List[TorrentInfo]:
""" """
过滤种子资源 过滤种子资源
:param rule_string: 过滤规则 :param rule_string: 过滤规则
:param torrent_list: 资源列表 :param torrent_list: 资源列表
:param season_episodes: 季集数过滤 {season:[episodes]} :param season_episodes: 季集数过滤 {season:[episodes]}
:param mediainfo: 识别的媒体信息
:return: 过滤后的资源列表添加资源优先级 :return: 过滤后的资源列表添加资源优先级
""" """
return self.run_module("filter_torrents", rule_string=rule_string, return self.run_module("filter_torrents", rule_string=rule_string,
torrent_list=torrent_list, season_episodes=season_episodes) torrent_list=torrent_list, season_episodes=season_episodes,
mediainfo=mediainfo)
def download(self, content: Union[Path, str], download_dir: Path, cookie: str, def download(self, content: Union[Path, str], download_dir: Path, cookie: str,
episodes: Set[int] = None, category: str = None episodes: Set[int] = None, category: str = None

View File

@ -225,7 +225,7 @@ class DownloadChain(ChainBase):
self.downloadhis.add_files(files_to_add) self.downloadhis.add_files(files_to_add)
# 发送消息 # 发送消息
self.post_download_message(meta=_meta, mediainfo=_media, torrent=_torrent, channel=channel) self.post_download_message(meta=_meta, mediainfo=_media, torrent=_torrent, channel=channel, userid=userid)
# 下载成功后处理 # 下载成功后处理
self.download_added(context=context, download_dir=download_dir, torrent_path=torrent_file) self.download_added(context=context, download_dir=download_dir, torrent_path=torrent_file)
# 广播事件 # 广播事件

View File

@ -135,7 +135,8 @@ class SearchChain(ChainBase):
logger.info(f'开始过滤资源,当前规则:{filter_rule} ...') logger.info(f'开始过滤资源,当前规则:{filter_rule} ...')
result: List[TorrentInfo] = self.filter_torrents(rule_string=filter_rule, result: List[TorrentInfo] = self.filter_torrents(rule_string=filter_rule,
torrent_list=torrents, torrent_list=torrents,
season_episodes=season_episodes) season_episodes=season_episodes,
mediainfo=mediainfo)
if result is not None: if result is not None:
torrents = result torrents = result
if not torrents: if not torrents:

View File

@ -512,7 +512,8 @@ class SubscribeChain(ChainBase):
filter_rule = self.systemconfig.get(SystemConfigKey.FilterRules) filter_rule = self.systemconfig.get(SystemConfigKey.FilterRules)
result: List[TorrentInfo] = self.filter_torrents( result: List[TorrentInfo] = self.filter_torrents(
rule_string=filter_rule, rule_string=filter_rule,
torrent_list=[torrent_info]) torrent_list=[torrent_info],
mediainfo=torrent_mediainfo)
if result is not None and not result: if result is not None and not result:
# 不符合过滤规则 # 不符合过滤规则
logger.info(f"{torrent_info.title} 不匹配当前过滤规则") logger.info(f"{torrent_info.title} 不匹配当前过滤规则")

View File

@ -1,3 +1,4 @@
import glob
import re import re
import shutil import shutil
import threading import threading
@ -601,8 +602,10 @@ class TransferChain(ChainBase):
if not path.exists(): if not path.exists():
return return
if path.is_file(): if path.is_file():
# 删除文件 # 删除文件、nfo、jpg
path.unlink() files = glob.glob(f"{Path(path.parent).joinpath(path.stem)}*")
for file in files:
Path(file).unlink()
logger.warn(f"文件 {path} 已删除") logger.warn(f"文件 {path} 已删除")
# 需要删除父目录 # 需要删除父目录
elif str(path.parent) == str(path.root): elif str(path.parent) == str(path.root):
@ -615,11 +618,24 @@ class TransferChain(ChainBase):
# 删除目录 # 删除目录
logger.warn(f"目录 {path} 已删除") logger.warn(f"目录 {path} 已删除")
# 需要删除父目录 # 需要删除父目录
# 判断当前媒体父路径下是否有媒体文件,如有则无需遍历父级
if not SystemUtils.exits_files(path.parent, settings.RMT_MEDIAEXT):
# 媒体库二级分类根路径
library_root_names = [
settings.LIBRARY_MOVIE_NAME or '电影',
settings.LIBRARY_TV_NAME or '电视剧',
settings.LIBRARY_ANIME_NAME or '动漫',
]
# 判断父目录是否为空, 为空则删除 # 判断父目录是否为空, 为空则删除
for parent_path in path.parents: for parent_path in path.parents:
# 遍历父目录到媒体库二级分类根路径
if str(parent_path.name) in library_root_names:
break
if str(parent_path.parent) != str(path.root): if str(parent_path.parent) != str(path.root):
# 父目录非根目录,才删除父目录 # 父目录非根目录,才删除父目录
files = SystemUtils.list_files(parent_path, settings.RMT_MEDIAEXT) if not SystemUtils.exits_files(path.parent, settings.RMT_MEDIAEXT):
if not files: # 当前路径下没有媒体文件则删除
shutil.rmtree(parent_path) shutil.rmtree(parent_path)
logger.warn(f"目录 {parent_path} 已删除") logger.warn(f"目录 {parent_path} 已删除")

View File

@ -1,7 +1,7 @@
import re import re
from typing import List, Tuple, Union, Dict, Optional from typing import List, Tuple, Union, Dict, Optional
from app.core.context import TorrentInfo from app.core.context import TorrentInfo, MediaInfo
from app.core.metainfo import MetaInfo from app.core.metainfo import MetaInfo
from app.log import logger from app.log import logger
from app.modules import _ModuleBase from app.modules import _ModuleBase
@ -9,9 +9,10 @@ from app.modules.filter.RuleParser import RuleParser
class FilterModule(_ModuleBase): class FilterModule(_ModuleBase):
# 规则解析器 # 规则解析器
parser: RuleParser = None parser: RuleParser = None
# 媒体信息
media: MediaInfo = None
# 内置规则集 # 内置规则集
rule_set: Dict[str, dict] = { rule_set: Dict[str, dict] = {
@ -37,8 +38,13 @@ class FilterModule(_ModuleBase):
}, },
# 中字 # 中字
"CNSUB": { "CNSUB": {
"include": [r'[中国國繁简](/|\s|\\|\|)?[繁简英粤]|[英简繁](/|\s|\\|\|)?[中繁简]|繁體|简体|[中国國][字配]|国语|國語|中文|中字'], "include": [
"exclude": [] r'[中国國繁简](/|\s|\\|\|)?[繁简英粤]|[英简繁](/|\s|\\|\|)?[中繁简]|繁體|简体|[中国國][字配]|国语|國語|中文|中字'],
"exclude": [],
# 只处理对应TMDB信息的数据
"tmdb": {
"original_language": "zh,cn"
}
}, },
# 特效字幕 # 特效字幕
"SPECSUB": { "SPECSUB": {
@ -107,16 +113,19 @@ class FilterModule(_ModuleBase):
def filter_torrents(self, rule_string: str, def filter_torrents(self, rule_string: str,
torrent_list: List[TorrentInfo], torrent_list: List[TorrentInfo],
season_episodes: Dict[int, list] = None) -> List[TorrentInfo]: season_episodes: Dict[int, list] = None,
mediainfo: MediaInfo = None) -> List[TorrentInfo]:
""" """
过滤种子资源 过滤种子资源
:param rule_string: 过滤规则 :param rule_string: 过滤规则
:param torrent_list: 资源列表 :param torrent_list: 资源列表
:param season_episodes: 季集数过滤 {season:[episodes]} :param season_episodes: 季集数过滤 {season:[episodes]}
:param mediainfo: 媒体信息
:return: 过滤后的资源列表添加资源优先级 :return: 过滤后的资源列表添加资源优先级
""" """
if not rule_string: if not rule_string:
return torrent_list return torrent_list
self.media = mediainfo
# 返回种子列表 # 返回种子列表
ret_torrents = [] ret_torrents = []
for torrent in torrent_list: for torrent in torrent_list:
@ -215,6 +224,11 @@ class FilterModule(_ModuleBase):
if not self.rule_set.get(rule_name): if not self.rule_set.get(rule_name):
# 规则不存在 # 规则不存在
return False return False
# TMDB规则
tmdb = self.rule_set[rule_name].get("tmdb")
# 不符合TMDB规则的直接返回True即不过滤
if tmdb and not self.__match_tmdb(tmdb):
return True
# 包含规则项 # 包含规则项
includes = self.rule_set[rule_name].get("include") or [] includes = self.rule_set[rule_name].get("include") or []
# 排除规则项 # 排除规则项
@ -236,3 +250,44 @@ class FilterModule(_ModuleBase):
# FREE规则不匹配 # FREE规则不匹配
return False return False
return True return True
def __match_tmdb(self, tmdb: dict) -> bool:
"""
判断种子是否匹配TMDB规则
"""
def __get_media_value(key: str):
try:
return getattr(self.media, key)
except ValueError:
return ""
if not self.media:
return False
for attr, value in tmdb.items():
if not value:
continue
# 获取media信息的值
info_value = __get_media_value(attr)
if not info_value:
# 没有该值,不匹配
return False
elif attr == "production_countries":
# 国家信息
info_values = [str(val.get("iso_3166_1")).upper() for val in info_value]
else:
# media信息转化为数组
if isinstance(info_value, list):
info_values = [str(val).upper() for val in info_value]
else:
info_values = [str(info_value).upper()]
# 过滤值转化为数组
if value.find(",") != -1:
values = [str(val).upper() for val in value.split(",")]
else:
values = [str(value).upper()]
# 没有交集为不匹配
if not set(values).intersection(set(info_values)):
return False
return True

View File

@ -131,7 +131,7 @@ class TransmissionModule(_ModuleBase):
title=torrent.name, title=torrent.name,
path=Path(torrent.download_dir) / torrent.name, path=Path(torrent.download_dir) / torrent.name,
hash=torrent.hashString, hash=torrent.hashString,
tags=torrent.labels tags=",".join(torrent.labels or [])
)) ))
elif status == TorrentStatus.DOWNLOADING: elif status == TorrentStatus.DOWNLOADING:
# 获取正在下载的任务 # 获取正在下载的任务

View File

@ -593,7 +593,8 @@ class RssSubscribe(_PluginBase):
if self._filter: if self._filter:
result = self.chain.filter_torrents( result = self.chain.filter_torrents(
rule_string=filter_rule, rule_string=filter_rule,
torrent_list=[torrentinfo] torrent_list=[torrentinfo],
mediainfo=mediainfo
) )
if not result: if not result:
logger.info(f"{title} {description} 不匹配过滤规则") logger.info(f"{title} {description} 不匹配过滤规则")

View File

@ -122,6 +122,36 @@ class SystemUtils:
return files return files
@staticmethod
def exits_files(directory: Path, extensions: list, min_filesize: int = 0) -> bool:
"""
判断目录下是否存在指定扩展名的文件
:return True存在 False不存在
"""
if not min_filesize:
min_filesize = 0
if not directory.exists():
return False
if directory.is_file():
return True
if not min_filesize:
min_filesize = 0
pattern = r".*(" + "|".join(extensions) + ")$"
# 遍历目录及子目录
for path in directory.rglob('**/*'):
if path.is_file() \
and re.match(pattern, path.name, re.IGNORECASE) \
and path.stat().st_size >= min_filesize * 1024 * 1024:
return True
return False
@staticmethod @staticmethod
def list_sub_files(directory: Path, extensions: list) -> List[Path]: def list_sub_files(directory: Path, extensions: list) -> List[Path]:
""" """