fix filter rules

This commit is contained in:
jxxghp
2024-07-04 21:25:50 +08:00
parent 28345817d9
commit 604c418bd4
10 changed files with 211 additions and 256 deletions

View File

@@ -19,9 +19,9 @@ from app.db.systemconfig_oper import SystemConfigOper
from app.db.userauth import get_current_active_superuser
from app.helper.message import MessageHelper
from app.helper.progress import ProgressHelper
from app.helper.rule import RuleHelper
from app.helper.sites import SitesHelper
from app.scheduler import Scheduler
from app.schemas.types import SystemConfigKey
from app.utils.http import RequestUtils
from app.utils.system import SystemUtils
from version import APP_VERSION
@@ -223,10 +223,10 @@ def latest_version(_: schemas.TokenPayload = Depends(verify_token)):
return schemas.Response(success=False)
@router.get("/ruletest", summary="优先级规则测试", response_model=schemas.Response)
@router.get("/ruletest", summary="过滤规则测试", response_model=schemas.Response)
def ruletest(title: str,
rulegroup_name: str,
subtitle: str = None,
ruletype: str = None,
_: schemas.TokenPayload = Depends(verify_token)):
"""
过滤规则测试,规则类型 1-订阅2-洗版3-搜索
@@ -235,20 +235,16 @@ def ruletest(title: str,
title=title,
description=subtitle,
)
if ruletype == "2":
rule_string = SystemConfigOper().get(SystemConfigKey.BestVersionFilterRules)
elif ruletype == "3":
rule_string = SystemConfigOper().get(SystemConfigKey.SearchFilterRules)
else:
rule_string = SystemConfigOper().get(SystemConfigKey.SubscribeFilterRules)
if not rule_string:
return schemas.Response(success=False, message="优先级规则未设置!")
# 查询规则组详情
rulegroup = RuleHelper().get_rule_group(rulegroup_name)
if not rulegroup:
return schemas.Response(success=False, message=f"过滤规则组 {rulegroup_name} 不存在!")
# 过滤
result = SearchChain().filter_torrents(rule_string=rule_string,
result = SearchChain().filter_torrents(rule_groups=[rulegroup.name],
torrent_list=[torrent])
if not result:
return schemas.Response(success=False, message="不符合优先级规则!")
return schemas.Response(success=False, message="不符合过滤规则!")
return schemas.Response(success=True, data={
"priority": 100 - result[0].pri_order + 1
})

View File

@@ -22,7 +22,7 @@ from app.helper.notification import NotificationHelper
from app.log import logger
from app.schemas import TransferInfo, TransferTorrent, ExistMediaInfo, DownloadingTorrent, CommingMessage, Notification, \
WebhookEventInfo, TmdbEpisode, MediaPerson, FileItem
from app.schemas.types import TorrentStatus, MediaType, MediaImageType, EventType, NotificationType
from app.schemas.types import TorrentStatus, MediaType, MediaImageType, EventType
from app.utils.object import ObjectUtils
@@ -316,19 +316,19 @@ class ChainBase(metaclass=ABCMeta):
"""
return self.run_module("refresh_torrents", site=site)
def filter_torrents(self, rule_string: str,
def filter_torrents(self, rule_groups: List[str],
torrent_list: List[TorrentInfo],
season_episodes: Dict[int, list] = None,
mediainfo: MediaInfo = None) -> List[TorrentInfo]:
"""
过滤种子资源
:param rule_string: 过滤规则
:param rule_groups: 过滤规则组名称列表
:param torrent_list: 资源列表
:param season_episodes: 季集数过滤 {season:[episodes]}
:param mediainfo: 识别的媒体信息
:return: 过滤后的资源列表,添加资源优先级
"""
return self.run_module("filter_torrents", rule_string=rule_string,
return self.run_module("filter_torrents", rule_groups=rule_groups,
torrent_list=torrent_list, season_episodes=season_episodes,
mediainfo=mediainfo)

View File

@@ -97,8 +97,7 @@ class SearchChain(ChainBase):
keyword: str = None,
no_exists: Dict[int, Dict[int, NotExistMediaInfo]] = None,
sites: List[int] = None,
priority_rule: str = None,
filter_rule: Dict[str, str] = None,
rule_groups: List[str] = None,
area: str = "title") -> List[Context]:
"""
根据媒体信息搜索种子资源精确匹配应用过滤规则同时根据no_exists过滤本地已存在的资源
@@ -106,8 +105,7 @@ class SearchChain(ChainBase):
:param keyword: 搜索关键词
:param no_exists: 缺失的媒体信息
:param sites: 站点ID列表为空时搜索所有站点
:param priority_rule: 优先级规则,为空时使用搜索优先级规则
:param filter_rule: 过滤规则,为空是使用默认过滤规则
:param rule_groups: 过滤规则组名称列表
:param area: 搜索范围title or imdbid
"""
@@ -115,7 +113,7 @@ class SearchChain(ChainBase):
"""
执行优先级过滤
"""
return self.filter_torrents(rule_string=priority_rule,
return self.filter_torrents(rule_groups=rule_groups,
torrent_list=torrent_list,
season_episodes=season_episodes,
mediainfo=mediainfo) or []
@@ -220,27 +218,16 @@ class SearchChain(ChainBase):
key=ProgressKey.Search)
# 开始过滤规则过滤
if _match_torrents:
logger.info(f'开始过滤规则过滤,当前规则:{filter_rule} ...')
_match_torrents = self.filter_torrents_by_rule(torrents=_match_torrents,
mediainfo=mediainfo,
filter_rule=filter_rule)
if not _match_torrents:
logger.warn(f'{keyword or mediainfo.title} 没有符合过滤规则的资源')
return []
logger.info(f"过滤规则过滤完成,剩余 {len(_match_torrents)} 个资源")
# 开始优先级规则/剧集过滤
if priority_rule is None:
# 取搜索优先级规则
priority_rule = self.systemconfig.get(SystemConfigKey.SearchFilterRules)
if priority_rule:
logger.info(f'开始优先级规则/剧集过滤,当前规则:{priority_rule} ...')
if rule_groups is None:
# 取搜索过滤规则
rule_groups: List[str] = self.systemconfig.get(SystemConfigKey.SearchFilterRuleGroups)
if rule_groups:
logger.info(f'开始过滤规则/剧集过滤,使用规则组:{rule_groups} ...')
_match_torrents = __do_filter(_match_torrents)
if not _match_torrents:
logger.warn(f'{keyword or mediainfo.title} 没有符合优先级规则的资源')
logger.warn(f'{keyword or mediainfo.title} 没有符合过滤规则的资源')
return []
logger.info(f"优先级规则/剧集过滤完成,剩余 {len(_match_torrents)} 个资源")
logger.info(f"过滤规则/剧集过滤完成,剩余 {len(_match_torrents)} 个资源")
# 去掉mediainfo中多余的数据
mediainfo.clear()
@@ -354,34 +341,6 @@ class SearchChain(ChainBase):
# 返回
return results
def filter_torrents_by_rule(self,
torrents: List[TorrentInfo],
mediainfo: MediaInfo,
filter_rule: Dict[str, str] = None,
) -> List[TorrentInfo]:
"""
使用过滤规则过滤种子
:param torrents: 种子列表
:param filter_rule: 过滤规则
:param mediainfo: 媒体信息
"""
if not filter_rule:
# 没有则取搜索默认过滤规则
filter_rule = self.systemconfig.get(SystemConfigKey.DefaultSearchFilterRules)
if not filter_rule:
return torrents
# 使用默认过滤规则再次过滤
return list(filter(
lambda t: self.torrenthelper.filter_torrent(
torrent_info=t,
filter_rule=filter_rule,
mediainfo=mediainfo
),
torrents
))
@eventmanager.register(EventType.SiteDeleted)
def remove_site(self, event: Event):
"""

View File

@@ -329,20 +329,16 @@ class SubscribeChain(ChainBase):
# 优先级过滤规则
if subscribe.best_version:
priority_rule = self.systemconfig.get(SystemConfigKey.BestVersionFilterRules)
rule_groups = self.systemconfig.get(SystemConfigKey.BeseVersionFilterRuleGroups)
else:
priority_rule = self.systemconfig.get(SystemConfigKey.SubscribeFilterRules)
# 过滤规则
filter_rule = self.get_filter_rule(subscribe)
rule_groups = self.systemconfig.get(SystemConfigKey.SubscribeFilterRuleGroups)
# 搜索,同时电视剧会过滤掉不需要的剧集
contexts = self.searchchain.process(mediainfo=mediainfo,
keyword=subscribe.keyword,
no_exists=no_exists,
sites=sites,
priority_rule=priority_rule,
filter_rule=filter_rule,
rule_groups=rule_groups,
area="imdbid" if subscribe.search_imdbid else "title")
if not contexts:
logger.warn(f'订阅 {subscribe.keyword or subscribe.name} 未搜索到资源')
@@ -515,24 +511,6 @@ class SubscribeChain(ChainBase):
return ret_sites
def get_filter_rule(self, subscribe: Subscribe):
"""
获取订阅过滤规则,同时组合默认规则
"""
# 默认过滤规则
default_rule = self.systemconfig.get(SystemConfigKey.DefaultFilterRules) or {}
return {
"include": subscribe.include or default_rule.get("include"),
"exclude": subscribe.exclude or default_rule.get("exclude"),
"quality": subscribe.quality or default_rule.get("quality"),
"resolution": subscribe.resolution or default_rule.get("resolution"),
"effect": subscribe.effect or default_rule.get("effect"),
"tv_size": default_rule.get("tv_size"),
"movie_size": default_rule.get("movie_size"),
"min_seeders": default_rule.get("min_seeders"),
"min_seeders_time": default_rule.get("min_seeders_time"),
}
def match(self, torrents: Dict[str, List[Context]]):
"""
从缓存中匹配订阅,并自动下载
@@ -624,9 +602,6 @@ class SubscribeChain(ChainBase):
downloaded_episodes=self.__get_downloaded_episodes(subscribe)
)
# 过滤规则
filter_rule = self.get_filter_rule(subscribe)
# 遍历缓存种子
_match_context = []
for domain, contexts in torrents.items():
@@ -678,18 +653,18 @@ class SubscribeChain(ChainBase):
else:
continue
# 优先级过滤规则
# 过滤规则
if subscribe.best_version:
priority_rule = self.systemconfig.get(SystemConfigKey.BestVersionFilterRules)
rule_groups = self.systemconfig.get(SystemConfigKey.BeseVersionFilterRuleGroups)
else:
priority_rule = self.systemconfig.get(SystemConfigKey.SubscribeFilterRules)
rule_groups = self.systemconfig.get(SystemConfigKey.SubscribeFilterRuleGroups)
result: List[TorrentInfo] = self.filter_torrents(
rule_string=priority_rule,
rule_groups=rule_groups,
torrent_list=[torrent_info],
mediainfo=torrent_mediainfo)
if result is not None and not result:
# 不符合过滤规则
logger.debug(f"{torrent_info.title} 不匹配当前过滤规则")
logger.debug(f"{torrent_info.title} 不匹配过滤规则")
continue
# 不在订阅站点范围的不处理
@@ -736,12 +711,6 @@ class SubscribeChain(ChainBase):
logger.debug(f'{subscribe.name} 正在洗版,{torrent_info.title} 不是整季')
continue
# 过滤规则
if not self.torrenthelper.filter_torrent(torrent_info=torrent_info,
filter_rule=filter_rule,
mediainfo=torrent_mediainfo):
continue
# 洗版时,优先级小于已下载优先级的不要
if subscribe.best_version:
if subscribe.current_priority \

