Initial commit: rdgen with GitHub/Gitea dual build backend

This commit is contained in:
naeeo
2026-09-29 19:56:02 +08:00
commit a3686a49d4
103 changed files with 20007 additions and 0 deletions
+85
View File
@@ -0,0 +1,85 @@
"""
RustDesk 可选版本列表。
优先从 GitHub 官方仓库 rustdesk/rustdesk 的 tags 动态获取(跟随官方发版自动更新),
进程内缓存 6 小时;网络失败时回退内置版本列表,且失败结果短缓存 10 分钟,
避免每次打开页面都等待 GitHub 超时。所有请求经由 ghnet,自动使用代理配置。
"""
import re
import time
from . import ghnet
TAGS_URL = 'https://api.github.com/repos/rustdesk/rustdesk/tags?per_page=100'
# 离线兜底(截至本版本发布时的近期正式版)
FALLBACK_VERSIONS = [
'1.4.9', '1.4.8', '1.4.7', '1.4.6', '1.4.5',
'1.4.4', '1.4.3', '1.4.2', '1.4.1', '1.4.0',
]
# 形如 1.4.9 / 1.4.10 / 1.5.0-rc.1 的正式 tag
TAG_RE = re.compile(r'^\d+\.\d+\.\d+(?:[.-][0-9A-Za-z.]+)?$')
# 表单/API 对用户提交版本号的宽松校验,兼容动态列表刷新窗口期
VERSION_RE = re.compile(r'^(?:master|main|\d+\.\d+\.\d+(?:[.-][0-9A-Za-z.]+)?)$')
MAX_VERSIONS = 20
CACHE_TTL = 6 * 3600 # 成功结果缓存 6 小时
FALLBACK_TTL = 10 * 60 # 失败回退缓存 10 分钟
_memo = {
'ts': 0.0,
'ttl': CACHE_TTL,
'versions': FALLBACK_VERSIONS,
'source': 'builtin',
}
def _sort_versions(versions):
"""按版本号数字段降序排列,预发布标识排在同正式版之后。"""
def key(v):
main, _, suffix = v.partition('-')
parts = [int(x) if x.isdigit() else 0 for x in main.split('.')]
parts += [0] * (3 - len(parts))
# 无后缀(正式版)排在 rc/beta 之前
return (parts, 1 if not suffix else 0, suffix)
return sorted(versions, key=key, reverse=True)
def _fetch_from_github():
resp = ghnet.get(TAGS_URL, timeout=8)
resp.raise_for_status()
tags = [item['name'].lstrip('v') for item in resp.json() if item.get('name')]
versions = _sort_versions({t for t in tags if TAG_RE.match(t)})
return versions[:MAX_VERSIONS]
def get_versions(force=False):
"""返回 (版本号列表, 来源 source, 缓存时间戳);source: github / builtin。"""
now = time.time()
if not force and now - _memo['ts'] < _memo['ttl']:
return _memo['versions'], _memo['source'], _memo['ts']
try:
versions = _fetch_from_github()
if versions:
_memo.update(ts=now, ttl=CACHE_TTL, versions=versions, source='github')
else:
_memo.update(ts=now, ttl=FALLBACK_TTL, versions=FALLBACK_VERSIONS, source='builtin')
except Exception:
_memo.update(ts=now, ttl=FALLBACK_TTL, versions=FALLBACK_VERSIONS, source='builtin')
return _memo['versions'], _memo['source'], _memo['ts']
def version_choices():
"""供 ChoiceField 使用的 (value, label) 列表。"""
versions, source, _ = get_versions()
label_suffix = '' if source == 'github' else '(内置列表,获取官方列表失败)'
choices = [('master', '开发版(nightly 每夜构建)')]
choices += [(v, v) for v in versions]
return choices
def is_valid_version(value):
"""API / 表单提交的版本号合法性校验。"""
return bool(value) and bool(VERSION_RE.match(str(value)))