From 47ddfec30ea822133840211fc0592cf403d83d91 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Thu, 16 Nov 2023 20:57:41 +0800 Subject: [PATCH] =?UTF-8?q?feat=20=E8=B5=84=E6=BA=90=E5=8C=85=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +- app/core/config.py | 2 + app/helper/plugin.py | 8 ++-- app/helper/resource.py | 101 +++++++++++++++++++++++++++++++++++++++++ app/main.py | 4 ++ config/app.env | 2 + 6 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 app/helper/resource.py diff --git a/README.md b/README.md index 8fce8051..58bb3ab5 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,8 @@ MoviePilot需要配套下载器和媒体服务器配合使用。 - **PGID**:运行程序用户的`gid`,默认`0`(仅支持环境变量配置) - **UMASK**:掩码权限,默认`000`,可以考虑设置为`022`(仅支持环境变量配置) - **PROXY_HOST:** 网络代理,访问themoviedb或者重启更新需要使用代理访问,格式为`http(s)://ip:port`、`socks5://user:pass@host:port`(仅支持环境变量配置) -- **MOVIEPILOT_AUTO_UPDATE**:重启更新,`true`/`release`/`dev`/`false`,默认`release` **注意:如果出现网络问题可以配置`PROXY_HOST`**(仅支持环境变量配置) +- **MOVIEPILOT_AUTO_UPDATE:** 重启时自动更新,`true`/`release`/`dev`/`false`,默认`release`,需要能正常连接Github **注意:如果出现网络问题可以配置`PROXY_HOST`**(仅支持环境变量配置) +- **AUTO_UPDATE_RESOURCE**:启动时自动检测和更新资源包(站点索引及认证等),`true`/`false`,默认`true`,需要能正常连接Github,仅支持Docker --- - **❗SUPERUSER:** 超级管理员用户名,默认`admin`,安装后使用该用户登录后台管理界面 - **❗SUPERUSER_PASSWORD:** 超级管理员初始密码,默认`password`,建议修改为复杂密码 diff --git a/app/core/config.py b/app/core/config.py index f738248f..7dbbf97e 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -214,6 +214,8 @@ class Settings(BaseSettings): PLUGIN_MARKET: str = "https://raw.githubusercontent.com/jxxghp/MoviePilot-Plugins/main/" # Github token,提高请求api限流阈值 ghp_**** GITHUB_TOKEN: str = None + # 自动检查和更新站点资源包(站点索引、认证等) + AUTO_UPDATE_RESOURCE: bool = True @property def INNER_CONFIG_PATH(self): diff --git a/app/helper/plugin.py b/app/helper/plugin.py index de60ddca..c518a82d 100644 --- a/app/helper/plugin.py +++ b/app/helper/plugin.py @@ -24,7 +24,8 @@ class PluginHelper(metaclass=Singleton): """ if not repo_url: return {} - res = RequestUtils(proxies=settings.PROXY, timeout=10).get_res(f"{repo_url}package.json") + res = RequestUtils(proxies=settings.PROXY, headers=settings.GITHUB_HEADERS, + timeout=10).get_res(f"{repo_url}package.json") if res: return json.loads(res.text) return {} @@ -49,7 +50,7 @@ class PluginHelper(metaclass=Singleton): 获取插件的文件列表 """ file_api = f"https://api.github.com/repos/{user}/{repo}/contents/plugins/{_p.lower()}" - r = RequestUtils(proxies=settings.PROXY, headers=settings.GITHUB_HEADERS).get_res(file_api) + r = RequestUtils(proxies=settings.PROXY, headers=settings.GITHUB_HEADERS, timeout=10).get_res(file_api) if not r or r.status_code != 200: return None, f"连接仓库失败:{r.status_code} - {r.reason}" ret = r.json() @@ -66,7 +67,8 @@ class PluginHelper(metaclass=Singleton): for item in _l: if item.get("download_url"): # 下载插件文件 - res = RequestUtils(proxies=settings.PROXY).get_res(item["download_url"]) + res = RequestUtils(proxies=settings.PROXY, + headers=settings.GITHUB_HEADERS, timeout=30).get_res(item["download_url"]) if not res: return False, f"文件 {item.get('name')} 下载失败!" elif res.status_code != 200: diff --git a/app/helper/resource.py b/app/helper/resource.py new file mode 100644 index 00000000..d1223edd --- /dev/null +++ b/app/helper/resource.py @@ -0,0 +1,101 @@ +import json +from pathlib import Path + +from app.core.config import settings +from app.helper.sites import SitesHelper +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 + + +class ResourceHelper(metaclass=Singleton): + """ + 检测和更新资源包 + """ + # 资源包的git仓库地址 + _repo = "https://raw.githubusercontent.com/jxxghp/MoviePilot-Resources/main/package.json" + _files_api = f"https://api.github.com/repos/jxxghp/MoviePilot-Resources/contents/resources" + _base_dir: Path = settings.ROOT_PATH / "app" + + def __init__(self): + self.siteshelper = SitesHelper() + self.check() + + def check(self): + """ + 检测是否有更新,如有则下载安装 + """ + if not settings.AUTO_UPDATE_RESOURCE: + return + if SystemUtils.is_frozen(): + return + logger.info("开始检测资源包版本...") + res = RequestUtils(proxies=settings.PROXY, headers=settings.GITHUB_HEADERS, timeout=10).get_res(self._repo) + if res: + resource_info = json.loads(res.text) + 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 + # 判断本地是否存在 + local_path = self._base_dir / target + if not local_path.exists(): + 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) > 0: + logger.info(f"{rname} 资源包有更新,最新版本:v{version}") + # 需要安装 + need_updates[rname] = target + if need_updates: + # 下载文件信息列表 + r = RequestUtils(proxies=settings.PROXY, headers=settings.GITHUB_HEADERS, + timeout=10).get_res(self._files_api) + if not r or r.status_code != 200: + return None, f"连接仓库失败:{r.status_code} - {r.reason}" + 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"): + # 下载插件文件 + res = RequestUtils(proxies=settings.PROXY, headers=settings.GITHUB_HEADERS, + timeout=60).get_res(item["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 + 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("所有资源已最新,无需更新") diff --git a/app/main.py b/app/main.py index 5973cb6b..ea48878b 100644 --- a/app/main.py +++ b/app/main.py @@ -22,10 +22,12 @@ from app.core.plugin import PluginManager from app.db.init import init_db, update_db from app.helper.thread import ThreadHelper from app.helper.display import DisplayHelper +from app.helper.resource import ResourceHelper from app.helper.sites import SitesHelper from app.scheduler import Scheduler from app.command import Command + # App App = FastAPI(title=settings.PROJECT_NAME, openapi_url=f"{settings.API_V1_STR}/openapi.json") @@ -169,6 +171,8 @@ def start_module(): DisplayHelper() # 站点管理 SitesHelper() + # 资源包检测 + ResourceHelper() # 加载模块 ModuleManager() # 加载插件 diff --git a/config/app.env b/config/app.env index 8bff6387..0aa6accf 100644 --- a/config/app.env +++ b/config/app.env @@ -27,6 +27,8 @@ TMDB_API_DOMAIN=api.themoviedb.org RECOGNIZE_SOURCE=themoviedb # 大内存模式,开启后会增加缓存数量,但会占用更多内存 BIG_MEMORY_MODE=false +# 自动检查和更新站点资源包(索引、认证等) +AUTO_UPDATE_RESOURCE=true #################################### # 媒体识别&刮削 #