修复:
- PAC 数据更新源改为直接拉取数据文件(原 manifest 方案简化,文件自带资源号/日期) - 远端数据缺少版本号时改为按内容比对,避免每次启动重复下载 新增功能: - 配置真实 PAC CDN 地址(cdn.rrrosmontis.icu)
This commit is contained in:
+33
-29
@@ -536,8 +536,7 @@ _TLS_LOCAL_PORT = int(_config_val("local_port", 1080)) # 本地转发器监听
|
|||||||
PROXY_PORT = _TLS_LOCAL_PORT
|
PROXY_PORT = _TLS_LOCAL_PORT
|
||||||
|
|
||||||
# ── PAC 数据在线更新(CDN 直连,无需认证) ─────────────
|
# ── PAC 数据在线更新(CDN 直连,无需认证) ─────────────
|
||||||
# 更新源地址取 config.json 的 pac_base_url;目录结构:
|
# 更新源地址取 config.json 的 pac_base_url,目录下直接放两个数据文件:
|
||||||
# {pac_base_url}/pac_manifest.json 资源号清单
|
|
||||||
# {pac_base_url}/pac_domains.json 强制隧道域名表(version/date 字段随文件下发)
|
# {pac_base_url}/pac_domains.json 强制隧道域名表(version/date 字段随文件下发)
|
||||||
# {pac_base_url}/pac_ip_cn.json 中国 IP 段(同上)
|
# {pac_base_url}/pac_ip_cn.json 中国 IP 段(同上)
|
||||||
_PAC_FILES = ("pac_domains", "pac_ip_cn")
|
_PAC_FILES = ("pac_domains", "pac_ip_cn")
|
||||||
@@ -574,17 +573,13 @@ def _pac_validate(name, data):
|
|||||||
return isinstance(data.get("cidrs"), list)
|
return isinstance(data.get("cidrs"), list)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _pac_download(base, name):
|
def _pac_write(name, data):
|
||||||
"""下载 PAC 数据并原子写入 ~/RRPP;返回 (version, date)。"""
|
"""PAC 数据原子写入 ~/RRPP(tmp+replace,写不坏旧文件)。"""
|
||||||
import json
|
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)
|
_USER_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
tmp = _USER_DIR / f"{name}.json.tmp"
|
tmp = _USER_DIR / f"{name}.json.tmp"
|
||||||
tmp.write_text(json.dumps(data, ensure_ascii=False), "utf-8")
|
tmp.write_text(json.dumps(data, ensure_ascii=False), "utf-8")
|
||||||
os.replace(tmp, _USER_DIR / f"{name}.json") # 原子替换,避免写一半
|
os.replace(tmp, _USER_DIR / f"{name}.json")
|
||||||
return str(data.get("version") or ""), str(data.get("date") or "")
|
|
||||||
|
|
||||||
def _user_init_local():
|
def _user_init_local():
|
||||||
"""初始化 ~/RRPP(同步):建目录,nodes.json 缺失时写入空模板。"""
|
"""初始化 ~/RRPP(同步):建目录,nodes.json 缺失时写入空模板。"""
|
||||||
@@ -599,35 +594,44 @@ def _user_init_local():
|
|||||||
|
|
||||||
def _user_init_remote(base_url=None, nodes_url=None):
|
def _user_init_remote(base_url=None, nodes_url=None):
|
||||||
"""检查并更新 PAC 数据与节点配置(后台线程):
|
"""检查并更新 PAC 数据与节点配置(后台线程):
|
||||||
PAC 按 manifest 版本比对(失败用本地副本);nodes 按内容比对(独立地址)。
|
PAC 直接拉取两个数据文件(内含 version/date),按版本比对后更新;失败用本地副本。
|
||||||
|
nodes 按内容比对(独立地址)。
|
||||||
"""
|
"""
|
||||||
base = (base_url or str(_config_val("pac_base_url", "") or "")).strip().rstrip("/")
|
base = (base_url or str(_config_val("pac_base_url", "") or "")).strip().rstrip("/")
|
||||||
if not base:
|
if not base:
|
||||||
log("未配置 PAC 更新源(config.json 的 pac_base_url),使用本地数据")
|
log("未配置 PAC 更新源(config.json 的 pac_base_url),使用本地数据")
|
||||||
else:
|
else:
|
||||||
try:
|
import json
|
||||||
manifest = _pac_fetch_json(f"{base}/pac_manifest.json")
|
updated = failed = 0
|
||||||
except Exception as e:
|
for name in _PAC_FILES:
|
||||||
log(f"PAC 更新源不可达,使用本地数据 ({e})")
|
try:
|
||||||
manifest = None
|
data = _pac_fetch_json(f"{base}/{name}.json")
|
||||||
if manifest is not None:
|
if not _pac_validate(name, data):
|
||||||
updated = 0
|
raise ValueError(f"{name}.json 数据格式不正确")
|
||||||
for name in _PAC_FILES:
|
rver = str(data.get("version") or "")
|
||||||
remote = manifest.get(name) or {}
|
rdate = str(data.get("date") or "")
|
||||||
rver = str(remote.get("version") or "")
|
|
||||||
rdate = str(remote.get("date") or "")
|
|
||||||
# 版本只与 ~/RRPP 本地文件比对(回退文件仅用于读取,不参与更新判定)
|
# 版本只与 ~/RRPP 本地文件比对(回退文件仅用于读取,不参与更新判定)
|
||||||
local = _USER_DIR / f"{name}.json"
|
local = _USER_DIR / f"{name}.json"
|
||||||
lver = _pac_read_version(local)[0] if local.is_file() else ""
|
lver = _pac_read_version(local)[0] if local.is_file() else ""
|
||||||
if rver and rver > lver:
|
if rver:
|
||||||
try:
|
if rver > lver:
|
||||||
ver, date = _pac_download(base, name)
|
_pac_write(name, data)
|
||||||
log(f"PAC 数据已更新: {name}.json {ver or rver} ({date or rdate})")
|
log(f"PAC 数据已更新: {name}.json {rver} ({rdate})")
|
||||||
updated += 1
|
updated += 1
|
||||||
except Exception as e:
|
# 否则已是最新,跳过
|
||||||
log(f"PAC 数据 {name}.json 更新失败,使用本地副本: {e}")
|
else:
|
||||||
if updated == 0 and (_USER_DIR / "pac_domains.json").is_file():
|
# 远端缺版本号:本地没有 -> 兜底下载;本地有 -> 按内容比对
|
||||||
log("PAC 数据已是最新")
|
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,按内容比对,仅变化时原子覆盖
|
# 节点配置在线更新:地址独立于 PAC,按内容比对,仅变化时原子覆盖
|
||||||
nurl = (nodes_url or str(_config_val("nodes_url", "") or "")).strip()
|
nurl = (nodes_url or str(_config_val("nodes_url", "") or "")).strip()
|
||||||
if not nurl:
|
if not nurl:
|
||||||
|
|||||||
Reference in New Issue
Block a user