mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-04-05 03:38:36 +08:00
v2.5.3
This commit is contained in:
@@ -81,7 +81,6 @@ class ReleaseGroupsMatcher(metaclass=Singleton):
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.systemconfig = SystemConfigOper()
|
||||
release_groups = []
|
||||
for site_groups in self.RELEASE_GROUPS.values():
|
||||
for release_group in site_groups:
|
||||
@@ -98,7 +97,7 @@ class ReleaseGroupsMatcher(metaclass=Singleton):
|
||||
return ""
|
||||
if not groups:
|
||||
# 自定义组
|
||||
custom_release_groups = self.systemconfig.get(SystemConfigKey.CustomReleaseGroups)
|
||||
custom_release_groups = SystemConfigOper().get(SystemConfigKey.CustomReleaseGroups)
|
||||
if isinstance(custom_release_groups, list):
|
||||
custom_release_groups = list(filter(None, custom_release_groups))
|
||||
if custom_release_groups:
|
||||
|
||||
@@ -197,67 +197,3 @@ def find_metainfo(title: str) -> Tuple[str, dict]:
|
||||
elif metainfo.get('begin_episode') and not metainfo.get('end_episode'):
|
||||
metainfo['total_episode'] = 1
|
||||
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()
|
||||
|
||||
@@ -87,7 +87,6 @@ class PluginManager(metaclass=Singleton):
|
||||
"""
|
||||
插件管理器
|
||||
"""
|
||||
systemconfig: SystemConfigOper = None
|
||||
|
||||
# 插件列表
|
||||
_plugins: dict = {}
|
||||
@@ -99,10 +98,6 @@ class PluginManager(metaclass=Singleton):
|
||||
_observer: Observer = None
|
||||
|
||||
def __init__(self):
|
||||
self.siteshelper = SitesHelper()
|
||||
self.pluginhelper = PluginHelper()
|
||||
self.systemconfig = SystemConfigOper()
|
||||
self.plugindata = PluginDataOper()
|
||||
# 开发者模式监测插件修改
|
||||
if settings.DEV or settings.PLUGIN_AUTO_RELOAD:
|
||||
self.__start_monitor()
|
||||
@@ -141,7 +136,7 @@ class PluginManager(metaclass=Singleton):
|
||||
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)
|
||||
for plugin in plugins:
|
||||
@@ -331,7 +326,7 @@ class PluginManager(metaclass=Singleton):
|
||||
|
||||
def install_plugin(plugin):
|
||||
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
|
||||
if state:
|
||||
logger.info(
|
||||
@@ -346,7 +341,7 @@ class PluginManager(metaclass=Singleton):
|
||||
return []
|
||||
|
||||
# 获取已安装插件列表
|
||||
install_plugins = self.systemconfig.get(SystemConfigKey.UserInstalledPlugins) or []
|
||||
install_plugins = SystemConfigOper().get(SystemConfigKey.UserInstalledPlugins) or []
|
||||
# 获取在线插件列表
|
||||
online_plugins = self.get_online_plugins()
|
||||
# 确定需要安装的插件
|
||||
@@ -382,19 +377,21 @@ class PluginManager(metaclass=Singleton):
|
||||
)
|
||||
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:
|
||||
return missing_dependencies
|
||||
logger.debug(f"检测到缺失的依赖项: {missing_dependencies}")
|
||||
logger.info(f"开始安装缺失的依赖项,共 {len(missing_dependencies)} 个...")
|
||||
# 第二步:安装依赖项并返回结果
|
||||
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
|
||||
if success:
|
||||
logger.info(f"已完成 {len(missing_dependencies)} 个依赖项安装,总耗时:{total_elapsed_time:.2f} 秒")
|
||||
@@ -409,7 +406,7 @@ class PluginManager(metaclass=Singleton):
|
||||
"""
|
||||
if not self._plugins.get(pid):
|
||||
return {}
|
||||
conf = self.systemconfig.get(self._config_key % pid)
|
||||
conf = SystemConfigOper().get(self._config_key % pid)
|
||||
if conf:
|
||||
# 去掉空Key
|
||||
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):
|
||||
return False
|
||||
self.systemconfig.set(self._config_key % pid, conf)
|
||||
SystemConfigOper().set(self._config_key % pid, conf)
|
||||
return True
|
||||
|
||||
def delete_plugin_config(self, pid: str) -> bool:
|
||||
@@ -433,7 +430,7 @@ class PluginManager(metaclass=Singleton):
|
||||
"""
|
||||
if not self._plugins.get(pid):
|
||||
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:
|
||||
"""
|
||||
@@ -442,7 +439,7 @@ class PluginManager(metaclass=Singleton):
|
||||
"""
|
||||
if not self._plugins.get(pid):
|
||||
return False
|
||||
self.plugindata.del_data(pid)
|
||||
PluginDataOper().del_data(pid)
|
||||
return True
|
||||
|
||||
def get_plugin_state(self, pid: str) -> bool:
|
||||
@@ -804,7 +801,7 @@ class PluginManager(metaclass=Singleton):
|
||||
# 返回值
|
||||
plugins = []
|
||||
# 已安装插件
|
||||
installed_apps = self.systemconfig.get(SystemConfigKey.UserInstalledPlugins) or []
|
||||
installed_apps = SystemConfigOper().get(SystemConfigKey.UserInstalledPlugins) or []
|
||||
for pid, plugin_class in self._plugins.items():
|
||||
# 运行状插件
|
||||
plugin_obj = self._running_plugins.get(pid)
|
||||
@@ -901,9 +898,9 @@ class PluginManager(metaclass=Singleton):
|
||||
if not market:
|
||||
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:
|
||||
logger.warning(
|
||||
f"获取{package_version if package_version else ''}插件库失败:{market},请检查 GitHub 网络连接")
|
||||
@@ -990,7 +987,8 @@ class PluginManager(metaclass=Singleton):
|
||||
|
||||
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:
|
||||
"""
|
||||
设置并检查插件的认证级别
|
||||
@@ -1014,7 +1012,8 @@ class PluginManager(metaclass=Singleton):
|
||||
# 3 - 站点&密钥认证可见
|
||||
# 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__
|
||||
public_key = plugin.plugin_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)
|
||||
return verify
|
||||
# 如果当前站点认证级别小于插件级别,则返回 False
|
||||
if self.siteshelper.auth_level < plugin.auth_level:
|
||||
if siteshelper.auth_level < plugin.auth_level:
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -1101,10 +1100,11 @@ class PluginManager(metaclass=Singleton):
|
||||
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:
|
||||
installed_plugins.append(clone_id)
|
||||
self.systemconfig.set(SystemConfigKey.UserInstalledPlugins, installed_plugins)
|
||||
systemconfig.set(SystemConfigKey.UserInstalledPlugins, installed_plugins)
|
||||
|
||||
# 为分身插件创建初始配置(从原插件复制配置)
|
||||
logger.info(f"正在为分身插件 {clone_id} 创建初始配置...")
|
||||
|
||||
@@ -14,7 +14,6 @@ class CookieCloudHelper:
|
||||
|
||||
def __init__(self):
|
||||
self.__sync_setting()
|
||||
self._req = RequestUtils(content_type="application/json")
|
||||
|
||||
def __sync_setting(self):
|
||||
"""
|
||||
@@ -46,7 +45,7 @@ class CookieCloudHelper:
|
||||
return {}, "未从本地CookieCloud服务加载到cookie数据,请检查服务器设置、用户KEY及加密密码是否正确"
|
||||
else:
|
||||
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:
|
||||
try:
|
||||
result = ret.json()
|
||||
|
||||
@@ -13,14 +13,12 @@ class DirectoryHelper:
|
||||
下载目录/媒体库目录帮助类
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.systemconfig = SystemConfigOper()
|
||||
|
||||
def get_dirs(self) -> List[schemas.TransferDirectoryConf]:
|
||||
@staticmethod
|
||||
def get_dirs() -> List[schemas.TransferDirectoryConf]:
|
||||
"""
|
||||
获取所有下载目录
|
||||
"""
|
||||
dir_confs: List[dict] = self.systemconfig.get(SystemConfigKey.Directories)
|
||||
dir_confs: List[dict] = SystemConfigOper().get(SystemConfigKey.Directories)
|
||||
if not dir_confs:
|
||||
return []
|
||||
return [schemas.TransferDirectoryConf(**d) for d in dir_confs]
|
||||
|
||||
@@ -41,7 +41,7 @@ class PluginHelper(metaclass=Singleton):
|
||||
if self.install_report():
|
||||
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]]:
|
||||
"""
|
||||
获取Github所有最新插件列表
|
||||
|
||||
@@ -3,15 +3,14 @@ from pathlib import Path
|
||||
|
||||
from app.core.config import settings
|
||||
from app.helper.sites import SitesHelper
|
||||
from app.helper.system import SystemHelper
|
||||
from app.log import logger
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.singleton import Singleton
|
||||
from app.utils.string import StringUtils
|
||||
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
|
||||
|
||||
def __init__(self):
|
||||
self.siteshelper = SitesHelper()
|
||||
self.check()
|
||||
|
||||
@property
|
||||
@@ -59,10 +57,10 @@ class ResourceHelper(metaclass=Singleton):
|
||||
# 判断版本号
|
||||
if rtype == "auth":
|
||||
# 站点认证资源
|
||||
local_version = self.siteshelper.auth_version
|
||||
local_version = SitesHelper().auth_version
|
||||
elif rtype == "sites":
|
||||
# 站点索引资源
|
||||
local_version = self.siteshelper.indexer_version
|
||||
local_version = SitesHelper().indexer_version
|
||||
else:
|
||||
continue
|
||||
if StringUtils.compare_version(version, ">", local_version):
|
||||
|
||||
@@ -11,14 +11,12 @@ class RuleHelper:
|
||||
规划帮助类
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.systemconfig = SystemConfigOper()
|
||||
|
||||
def get_rule_groups(self) -> List[FilterRuleGroup]:
|
||||
@staticmethod
|
||||
def get_rule_groups() -> List[FilterRuleGroup]:
|
||||
"""
|
||||
获取用户所有规则组
|
||||
"""
|
||||
rule_groups: List[dict] = self.systemconfig.get(SystemConfigKey.UserFilterRuleGroups)
|
||||
rule_groups: List[dict] = SystemConfigOper().get(SystemConfigKey.UserFilterRuleGroups)
|
||||
if not rule_groups:
|
||||
return []
|
||||
return [FilterRuleGroup(**group) for group in rule_groups]
|
||||
@@ -50,11 +48,12 @@ class RuleHelper:
|
||||
ret_groups.append(group)
|
||||
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:
|
||||
return []
|
||||
return [CustomRule(**rule) for rule in rules]
|
||||
|
||||
@@ -10,14 +10,12 @@ class StorageHelper:
|
||||
存储帮助类
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.systemconfig = SystemConfigOper()
|
||||
|
||||
def get_storagies(self) -> List[schemas.StorageConf]:
|
||||
@staticmethod
|
||||
def get_storagies() -> List[schemas.StorageConf]:
|
||||
"""
|
||||
获取所有存储设置
|
||||
"""
|
||||
storage_confs: List[dict] = self.systemconfig.get(SystemConfigKey.Storages)
|
||||
storage_confs: List[dict] = SystemConfigOper().get(SystemConfigKey.Storages)
|
||||
if not storage_confs:
|
||||
return []
|
||||
return [schemas.StorageConf(**s) for s in storage_confs]
|
||||
@@ -49,7 +47,7 @@ class StorageHelper:
|
||||
if s.type == storage:
|
||||
s.config = conf
|
||||
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):
|
||||
"""
|
||||
@@ -70,7 +68,7 @@ class StorageHelper:
|
||||
name=name,
|
||||
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):
|
||||
"""
|
||||
@@ -81,4 +79,4 @@ class StorageHelper:
|
||||
if s.type == storage:
|
||||
s.config = {}
|
||||
break
|
||||
self.systemconfig.set(SystemConfigKey.Storages, [s.dict() for s in storagies])
|
||||
SystemConfigOper().set(SystemConfigKey.Storages, [s.dict() for s in storagies])
|
||||
|
||||
@@ -50,11 +50,11 @@ class SubscribeHelper(metaclass=Singleton):
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
self.systemconfig = SystemConfigOper()
|
||||
systemconfig = SystemConfigOper()
|
||||
if settings.SUBSCRIBE_STATISTIC_SHARE:
|
||||
if not self.systemconfig.get(SystemConfigKey.SubscribeReport):
|
||||
if not systemconfig.get(SystemConfigKey.SubscribeReport):
|
||||
if self.sub_report():
|
||||
self.systemconfig.set(SystemConfigKey.SubscribeReport, "1")
|
||||
systemconfig.set(SystemConfigKey.SubscribeReport, "1")
|
||||
self.get_user_uuid()
|
||||
self.get_github_user()
|
||||
|
||||
|
||||
@@ -8,6 +8,10 @@ from app.utils.system import SystemUtils
|
||||
|
||||
|
||||
class SystemHelper:
|
||||
"""
|
||||
系统工具类,提供系统相关的操作和判断
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def can_restart() -> bool:
|
||||
"""
|
||||
|
||||
@@ -28,10 +28,6 @@ class TorrentHelper(metaclass=Singleton):
|
||||
# 失败的种子:站点链接
|
||||
_invalid_torrents = []
|
||||
|
||||
def __init__(self):
|
||||
self.system_config = SystemConfigOper()
|
||||
self.site_oper = SiteOper()
|
||||
|
||||
def download_torrent(self, url: str,
|
||||
cookie: Optional[str] = None,
|
||||
ua: Optional[str] = None,
|
||||
@@ -192,7 +188,8 @@ class TorrentHelper(metaclass=Singleton):
|
||||
file_name = str(datetime.datetime.now())
|
||||
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
|
||||
"""
|
||||
@@ -200,11 +197,11 @@ class TorrentHelper(metaclass=Singleton):
|
||||
return []
|
||||
|
||||
# 下载规则
|
||||
priority_rule: List[str] = self.system_config.get(
|
||||
priority_rule: List[str] = SystemConfigOper().get(
|
||||
SystemConfigKey.TorrentsPriority) or ["torrent", "upload", "seeder"]
|
||||
# 站点上传量
|
||||
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):
|
||||
|
||||
@@ -9,9 +9,9 @@ from app.utils.singleton import Singleton
|
||||
|
||||
|
||||
class WallpaperHelper(metaclass=Singleton):
|
||||
|
||||
def __init__(self):
|
||||
self.req = RequestUtils(timeout=5)
|
||||
"""
|
||||
壁纸帮助类
|
||||
"""
|
||||
|
||||
def get_wallpaper(self) -> Optional[str]:
|
||||
"""
|
||||
@@ -60,7 +60,7 @@ class WallpaperHelper(metaclass=Singleton):
|
||||
获取Bing每日壁纸
|
||||
"""
|
||||
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:
|
||||
try:
|
||||
result = resp.json()
|
||||
@@ -77,7 +77,7 @@ class WallpaperHelper(metaclass=Singleton):
|
||||
获取7天的Bing每日壁纸
|
||||
"""
|
||||
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:
|
||||
try:
|
||||
result = resp.json()
|
||||
@@ -144,7 +144,7 @@ class WallpaperHelper(metaclass=Singleton):
|
||||
# 判断是否存在自定义壁纸api
|
||||
if settings.CUSTOMIZE_WALLPAPER_API_URL:
|
||||
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:
|
||||
# 如果返回的是图片格式
|
||||
content_type = resp.headers.get('Content-Type')
|
||||
|
||||
@@ -291,8 +291,8 @@ class PlexModule(_ModuleBase, _MediaServerBase[Plex]):
|
||||
episodes=episodes
|
||||
) for season, episodes in seasoninfo.items()]
|
||||
|
||||
def mediaserver_playing(self, server: str, count: Optional[int] = 20, **kwargs) -> List[
|
||||
schemas.MediaServerPlayItem]:
|
||||
def mediaserver_playing(self, server: str, count: Optional[int] = 20,
|
||||
**kwargs) -> List[schemas.MediaServerPlayItem]:
|
||||
"""
|
||||
获取媒体服务器正在播放信息
|
||||
"""
|
||||
|
||||
@@ -406,7 +406,8 @@ class TheMovieDbModule(_ModuleBase):
|
||||
return None
|
||||
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
|
||||
:param mediainfo: 媒体信息
|
||||
@@ -506,7 +507,6 @@ class TheMovieDbModule(_ModuleBase):
|
||||
air_date=sea.get("episodes")[0].get("air_date") if sea.get("episodes") else None,
|
||||
) for sea in group_seasons]
|
||||
|
||||
|
||||
def tmdb_episodes(self, tmdbid: int, season: int, episode_group: Optional[str] = None) -> List[schemas.TmdbEpisode]:
|
||||
"""
|
||||
根据TMDBID查询某季的所有集信息
|
||||
|
||||
@@ -636,7 +636,6 @@ class TmdbApi:
|
||||
return None
|
||||
# dict[地区:分级]
|
||||
ratings = {}
|
||||
results = []
|
||||
if results := (tmdb_info.get("release_dates") or {}).get("results"):
|
||||
"""
|
||||
[
|
||||
@@ -1362,8 +1361,6 @@ class TmdbApi:
|
||||
return group_season
|
||||
return {}
|
||||
|
||||
|
||||
|
||||
def get_person_detail(self, person_id: int) -> dict:
|
||||
"""
|
||||
获取人物详情
|
||||
|
||||
@@ -15,15 +15,14 @@ from app.chain import ChainBase
|
||||
from app.chain.storage import StorageChain
|
||||
from app.chain.transfer import TransferChain
|
||||
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.message import MessageHelper
|
||||
from app.log import logger
|
||||
from app.schemas import ConfigChangeEventData
|
||||
from app.schemas import FileItem
|
||||
from app.schemas.types import SystemConfigKey, EventType
|
||||
from app.utils.singleton import Singleton
|
||||
from app.core.event import Event, eventmanager
|
||||
from app.schemas import ConfigChangeEventData
|
||||
|
||||
lock = Lock()
|
||||
snapshot_lock = Lock()
|
||||
@@ -77,14 +76,7 @@ class Monitor(metaclass=Singleton):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.transferchain = TransferChain()
|
||||
self.storagechain = StorageChain()
|
||||
self.directoryhelper = DirectoryHelper()
|
||||
self.systemmessage = MessageHelper()
|
||||
self.systemconfig = SystemConfigOper()
|
||||
|
||||
self.all_exts = settings.RMT_MEDIAEXT
|
||||
|
||||
# 启动目录监控和文件整理
|
||||
self.init()
|
||||
|
||||
@@ -109,7 +101,7 @@ class Monitor(metaclass=Singleton):
|
||||
self.stop()
|
||||
|
||||
# 读取目录配置
|
||||
monitor_dirs = self.directoryhelper.get_download_dirs()
|
||||
monitor_dirs = DirectoryHelper().get_download_dirs()
|
||||
if not monitor_dirs:
|
||||
return
|
||||
|
||||
@@ -119,6 +111,7 @@ class Monitor(metaclass=Singleton):
|
||||
# 启动定时服务进程
|
||||
self._scheduler = BackgroundScheduler(timezone=settings.TZ)
|
||||
|
||||
messagehelper = MessageHelper()
|
||||
for mon_dir in monitor_dirs:
|
||||
if not mon_dir.library_path:
|
||||
continue
|
||||
@@ -129,7 +122,7 @@ class Monitor(metaclass=Singleton):
|
||||
target_path = Path(mon_dir.library_path)
|
||||
if target_path.is_relative_to(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
|
||||
|
||||
# 启动监控
|
||||
@@ -159,7 +152,7 @@ class Monitor(metaclass=Singleton):
|
||||
""")
|
||||
else:
|
||||
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:
|
||||
# 远程目录监控
|
||||
self._scheduler.add_job(self.polling_observer, 'interval', minutes=self._snapshot_interval,
|
||||
@@ -199,7 +192,7 @@ class Monitor(metaclass=Singleton):
|
||||
"""
|
||||
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:
|
||||
# 比较快照
|
||||
old_snapshot = self._storage_snapshot.get(storage)
|
||||
@@ -265,7 +258,7 @@ class Monitor(metaclass=Singleton):
|
||||
|
||||
try:
|
||||
# 开始整理
|
||||
self.transferchain.do_transfer(
|
||||
TransferChain().do_transfer(
|
||||
fileitem=FileItem(
|
||||
storage=storage,
|
||||
path=str(event_path).replace("\\", "/"),
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
APP_VERSION = 'v2.5.2'
|
||||
FRONTEND_VERSION = 'v2.5.2'
|
||||
APP_VERSION = 'v2.5.3'
|
||||
FRONTEND_VERSION = 'v2.5.3'
|
||||
|
||||
Reference in New Issue
Block a user