auto update from Flowseal/tg-ws-proxy
This commit is contained in:
parent
99fcdfee0c
commit
01396dae78
27
macos.py
27
macos.py
|
|
@ -21,6 +21,7 @@ import rumps
|
|||
# ── proxy core is a sibling package ────────────────────────────────────────
|
||||
sys.path.insert(0, str(Path(__file__).parent))
|
||||
import proxy.tg_ws_proxy as tg_ws_proxy
|
||||
import updater
|
||||
|
||||
# ── paths ───────────────────────────────────────────────────────────────────
|
||||
APP_NAME = "TgWsProxy"
|
||||
|
|
@ -363,7 +364,31 @@ def main():
|
|||
log.info("Config: %s", _config)
|
||||
log.info("Log file: %s", LOG_FILE)
|
||||
|
||||
start_proxy(_config)
|
||||
# ── Auto-update proxy core at startup ────────────────────────────────
|
||||
def _do_update():
|
||||
updated = updater.check_and_update()
|
||||
if updated:
|
||||
log.info("Proxy core updated — reloading and restarting proxy")
|
||||
import importlib
|
||||
global tg_ws_proxy
|
||||
try:
|
||||
import proxy.tg_ws_proxy as _fresh
|
||||
importlib.reload(_fresh)
|
||||
tg_ws_proxy = _fresh
|
||||
except Exception as exc:
|
||||
log.error("Failed to reload proxy core after update: %s", exc)
|
||||
restart_proxy()
|
||||
rumps.notification(
|
||||
APP_NAME,
|
||||
"Обновление установлено",
|
||||
"Proxy core обновлён и перезапущен.",
|
||||
sound=False,
|
||||
)
|
||||
else:
|
||||
start_proxy(_config)
|
||||
|
||||
threading.Thread(target=_do_update, daemon=True).start()
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
if not FIRST_RUN_MARKER.exists():
|
||||
threading.Thread(target=show_first_run, daemon=True).start()
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ a = Analysis(
|
|||
datas=[],
|
||||
hiddenimports=[
|
||||
'proxy.tg_ws_proxy',
|
||||
'updater',
|
||||
'cryptography',
|
||||
'cryptography.hazmat.primitives.ciphers',
|
||||
'cryptography.hazmat.primitives.ciphers.algorithms',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
"""
|
||||
updater.py — автообновление proxy/tg_ws_proxy.py с GitHub main ветки.
|
||||
|
||||
Логика:
|
||||
1. Скачивает актуальный файл с GitHub raw
|
||||
2. Сравнивает SHA-256 с локальной копией
|
||||
3. Если отличается — сохраняет новую версию, возвращает True
|
||||
4. Вся работа синхронная (вызывается из фонового потока)
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import logging
|
||||
import shutil
|
||||
import sys
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
log = logging.getLogger("tg-ws-updater")
|
||||
|
||||
RAW_URL = (
|
||||
"https://raw.githubusercontent.com/"
|
||||
"Flowseal/tg-ws-proxy/main/proxy/tg_ws_proxy.py"
|
||||
)
|
||||
|
||||
# Локальный путь к файлу ядра (рядом с этим скриптом)
|
||||
_HERE = Path(__file__).parent
|
||||
PROXY_CORE = _HERE / "proxy" / "tg_ws_proxy.py"
|
||||
|
||||
TIMEOUT = 15 # секунд на скачивание
|
||||
|
||||
|
||||
def _sha256(path: Path) -> Optional[str]:
|
||||
"""SHA-256 файла или None если файл не существует."""
|
||||
if not path.exists():
|
||||
return None
|
||||
h = hashlib.sha256()
|
||||
with open(path, "rb") as fh:
|
||||
for chunk in iter(lambda: fh.read(65536), b""):
|
||||
h.update(chunk)
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def _fetch(url: str) -> bytes:
|
||||
"""Скачать URL, вернуть содержимое как bytes."""
|
||||
req = urllib.request.Request(
|
||||
url,
|
||||
headers={"User-Agent": "tg-ws-proxy-macos-updater/1.0"},
|
||||
)
|
||||
with urllib.request.urlopen(req, timeout=TIMEOUT) as resp:
|
||||
return resp.read()
|
||||
|
||||
|
||||
def check_and_update() -> bool:
|
||||
"""
|
||||
Проверить обновление proxy core.
|
||||
|
||||
Возвращает True если файл был обновлён, False если уже актуален
|
||||
или произошла ошибка (ошибки логируются, не бросаются).
|
||||
"""
|
||||
log.info("Checking for proxy core update: %s", RAW_URL)
|
||||
try:
|
||||
new_content = _fetch(RAW_URL)
|
||||
except Exception as exc:
|
||||
log.warning("Update check failed (network): %s", exc)
|
||||
return False
|
||||
|
||||
new_hash = hashlib.sha256(new_content).hexdigest()
|
||||
old_hash = _sha256(PROXY_CORE)
|
||||
|
||||
if new_hash == old_hash:
|
||||
log.info("Proxy core is up to date (sha256: %s…)", new_hash[:12])
|
||||
return False
|
||||
|
||||
log.info(
|
||||
"Proxy core update detected: %s… → %s…",
|
||||
(old_hash or "none")[:12],
|
||||
new_hash[:12],
|
||||
)
|
||||
|
||||
# Атомарная замена: пишем во временный файл, потом переименовываем
|
||||
tmp = PROXY_CORE.with_suffix(".py.tmp")
|
||||
try:
|
||||
PROXY_CORE.parent.mkdir(parents=True, exist_ok=True)
|
||||
tmp.write_bytes(new_content)
|
||||
shutil.move(str(tmp), str(PROXY_CORE))
|
||||
except Exception as exc:
|
||||
log.error("Failed to write updated proxy core: %s", exc)
|
||||
tmp.unlink(missing_ok=True)
|
||||
return False
|
||||
|
||||
# Выгрузить старый модуль из sys.modules, чтобы следующий import
|
||||
# подхватил новый файл с диска
|
||||
for key in list(sys.modules.keys()):
|
||||
if "tg_ws_proxy" in key:
|
||||
del sys.modules[key]
|
||||
|
||||
log.info("Proxy core updated successfully")
|
||||
return True
|
||||
Loading…
Reference in New Issue