52
app/helper/rule.py Normal file
View File

@@ -0,0 +1,52 @@
from typing import List, Optional
from app.db.systemconfig_oper import SystemConfigOper
from app.schemas import FilterRuleGroup, CustomRule
from app.schemas.types import SystemConfigKey
class RuleHelper:
"""
规划帮助类
"""
def __init__(self):
self.systemconfig = SystemConfigOper()
def get_rule_groups(self) -> List[FilterRuleGroup]:
"""
获取用户所有规则组
"""
rule_groups: List[dict] = self.systemconfig.get(SystemConfigKey.UserRuleGroups)
if not rule_groups:
return []
return [FilterRuleGroup(**group) for group in rule_groups]
def get_rule_group(self, group_name: str) -> Optional[FilterRuleGroup]:
"""
获取规则组
"""
rule_groups = self.get_rule_groups()
for group in rule_groups:
if group.name == group_name:
return group
return None
def get_custom_rules(self) -> List[CustomRule]:
"""
获取用户所有自定义规则
"""
rules: List[dict] = self.systemconfig.get(SystemConfigKey.CustomFilterRules)
if not rules:
return []
return [CustomRule(**rule) for rule in rules]
def get_custom_rule(self, rule_id: str) -> Optional[CustomRule]:
"""
获取自定义规则
"""
rules = self.get_custom_rules()
for rule in rules:
if rule.id == rule_id:
return rule
return None

