From db77b57f74577d30ea23c8b6ab31a18eea609600 Mon Sep 17 00:00:00 2001 From: Burer Date: Sat, 4 Oct 2025 17:13:08 +0300 Subject: [PATCH] feat/flask: reworked downloads page - new table styles - info about last version and build date - "viruses" warning paragraph --- app.py | 93 +++++++++++++++++++++++-------- locales/de.ini | 7 +++ locales/en.ini | 7 +++ locales/es.ini | 7 +++ locales/fr.ini | 7 +++ locales/it.ini | 7 +++ locales/nl.ini | 7 +++ locales/ru.ini | 9 ++- static/img/icons/i_info.png | Bin 0 -> 612 bytes static/img/icons/i_kolibrios.png | Bin 0 -> 1493 bytes static/img/icons/i_warn.png | Bin 0 -> 542 bytes static/style.scss | 72 ++++++++++++++---------- templates/download.html | 72 ++++++++++++++++++------ 13 files changed, 217 insertions(+), 71 deletions(-) create mode 100644 static/img/icons/i_info.png create mode 100644 static/img/icons/i_kolibrios.png create mode 100644 static/img/icons/i_warn.png diff --git a/app.py b/app.py index 69df2ab..e924377 100644 --- a/app.py +++ b/app.py @@ -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"(]*>.*?)", 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 diff --git a/locales/de.ini b/locales/de.ini index abf854a..aafe58b 100644 --- a/locales/de.ini +++ b/locales/de.ini @@ -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 diff --git a/locales/en.ini b/locales/en.ini index d133bc0..2631137 100644 --- a/locales/en.ini +++ b/locales/en.ini @@ -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 diff --git a/locales/es.ini b/locales/es.ini index fee15c4..443432b 100644 --- a/locales/es.ini +++ b/locales/es.ini @@ -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 diff --git a/locales/fr.ini b/locales/fr.ini index ecebc0e..349d29a 100644 --- a/locales/fr.ini +++ b/locales/fr.ini @@ -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 l’image {kolibrios} comme une menace. + Il s’agit d’un faux positif. + {kolibrios} est entièrement open source et vous pouvez toujours le compiler vous-même pour vous assurer qu’il est totalement sûr. + [screenshots] header = Captures d`écran diff --git a/locales/it.ini b/locales/it.ini index 987fc06..e150505 100644 --- a/locales/it.ini +++ b/locales/it.ini @@ -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 l’immagine 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 diff --git a/locales/nl.ini b/locales/nl.ini index df26340..e953fc9 100644 --- a/locales/nl.ini +++ b/locales/nl.ini @@ -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 antivirusprogramma’s 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 diff --git a/locales/ru.ini b/locales/ru.ini index ecf86ee..c22f8b6 100644 --- a/locales/ru.ini +++ b/locales/ru.ini @@ -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 = Скриншоты diff --git a/static/img/icons/i_info.png b/static/img/icons/i_info.png new file mode 100644 index 0000000000000000000000000000000000000000..e18f150eaf87852ac0bdc9ec8aa5c6069283bb0b GIT binary patch literal 612 zcmV-q0-ODbP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf6951U69E94oEQKA0r^QpK~y+TjZ;l) z6hRQJ>itM!1U)Drm+T_qK@bHAdf(iVUtkXF7~I7}ZeI1E9zDBeFdq_LNsy9q0pt)K*YZ5afL{lszj%c5%?)A%P z?`v?$F%%$LzIfiH>0=_f!^D+f_Ru&93olox@*r-1It*qq;Y(3x>ay#n+nTYdai2M+ z8~xFrr?FV%rUvW?OJq6OhHrS5G4Pr7vF0&MW_GQ;``+Ic5OwNTouMse?pLKU4JMv} z^wTFAX`=Y}c3gjo6^^ueulvq8n$vP7du$)UX3#KD)BW?mWgY~AXfI+db)mI%;Y^vV zX)qHSwwby7!CI?(KWvA*5DDfi>^8^k_zv#AmyfO(!?%!GX&t1-&92|w^Ha+M0AK=zK_tXn4dx75GibY> yeTdA#Ivn5_P?$B;U?(-4(QPygHG78~M85%DSK|nHr|mib0000Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf6951U69E94oEQKA1!_q|K~z{r&6f*I zQ&$+r|1AXz6e3Wt0s+B-3ch&;Uvc=_Aoz$*bS|Qc*?1VDVq%=mIj7m8PB+HfmO0s6 z7RJotoEjAkOGHPeg3*B>OrBzS2nvOk+Iq+L^)a!?Lz-p3n#kBQ_rqO@7TslM8*R+e9X=p&iVNT6>ZH5;|fuM)4cyFgw6mE2RqT<3I z5Z#klBJgY)Nc^&V9yT{La-+U!s$aw#v(AWa+z*7DDM81eMr_=hD`OS;U19B{zj^$DmAb>>Ha~a3Z&u2b?^d`ACu2u+=&e z4iVEJ1nT*mQbpq4`{P-BQ{k_OpM9L?d=(|w>An@oUyknAgv4}2Y?KS!{FTT#SBQj& zNj*zPo2YKr2|pF&A)*)$KgHU&;7{zz%kgzxb?jCZC4G4f;;9Q7|^1#>W%LTIuDm21?5ZD>!qDJ)) zc?aG`%BBb&7ke*)Rx}04Damk*I*(7*Z{cf+_*NZSoK*V18cJKk#_KPi_Y^H z%fE+iy#_whr|@~hi4ty953tLEzrq9aGrmIlp5O39t>W~MDcRH8SUo!s>+G*1TD*Xp zSv;|#2}^R1_A5^GnxuCi8BkZq74qu|n@h0R!MzzppRBu)hxk{-)xDE~AQ4z+5Yr#<3O z$46G;FN>7{g0^RZ((uiud`<%yAr3w2z$tYahn?DR>C-^=v24-VD@{0cQiG0N;qYD_ z%HtFT>BTsUFcsc#R!{V4fS^>+4!QDTEx(eRzdeY>`AXzQ(^h27Ua8h}HZ)#nfFKiD zMIP9bC&2$vI$B~E_6qy6tKWBXP~V=Hpf1xsP%$Kdka{LTYO2u!PO@dWczEJ1UauA+dE(g05Tum1@{x+p)>tA??OBAxDh0xK&VxtuMLep1fQ-EfSoLr}z8Gh_ zKO)b=296%d6ph_|iN)nDr=dSm0p;?Q2(s71_2W=Dxyjg+`nD6_WJ@dsMQLc99>pt9 vRQn@GR>Rd!X&_{ix{#EVWYYrt9{~IVGy!egRt&B_00000NkvXXu0mjfSk>2` literal 0 HcmV?d00001 diff --git a/static/img/icons/i_warn.png b/static/img/icons/i_warn.png new file mode 100644 index 0000000000000000000000000000000000000000..4ae4cfe0800e4736f3a901d459ed4ee9fe408109 GIT binary patch literal 542 zcmV+(0^$9MP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf6951U69E94oEQKA0kcU&K~y+TjZ;l8 zLqQZhGgKlXEQpANZZ(8NELdXK{sLA?S{8P;EOcut(nix2zd-Ej4>S@YtQ#8}5>^#$ z-#Bw;`r1AsJj}<(Fz(E76Det7iix_KPu)7vl2u|1#+?tHZ%h% zwT}nOM_~$BWa4Y7rh#Q!iK`$$j{lRCu3%PmYQ?Ki8Qinx6t`1|$yK3E38P%o%$omo zvci%`2PBEVj%~I^joo$)yL2u+AfT^}39zQohq#bUJj>b(>Y;Bue1$(@a3>PQ5LpWa zrFn8ylvw*|T3}BOt$4MKCZF7)sxgQ%^VNBuO;3i1zCwrqTa2-TRn}@7AEZi@J$7|o z9R2|lE-)~|ZPAXl8>Aw}Swn?eO=FUVN6SYc!Qdb%j*;RZW$_k%3p6H3-mtU@u6eFk zY}S()YnYQODrBj>(w1azof!H g@5MIT_p1ZI54n?%HS3n#tpET307*qoM6N<$f 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; } } diff --git a/templates/download.html b/templates/download.html index 08cd1a0..a82a921 100644 --- a/templates/download.html +++ b/templates/download.html @@ -11,7 +11,28 @@

{{ _('downloads:header') }}

+ + + + + + + + + + + + + + + {% for ext, alt in ( ('img', 'floppy'), ('iso', 'cd'), @@ -28,9 +49,6 @@ BETA {% endif %} - {% endfor %} + - + +

+ kolibrios + + {{ _('downloads:version') }} {{ autobuild_vers }} + + {{ _('downloads:date') }} {{ autobuild_date }} +

- {{ autobuild_date }} - {% for l, lang in ( ('en_US', 'English'), @@ -38,27 +56,42 @@ ('es_ES', 'Español') ) %} {{ lang }} + title="ver. $autobuild_cmtid_{{ l }}, $autobuild_size_{{ l }}_{{ ext }}" + class="button"> + {{ lang }} + {% if l == 'en_US' %} + {{ lang }} + {% elif l == 'ru_RU' %} + {{ lang }} + {% elif l == 'es_ES' %} + {{ lang }} + {% endif %} {% endfor %}
-
-

+ +
- {{ _('downloads:download_choice') }} + onclick="alert('{{ _('downloads:download_help') }}');"> + Info + {{ _('downloads:download_choice') }}
-
- {{ _('downloads:prev_rev') }} - {{ _('downloads:all_rev') }} + + {{ _('downloads:prev_rev') }} + + + {{ _('downloads:all_rev') }} +
@@ -66,12 +99,17 @@

{{ _( 'downloads:download_description', - kolibrios="{0}" - .format(_('title:index')), + kolibrios="{0}".format(_('title:index')), zip="7zip", gpl="GPLv2", - git="{0}" - .format(_('downloads:git-server')) + git="{0}".format(_('downloads:git-server')) + ) | safe }} +

+ +

+ Warn{{ _( + 'downloads:download_warn', + kolibrios="{0}".format(_('title:index')) ) | safe }}

@@ -96,4 +134,4 @@ {% include 'tmpl/_footer.htm' %} - \ No newline at end of file +