diff --git a/app/api/endpoints/plugin.py b/app/api/endpoints/plugin.py index 8068ed13..fe562cbb 100644 --- a/app/api/endpoints/plugin.py +++ b/app/api/endpoints/plugin.py @@ -395,10 +395,6 @@ def save_plugin_folders(folders: dict, _: schemas.TokenPayload = Depends(get_cur """ try: SystemConfigOper().set(SystemConfigKey.PluginFolders, folders) - - # 验证保存结果 - saved_result = SystemConfigOper().get(SystemConfigKey.PluginFolders) - return schemas.Response(success=True) except Exception as e: logger.error(f"[文件夹API] 保存文件夹配置失败: {str(e)}") diff --git a/app/api/endpoints/system.py b/app/api/endpoints/system.py index 6d0c1dbf..97eabbce 100644 --- a/app/api/endpoints/system.py +++ b/app/api/endpoints/system.py @@ -36,8 +36,8 @@ from app.schemas.types import SystemConfigKey from app.utils.crypto import HashUtils from app.utils.http import RequestUtils from app.utils.security import SecurityUtils -from app.utils.system import SystemUtils from app.utils.url import UrlUtils +from helper.system import SystemHelper from version import APP_VERSION router = APIRouter() @@ -474,12 +474,12 @@ def restart_system(_: User = Depends(get_current_active_superuser)): """ 重启系统(仅管理员) """ - if not SystemUtils.can_restart(): + if not SystemHelper.can_restart(): return schemas.Response(success=False, message="当前运行环境不支持重启操作!") # 标识停止事件 global_vars.stop_system() # 执行重启 - ret, msg = SystemUtils.restart() + ret, msg = SystemHelper.restart() return schemas.Response(success=ret, message=msg) diff --git a/app/chain/system.py b/app/chain/system.py index 973c90f0..7696364e 100644 --- a/app/chain/system.py +++ b/app/chain/system.py @@ -10,6 +10,7 @@ from app.schemas import Notification, MessageChannel from app.utils.http import RequestUtils from app.utils.singleton import Singleton from app.utils.system import SystemUtils +from helper.system import SystemHelper from version import FRONTEND_VERSION, APP_VERSION @@ -45,7 +46,8 @@ class SystemChain(ChainBase, metaclass=Singleton): "channel": channel.value, "userid": userid }, self._restart_file) - SystemUtils.restart() + # 重启 + SystemHelper.restart() def __get_version_message(self) -> str: """ diff --git a/app/core/config.py b/app/core/config.py index 920ed761..41a3e8e8 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -280,6 +280,8 @@ class ConfigModel(BaseModel): TOKENIZED_SEARCH: bool = False # 为指定默认字幕添加.default后缀 DEFAULT_SUB: Optional[str] = "zh-cn" + # Docker Client API地址 + DOCKER_CLIENT_API: Optional[str] = "tcp://127.0.0.1:38379" class Settings(BaseSettings, ConfigModel, LogConfigModel): diff --git a/app/helper/resource.py b/app/helper/resource.py index 8fa47e6d..2abab2a7 100644 --- a/app/helper/resource.py +++ b/app/helper/resource.py @@ -8,6 +8,7 @@ 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 helper.system import SystemHelper class ResourceHelper(metaclass=Singleton): @@ -32,80 +33,80 @@ class ResourceHelper(metaclass=Singleton): 检测是否有更新,如有则下载安装 """ if not settings.AUTO_UPDATE_RESOURCE: - return + return None if SystemUtils.is_frozen(): - return + return None logger.info("开始检测资源包版本...") res = RequestUtils(proxies=self.proxies, headers=settings.GITHUB_HEADERS, timeout=10).get_res(self._repo) if res: try: resource_info = json.loads(res.text) + online_version = resource_info.get("version") + if online_version: + logger.info(f"最新资源包版本:v{online_version}") + # 需要更新的资源包 + need_updates = {} + # 资源明细 + resources: dict = resource_info.get("resources") or {} + for rname, resource in resources.items(): + rtype = resource.get("type") + platform = resource.get("platform") + target = resource.get("target") + version = resource.get("version") + # 判断平台 + if platform and platform != SystemUtils.platform(): + continue + # 判断版本号 + if rtype == "auth": + # 站点认证资源 + local_version = self.siteshelper.auth_version + elif rtype == "sites": + # 站点索引资源 + local_version = self.siteshelper.indexer_version + else: + continue + if StringUtils.compare_version(version, ">", local_version): + logger.info(f"{rname} 资源包有更新,最新版本:v{version}") + else: + continue + # 需要安装 + need_updates[rname] = target + if need_updates: + # 下载文件信息列表 + r = RequestUtils(proxies=settings.PROXY, headers=settings.GITHUB_HEADERS, + timeout=30).get_res(self._files_api) + if r and not r.ok: + return None, f"连接仓库失败:{r.status_code} - {r.reason}" + elif not r: + return None, "连接仓库失败" + files_info = r.json() + for item in files_info: + save_path = need_updates.get(item.get("name")) + if not save_path: + continue + if item.get("download_url"): + logger.info(f"开始更新资源文件:{item.get('name')} ...") + download_url = f"{settings.GITHUB_PROXY}{item.get('download_url')}" + # 下载资源文件 + res = RequestUtils(proxies=self.proxies, headers=settings.GITHUB_HEADERS, + timeout=180).get_res(download_url) + if not res: + logger.error(f"文件 {item.get('name')} 下载失败!") + elif res.status_code != 200: + logger.error(f"下载文件 {item.get('name')} 失败:{res.status_code} - {res.reason}") + # 创建插件文件夹 + file_path = self._base_dir / save_path / item.get("name") + if not file_path.parent.exists(): + file_path.parent.mkdir(parents=True, exist_ok=True) + # 写入文件 + file_path.write_bytes(res.content) + logger.info("资源包更新完成,开始重启服务...") + SystemHelper.restart() + else: + logger.info("所有资源已最新,无需更新") except json.JSONDecodeError: logger.error("资源包仓库数据解析失败!") - return + return None else: logger.warn("无法连接资源包仓库!") - return - online_version = resource_info.get("version") - if online_version: - logger.info(f"最新资源包版本:v{online_version}") - # 需要更新的资源包 - need_updates = {} - # 资源明细 - resources: dict = resource_info.get("resources") or {} - for rname, resource in resources.items(): - rtype = resource.get("type") - platform = resource.get("platform") - target = resource.get("target") - version = resource.get("version") - # 判断平台 - if platform and platform != SystemUtils.platform(): - continue - # 判断版本号 - if rtype == "auth": - # 站点认证资源 - local_version = self.siteshelper.auth_version - elif rtype == "sites": - # 站点索引资源 - local_version = self.siteshelper.indexer_version - else: - continue - if StringUtils.compare_version(version, ">", local_version): - logger.info(f"{rname} 资源包有更新,最新版本:v{version}") - else: - continue - # 需要安装 - need_updates[rname] = target - if need_updates: - # 下载文件信息列表 - r = RequestUtils(proxies=settings.PROXY, headers=settings.GITHUB_HEADERS, - timeout=30).get_res(self._files_api) - if r and not r.ok: - return None, f"连接仓库失败:{r.status_code} - {r.reason}" - elif not r: - return None, "连接仓库失败" - files_info = r.json() - for item in files_info: - save_path = need_updates.get(item.get("name")) - if not save_path: - continue - if item.get("download_url"): - logger.info(f"开始更新资源文件:{item.get('name')} ...") - download_url = f"{settings.GITHUB_PROXY}{item.get('download_url')}" - # 下载资源文件 - res = RequestUtils(proxies=self.proxies, headers=settings.GITHUB_HEADERS, - timeout=180).get_res(download_url) - if not res: - logger.error(f"文件 {item.get('name')} 下载失败!") - elif res.status_code != 200: - logger.error(f"下载文件 {item.get('name')} 失败:{res.status_code} - {res.reason}") - # 创建插件文件夹 - file_path = self._base_dir / save_path / item.get("name") - if not file_path.parent.exists(): - file_path.parent.mkdir(parents=True, exist_ok=True) - # 写入文件 - file_path.write_bytes(res.content) - logger.info("资源包更新完成,开始重启服务...") - SystemUtils.restart() - else: - logger.info("所有资源已最新,无需更新") + return None diff --git a/app/helper/system.py b/app/helper/system.py new file mode 100644 index 00000000..701c99f3 --- /dev/null +++ b/app/helper/system.py @@ -0,0 +1,51 @@ +from pathlib import Path +from typing import Tuple + +import docker + +from app.core.config import settings +from app.utils.system import SystemUtils + + +class SystemHelper: + + @staticmethod + def can_restart() -> bool: + """ + 判断是否可以内部重启 + """ + return Path("/var/run/docker.sock").exists() + + @staticmethod + def restart() -> Tuple[bool, str]: + """ + 执行Docker重启操作 + """ + if not SystemUtils.is_docker(): + return False, "非Docker环境,无法重启!" + try: + # 创建 Docker 客户端 + client = docker.DockerClient(base_url=settings.DOCKER_CLIENT_API) + # 获取当前容器的 ID + container_id = None + with open('/proc/self/mountinfo', 'r') as f: + data = f.read() + index_resolv_conf = data.find("resolv.conf") + if index_resolv_conf != -1: + index_second_slash = data.rfind("/", 0, index_resolv_conf) + index_first_slash = data.rfind("/", 0, index_second_slash) + 1 + container_id = data[index_first_slash:index_second_slash] + if len(container_id) < 20: + index_resolv_conf = data.find("/sys/fs/cgroup/devices") + if index_resolv_conf != -1: + index_second_slash = data.rfind(" ", 0, index_resolv_conf) + index_first_slash = data.rfind("/", 0, index_second_slash) + 1 + container_id = data[index_first_slash:index_second_slash] + if not container_id: + return False, "获取容器ID失败!" + # 重启当前容器 + client.containers.get(container_id.strip()).restart() + return True, "" + except Exception as err: + print(str(err)) + return False, f"重启时发生错误:{str(err)}" diff --git a/app/utils/system.py b/app/utils/system.py index ef5617e8..b3b54796 100644 --- a/app/utils/system.py +++ b/app/utils/system.py @@ -11,7 +11,6 @@ from glob import glob from pathlib import Path from typing import List, Optional, Tuple, Union -import docker import psutil from app import schemas @@ -439,47 +438,6 @@ class SystemUtils: """ return [psutil.virtual_memory().used, int(psutil.virtual_memory().percent)] - @staticmethod - def can_restart() -> bool: - """ - 判断是否可以内部重启 - """ - return Path("/var/run/docker.sock").exists() - - @staticmethod - def restart() -> Tuple[bool, str]: - """ - 执行Docker重启操作 - """ - if not SystemUtils.is_docker(): - return False, "非Docker环境,无法重启!" - try: - # 创建 Docker 客户端 - client = docker.DockerClient(base_url='tcp://127.0.0.1:38379') - # 获取当前容器的 ID - container_id = None - with open('/proc/self/mountinfo', 'r') as f: - data = f.read() - index_resolv_conf = data.find("resolv.conf") - if index_resolv_conf != -1: - index_second_slash = data.rfind("/", 0, index_resolv_conf) - index_first_slash = data.rfind("/", 0, index_second_slash) + 1 - container_id = data[index_first_slash:index_second_slash] - if len(container_id) < 20: - index_resolv_conf = data.find("/sys/fs/cgroup/devices") - if index_resolv_conf != -1: - index_second_slash = data.rfind(" ", 0, index_resolv_conf) - index_first_slash = data.rfind("/", 0, index_second_slash) + 1 - container_id = data[index_first_slash:index_second_slash] - if not container_id: - return False, "获取容器ID失败!" - # 重启当前容器 - client.containers.get(container_id.strip()).restart() - return True, "" - except Exception as err: - print(str(err)) - return False, f"重启时发生错误:{str(err)}" - @staticmethod def is_hardlink(src: Path, dest: Path) -> bool: """