From e8f3d8b6452a95c658af8aa2c6347f482aa48f72 Mon Sep 17 00:00:00 2001 From: RoyirinRosmontis Date: Sun, 23 Aug 2026 12:19:17 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=20-=20PAC=20?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=9B=B4=E6=96=B0=E6=BA=90=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E6=8B=89=E5=8F=96=E6=95=B0=E6=8D=AE=E6=96=87?= =?UTF-8?q?=E4=BB=B6=EF=BC=88=E5=8E=9F=20manifest=20=E6=96=B9=E6=A1=88?= =?UTF-8?q?=E7=AE=80=E5=8C=96=EF=BC=8C=E6=96=87=E4=BB=B6=E8=87=AA=E5=B8=A6?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=8F=B7/=E6=97=A5=E6=9C=9F=EF=BC=89=20-=20?= =?UTF-8?q?=E8=BF=9C=E7=AB=AF=E6=95=B0=E6=8D=AE=E7=BC=BA=E5=B0=91=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7=E6=97=B6=E6=94=B9=E4=B8=BA=E6=8C=89=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E6=AF=94=E5=AF=B9=EF=BC=8C=E9=81=BF=E5=85=8D=E6=AF=8F?= =?UTF-8?q?=E6=AC=A1=E5=90=AF=E5=8A=A8=E9=87=8D=E5=A4=8D=E4=B8=8B=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增功能: - 配置真实 PAC CDN 地址(cdn.rrrosmontis.icu) --- lite/proxy_lite.py | 62 ++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/lite/proxy_lite.py b/lite/proxy_lite.py index 2028709..ad5e03f 100644 --- a/lite/proxy_lite.py +++ b/lite/proxy_lite.py @@ -536,8 +536,7 @@ _TLS_LOCAL_PORT = int(_config_val("local_port", 1080)) # 本地转发器监听 PROXY_PORT = _TLS_LOCAL_PORT # ── PAC 数据在线更新(CDN 直连,无需认证) ───────────── -# 更新源地址取 config.json 的 pac_base_url;目录结构: -# {pac_base_url}/pac_manifest.json 资源号清单 +# 更新源地址取 config.json 的 pac_base_url,目录下直接放两个数据文件: # {pac_base_url}/pac_domains.json 强制隧道域名表(version/date 字段随文件下发) # {pac_base_url}/pac_ip_cn.json 中国 IP 段(同上) _PAC_FILES = ("pac_domains", "pac_ip_cn") @@ -574,17 +573,13 @@ def _pac_validate(name, data): return isinstance(data.get("cidrs"), list) return False -def _pac_download(base, name): - """下载 PAC 数据并原子写入 ~/RRPP;返回 (version, date)。""" +def _pac_write(name, data): + """PAC 数据原子写入 ~/RRPP(tmp+replace,写不坏旧文件)。""" import json - data = _pac_fetch_json(f"{base}/{name}.json") - if not _pac_validate(name, data): - raise ValueError(f"{name}.json 数据格式不正确") _USER_DIR.mkdir(parents=True, exist_ok=True) tmp = _USER_DIR / f"{name}.json.tmp" tmp.write_text(json.dumps(data, ensure_ascii=False), "utf-8") - os.replace(tmp, _USER_DIR / f"{name}.json") # 原子替换,避免写一半 - return str(data.get("version") or ""), str(data.get("date") or "") + os.replace(tmp, _USER_DIR / f"{name}.json") def _user_init_local(): """初始化 ~/RRPP(同步):建目录,nodes.json 缺失时写入空模板。""" @@ -599,35 +594,44 @@ def _user_init_local(): def _user_init_remote(base_url=None, nodes_url=None): """检查并更新 PAC 数据与节点配置(后台线程): - PAC 按 manifest 版本比对(失败用本地副本);nodes 按内容比对(独立地址)。 + PAC 直接拉取两个数据文件(内含 version/date),按版本比对后更新;失败用本地副本。 + nodes 按内容比对(独立地址)。 """ base = (base_url or str(_config_val("pac_base_url", "") or "")).strip().rstrip("/") if not base: log("未配置 PAC 更新源(config.json 的 pac_base_url),使用本地数据") else: - try: - manifest = _pac_fetch_json(f"{base}/pac_manifest.json") - except Exception as e: - log(f"PAC 更新源不可达,使用本地数据 ({e})") - manifest = None - if manifest is not None: - updated = 0 - for name in _PAC_FILES: - remote = manifest.get(name) or {} - rver = str(remote.get("version") or "") - rdate = str(remote.get("date") or "") + import json + updated = failed = 0 + for name in _PAC_FILES: + try: + data = _pac_fetch_json(f"{base}/{name}.json") + if not _pac_validate(name, data): + raise ValueError(f"{name}.json 数据格式不正确") + rver = str(data.get("version") or "") + rdate = str(data.get("date") or "") # 版本只与 ~/RRPP 本地文件比对(回退文件仅用于读取,不参与更新判定) local = _USER_DIR / f"{name}.json" lver = _pac_read_version(local)[0] if local.is_file() else "" - if rver and rver > lver: - try: - ver, date = _pac_download(base, name) - log(f"PAC 数据已更新: {name}.json {ver or rver} ({date or rdate})") + if rver: + if rver > lver: + _pac_write(name, data) + log(f"PAC 数据已更新: {name}.json {rver} ({rdate})") updated += 1 - except Exception as e: - log(f"PAC 数据 {name}.json 更新失败,使用本地副本: {e}") - if updated == 0 and (_USER_DIR / "pac_domains.json").is_file(): - log("PAC 数据已是最新") + # 否则已是最新,跳过 + else: + # 远端缺版本号:本地没有 -> 兜底下载;本地有 -> 按内容比对 + new_bytes = json.dumps(data, ensure_ascii=False).encode("utf-8") + if local.is_file() and local.read_bytes() == new_bytes: + continue + _pac_write(name, data) + log(f"PAC 数据已下载: {name}.json 无版本号 ({rdate})") + updated += 1 + except Exception as e: + log(f"PAC 数据 {name}.json 更新失败,使用本地副本: {e}") + failed += 1 + if updated == 0 and failed == 0 and (_USER_DIR / "pac_domains.json").is_file(): + log("PAC 数据已是最新") # 节点配置在线更新:地址独立于 PAC,按内容比对,仅变化时原子覆盖 nurl = (nodes_url or str(_config_val("nodes_url", "") or "")).strip() if not nurl: