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)."""