重构:模块化 RRPP Lite 并更新入口
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
"""PAC 数据文件的网络传输与安全落盘。"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def read_version(path):
|
||||
"""读取 PAC JSON 的 version/date;无效文件返回空字符串。"""
|
||||
try:
|
||||
data = json.loads(Path(path).read_text("utf-8"))
|
||||
return str(data.get("version") or ""), str(data.get("date") or "")
|
||||
except Exception:
|
||||
return "", ""
|
||||
|
||||
|
||||
def no_proxy_opener():
|
||||
"""创建忽略环境/系统代理的直连 HTTP opener。"""
|
||||
return urllib.request.build_opener(urllib.request.ProxyHandler({}))
|
||||
|
||||
|
||||
def fetch_json(url, timeout=15, tries=2):
|
||||
"""以直连方式拉取 JSON;最后一次失败时保留原始异常。"""
|
||||
opener = no_proxy_opener()
|
||||
for attempt in range(tries):
|
||||
try:
|
||||
with opener.open(url, timeout=timeout) as response:
|
||||
return json.loads(response.read().decode("utf-8"))
|
||||
except Exception:
|
||||
if attempt == tries - 1:
|
||||
raise
|
||||
|
||||
|
||||
def validate_document(name, data):
|
||||
"""校验各 PAC 文件的最小结构,避免错误响应覆盖有效缓存。"""
|
||||
if not isinstance(data, dict):
|
||||
return False
|
||||
if name in ("pac_domains", "pac_direct_domains"):
|
||||
return isinstance(data.get("domains"), list)
|
||||
if name == "pac_ip_cn":
|
||||
return isinstance(data.get("cidrs"), list)
|
||||
return False
|
||||
|
||||
|
||||
def atomic_write(directory, name, data):
|
||||
"""将 PAC JSON 以 tmp + replace 原子写入指定用户目录。"""
|
||||
directory = Path(directory)
|
||||
directory.mkdir(parents=True, exist_ok=True)
|
||||
target = directory / f"{name}.json"
|
||||
temporary_path = directory / f"{name}.json.tmp"
|
||||
temporary_path.write_text(json.dumps(data, ensure_ascii=False), "utf-8")
|
||||
os.replace(temporary_path, target)
|
||||
Reference in New Issue
Block a user