import json 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.string import StringUtils from app.utils.system import SystemUtils from version import APP_VERSION class ResourceHelper: """ 检测和更新资源包 """ # 资源包的git仓库地址 _repo = f"{settings.GITHUB_PROXY}https://raw.githubusercontent.com/jxxghp/MoviePilot-Resources/main/package.v2.json" _files_api = f"https://api.github.com/repos/jxxghp/MoviePilot-Resources/contents/resources.v2" _base_dir: Path = settings.ROOT_PATH def __init__(self): self.check() @property def proxies(self): return None if settings.GITHUB_PROXY else settings.PROXY def check(self): """ 检测是否有更新,如有则下载安装 """ if not settings.AUTO_UPDATE_RESOURCE: return None if SystemUtils.is_frozen(): 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 = SitesHelper().auth_version # 阻断站点认证资源v2.3.0以下的版本直接更新,避免无限重启 if StringUtils.compare_version(local_version, "<", "2.3.0"): continue # 阻断主程序版本v2.6.3以下的版本直接更新,避免搜索异常 if StringUtils.compare_version(APP_VERSION, "<", "2.6.3"): continue elif rtype == "sites": # 站点索引资源 local_version = 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() # 下载资源文件 success = True 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')} 下载失败!") success = False break elif res.status_code != 200: logger.error(f"下载文件 {item.get('name')} 失败:{res.status_code} - {res.reason}") success = False break # 创建插件文件夹 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) if success: logger.info("资源包更新完成,开始重启服务...") SystemHelper.restart() else: logger.warn("资源包更新失败,跳过升级!") else: logger.info("所有资源已最新,无需更新") except json.JSONDecodeError: logger.error("资源包仓库数据解析失败!") return None else: logger.warn("无法连接资源包仓库!") return None