feat/flask: reworked downloads page

- new table styles
- info about last version and build date
- "viruses" warning paragraph
This commit is contained in:
2025-12-27 23:07:46 +03:00
committed by Sweetbread
parent 71681f43b7
commit db77b57f74
13 changed files with 217 additions and 71 deletions
+69 -24
View File
@@ -1,30 +1,23 @@
import threading
import time
import json
import re
from os import path, listdir
from datetime import date, datetime, timezone
from datetime import date
from configparser import ConfigParser
from urllib.request import urlopen
import sass
from flask import (
Flask,
redirect,
render_template,
request,
url_for,
g,
Response
)
from flask import Flask, redirect, render_template, request, url_for, g, Response
# ---------- ENV VARS --------------------------------------------------------
GIT_URL = "https://git.kolibrios.org/api/v1/repos/KolibriOS/kolibrios/branches/main"
GIT_FETCH_DELAY_SEC = 300 # 5 minutes
STATUS_URL = "https://builds.kolibrios.org/status.html"
STATUS_FETCH_DELAY_SEC = 300 # 5 minutes
# ---------- APP CONFIG ------------------------------------------------------
@@ -41,18 +34,64 @@ if app.debug:
autobuild_date = "DD.MM.YYYY"
autobuild_vers = "0.0.0.0+0000-0000000"
def _refresh_build_date_once():
global autobuild_date
global autobuild_date, autobuild_vers
try:
with urlopen(GIT_URL, timeout=10) as r:
b = json.load(r)
c = b.get("commit", {}) or {}
ts = c.get("timestamp")
if ts:
dt = datetime.fromisoformat(ts.replace("Z", "+00:00")).astimezone(timezone.utc)
autobuild_date = dt.strftime("%d.%m.%Y")
from urllib.request import Request, urlopen
import re
req = Request(
STATUS_URL,
headers={
"User-Agent": "Mozilla/5.0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
},
)
with urlopen(req, timeout=10) as r:
html = r.read().decode(
r.headers.get_content_charset() or "utf-8", "replace"
)
rows = re.findall(r"(<tr\b[^>]*>.*?</tr>)", html, flags=re.I | re.S)
if not rows:
return
last_commit_ver = None
for row in rows:
cls = re.search(r'class\s*=\s*"([^"]*)"', row, flags=re.I)
classes = cls.group(1).lower() if cls else ""
text = re.sub(r"<[^>]+>", " ", row)
if "commit" in classes:
mver = re.search(
r"\b(\d+\.\d+\.\d+\.\d+\+\d{3,8}-[0-9a-fA-F]{7,40})\b", row
)
if mver:
last_commit_ver = mver.group(1)
elif "success" in classes:
mts = re.search(
r"\b(\d{4})\.(\d{2})\.(\d{2})\s+\d{2}:\d{2}:\d{2}\b", text
)
if not mts:
mds = re.search(r"\b(\d{2})\.(\d{2})\.(\d{4})\b", text)
if mds:
autobuild_date = f"{mds.group(1)}.{mds.group(2)}.{mds.group(3)}"
else:
return
else:
y, mo, d = mts.groups()
autobuild_date = f"{d}.{mo}.{y}"
if last_commit_ver:
autobuild_vers = last_commit_ver
return
except Exception:
pass
@@ -60,7 +99,7 @@ def _refresh_build_date_once():
def _updater_loop():
while True:
_refresh_build_date_once()
time.sleep(GIT_FETCH_DELAY_SEC)
time.sleep(STATUS_FETCH_DELAY_SEC)
_started = False
@@ -69,6 +108,7 @@ _refresh_build_date_once()
# Flask 3.x fix: start updater lazily on first request (since before_first_request is removed)
_updater_lock = threading.Lock()
@app.before_request
def _ensure_updater_started():
global _started
@@ -79,9 +119,14 @@ def _ensure_updater_started():
threading.Thread(target=_updater_loop, daemon=True).start()
@app.context_processor
def _inject_autobuild_vers():
return {'autobuild_vers': autobuild_vers}
@app.context_processor
def _inject_autobuild_date():
return {"autobuild_date": autobuild_date}
return {'autobuild_date': autobuild_date}
# ---------- LOCALES FUNCTIONS -----------------------------------------------
@@ -138,7 +183,7 @@ def render_localized_template(lang, template_name):
@app.before_request
def before_request():
if args := request.view_args:
g.locale = args.get('lang', 'en')
g.locale = args.get("lang", "en")
g.translations = translations.get(g.locale, get_best_lang())
g.locales_name = locales_name
+7
View File
@@ -49,6 +49,9 @@ p_subscription = Wir hoffen, es gefällt Ihnen!
[downloads]
header = Herunterladen
version = Version:
date = Build-Datum:
img-descr = Disketten-Image
iso-descr = LiveCD-Abbild
distr-descr = Universal Flash/Multi-Boot-Abbild
@@ -75,6 +78,10 @@ download_description = Auf dieser Seite können Sie die nächtlichen
vertrieben, und der Quellcode ist auf unserem {git} verfügbar.
git-server = Git-Server
download_warn = Gelegentlich stufen einige Antivirenprogramme das {kolibrios}-Image fälschlicherweise als Bedrohung ein.
Das ist ein Fehlalarm.
{kolibrios} ist vollständig quelloffen, und Sie können es jederzeit selbst erstellen, um sicherzugehen, dass es vollständig sicher ist.
[screenshots]
header = Bildschirmfotos
+7
View File
@@ -47,6 +47,9 @@ p_subscription = We hope you will enjoy it!
[downloads]
header = Downloads
version = Version:
date = Build date:
img-descr = Floppy disk image
iso-descr = LiveCD image
distr-descr = Universal Flash/Multi-boot image
@@ -71,6 +74,10 @@ download_description = On this page you can download the nightly builds
available on our {git}.
git-server = Git server
download_warn = Occasionally, some antivirus software may incorrectly flag the {kolibrios} image as a threat.
This is a false positive.
{kolibrios} is fully open source, and you can always build it yourself to be sure that it is completely safe.
[screenshots]
header = Screenshots
+7
View File
@@ -49,6 +49,9 @@ p_subscription = ¡Esperamos que lo disfrutes!
[downloads]
header = Descargas
version = Versión:
date = Fecha de compilación:
img-descr = Imagen de disquete
iso-descr = Imagen LiveCD
distr-descr = Imagen Flash Universal/Multi-boot
@@ -73,6 +76,10 @@ download_description = En esta página puedes descargar la distribución de
licencia {gpl} y su código fuente está disponible en nuestro {git}.
git-server = servidor Git
download_warn = Ocasionalmente, algunos programas antivirus pueden marcar incorrectamente la imagen de {kolibrios} como una amenaza.
Esto es un falso positivo.
{kolibrios} es completamente de código abierto y siempre puedes compilarlo tú mismo para asegurarte de que es totalmente seguro.
[screenshots]
header = Pantallas
+7
View File
@@ -49,6 +49,9 @@ p_subscription = Nous espérons que vous l`apprécierez !
[downloads]
header = Téléchargements
version = Version :
date = Date de compilation :
img-descr = Image de la disquette
iso-descr = Image du LiveCD
distr-descr = Image Universal Flash/Multi-boot
@@ -73,6 +76,10 @@ download_description = Sur cette page, vous pouvez télécharger la distribution
licence {gpl} et son code source est disponible sur notre {git}.
git-server = serveur Git
download_warn = Il arrive que certains antivirus signalent à tort limage {kolibrios} comme une menace.
Il sagit dun faux positif.
{kolibrios} est entièrement open source et vous pouvez toujours le compiler vous-même pour vous assurer quil est totalement sûr.
[screenshots]
header = Captures d`écran
+7
View File
@@ -48,6 +48,9 @@ p_subscription = Ci auguriamo che vi piaccia!
[downloads]
header = Scaricamento
version = Versione:
date = Data di compilazione:
img-descr = Immagine su dischetto
iso-descr = Immagine LiveCD
distr-descr = Immagine universale Flash/MultiBoot
@@ -72,6 +75,10 @@ download_description = In questa pagina puoi scaricare la distribuzione delle
suo codice sorgente è disponibile sul nostro {git}.
git-server = server Git
download_warn = Occasionalmente, alcuni software antivirus potrebbero segnalare erroneamente limmagine di {kolibrios} come una minaccia.
Si tratta di un falso positivo.
{kolibrios} è completamente open source e puoi sempre compilarlo tu stesso per essere certo che è del tutto sicuro.
[screenshots]
header = Captures d`écran
+7
View File
@@ -49,6 +49,9 @@ p_subscription = We hopen dat je ervan zult genieten!
[downloads]
header = Downloads
version = Versie:
date = Builddatum:
img-descr = Afbeelding op diskette
iso-descr = LiveCD-afbeelding
distr-descr = Universele Flash/Multi-boot image
@@ -73,6 +76,10 @@ download_description = Op deze pagina kunt u de nightly builds-distributie
broncode is beschikbaar op onze {git}.
git-server = Git-server
download_warn = Af en toe kunnen sommige antivirusprogrammas het {kolibrios}-image ten onrechte als een bedreiging aanmerken.
Dit is een vals-positief.
{kolibrios} is volledig open-source en je kunt het altijd zelf bouwen om er zeker van te zijn dat het volledig veilig is.
[screenshots]
header = Schermafbeeldingen
+8 -1
View File
@@ -24,7 +24,7 @@ p1 = {kolibrios} — это крошечная, но невероятно мощ
мегабайт места на диске, процессора i586 и 12 МБ оперативной памяти. При
этом она содержит богатый набор приложений, таких как текстовый редактор,
просмотрщик изображений, графический редактор, веб-браузер и более 30
захватывающих игр.Имеется полная поддержка файловых систем FAT12/16/32,
захватывающих игр. Имеется полная поддержка файловых систем FAT12/16/32,
только на чтение доступны NTFS, exFAT, ISO9660 и Ext2/3/4, а также
присутсвтвует обширный набор {drivers} для популярных звуковых, сетевых и
графических карт.
@@ -49,6 +49,9 @@ p_subscription = Надеемся, вам понравится!
[downloads]
header = Скачать
version = Версия:
date = Дата сборки:
img-descr = Образ дискеты
iso-descr = Образ LiveCD
distr-descr = Универсальный образ Flash/Multi-boot
@@ -73,6 +76,10 @@ download_description = На этой странице вы можете скач
исходный код доступен на нашем {git}.
git-server = Git-сервере
download_warn = Иногда антивирусы могут по ошибке помечать образ {kolibrios} как угрозу.
Это ложное срабатывание.
{kolibrios} имеет полностью открытый исходный код, и вы всегда можете собрать её самостоятельно, чтобы убедиться, что она абсолютно безопасна.
[screenshots]
header = Скриншоты
Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

+43 -29
View File
@@ -223,6 +223,13 @@ p {
&-subscription {
text-align: center;
}
&-warn {
img {
margin-bottom: -2px;
margin-right: 0.25em;
}
}
}
/* DOWNLOADS */
@@ -247,13 +254,21 @@ tr {
vertical-align: middle;
}
.tr-margin {
&-bot > td {
padding-bottom: 1em;
.tr {
&-header {
b {
display: inline;
}
}
&-top > td {
padding-top: 1em;
&-margin {
&-bot > td {
padding-bottom: 1em;
}
&-top > td {
padding-top: 1em;
}
}
}
@@ -284,18 +299,17 @@ td {
}
}
&-date {
text-align: right;
padding-right: 2em;
}
&-languages {
text-align: right;
padding-left: 2em;
a {
display: inline-block;
white-space: nowrap;
}
a + a {
display: inline;
margin-left: 1em;
margin-top: 0em;
}
}
}
@@ -307,16 +321,10 @@ hr {
.help-button {
cursor: pointer;
display: inline-block;
background: #FF9800;
border-radius: 4px;
box-shadow: inset 0 1px rgba(254,181,94,0.9), inset 0 -2px rgba(0,0,0,0.04);
color: #FFFFFF;
padding: 0.5em 1em;
text-align: center;
transition: 0.5s;
color: #609A21;
&:hover {
background: #F6920B;
img {
padding-bottom: 1px;
}
}
@@ -444,22 +452,28 @@ iframe {
margin: 0 0.5em;
}
.tr {
&-header {
b {
display: block;
}
}
}
.td {
&-description {
width: auto;
}
&-date {
display: none;
padding-right: 1em;
padding-left: 1em;
}
&-languages a {
display: block;
width: max-content;
margin-left: auto;
}
&-languages a + a {
display: inline-block;
white-space: nowrap;
margin-top: 0.5em;
margin-left: 0em;
margin-left: auto;
}
}
+55 -17
View File
@@ -11,7 +11,28 @@
<div id="article">
<h1>{{ _('downloads:header') }}</h1>
<table>
<tr class="tr-margin-bot">
<td colspan="3"><hr /></td>
</tr>
<tr class="tr-margin-bot tr-header">
<td class="td-image" width="40">
<img src="{{ url_for('static', filename='img/icons/i_kolibrios.png') }}" alt="kolibrios">
</td>
<td class="td-description">
{{ _('downloads:version') }} <b>{{ autobuild_vers }}</b>
</td>
<td class="td-languages">
{{ _('downloads:date') }} <b>{{ autobuild_date }}</b>
</td>
</tr>
<tr class="tr-margin-bot">
<td colspan="3"><hr /></td>
</tr>
{% for ext, alt in (
('img', 'floppy'),
('iso', 'cd'),
@@ -28,9 +49,6 @@
<span class="beta">BETA</span>
{% endif %}
</td>
<td class="td-date">
{{ autobuild_date }}
</td>
<td class="td-languages">
{% for l, lang in (
('en_US', 'English'),
@@ -38,27 +56,42 @@
('es_ES', 'Español')
) %}
<a href="//builds.kolibrios.org/{{ l }}/latest-{{ ext }}.7z"
title="ver. $autobuild_cmtid_{{ l }}, $autobuild_size_{{ l }}_{{ ext }}">{{ lang }}</a>
title="ver. $autobuild_cmtid_{{ l }}, $autobuild_size_{{ l }}_{{ ext }}"
class="button">
{{ lang }}
{% if l == 'en_US' %}
<img src="{{ url_for('static', filename='img/flags/en.png') }}" alt="{{ lang }}">
{% elif l == 'ru_RU' %}
<img src="{{ url_for('static', filename='img/flags/ru.png') }}" alt="{{ lang }}">
{% elif l == 'es_ES' %}
<img src="{{ url_for('static', filename='img/flags/es.png') }}" alt="{{ lang }}">
{% endif %}</a>
{% endfor %}
</td>
</tr>
{% endfor %}
<tr>
<td colspan="4">
<hr />
</td>
<td colspan="3"><hr /></td>
</tr>
</table>
<table>
<tr class="tr-margin-top">
<td class="td-description" colspan="2">
<div role="button" class="help-button"
onclick="alert('{{ _('downloads:download_help') }}');">
{{ _('downloads:download_choice') }}
onclick="alert('{{ _('downloads:download_help') }}');">
<img src="{{ url_for('static', filename='img/icons/i_info.png') }}" alt="Info">
<u>{{ _('downloads:download_choice') }}</u>
</div>
<td class="td-date">
<a href="//archive.kolibrios.org/ru/">{{ _('downloads:prev_rev') }}</a>
</td>
<td class="td-languages">
<a href="//builds.kolibrios.org/">{{ _('downloads:all_rev') }}</a>
<a href="//archive.kolibrios.org/ru/">
{{ _('downloads:prev_rev') }}
</a>
<a href="//builds.kolibrios.org/">
{{ _('downloads:all_rev') }}
</a>
</td>
</tr>
</table>
@@ -66,12 +99,17 @@
<p>
{{ _(
'downloads:download_description',
kolibrios="<b>{0}</b>"
.format(_('title:index')),
kolibrios="<b>{0}</b>".format(_('title:index')),
zip="<a href='http://www.7-zip.org' target='_blank'>7zip</a>",
gpl="<a href='http://www.gnu.org/licenses/gpl-2.0.html' target='_blank'>GPLv2</a>",
git="<a href='https://git.kolibrios.org'>{0}</a>"
.format(_('downloads:git-server'))
git="<a href='https://git.kolibrios.org'>{0}</a>".format(_('downloads:git-server'))
) | safe }}
</p>
<p class="p-warn">
<img src="{{ url_for('static', filename='img/icons/i_warn.png') }}" alt="Warn">{{ _(
'downloads:download_warn',
kolibrios="<b>{0}</b>".format(_('title:index'))
) | safe }}
</p>
@@ -96,4 +134,4 @@
{% include 'tmpl/_footer.htm' %}
</body>
</html>
</html>