mirror of
https://github.com/Flowseal/tg-ws-proxy.git
synced 2026-05-25 00:41:43 +03:00
Общий UI трея в ui/, тултипы, исправление tg:// с реальным host, доработки windows.py (импорты, lock, IPv6, остановка прокси) (#417)
This commit is contained in:
102
utils/update_check.py
Normal file
102
utils/update_check.py
Normal file
@@ -0,0 +1,102 @@
|
||||
"""
|
||||
Минимальная проверка новой версии через GitHub Releases API (без сторонних зависимостей).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from itertools import zip_longest
|
||||
from typing import Any, Dict, Optional
|
||||
from urllib.error import HTTPError, URLError
|
||||
from urllib.request import Request, urlopen
|
||||
|
||||
REPO = "Flowseal/tg-ws-proxy"
|
||||
RELEASES_LATEST_API = f"https://api.github.com/repos/{REPO}/releases/latest"
|
||||
RELEASES_PAGE_URL = f"https://github.com/{REPO}/releases/latest"
|
||||
|
||||
_state: Dict[str, Any] = {
|
||||
"checked": False,
|
||||
"has_update": False,
|
||||
"ahead_of_release": False,
|
||||
"latest": None,
|
||||
"html_url": None,
|
||||
"error": None,
|
||||
}
|
||||
|
||||
|
||||
def _parse_version_tuple(s: str) -> tuple:
|
||||
s = (s or "").strip().lstrip("vV")
|
||||
if not s:
|
||||
return (0,)
|
||||
parts = []
|
||||
for seg in s.split("."):
|
||||
digits = "".join(c for c in seg if c.isdigit())
|
||||
if digits:
|
||||
try:
|
||||
parts.append(int(digits))
|
||||
except ValueError:
|
||||
parts.append(0)
|
||||
else:
|
||||
parts.append(0)
|
||||
return tuple(parts) if parts else (0,)
|
||||
|
||||
|
||||
def _version_gt(a: str, b: str) -> bool:
|
||||
"""True, если версия a новее b (простое сравнение по сегментам)."""
|
||||
ta = _parse_version_tuple(a)
|
||||
tb = _parse_version_tuple(b)
|
||||
for x, y in zip_longest(ta, tb, fillvalue=0):
|
||||
if x > y:
|
||||
return True
|
||||
if x < y:
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
def fetch_latest_release(timeout: float = 12.0) -> Optional[dict]:
|
||||
req = Request(
|
||||
RELEASES_LATEST_API,
|
||||
headers={
|
||||
"Accept": "application/vnd.github+json",
|
||||
"User-Agent": "tg-ws-proxy-update-check",
|
||||
},
|
||||
method="GET",
|
||||
)
|
||||
with urlopen(req, timeout=timeout) as resp:
|
||||
raw = resp.read().decode("utf-8", errors="replace")
|
||||
return json.loads(raw)
|
||||
|
||||
|
||||
def run_check(current_version: str) -> None:
|
||||
"""Запрашивает последний релиз и обновляет внутреннее состояние."""
|
||||
global _state
|
||||
_state["checked"] = True
|
||||
_state["error"] = None
|
||||
try:
|
||||
data = fetch_latest_release()
|
||||
tag = (data.get("tag_name") or "").strip()
|
||||
html_url = (data.get("html_url") or "").strip() or RELEASES_PAGE_URL
|
||||
if not tag:
|
||||
_state["has_update"] = False
|
||||
_state["ahead_of_release"] = False
|
||||
_state["latest"] = None
|
||||
_state["html_url"] = html_url
|
||||
return
|
||||
latest_clean = tag.lstrip("vV")
|
||||
cur = (current_version or "").strip().lstrip("vV")
|
||||
_state["latest"] = latest_clean
|
||||
_state["html_url"] = html_url
|
||||
_state["has_update"] = _version_gt(latest_clean, cur)
|
||||
_state["ahead_of_release"] = bool(latest_clean) and _version_gt(
|
||||
cur, latest_clean
|
||||
)
|
||||
except (HTTPError, URLError, OSError, TimeoutError, ValueError, json.JSONDecodeError) as e:
|
||||
_state["error"] = str(e)
|
||||
_state["has_update"] = False
|
||||
_state["ahead_of_release"] = False
|
||||
_state["latest"] = None
|
||||
_state["html_url"] = RELEASES_PAGE_URL
|
||||
|
||||
|
||||
def get_status() -> Dict[str, Any]:
|
||||
"""Снимок состояния после run_check (для подписей в настройках)."""
|
||||
return dict(_state)
|
||||
Reference in New Issue
Block a user