From 1a129481e446ac18087214608c0a6c7f30d0f413 Mon Sep 17 00:00:00 2001 From: Falck Date: Sat, 18 Apr 2026 00:27:33 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E9=99=A4=20data/pkg=20=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=E7=9B=B8=E5=85=B3=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + Dockerfile | 2 +- start.sh | 2 +- .../hot-reload.disabled/manifest.json | 2 +- store/@{FutureOSS}/pkg/README.md | 43 ---- store/@{FutureOSS}/pkg/SIGNATURE | 8 - .../pkg/__pycache__/main.cpython-313.pyc | Bin 11228 -> 0 bytes store/@{FutureOSS}/pkg/main.py | 216 ------------------ store/@{FutureOSS}/pkg/manifest.json | 18 -- .../core/manager.py | 1 - store/@{FutureOSS}/plugin-loader/README.md | 2 +- store/@{FutureOSS}/plugin-loader/main.py | 38 +-- .../@{FutureOSS}/plugin-loader/manifest.json | 2 +- store/@{FutureOSS}/webui/main.py | 1 - 14 files changed, 8 insertions(+), 328 deletions(-) delete mode 100644 store/@{FutureOSS}/pkg/README.md delete mode 100644 store/@{FutureOSS}/pkg/SIGNATURE delete mode 100644 store/@{FutureOSS}/pkg/__pycache__/main.cpython-313.pyc delete mode 100644 store/@{FutureOSS}/pkg/main.py delete mode 100644 store/@{FutureOSS}/pkg/manifest.json diff --git a/.gitignore b/.gitignore index d3ed4c7..00dcd4f 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ data/signature-verifier/keys/private/ # 签名文件(可选,本地开发可能不需要) # store/**/SIGNATURE +.codebuddy/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index e397be2..4096e44 100644 --- a/Dockerfile +++ b/Dockerfile @@ -33,7 +33,7 @@ COPY pyproject.toml ./pyproject.toml COPY README.md ./README.md # 创建必要目录 -RUN mkdir -p /app/data/html-render /app/data/web-toolkit /app/data/plugin-storage /app/data/DCIM /app/data/pkg /app/logs +RUN mkdir -p /app/data/html-render /app/data/web-toolkit /app/data/plugin-storage /app/data/DCIM /app/logs # 暴露端口 EXPOSE 8080 8081 8082 diff --git a/start.sh b/start.sh index 15fdce6..3decffc 100755 --- a/start.sh +++ b/start.sh @@ -303,7 +303,7 @@ ok "Python 依赖安装完成" # ═══════════════════════════════════════════════════════════ step "初始化数据目录" -DATA_DIRS=("data" "data/html-render" "data/web-toolkit" "data/plugin-storage" "data/DCIM" "data/pkg" "data/signature-verifier/keys/private" "data/signature-verifier/keys/public" "logs") +DATA_DIRS=("data" "data/html-render" "data/web-toolkit" "data/plugin-storage" "data/DCIM" "data/signature-verifier/keys/private" "data/signature-verifier/keys/public" "logs") DIR_COUNT=${#DATA_DIRS[@]} DIR_CURRENT=0 diff --git a/store/@{FutureOSS}/hot-reload.disabled/manifest.json b/store/@{FutureOSS}/hot-reload.disabled/manifest.json index 3856e3d..3959012 100644 --- a/store/@{FutureOSS}/hot-reload.disabled/manifest.json +++ b/store/@{FutureOSS}/hot-reload.disabled/manifest.json @@ -9,7 +9,7 @@ "config": { "enabled": true, "args": { - "watch_dirs": ["store", "./data/pkg"], + "watch_dirs": ["store"], "watch_extensions": [".py", ".json"] } }, diff --git a/store/@{FutureOSS}/pkg/README.md b/store/@{FutureOSS}/pkg/README.md deleted file mode 100644 index 4cc3963..0000000 --- a/store/@{FutureOSS}/pkg/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# pkg 包管理 - -插件的搜索、安装、卸载和更新功能。 - -## 功能 - -- 从远程仓库搜索插件 -- 下载并安装到 `./data/pkg/` 目录 -- 卸载已安装的插件 -- 更新单个或所有插件 -- 维护已安装插件列表 - -## 使用 - -```python -pm = pkg_plugin.manager - -# 搜索 -results = pm.search("keyword") - -# 安装 -pm.install("plugin-name") -pm.install("plugin-name", version="1.0.0") - -# 卸载 -pm.uninstall("plugin-name") - -# 更新 -pm.update() # 更新所有 -pm.update("plugin-name") # 更新单个 - -# 列出已安装 -installed = pm.list_installed() -``` - -## 安装位置 - -``` -./data/pkg/ -└── <插件名>/ - ├── main.py - └── manifest.json -``` diff --git a/store/@{FutureOSS}/pkg/SIGNATURE b/store/@{FutureOSS}/pkg/SIGNATURE deleted file mode 100644 index 4afd13b..0000000 --- a/store/@{FutureOSS}/pkg/SIGNATURE +++ /dev/null @@ -1,8 +0,0 @@ -{ - "signature": "dXU/zN0Zge7OC8UZgWXZVhPn7LQyiKQw4iUVZAI0P4PA7zGed3cnXa7GFzVnUKxyZMKaOITcGeg7yIM9SWM7WRTWj3N1e6F/0ac6zQ57WgREUA2zc4w0/Vc742i0+KSrE1TkICZl1CTa1x3TG3VJQo0qw4FGPijKjJQIaA9yw+yLhm0dkMefZGVAuYRnupFvKxX1xar0vx6JPpoDmHxvU92PdzbR1ggsB5hOzIrvd3aVJ1U8GbogVhtaabToK9IXbX6qrTY32ffZpEOI5n0IqAvxZ81IUV3bwhf72nP6sedEEKJzgOGfqHhMalOpjsEHNiHnX3UgBfiXzeDn2zN0NevTGCGzvgQHc3/5o/Ct9wG8ujqlNLi37jXt1DrTnIF1IBsW73ltdaMvl4IgQ0Sln2Y7QMNt3CDtwNBSBiLUhTnMjPN7QVaCl7lMM0PJH5tWg3rlSdf7+LGUN535uMwrtEJEmhafo2lcApInEZryEmRcUb22Wl3xCqGgK5yk30QqGHCwY/h4fNhx2VE7LWIoD/jMJNH+TPXTzPPUGHOGB5zaR8v+qtohOwRYPewUkbEArg7qjsOgHerHziLYBY2yH1/4oi9/N7DYsgmRyHrl4siuo+5HtPar+q29yDORs5UgxK3VNHncElVWXQ9DGzIrm3Ffj610nw7kOiU58HrBjj8=", - "signer": "FutureOSS", - "algorithm": "RSA-SHA256", - "timestamp": 1775964952.754572, - "plugin_hash": "36a948e470e6cd7ac1b51a385f21fc615c36049e9cb3fac25cdaef8161063ef1", - "author": "FutureOSS" -} \ No newline at end of file diff --git a/store/@{FutureOSS}/pkg/__pycache__/main.cpython-313.pyc b/store/@{FutureOSS}/pkg/__pycache__/main.cpython-313.pyc deleted file mode 100644 index 5db320e01beed828b2cf389c261c43edb72ea796..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11228 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 CS5DFZ diff --git a/store/@{FutureOSS}/pkg/main.py b/store/@{FutureOSS}/pkg/main.py deleted file mode 100644 index 905556e..0000000 --- a/store/@{FutureOSS}/pkg/main.py +++ /dev/null @@ -1,216 +0,0 @@ -"""包管理插件 - 搜索、安装、卸载、更新插件""" -import os -import json -import shutil -import urllib.request -import urllib.parse -from pathlib import Path -from typing import Any, Optional - -from oss.logger.logger import Log -from oss.plugin.types import Plugin, register_plugin_type - - -# 远程仓库地址(可配置) -# 插件存储在 future-oss 仓库的 store/ 目录下 -DEFAULT_REGISTRY = "https://gitee.com/starlight-apk/future-oss/raw/main" - -# 插件安装目录 -PKG_DIR = Path("./data/pkg") - - -class PackageInfo: - """包信息""" - def __init__(self): - self.name: str = "" - self.version: str = "" - self.author: str = "" - self.description: str = "" - self.download_url: str = "" - self.dependencies: list[str] = [] - - -class PackageManager: - """包管理器""" - - def __init__(self): - self.registry = DEFAULT_REGISTRY - self.index_cache: dict[str, PackageInfo] = {} - self.installed: dict[str, dict[str, Any]] = {} - self._load_installed() - - def _load_installed(self): - """加载已安装的包""" - if not PKG_DIR.exists(): - return - # 扫描 @{author}/plugin_name 结构 - for author_dir in PKG_DIR.iterdir(): - if author_dir.is_dir() and author_dir.name.startswith("@{"): - for plugin_dir in author_dir.iterdir(): - if plugin_dir.is_dir(): - manifest = plugin_dir / "manifest.json" - if manifest.exists(): - with open(manifest, "r", encoding="utf-8") as f: - full_name = author_dir.name + "/" + plugin_dir.name - self.installed[full_name] = json.load(f) - - def search(self, query: str = "") -> list[PackageInfo]: - """搜索可用的包""" - # 简化版本:直接返回本地缓存 - # 实际使用时可以通过 API 或配置文件维护一个插件索引 - return self._search_from_cache(query) - - def _search_from_cache(self, query: str = "") -> list[PackageInfo]: - """从本地缓存搜索包""" - results = [] - for pkg_name, pkg_info in self.index_cache.items(): - if not query or query.lower() in pkg_name.lower() or query.lower() in pkg_info.get("description", "").lower(): - results.append(pkg_info) - return results - - def install(self, name: str, version: str = "") -> bool: - """安装包,支持 @{作者名称}/插件名称 格式""" - # 解析输入格式 @{author}/plugin 或直接插件名 - author = "FutureOSS" # 默认作者 - plugin_name = name - - if name.startswith("@{") and "}/" in name: - # 解析 @{author}/plugin 格式 - end_bracket = name.index("}/") - author = name[2:end_bracket] - plugin_name = name[end_bracket + 2:] - elif name.startswith("@{") and name.endswith("}") and "/" in name: - # 兼容旧格式 @{author/plugin} - inner = name[2:-1] - parts = inner.split("/", 1) - if len(parts) == 2: - author, plugin_name = parts - - # 搜索获取下载链接 - packages = self.search(plugin_name) - pkg_info = None - for p in packages: - if p.name == plugin_name and p.author == author: - if not version or p.version == version: - pkg_info = p - break - - if not pkg_info or not pkg_info.download_url: - # 尝试从远程仓库直接构建 URL - # 插件存储在 store/@{author}/plugin_name 目录下 - pkg_info = PackageInfo() - pkg_info.name = plugin_name - pkg_info.author = author - pkg_info.version = version or "1.0.0" - pkg_info.download_url = f"{self.registry}/store/@{{{author}}}/{plugin_name}" - - # 创建安装目录 @{author}/plugin_name - install_dir = PKG_DIR / ("@{" + author + "}") / plugin_name - install_dir.mkdir(parents=True, exist_ok=True) - - try: - # 下载 manifest.json - manifest_url = f"{pkg_info.download_url}/manifest.json" - with urllib.request.urlopen(manifest_url, timeout=10) as resp: - manifest_data = json.loads(resp.read().decode("utf-8")) - with open(install_dir / "manifest.json", "w", encoding="utf-8") as f: - json.dump(manifest_data, f, ensure_ascii=False, indent=2) - - # 下载 main.py - main_url = f"{pkg_info.download_url}/main.py" - with urllib.request.urlopen(main_url, timeout=10) as resp: - main_data = resp.read().decode("utf-8") - with open(install_dir / "main.py", "w", encoding="utf-8") as f: - f.write(main_data) - - # 更新已安装列表 - full_name = "@{" + author + "}/" + plugin_name - self.installed[full_name] = manifest_data - Log.info("pkg", f"已安装: {full_name} {manifest_data.get('metadata', {}).get('version', '')}") - return True - except Exception as e: - Log.error("pkg", f"安装失败 {name}: {e}") - # 清理失败的安装 - if install_dir.exists(): - shutil.rmtree(install_dir) - return False - - def uninstall(self, name: str) -> bool: - """卸载包,支持 @{作者名称}/插件名称 格式""" - # 解析格式获取目录路径 - if name.startswith("@{") and "}/" in name: - end_bracket = name.index("}/") - author = name[2:end_bracket] - plugin_name = name[end_bracket + 2:] - install_dir = PKG_DIR / ("@{" + author + "}") / plugin_name - elif name.startswith("@{") and name.endswith("}") and "/" in name: - # 兼容旧格式 - install_dir = PKG_DIR / name - else: - install_dir = PKG_DIR / name - - if not install_dir.exists(): - Log.info("pkg", f"包未安装: {name}") - return False - - try: - shutil.rmtree(install_dir) - # 从已安装列表中移除 - for key in list(self.installed.keys()): - if key == name or key.endswith("/" + install_dir.name): - del self.installed[key] - break - Log.info("pkg", f"已卸载: {name}") - return True - except Exception as e: - Log.error("pkg", f"卸载失败 {name}: {e}") - return False - - def update(self, name: str = "") -> bool: - """更新包""" - if name: - # 更新单个包 - if name not in self.installed: - Log.info("pkg", f"包未安装: {name}") - return False - return self.install(name) - else: - # 更新所有已安装的包 - success = True - for pkg_name in list(self.installed.keys()): - if not self.install(pkg_name): - success = False - return success - - def list_installed(self) -> dict[str, Any]: - """列出已安装的包""" - return self.installed - - -class PkgPlugin(Plugin): - """包管理插件""" - - def __init__(self): - self.manager = PackageManager() - - def init(self, deps: dict = None): - """初始化""" - PKG_DIR.mkdir(parents=True, exist_ok=True) - Log.info("pkg", "包管理器已初始化") - - def start(self): - """启动""" - Log.info("pkg", f"包管理器已启动,已安装 {len(self.manager.installed)} 个包") - - def stop(self): - """停止""" - pass - - -# 注册类型 -register_plugin_type("PackageManager", PackageManager) -register_plugin_type("PackageInfo", PackageInfo) - - -def New(): - return PkgPlugin() diff --git a/store/@{FutureOSS}/pkg/manifest.json b/store/@{FutureOSS}/pkg/manifest.json deleted file mode 100644 index 1fdf373..0000000 --- a/store/@{FutureOSS}/pkg/manifest.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "metadata": { - "name": "pkg", - "version": "1.0.0", - "author": "FutureOSS", - "description": "包管理 - 插件的搜索、安装、卸载和更新", - "type": "utility" - }, - "config": { - "enabled": true, - "args": { - "registry": "https://gitee.com/starlight-apk/future-oss-pkg/raw/main", - "install_dir": "./data/pkg" - } - }, - "dependencies": [], - "permissions": [] -} diff --git a/store/@{FutureOSS}/plugin-loader-pro.disabled/core/manager.py b/store/@{FutureOSS}/plugin-loader-pro.disabled/core/manager.py index 7563d3e..c53c938 100644 --- a/store/@{FutureOSS}/plugin-loader-pro.disabled/core/manager.py +++ b/store/@{FutureOSS}/plugin-loader-pro.disabled/core/manager.py @@ -43,7 +43,6 @@ class ProPluginManager: ProLogger.info("loader", "开始扫描插件...") self._load_from_dir(Path(store_dir)) - self._load_from_dir(Path("./data/pkg")) ProLogger.info("loader", f"共加载 {len(self.plugins)} 个插件") diff --git a/store/@{FutureOSS}/plugin-loader/README.md b/store/@{FutureOSS}/plugin-loader/README.md index 652aa52..d4c368f 100644 --- a/store/@{FutureOSS}/plugin-loader/README.md +++ b/store/@{FutureOSS}/plugin-loader/README.md @@ -4,7 +4,7 @@ ## 功能 -- 自动扫描 `store/` 和 `./data/pkg/` 目录 +- 自动扫描 `store/` 目录 - 动态加载 `main.py` 并调用 `New()` 获取实例 - 解析 `manifest.json` 获取插件元数据 - 自动扫描插件能力(AST 分析) diff --git a/store/@{FutureOSS}/plugin-loader/main.py b/store/@{FutureOSS}/plugin-loader/main.py index f6b6c58..6653504 100644 --- a/store/@{FutureOSS}/plugin-loader/main.py +++ b/store/@{FutureOSS}/plugin-loader/main.py @@ -350,7 +350,7 @@ class PluginManager: return instance def load_all(self, store_dir: str = "store"): - """加载 store 和 data/pkg 下所有插件(跳过自己)""" + """加载 store 下所有插件(跳过自己)""" # 确保 plugin 命名空间包存在(必须在最开头) import types if 'plugin' not in sys.modules: @@ -411,7 +411,6 @@ class PluginManager: # 加载其他插件 self._load_plugins_from_dir(Path(store_dir)) - self._load_plugins_from_dir(Path("./data/pkg")) # 按依赖排序 if dependency_plugin: @@ -448,44 +447,11 @@ class PluginManager: if plugin_dir.is_dir() and (plugin_dir / "main.py").exists(): return True - pkg_dir = Path("./data/pkg") - if pkg_dir.exists(): - for d in pkg_dir.iterdir(): - if d.is_dir() and (d / "main.py").exists(): - return True - return False def _bootstrap_installation(self): """引导安装 FutureOSS 官方插件""" - # 加载 pkg 插件 - pkg_dir = Path("store/@{FutureOSS}/pkg") - if pkg_dir.exists() and (pkg_dir / "main.py").exists(): - try: - pkg_instance = self.load(pkg_dir, use_sandbox=False) - if pkg_instance: - pkg_mgr = pkg_instance.manager - - Log.info("plugin-loader", "正在搜索可用插件...") - results = pkg_mgr.search() - if not results: - Log.warn("plugin-loader", "未找到远程插件") - return - - Log.info("plugin-loader", f"发现 {len(results)} 个插件,开始安装...") - installed_count = 0 - for pkg_info in results: - Log.info("plugin-loader", f"安装: {pkg_info.name}") - if pkg_mgr.install(pkg_info.name): - installed_count += 1 - - if installed_count > 0: - Log.info("plugin-loader", f"已安装 {installed_count} 个插件,重新扫描加载...") - # pkg 保留,重新加载其他插件 - except Exception as e: - Log.error("plugin-loader", f"引导安装失败: {e}") - else: - Log.info("plugin-loader", "pkg 插件不存在,跳过引导安装") + Log.info("plugin-loader", "跳过引导安装(pkg 插件已移除)") def _sort_by_dependencies(self, dep_plugin): """按依赖关系排序""" diff --git a/store/@{FutureOSS}/plugin-loader/manifest.json b/store/@{FutureOSS}/plugin-loader/manifest.json index 70fff14..9027f05 100644 --- a/store/@{FutureOSS}/plugin-loader/manifest.json +++ b/store/@{FutureOSS}/plugin-loader/manifest.json @@ -9,7 +9,7 @@ "config": { "enabled": true, "args": { - "scan_dirs": ["store", "./data/pkg"], + "scan_dirs": ["store"], "sandbox_enabled": true, "permission_check": true } diff --git a/store/@{FutureOSS}/webui/main.py b/store/@{FutureOSS}/webui/main.py index 4b82818..125e744 100644 --- a/store/@{FutureOSS}/webui/main.py +++ b/store/@{FutureOSS}/webui/main.py @@ -75,7 +75,6 @@ class WebUIPlugin(Plugin): dashboard_exists = False store_dirs = [ Path("store/@{FutureOSS}/dashboard"), - Path("./data/pkg/dashboard"), ] for d in store_dirs: if d.exists() and (d / "main.py").exists():