This commit is contained in:
jxxghp
2025-06-05 20:28:43 +08:00
parent 304af5e980
commit 13f9ea8be4
18 changed files with 76 additions and 158 deletions
+1 -2
View File
@@ -81,7 +81,6 @@ class ReleaseGroupsMatcher(metaclass=Singleton):
} }
def __init__(self): def __init__(self):
self.systemconfig = SystemConfigOper()
release_groups = [] release_groups = []
for site_groups in self.RELEASE_GROUPS.values(): for site_groups in self.RELEASE_GROUPS.values():
for release_group in site_groups: for release_group in site_groups:
@@ -98,7 +97,7 @@ class ReleaseGroupsMatcher(metaclass=Singleton):
return "" return ""
if not groups: if not groups:
# 自定义组 # 自定义组
custom_release_groups = self.systemconfig.get(SystemConfigKey.CustomReleaseGroups) custom_release_groups = SystemConfigOper().get(SystemConfigKey.CustomReleaseGroups)
if isinstance(custom_release_groups, list): if isinstance(custom_release_groups, list):
custom_release_groups = list(filter(None, custom_release_groups)) custom_release_groups = list(filter(None, custom_release_groups))
if custom_release_groups: if custom_release_groups:
-64
View File
@@ -197,67 +197,3 @@ def find_metainfo(title: str) -> Tuple[str, dict]:
elif metainfo.get('begin_episode') and not metainfo.get('end_episode'): elif metainfo.get('begin_episode') and not metainfo.get('end_episode'):
metainfo['total_episode'] = 1 metainfo['total_episode'] = 1
return title, metainfo return title, metainfo
def test_find_metainfo():
"""
测试find_metainfo函数的各种ID识别格式
"""
test_cases = [
# 测试 [tmdbid=xxxx] 格式
("The Vampire Diaries (2009) [tmdbid=18165]", "18165"),
# 测试 [tmdbid-xxxx] 格式
("Inception (2010) [tmdbid-27205]", "27205"),
# 测试 [tmdb=xxxx] 格式
("Breaking Bad (2008) [tmdb=1396]", "1396"),
# 测试 [tmdb-xxxx] 格式
("Interstellar (2014) [tmdb-157336]", "157336"),
# 测试 {tmdbid=xxxx} 格式
("Stranger Things (2016) {tmdbid=66732}", "66732"),
# 测试 {tmdbid-xxxx} 格式
("The Matrix (1999) {tmdbid-603}", "603"),
# 测试 {tmdb=xxxx} 格式
("Game of Thrones (2011) {tmdb=1399}", "1399"),
# 测试 {tmdb-xxxx} 格式
("Avatar (2009) {tmdb-19995}", "19995"),
]
for title, expected_tmdbid in test_cases:
cleaned_title, metainfo = find_metainfo(title)
found_tmdbid = metainfo.get('tmdbid')
print(f"原标题: {title}")
print(f"清理后标题: {cleaned_title}")
print(f"期望的tmdbid: {expected_tmdbid}")
print(f"识别的tmdbid: {found_tmdbid}")
print(f"结果: {'通过' if found_tmdbid == expected_tmdbid else '失败'}")
print("-" * 50)
def test_meta_info_path():
"""
测试MetaInfoPath函数
"""
# 测试文件路径
path_tests = [
# 文件名中包含tmdbid
Path("/movies/The Vampire Diaries (2009) [tmdbid=18165]/The.Vampire.Diaries.S01E01.1080p.mkv"),
# 目录名中包含tmdbid
Path("/movies/Inception (2010) [tmdbid-27205]/Inception.2010.1080p.mkv"),
# 父目录名中包含tmdbid
Path("/movies/Breaking Bad (2008) [tmdb=1396]/Season 1/Breaking.Bad.S01E01.1080p.mkv"),
# 祖父目录名中包含tmdbid
Path("/tv/Game of Thrones (2011) {tmdb=1399}/Season 1/Game.of.Thrones.S01E01.1080p.mkv"),
]
for path in path_tests:
meta = MetaInfoPath(path)
print(f"测试路径: {path}")
print(f"识别结果: tmdbid={meta.tmdbid}")
print("-" * 50)
if __name__ == "__main__":
# 运行测试函数
# test_find_metainfo()
test_meta_info_path()
+23 -23
View File
@@ -87,7 +87,6 @@ class PluginManager(metaclass=Singleton):
""" """
插件管理器 插件管理器
""" """
systemconfig: SystemConfigOper = None
# 插件列表 # 插件列表
_plugins: dict = {} _plugins: dict = {}
@@ -99,10 +98,6 @@ class PluginManager(metaclass=Singleton):
_observer: Observer = None _observer: Observer = None
def __init__(self): def __init__(self):
self.siteshelper = SitesHelper()
self.pluginhelper = PluginHelper()
self.systemconfig = SystemConfigOper()
self.plugindata = PluginDataOper()
# 开发者模式监测插件修改 # 开发者模式监测插件修改
if settings.DEV or settings.PLUGIN_AUTO_RELOAD: if settings.DEV or settings.PLUGIN_AUTO_RELOAD:
self.__start_monitor() self.__start_monitor()
@@ -141,7 +136,7 @@ class PluginManager(metaclass=Singleton):
filter_func=lambda _, obj: check_module(obj) filter_func=lambda _, obj: check_module(obj)
) )
# 已安装插件 # 已安装插件
installed_plugins = self.systemconfig.get(SystemConfigKey.UserInstalledPlugins) or [] installed_plugins = SystemConfigOper().get(SystemConfigKey.UserInstalledPlugins) or []
# 排序 # 排序
plugins.sort(key=lambda x: x.plugin_order if hasattr(x, "plugin_order") else 0) plugins.sort(key=lambda x: x.plugin_order if hasattr(x, "plugin_order") else 0)
for plugin in plugins: for plugin in plugins:
@@ -331,7 +326,7 @@ class PluginManager(metaclass=Singleton):
def install_plugin(plugin): def install_plugin(plugin):
start_time = time.time() start_time = time.time()
state, msg = self.pluginhelper.install(pid=plugin.id, repo_url=plugin.repo_url, force_install=True) state, msg = PluginHelper().install(pid=plugin.id, repo_url=plugin.repo_url, force_install=True)
elapsed_time = time.time() - start_time elapsed_time = time.time() - start_time
if state: if state:
logger.info( logger.info(
@@ -346,7 +341,7 @@ class PluginManager(metaclass=Singleton):
return [] return []
# 获取已安装插件列表 # 获取已安装插件列表
install_plugins = self.systemconfig.get(SystemConfigKey.UserInstalledPlugins) or [] install_plugins = SystemConfigOper().get(SystemConfigKey.UserInstalledPlugins) or []
# 获取在线插件列表 # 获取在线插件列表
online_plugins = self.get_online_plugins() online_plugins = self.get_online_plugins()
# 确定需要安装的插件 # 确定需要安装的插件
@@ -382,19 +377,21 @@ class PluginManager(metaclass=Singleton):
) )
return sync_plugins return sync_plugins
def install_plugin_missing_dependencies(self) -> List[str]: @staticmethod
def install_plugin_missing_dependencies() -> List[str]:
""" """
安装插件中缺失或不兼容的依赖项 安装插件中缺失或不兼容的依赖项
""" """
pluginhelper = PluginHelper()
# 第一步:获取需要安装的依赖项列表 # 第一步:获取需要安装的依赖项列表
missing_dependencies = self.pluginhelper.find_missing_dependencies() missing_dependencies = pluginhelper.find_missing_dependencies()
if not missing_dependencies: if not missing_dependencies:
return missing_dependencies return missing_dependencies
logger.debug(f"检测到缺失的依赖项: {missing_dependencies}") logger.debug(f"检测到缺失的依赖项: {missing_dependencies}")
logger.info(f"开始安装缺失的依赖项,共 {len(missing_dependencies)} 个...") logger.info(f"开始安装缺失的依赖项,共 {len(missing_dependencies)} 个...")
# 第二步:安装依赖项并返回结果 # 第二步:安装依赖项并返回结果
total_start_time = time.time() total_start_time = time.time()
success, message = self.pluginhelper.install_dependencies(missing_dependencies) success, message = pluginhelper.install_dependencies(missing_dependencies)
total_elapsed_time = time.time() - total_start_time total_elapsed_time = time.time() - total_start_time
if success: if success:
logger.info(f"已完成 {len(missing_dependencies)} 个依赖项安装,总耗时:{total_elapsed_time:.2f}") logger.info(f"已完成 {len(missing_dependencies)} 个依赖项安装,总耗时:{total_elapsed_time:.2f}")
@@ -409,7 +406,7 @@ class PluginManager(metaclass=Singleton):
""" """
if not self._plugins.get(pid): if not self._plugins.get(pid):
return {} return {}
conf = self.systemconfig.get(self._config_key % pid) conf = SystemConfigOper().get(self._config_key % pid)
if conf: if conf:
# 去掉空Key # 去掉空Key
return {k: v for k, v in conf.items() if k} return {k: v for k, v in conf.items() if k}
@@ -423,7 +420,7 @@ class PluginManager(metaclass=Singleton):
""" """
if not self._plugins.get(pid): if not self._plugins.get(pid):
return False return False
self.systemconfig.set(self._config_key % pid, conf) SystemConfigOper().set(self._config_key % pid, conf)
return True return True
def delete_plugin_config(self, pid: str) -> bool: def delete_plugin_config(self, pid: str) -> bool:
@@ -433,7 +430,7 @@ class PluginManager(metaclass=Singleton):
""" """
if not self._plugins.get(pid): if not self._plugins.get(pid):
return False return False
return self.systemconfig.delete(self._config_key % pid) return SystemConfigOper().delete(self._config_key % pid)
def delete_plugin_data(self, pid: str) -> bool: def delete_plugin_data(self, pid: str) -> bool:
""" """
@@ -442,7 +439,7 @@ class PluginManager(metaclass=Singleton):
""" """
if not self._plugins.get(pid): if not self._plugins.get(pid):
return False return False
self.plugindata.del_data(pid) PluginDataOper().del_data(pid)
return True return True
def get_plugin_state(self, pid: str) -> bool: def get_plugin_state(self, pid: str) -> bool:
@@ -804,7 +801,7 @@ class PluginManager(metaclass=Singleton):
# 返回值 # 返回值
plugins = [] plugins = []
# 已安装插件 # 已安装插件
installed_apps = self.systemconfig.get(SystemConfigKey.UserInstalledPlugins) or [] installed_apps = SystemConfigOper().get(SystemConfigKey.UserInstalledPlugins) or []
for pid, plugin_class in self._plugins.items(): for pid, plugin_class in self._plugins.items():
# 运行状插件 # 运行状插件
plugin_obj = self._running_plugins.get(pid) plugin_obj = self._running_plugins.get(pid)
@@ -901,9 +898,9 @@ class PluginManager(metaclass=Singleton):
if not market: if not market:
return [] return []
# 已安装插件 # 已安装插件
installed_apps = self.systemconfig.get(SystemConfigKey.UserInstalledPlugins) or [] installed_apps = SystemConfigOper().get(SystemConfigKey.UserInstalledPlugins) or []
# 获取在线插件 # 获取在线插件
online_plugins = self.pluginhelper.get_plugins(market, package_version) online_plugins = PluginHelper().get_plugins(market, package_version)
if online_plugins is None: if online_plugins is None:
logger.warning( logger.warning(
f"获取{package_version if package_version else ''}插件库失败:{market},请检查 GitHub 网络连接") f"获取{package_version if package_version else ''}插件库失败:{market},请检查 GitHub 网络连接")
@@ -990,7 +987,8 @@ class PluginManager(metaclass=Singleton):
return ret_plugins return ret_plugins
def __set_and_check_auth_level(self, plugin: Union[schemas.Plugin, Type[Any]], @staticmethod
def __set_and_check_auth_level(plugin: Union[schemas.Plugin, Type[Any]],
source: Optional[Union[dict, Type[Any]]] = None) -> bool: source: Optional[Union[dict, Type[Any]]] = None) -> bool:
""" """
设置并检查插件的认证级别 设置并检查插件的认证级别
@@ -1014,7 +1012,8 @@ class PluginManager(metaclass=Singleton):
# 3 - 站点&密钥认证可见 # 3 - 站点&密钥认证可见
# 99 - 站点&特殊密钥认证可见 # 99 - 站点&特殊密钥认证可见
# 如果当前站点认证级别大于 1 且插件级别为 99,并存在插件公钥,说明为特殊密钥认证,通过密钥匹配进行认证 # 如果当前站点认证级别大于 1 且插件级别为 99,并存在插件公钥,说明为特殊密钥认证,通过密钥匹配进行认证
if self.siteshelper.auth_level > 1 and plugin.auth_level == 99 and hasattr(plugin, "plugin_public_key"): siteshelper = SitesHelper()
if siteshelper.auth_level > 1 and plugin.auth_level == 99 and hasattr(plugin, "plugin_public_key"):
plugin_id = plugin.id if isinstance(plugin, schemas.Plugin) else plugin.__name__ plugin_id = plugin.id if isinstance(plugin, schemas.Plugin) else plugin.__name__
public_key = plugin.plugin_public_key public_key = plugin.plugin_public_key
if public_key: if public_key:
@@ -1022,7 +1021,7 @@ class PluginManager(metaclass=Singleton):
verify = RSAUtils.verify_rsa_keys(public_key=public_key, private_key=private_key) verify = RSAUtils.verify_rsa_keys(public_key=public_key, private_key=private_key)
return verify return verify
# 如果当前站点认证级别小于插件级别,则返回 False # 如果当前站点认证级别小于插件级别,则返回 False
if self.siteshelper.auth_level < plugin.auth_level: if siteshelper.auth_level < plugin.auth_level:
return False return False
return True return True
@@ -1101,10 +1100,11 @@ class PluginManager(metaclass=Singleton):
return False, msg return False, msg
# 将分身插件添加到已安装列表 # 将分身插件添加到已安装列表
installed_plugins = self.systemconfig.get(SystemConfigKey.UserInstalledPlugins) or [] systemconfig = SystemConfigOper()
installed_plugins = systemconfig.get(SystemConfigKey.UserInstalledPlugins) or []
if clone_id not in installed_plugins: if clone_id not in installed_plugins:
installed_plugins.append(clone_id) installed_plugins.append(clone_id)
self.systemconfig.set(SystemConfigKey.UserInstalledPlugins, installed_plugins) systemconfig.set(SystemConfigKey.UserInstalledPlugins, installed_plugins)
# 为分身插件创建初始配置(从原插件复制配置) # 为分身插件创建初始配置(从原插件复制配置)
logger.info(f"正在为分身插件 {clone_id} 创建初始配置...") logger.info(f"正在为分身插件 {clone_id} 创建初始配置...")
+1 -2
View File
@@ -14,7 +14,6 @@ class CookieCloudHelper:
def __init__(self): def __init__(self):
self.__sync_setting() self.__sync_setting()
self._req = RequestUtils(content_type="application/json")
def __sync_setting(self): def __sync_setting(self):
""" """
@@ -46,7 +45,7 @@ class CookieCloudHelper:
return {}, "未从本地CookieCloud服务加载到cookie数据,请检查服务器设置、用户KEY及加密密码是否正确" return {}, "未从本地CookieCloud服务加载到cookie数据,请检查服务器设置、用户KEY及加密密码是否正确"
else: else:
req_url = UrlUtils.combine_url(host=self._server, path=f"get/{self._key}") req_url = UrlUtils.combine_url(host=self._server, path=f"get/{self._key}")
ret = self._req.get_res(url=req_url) ret = RequestUtils(content_type="application/json").get_res(url=req_url)
if ret and ret.status_code == 200: if ret and ret.status_code == 200:
try: try:
result = ret.json() result = ret.json()
+3 -5
View File
@@ -13,14 +13,12 @@ class DirectoryHelper:
下载目录/媒体库目录帮助类 下载目录/媒体库目录帮助类
""" """
def __init__(self): @staticmethod
self.systemconfig = SystemConfigOper() def get_dirs() -> List[schemas.TransferDirectoryConf]:
def get_dirs(self) -> List[schemas.TransferDirectoryConf]:
""" """
获取所有下载目录 获取所有下载目录
""" """
dir_confs: List[dict] = self.systemconfig.get(SystemConfigKey.Directories) dir_confs: List[dict] = SystemConfigOper().get(SystemConfigKey.Directories)
if not dir_confs: if not dir_confs:
return [] return []
return [schemas.TransferDirectoryConf(**d) for d in dir_confs] return [schemas.TransferDirectoryConf(**d) for d in dir_confs]
+1 -1
View File
@@ -41,7 +41,7 @@ class PluginHelper(metaclass=Singleton):
if self.install_report(): if self.install_report():
self.systemconfig.set(SystemConfigKey.PluginInstallReport, "1") self.systemconfig.set(SystemConfigKey.PluginInstallReport, "1")
@cached(maxsize=1000, ttl=1800) @cached(maxsize=64, ttl=1800)
def get_plugins(self, repo_url: str, package_version: Optional[str] = None) -> Optional[Dict[str, dict]]: def get_plugins(self, repo_url: str, package_version: Optional[str] = None) -> Optional[Dict[str, dict]]:
""" """
获取Github所有最新插件列表 获取Github所有最新插件列表
+4 -6
View File
@@ -3,15 +3,14 @@ from pathlib import Path
from app.core.config import settings from app.core.config import settings
from app.helper.sites import SitesHelper from app.helper.sites import SitesHelper
from app.helper.system import SystemHelper
from app.log import logger from app.log import logger
from app.utils.http import RequestUtils from app.utils.http import RequestUtils
from app.utils.singleton import Singleton
from app.utils.string import StringUtils from app.utils.string import StringUtils
from app.utils.system import SystemUtils from app.utils.system import SystemUtils
from app.helper.system import SystemHelper
class ResourceHelper(metaclass=Singleton): class ResourceHelper:
""" """
检测和更新资源包 检测和更新资源包
""" """
@@ -21,7 +20,6 @@ class ResourceHelper(metaclass=Singleton):
_base_dir: Path = settings.ROOT_PATH _base_dir: Path = settings.ROOT_PATH
def __init__(self): def __init__(self):
self.siteshelper = SitesHelper()
self.check() self.check()
@property @property
@@ -59,10 +57,10 @@ class ResourceHelper(metaclass=Singleton):
# 判断版本号 # 判断版本号
if rtype == "auth": if rtype == "auth":
# 站点认证资源 # 站点认证资源
local_version = self.siteshelper.auth_version local_version = SitesHelper().auth_version
elif rtype == "sites": elif rtype == "sites":
# 站点索引资源 # 站点索引资源
local_version = self.siteshelper.indexer_version local_version = SitesHelper().indexer_version
else: else:
continue continue
if StringUtils.compare_version(version, ">", local_version): if StringUtils.compare_version(version, ">", local_version):
+6 -7
View File
@@ -11,14 +11,12 @@ class RuleHelper:
规划帮助类 规划帮助类
""" """
def __init__(self): @staticmethod
self.systemconfig = SystemConfigOper() def get_rule_groups() -> List[FilterRuleGroup]:
def get_rule_groups(self) -> List[FilterRuleGroup]:
""" """
获取用户所有规则组 获取用户所有规则组
""" """
rule_groups: List[dict] = self.systemconfig.get(SystemConfigKey.UserFilterRuleGroups) rule_groups: List[dict] = SystemConfigOper().get(SystemConfigKey.UserFilterRuleGroups)
if not rule_groups: if not rule_groups:
return [] return []
return [FilterRuleGroup(**group) for group in rule_groups] return [FilterRuleGroup(**group) for group in rule_groups]
@@ -50,11 +48,12 @@ class RuleHelper:
ret_groups.append(group) ret_groups.append(group)
return ret_groups return ret_groups
def get_custom_rules(self) -> List[CustomRule]: @staticmethod
def get_custom_rules() -> List[CustomRule]:
""" """
获取用户所有自定义规则 获取用户所有自定义规则
""" """
rules: List[dict] = self.systemconfig.get(SystemConfigKey.CustomFilterRules) rules: List[dict] = SystemConfigOper().get(SystemConfigKey.CustomFilterRules)
if not rules: if not rules:
return [] return []
return [CustomRule(**rule) for rule in rules] return [CustomRule(**rule) for rule in rules]
+6 -8
View File
@@ -10,14 +10,12 @@ class StorageHelper:
存储帮助类 存储帮助类
""" """
def __init__(self): @staticmethod
self.systemconfig = SystemConfigOper() def get_storagies() -> List[schemas.StorageConf]:
def get_storagies(self) -> List[schemas.StorageConf]:
""" """
获取所有存储设置 获取所有存储设置
""" """
storage_confs: List[dict] = self.systemconfig.get(SystemConfigKey.Storages) storage_confs: List[dict] = SystemConfigOper().get(SystemConfigKey.Storages)
if not storage_confs: if not storage_confs:
return [] return []
return [schemas.StorageConf(**s) for s in storage_confs] return [schemas.StorageConf(**s) for s in storage_confs]
@@ -49,7 +47,7 @@ class StorageHelper:
if s.type == storage: if s.type == storage:
s.config = conf s.config = conf
break break
self.systemconfig.set(SystemConfigKey.Storages, [s.dict() for s in storagies]) SystemConfigOper().set(SystemConfigKey.Storages, [s.dict() for s in storagies])
def add_storage(self, storage: str, name: str, conf: dict): def add_storage(self, storage: str, name: str, conf: dict):
""" """
@@ -70,7 +68,7 @@ class StorageHelper:
name=name, name=name,
config=conf config=conf
)) ))
self.systemconfig.set(SystemConfigKey.Storages, [s.dict() for s in storagies]) SystemConfigOper().set(SystemConfigKey.Storages, [s.dict() for s in storagies])
def reset_storage(self, storage: str): def reset_storage(self, storage: str):
""" """
@@ -81,4 +79,4 @@ class StorageHelper:
if s.type == storage: if s.type == storage:
s.config = {} s.config = {}
break break
self.systemconfig.set(SystemConfigKey.Storages, [s.dict() for s in storagies]) SystemConfigOper().set(SystemConfigKey.Storages, [s.dict() for s in storagies])
+3 -3
View File
@@ -50,11 +50,11 @@ class SubscribeHelper(metaclass=Singleton):
] ]
def __init__(self): def __init__(self):
self.systemconfig = SystemConfigOper() systemconfig = SystemConfigOper()
if settings.SUBSCRIBE_STATISTIC_SHARE: if settings.SUBSCRIBE_STATISTIC_SHARE:
if not self.systemconfig.get(SystemConfigKey.SubscribeReport): if not systemconfig.get(SystemConfigKey.SubscribeReport):
if self.sub_report(): if self.sub_report():
self.systemconfig.set(SystemConfigKey.SubscribeReport, "1") systemconfig.set(SystemConfigKey.SubscribeReport, "1")
self.get_user_uuid() self.get_user_uuid()
self.get_github_user() self.get_github_user()
+4
View File
@@ -8,6 +8,10 @@ from app.utils.system import SystemUtils
class SystemHelper: class SystemHelper:
"""
系统工具类,提供系统相关的操作和判断
"""
@staticmethod @staticmethod
def can_restart() -> bool: def can_restart() -> bool:
""" """
+4 -7
View File
@@ -28,10 +28,6 @@ class TorrentHelper(metaclass=Singleton):
# 失败的种子:站点链接 # 失败的种子:站点链接
_invalid_torrents = [] _invalid_torrents = []
def __init__(self):
self.system_config = SystemConfigOper()
self.site_oper = SiteOper()
def download_torrent(self, url: str, def download_torrent(self, url: str,
cookie: Optional[str] = None, cookie: Optional[str] = None,
ua: Optional[str] = None, ua: Optional[str] = None,
@@ -192,7 +188,8 @@ class TorrentHelper(metaclass=Singleton):
file_name = str(datetime.datetime.now()) file_name = str(datetime.datetime.now())
return file_name return file_name
def sort_torrents(self, torrent_list: List[Context]) -> List[Context]: @staticmethod
def sort_torrents(torrent_list: List[Context]) -> List[Context]:
""" """
对种子对行排序:torrent、site、upload、seeder 对种子对行排序:torrent、site、upload、seeder
""" """
@@ -200,11 +197,11 @@ class TorrentHelper(metaclass=Singleton):
return [] return []
# 下载规则 # 下载规则
priority_rule: List[str] = self.system_config.get( priority_rule: List[str] = SystemConfigOper().get(
SystemConfigKey.TorrentsPriority) or ["torrent", "upload", "seeder"] SystemConfigKey.TorrentsPriority) or ["torrent", "upload", "seeder"]
# 站点上传量 # 站点上传量
site_uploads = { site_uploads = {
site.name: site.upload for site in self.site_oper.get_userdata_latest() site.name: site.upload for site in SiteOper().get_userdata_latest()
} }
def get_sort_str(_context): def get_sort_str(_context):
+6 -6
View File
@@ -9,9 +9,9 @@ from app.utils.singleton import Singleton
class WallpaperHelper(metaclass=Singleton): class WallpaperHelper(metaclass=Singleton):
"""
def __init__(self): 壁纸帮助类
self.req = RequestUtils(timeout=5) """
def get_wallpaper(self) -> Optional[str]: def get_wallpaper(self) -> Optional[str]:
""" """
@@ -60,7 +60,7 @@ class WallpaperHelper(metaclass=Singleton):
获取Bing每日壁纸 获取Bing每日壁纸
""" """
url = "https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1" url = "https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1"
resp = self.req.get_res(url) resp = RequestUtils(timeout=5).get_res(url)
if resp and resp.status_code == 200: if resp and resp.status_code == 200:
try: try:
result = resp.json() result = resp.json()
@@ -77,7 +77,7 @@ class WallpaperHelper(metaclass=Singleton):
获取7天的Bing每日壁纸 获取7天的Bing每日壁纸
""" """
url = f"https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n={num}" url = f"https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n={num}"
resp = self.req.get_res(url) resp = RequestUtils(timeout=5).get_res(url)
if resp and resp.status_code == 200: if resp and resp.status_code == 200:
try: try:
result = resp.json() result = resp.json()
@@ -144,7 +144,7 @@ class WallpaperHelper(metaclass=Singleton):
# 判断是否存在自定义壁纸api # 判断是否存在自定义壁纸api
if settings.CUSTOMIZE_WALLPAPER_API_URL: if settings.CUSTOMIZE_WALLPAPER_API_URL:
wallpaper_list = [] wallpaper_list = []
resp = self.req.get_res(settings.CUSTOMIZE_WALLPAPER_API_URL) resp = RequestUtils(timeout=15).get_res(settings.CUSTOMIZE_WALLPAPER_API_URL)
if resp and resp.status_code == 200: if resp and resp.status_code == 200:
# 如果返回的是图片格式 # 如果返回的是图片格式
content_type = resp.headers.get('Content-Type') content_type = resp.headers.get('Content-Type')
+2 -2
View File
@@ -291,8 +291,8 @@ class PlexModule(_ModuleBase, _MediaServerBase[Plex]):
episodes=episodes episodes=episodes
) for season, episodes in seasoninfo.items()] ) for season, episodes in seasoninfo.items()]
def mediaserver_playing(self, server: str, count: Optional[int] = 20, **kwargs) -> List[ def mediaserver_playing(self, server: str, count: Optional[int] = 20,
schemas.MediaServerPlayItem]: **kwargs) -> List[schemas.MediaServerPlayItem]:
""" """
获取媒体服务器正在播放信息 获取媒体服务器正在播放信息
""" """
+2 -2
View File
@@ -406,7 +406,8 @@ class TheMovieDbModule(_ModuleBase):
return None return None
return self.scraper.get_metadata_nfo(meta=meta, mediainfo=mediainfo, season=season, episode=episode) return self.scraper.get_metadata_nfo(meta=meta, mediainfo=mediainfo, season=season, episode=episode)
def metadata_img(self, mediainfo: MediaInfo, season: Optional[int] = None, episode: Optional[int] = None) -> Optional[dict]: def metadata_img(self, mediainfo: MediaInfo, season: Optional[int] = None,
episode: Optional[int] = None) -> Optional[dict]:
""" """
获取图片名称和url 获取图片名称和url
:param mediainfo: 媒体信息 :param mediainfo: 媒体信息
@@ -506,7 +507,6 @@ class TheMovieDbModule(_ModuleBase):
air_date=sea.get("episodes")[0].get("air_date") if sea.get("episodes") else None, air_date=sea.get("episodes")[0].get("air_date") if sea.get("episodes") else None,
) for sea in group_seasons] ) for sea in group_seasons]
def tmdb_episodes(self, tmdbid: int, season: int, episode_group: Optional[str] = None) -> List[schemas.TmdbEpisode]: def tmdb_episodes(self, tmdbid: int, season: int, episode_group: Optional[str] = None) -> List[schemas.TmdbEpisode]:
""" """
根据TMDBID查询某季的所有集信息 根据TMDBID查询某季的所有集信息
-3
View File
@@ -636,7 +636,6 @@ class TmdbApi:
return None return None
# dict[地区:分级] # dict[地区:分级]
ratings = {} ratings = {}
results = []
if results := (tmdb_info.get("release_dates") or {}).get("results"): if results := (tmdb_info.get("release_dates") or {}).get("results"):
""" """
[ [
@@ -1362,8 +1361,6 @@ class TmdbApi:
return group_season return group_season
return {} return {}
def get_person_detail(self, person_id: int) -> dict: def get_person_detail(self, person_id: int) -> dict:
""" """
获取人物详情 获取人物详情
+8 -15
View File
@@ -15,15 +15,14 @@ from app.chain import ChainBase
from app.chain.storage import StorageChain from app.chain.storage import StorageChain
from app.chain.transfer import TransferChain from app.chain.transfer import TransferChain
from app.core.config import settings from app.core.config import settings
from app.db.systemconfig_oper import SystemConfigOper from app.core.event import Event, eventmanager
from app.helper.directory import DirectoryHelper from app.helper.directory import DirectoryHelper
from app.helper.message import MessageHelper from app.helper.message import MessageHelper
from app.log import logger from app.log import logger
from app.schemas import ConfigChangeEventData
from app.schemas import FileItem from app.schemas import FileItem
from app.schemas.types import SystemConfigKey, EventType from app.schemas.types import SystemConfigKey, EventType
from app.utils.singleton import Singleton from app.utils.singleton import Singleton
from app.core.event import Event, eventmanager
from app.schemas import ConfigChangeEventData
lock = Lock() lock = Lock()
snapshot_lock = Lock() snapshot_lock = Lock()
@@ -77,14 +76,7 @@ class Monitor(metaclass=Singleton):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.transferchain = TransferChain()
self.storagechain = StorageChain()
self.directoryhelper = DirectoryHelper()
self.systemmessage = MessageHelper()
self.systemconfig = SystemConfigOper()
self.all_exts = settings.RMT_MEDIAEXT self.all_exts = settings.RMT_MEDIAEXT
# 启动目录监控和文件整理 # 启动目录监控和文件整理
self.init() self.init()
@@ -109,7 +101,7 @@ class Monitor(metaclass=Singleton):
self.stop() self.stop()
# 读取目录配置 # 读取目录配置
monitor_dirs = self.directoryhelper.get_download_dirs() monitor_dirs = DirectoryHelper().get_download_dirs()
if not monitor_dirs: if not monitor_dirs:
return return
@@ -119,6 +111,7 @@ class Monitor(metaclass=Singleton):
# 启动定时服务进程 # 启动定时服务进程
self._scheduler = BackgroundScheduler(timezone=settings.TZ) self._scheduler = BackgroundScheduler(timezone=settings.TZ)
messagehelper = MessageHelper()
for mon_dir in monitor_dirs: for mon_dir in monitor_dirs:
if not mon_dir.library_path: if not mon_dir.library_path:
continue continue
@@ -129,7 +122,7 @@ class Monitor(metaclass=Singleton):
target_path = Path(mon_dir.library_path) target_path = Path(mon_dir.library_path)
if target_path.is_relative_to(mon_path): if target_path.is_relative_to(mon_path):
logger.warn(f"{target_path} 是监控目录 {mon_path} 的子目录,无法监控!") logger.warn(f"{target_path} 是监控目录 {mon_path} 的子目录,无法监控!")
self.systemmessage.put(f"{target_path} 是监控目录 {mon_path} 的子目录,无法监控", title="目录监控") messagehelper.put(f"{target_path} 是监控目录 {mon_path} 的子目录,无法监控", title="目录监控")
continue continue
# 启动监控 # 启动监控
@@ -159,7 +152,7 @@ class Monitor(metaclass=Singleton):
""") """)
else: else:
logger.error(f"{mon_path} 启动目录监控失败:{err_msg}") logger.error(f"{mon_path} 启动目录监控失败:{err_msg}")
self.systemmessage.put(f"{mon_path} 启动目录监控失败:{err_msg}", title="目录监控") messagehelper.put(f"{mon_path} 启动目录监控失败:{err_msg}", title="目录监控")
else: else:
# 远程目录监控 # 远程目录监控
self._scheduler.add_job(self.polling_observer, 'interval', minutes=self._snapshot_interval, self._scheduler.add_job(self.polling_observer, 'interval', minutes=self._snapshot_interval,
@@ -199,7 +192,7 @@ class Monitor(metaclass=Singleton):
""" """
with snapshot_lock: with snapshot_lock:
# 快照存储 # 快照存储
new_snapshot = self.storagechain.snapshot_storage(storage=storage, path=mon_path) new_snapshot = StorageChain().snapshot_storage(storage=storage, path=mon_path)
if new_snapshot: if new_snapshot:
# 比较快照 # 比较快照
old_snapshot = self._storage_snapshot.get(storage) old_snapshot = self._storage_snapshot.get(storage)
@@ -265,7 +258,7 @@ class Monitor(metaclass=Singleton):
try: try:
# 开始整理 # 开始整理
self.transferchain.do_transfer( TransferChain().do_transfer(
fileitem=FileItem( fileitem=FileItem(
storage=storage, storage=storage,
path=str(event_path).replace("\\", "/"), path=str(event_path).replace("\\", "/"),
+2 -2
View File
@@ -1,2 +1,2 @@
APP_VERSION = 'v2.5.2' APP_VERSION = 'v2.5.3'
FRONTEND_VERSION = 'v2.5.2' FRONTEND_VERSION = 'v2.5.3'