← pagan-web

Commit e2f4bcb

0
plików
+0
dodanych
-0
usuniętych
@@ -55,6 +55,91 @@ def status_live():
55 55 return jsonify(_live_build_data())
56 56
57 57
58 +def _welcome_vkey(v):
59 + """Klucz sortowania wersji: 0.9.0 < 0.10.0 < 1.0.0 (a nie alfabetycznie)."""
60 + import re as _re
61 + out = []
62 + for part in _re.split(r"[^0-9A-Za-z]+", str(v or "")):
63 + if not part:
64 + continue
65 + out.append((0, int(part)) if part.isdigit() else (1, part))
66 + return out
67 +
68 +
69 +@main_bp.route("/api/welcome.json")
70 +def welcome_json():
71 + """Dane dla okna powitalnego Pagan Linux (klient: /usr/bin/pagan-welcome).
72 +
73 + Kontrakt jest STABILNY, bo czytają go systemy wypalone w ISO (mogą być offline
74 + i nie da się ich szybko poprawić razem ze stroną):
75 + {
76 + "schema": 1,
77 + "version": "1.0.0", # najnowsze wydane ISO (z iso_files)
78 + "iso": [{"version","link","sha256","size","date"}],
79 + "news": [{"version","title","body"}], # z iso_files.changes
80 + "announcement": "…" # z content: welcome_announcement (per język)
81 + }
82 + Klient MUSI działać także wtedy, gdy pola braknie – dlatego wszystko jest
83 + opcjonalne, a zmiany rozszerzające podnoszą tylko numer "schema".
84 + """
85 + from database import get_db
86 + from datetime import datetime, timezone
87 + req_lang = (request.args.get("lang") or "pl")[:5]
88 +
89 + rows = []
90 + announcement = ""
91 + db = get_db()
92 + try:
93 + try:
94 + rows = [dict(r) for r in db.execute(
95 + "SELECT version, filename, size, sha256, description, changes, created_at "
96 + "FROM iso_files").fetchall()]
97 + except Exception:
98 + rows = []
99 + try:
100 + row = db.execute("SELECT value FROM content WHERE key=? AND lang=?",
101 + ("welcome_announcement", req_lang)).fetchone()
102 + if not row:
103 + row = db.execute("SELECT value FROM content WHERE key=? ORDER BY id LIMIT 1",
104 + ("welcome_announcement",)).fetchone()
105 + announcement = (dict(row).get("value") or "") if row else ""
106 + except Exception:
107 + announcement = ""
108 + finally:
109 + try:
110 + db.close()
111 + except Exception:
112 + pass
113 +
114 + rows.sort(key=lambda d: _welcome_vkey(d.get("version")), reverse=True)
115 +
116 + isos, news = [], []
117 + for d in rows:
118 + v = d.get("version") or ""
119 + if not v:
120 + continue
121 + if len(isos) < 10:
122 + isos.append({
123 + "version": v,
124 + "link": f"/download/iso/{v}",
125 + "sha256": d.get("sha256") or "",
126 + "size": d.get("size") or 0,
127 + "date": (d.get("created_at") or "")[:10],
128 + })
129 + changes = (d.get("changes") or "").strip()
130 + if changes and len(news) < 3:
131 + news.append({"version": v, "title": f"Pagan Linux {v}", "body": changes})
132 +
133 + return jsonify({
134 + "schema": 1,
135 + "generated": datetime.now(timezone.utc).isoformat(timespec="seconds"),
136 + "version": isos[0]["version"] if isos else "",
137 + "iso": isos[:5],
138 + "news": news,
139 + "announcement": announcement,
140 + })
141 +
142 +
58 143 def _server_status_payload():
59 144 """Kondycja serwera: metryki hosta, usługi i dostępność podstron.
60 145 Wszystko lokalnie – bez zewnętrznych serwisów (otwarte i darmowe)."""