View File

@@ -1,8 +1,7 @@
import datetime
import re
import traceback
from pathlib import Path
from typing import Tuple, Optional, List, Union, Dict
from typing import Tuple, Optional, List, Union
from urllib.parse import unquote
from requests import Response
@@ -13,8 +12,8 @@ from app.core.context import Context, TorrentInfo, MediaInfo
from app.core.metainfo import MetaInfo
from app.db.systemconfig_oper import SystemConfigOper
from app.log import logger
from app.utils.http import RequestUtils
from app.schemas.types import MediaType, SystemConfigKey
from app.utils.http import RequestUtils
from app.utils.singleton import Singleton
from app.utils.string import StringUtils
@@ -298,135 +297,6 @@ class TorrentHelper(metaclass=Singleton):
if url not in self._invalid_torrents:
self._invalid_torrents.append(url)
@staticmethod
def filter_torrent(torrent_info: TorrentInfo,
filter_rule: Dict[str, str],
mediainfo: MediaInfo) -> bool:
"""
检查种子是否匹配订阅过滤规则
"""
def __get_size_range(size_str: str) -> Tuple[float, float]:
"""
获取大小范围
"""
if not size_str:
return 0, 0
try:
size_range = size_str.split("-")
if len(size_range) == 1:
return 0, float(size_range[0])
elif len(size_range) == 2:
return float(size_range[0]), float(size_range[1])
except Exception as e:
logger.error(f"解析大小范围失败:{str(e)} - {traceback.format_exc()}")
return 0, 0
def __get_pubminutes(pubdate: str) -> float:
"""
将字符串转换为时间,并计算与当前时间差)(分钟)
"""
try:
if not pubdate:
return 0
pubdate = pubdate.replace("T", " ").replace("Z", "")
pubdate = datetime.datetime.strptime(pubdate, "%Y-%m-%d %H:%M:%S")
now = datetime.datetime.now()
return (now - pubdate).total_seconds() // 60
except Exception as e:
print(str(e))
return 0
if not filter_rule:
return True
# 匹配内容
content = (f"{torrent_info.title} "
f"{torrent_info.description} "
f"{' '.join(torrent_info.labels or [])} "
f"{torrent_info.volume_factor}")
# 最少做种人数
min_seeders = filter_rule.get("min_seeders")
if min_seeders and torrent_info.seeders < int(min_seeders):
# 最少做种人数生效发布时间(分钟)(在设置发布时间之外的最少做种人数生效)
min_seeders_time = filter_rule.get("min_seeders_time") or 0
if min_seeders_time:
# 发布时间与当前时间差(分钟)
pubdate_minutes = __get_pubminutes(torrent_info.pubdate)
if pubdate_minutes > int(min_seeders_time):
logger.info(f"{torrent_info.title} 发布时间大于 {min_seeders_time} 分钟,做种人数不足 {min_seeders}")
return False
else:
logger.info(f"{torrent_info.title} 做种人数不足 {min_seeders}")
return False
# 包含
include = filter_rule.get("include")
if include:
if not re.search(r"%s" % include, content, re.I):
logger.info(f"{content} 不匹配包含规则 {include}")
return False
# 排除
exclude = filter_rule.get("exclude")
if exclude:
if re.search(r"%s" % exclude, content, re.I):
logger.info(f"{content} 匹配排除规则 {exclude}")
return False
# 质量
quality = filter_rule.get("quality")
if quality:
if not re.search(r"%s" % quality, torrent_info.title, re.I):
logger.info(f"{torrent_info.title} 不匹配质量规则 {quality}")
return False
# 分辨率
resolution = filter_rule.get("resolution")
if resolution:
if not re.search(r"%s" % resolution, torrent_info.title, re.I):
logger.info(f"{torrent_info.title} 不匹配分辨率规则 {resolution}")
return False
# 特效
effect = filter_rule.get("effect")
if effect:
if not re.search(r"%s" % effect, torrent_info.title, re.I):
logger.info(f"{torrent_info.title} 不匹配特效规则 {effect}")
return False
# 大小
tv_size = filter_rule.get("tv_size")
movie_size = filter_rule.get("movie_size")
if movie_size or tv_size:
if mediainfo.type == MediaType.TV:
size = tv_size
else:
size = movie_size
# 大小范围
begin_size, end_size = __get_size_range(size)
if begin_size or end_size:
meta = MetaInfo(title=torrent_info.title, subtitle=torrent_info.description)
# 集数
if mediainfo.type == MediaType.TV:
# 电视剧
season = meta.begin_season or 1
if meta.total_episode:
# 识别的总集数
episodes_num = meta.total_episode
else:
# 整季集数
episodes_num = len(mediainfo.seasons.get(season) or [1])
# 比较大小
if not (begin_size * 1024 ** 3 <= (torrent_info.size / episodes_num) <= end_size * 1024 ** 3):
logger.info(f"{torrent_info.title} {StringUtils.str_filesize(torrent_info.size)} "
f"{episodes_num}集,不匹配大小规则 {size}")
return False
else:
# 电影比较大小
if not (begin_size * 1024 ** 3 <= torrent_info.size <= end_size * 1024 ** 3):
logger.info(
f"{torrent_info.title} {StringUtils.str_filesize(torrent_info.size)} 不匹配大小规则 {size}")
return False
return True
@staticmethod
def match_torrent(mediainfo: MediaInfo, torrent_meta: MetaInfo, torrent: TorrentInfo) -> bool:
"""

View File

@@ -3,6 +3,7 @@ from typing import List, Tuple, Union, Dict, Optional
from app.core.context import TorrentInfo, MediaInfo
from app.core.metainfo import MetaInfo
from app.helper.rule import RuleHelper
from app.log import logger
from app.modules import _ModuleBase
from app.modules.filter.RuleParser import RuleParser
@@ -133,8 +134,17 @@ class FilterModule(_ModuleBase):
},
}
def __init__(self):
super().__init__()
self.rulehelper = RuleHelper()
def init_module(self) -> None:
self.parser = RuleParser()
# 加载用户自定义规则,如跟内置规则冲突,以用户自定义规则为准
custom_rules = self.rulehelper.get_custom_rules()
for rule in custom_rules:
logger.info(f"加载自定义规则 {rule.id} - {rule.name}")
self.rule_set[rule.id] = rule.dict()
@staticmethod
def get_name() -> str:
@@ -149,21 +159,45 @@ class FilterModule(_ModuleBase):
def init_setting(self) -> Tuple[str, Union[str, bool]]:
pass
def filter_torrents(self, rule_string: str,
def filter_torrents(self, rule_groups: List[str],
torrent_list: List[TorrentInfo],
season_episodes: Dict[int, list] = None,
mediainfo: MediaInfo = None) -> List[TorrentInfo]:
"""
过滤种子资源
:param rule_string: 过滤规则
:param rule_groups: 过滤规则组名称列表
:param torrent_list: 资源列表
:param season_episodes: 季集数过滤 {season:[episodes]}
:param mediainfo: 媒体信息
:return: 过滤后的资源列表,添加资源优先级
"""
if not rule_string:
if not rule_groups:
return torrent_list
self.media = mediainfo
# 查询规则表详情
for group_name in rule_groups:
rule_group = self.rulehelper.get_rule_group(group_name)
if not rule_group:
logger.error(f"规则组 {group_name} 不存在")
continue
if rule_group.media_type and rule_group.media_type != mediainfo.type.value:
# 规则组不适用当前媒体类型
continue
# 过滤种子
torrent_list = self.__filter_torrents(
rule_string=rule_group.rule_string,
rule_name=rule_group.name,
torrent_list=torrent_list,
season_episodes=season_episodes
)
return torrent_list
def __filter_torrents(self, rule_string: str, rule_name: str,
torrent_list: List[TorrentInfo],
season_episodes: Dict[int, list]) -> List[TorrentInfo]:
"""
过滤种子
"""
# 返回种子列表
ret_torrents = []
for torrent in torrent_list:
@@ -173,7 +207,8 @@ class FilterModule(_ModuleBase):
continue
# 能命中优先级的才返回
if not self.__get_order(torrent, rule_string):
logger.debug(f"种子 {torrent.site_name} - {torrent.title} {torrent.description} 不匹配优先级规则")
logger.debug(f"种子 {torrent.site_name} - {torrent.title} {torrent.description} "
f"不匹配 {rule_name} 过滤规则")
continue
ret_torrents.append(torrent)
@@ -196,7 +231,8 @@ class FilterModule(_ModuleBase):
torrent_episodes = meta.episode_list
if not set(torrent_seasons).issubset(set(seasons)):
# 种子季不在过滤季中
logger.debug(f"种子 {torrent.site_name} - {torrent.title} 包含季 {torrent_seasons} 不是需要的季 {list(seasons)}")
logger.debug(
f"种子 {torrent.site_name} - {torrent.title} 包含季 {torrent_seasons} 不是需要的季 {list(seasons)}")
return False
if not torrent_episodes:
# 整季按匹配处理
@@ -207,7 +243,7 @@ class FilterModule(_ModuleBase):
and not set(torrent_episodes).intersection(set(need_episodes)):
# 单季集没有交集的不要
logger.debug(f"种子 {torrent.site_name} - {torrent.title} "
f"{torrent_episodes} 没有需要的集:{need_episodes}")
f"{torrent_episodes} 没有需要的集:{need_episodes}")
return False
return True
@@ -290,6 +326,10 @@ class FilterModule(_ModuleBase):
includes = self.rule_set[rule_name].get("include") or []
# 排除规则项
excludes = self.rule_set[rule_name].get("exclude") or []
# 大小范围规则项
size_range = self.rule_set[rule_name].get("size_range")
# 做种人数规则项
seeders = self.rule_set[rule_name].get("seeders")
# FREE规则
downloadvolumefactor = self.rule_set[rule_name].get("downloadvolumefactor")
for include in includes:
@@ -300,6 +340,14 @@ class FilterModule(_ModuleBase):
if re.search(r"%s" % exclude, content, re.IGNORECASE):
# 发现排除项
return False
if size_range:
if not self.__match_size(torrent, size_range):
# 大小范围不匹配
return False
if seeders:
if torrent.seeders < int(seeders):
# 做种人数不匹配
return False
if downloadvolumefactor is not None:
if torrent.downloadvolumefactor != downloadvolumefactor:
# FREE规则不匹配
@@ -310,6 +358,7 @@ class FilterModule(_ModuleBase):
"""
判断种子是否匹配TMDB规则
"""
def __get_media_value(key: str):
try:
return getattr(self.media, key)
@@ -346,3 +395,30 @@ class FilterModule(_ModuleBase):
return False
return True
@staticmethod
def __match_size(torrent: TorrentInfo, size_range: str) -> bool:
"""
判断种子是否匹配大小范围MB
"""
if not size_range:
return True
size_range = size_range.strip()
if size_range.find("-") != -1:
# 区间
size_min, size_max = size_range.split("-")
size_min = float(size_min.strip()) * 1024 * 1024
size_max = float(size_max.strip()) * 1024 * 1024
if size_min <= torrent.size <= size_max:
return True
elif size_range.startswith(">"):
# 大于
size_min = float(size_range[1:].strip()) * 1024 * 1024
if torrent.size >= size_min:
return True
elif size_range.startswith("<"):
# 小于
size_max = float(size_range[1:].strip()) * 1024 * 1024
if torrent.size <= size_max:
return True
return False

View File

@@ -13,5 +13,5 @@ from .mediaserver import *
from .message import *
from .tmdb import *
from .transfer import *
from .filetransfer import *
from .rule import *
from .system import *

33
app/schemas/rule.py Normal file
View File

@@ -0,0 +1,33 @@
from typing import Optional
from pydantic import BaseModel
class CustomRule(BaseModel):
"""
自定义规则项
"""
# 规则ID
id: Optional[str] = None
# 名称
name: Optional[str] = None
# 包含
include: Optional[list] = []
# 排除
exclude: Optional[list] = []
# 大小范围
size_range: Optional[str] = None
# 最少做种人数
seeders: Optional[str] = None
class FilterRuleGroup(BaseModel):
"""
过滤规则组
"""
# 名称
name: Optional[str] = None
# 规则串
rule_string: Optional[str] = None
# 适用类媒体类别 None-全部 电影/电视剧
media_type: Optional[str] = None

View File

@@ -84,16 +84,16 @@ class SystemConfigKey(Enum):
TransferExcludeWords = "TransferExcludeWords"
# 种子优先级规则
TorrentsPriority = "TorrentsPriority"
# 搜索优先级规则
SearchFilterRules = "SearchFilterRules"
# 订阅优先级规则
SubscribeFilterRules = "SubscribeFilterRules"
# 洗版规则
BestVersionFilterRules = "BestVersionFilterRules"
# 默认订阅过滤规则
DefaultFilterRules = "DefaultFilterRules"
# 默认搜索过滤规则
DefaultSearchFilterRules = "DefaultSearchFilterRules"
# 用户自定义规则
CustomFilterRules = "CustomFilterRules"
# 用户规则
UserRuleGroups = "UserRuleGroups"
# 搜索默认过滤规则
SearchFilterRuleGroups = "SearchFilterRuleGroups"
# 订阅默认过滤规则
SubscribeFilterRuleGroups = "SubscribeFilterRuleGroups"
# 洗版默认过滤规则
BeseVersionFilterRuleGroups = "BeseVersionFilterRuleGroups"
# 订阅统计
SubscribeReport = "SubscribeReport"
# 用户自定义CSS