docs: свежие скриншоты дашборда — находки с дедупом, вкладка free-API панелей (131/175), реестр 3815; tools/shots.py с проверкой на секреты в кадре
Some checks failed
ci / test (3.10) (push) Has been cancelled
ci / test (3.11) (push) Has been cancelled
ci / test (3.12) (push) Has been cancelled

This commit is contained in:
Vlad Gothbreach
2026-10-27 13:53:54 +03:00
parent 3b237af1f0
commit 81382e91b9
7 changed files with 64 additions and 2 deletions

View File

@@ -58,7 +58,7 @@ python -m omni serve --port 8077
## Скриншоты панели
Снято с живого инстанса (`python -m omni serve --port 8077`), база на момент съёмки: **46 423 записи · 3 815 источников · 6 746 находок**. Пересъёмка одной командой: `python tools/shots_ui.py` (нужен playwright, ждёт исчезновения скелетонов и только потом стреляет).
Снято с живого инстанса (`python -m omni serve --port 8077`), база на момент съёмки: **46 423 записи · 3 815 источников · 6 746 находок**. Пересъёмка одной командой: `python tools/shots.py` (нужен playwright, ждёт исчезновения скелетонов и только потом стреляет).
### Лента
@@ -68,10 +68,16 @@ python -m omni serve --port 8077
### Находки
Промо, триалы, сливы и панели с бесплатными API: 6 746 находок, 1 368 уникальных, фильтр по тегам (`ключи / промо / триалы / сливы / кредиты / инвайты / lifetime deal`).
Промо, триалы, сливы и панели с бесплатными API: 6 746 находок, 5 182 уникальных — перепечатки одного поста из разных каналов схлопнуты по подписи, в карточке видно сколько копий склеено. Фильтр по тегам (`ключи / промо / триалы / сливы / кредиты / инвайты / lifetime deal`).
![Находки — промо, триалы и бесплатные API-панели](docs/screenshots/abuse.png)
### Бесплатные API-панели
Отдельная вкладка в «Находках»: new-api шлюзы, у которых открыт бесплатный доступ к моделям. 175 панелей в реестре, 131 с бесплатными моделями, проверка идёт через публичный `/api/pricing` — учётные данные не запрашиваются.
![Бесплатные API-панели — 131 из 175 панелей отдают модели без оплаты](docs/screenshots/panels.png)
### Источники
Реестр на 3 815 источников: тумблер вкл/выкл, результат проверки, число записей в базе, дата последней проверки, добавление своего фида и health-аудит по категории.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 533 KiB

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 389 KiB

After

Width:  |  Height:  |  Size: 199 KiB

BIN
docs/screenshots/panels.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 286 KiB

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 KiB

After

Width:  |  Height:  |  Size: 216 KiB

56
tools/shots.py Normal file
View File

@@ -0,0 +1,56 @@
"""Пересъёмка скриншотов дашборда для README.
Запуск: python tools/shots.py
Пишет docs/screenshots/*.png с живого http://127.0.0.1:8078.
Перед сохранением проверяет кадр на токеноподобные строки —
скриншот с секретом в реестр не попадёт.
"""
import re
import sys
from camoufox.sync_api import Camoufox
BASE = "http://127.0.0.1:8078"
SHOTS = [
("/#/", "overview.png"),
("/#/feed", "feed.png"),
("/#/abuse", "abuse.png"),
("/#/abuse?tab=panels", "panels.png"),
("/#/sources", "sources.png"),
("/#/tg", "tg.png"),
("/#/watch", "watch.png"),
("/#/digest", "digest.png"),
("/#/runs", "runs.png"),
]
SECRET = re.compile(r"\b(sk-|pk-|ek_live_|ghp_|xoxb-)[A-Za-z0-9_\-]{12,}")
def main():
bad = []
with Camoufox(headless=True, geoip=False, humanize=True) as b:
for route, name in SHOTS:
p = b.new_page(viewport={"width": 1500, "height": 1350})
p.goto(BASE + route, wait_until="domcontentloaded", timeout=90000)
n = 0
for _ in range(12):
p.wait_for_timeout(2500)
n = p.evaluate("document.querySelectorAll('.item,tbody tr').length")
head = p.evaluate("document.body.innerText.slice(0,400)")
if n > 3 and "Загрузка" not in head:
break
txt = p.evaluate("document.body.innerText")
if SECRET.search(txt):
bad.append(name)
print("SKIP (секрет в кадре):", name)
p.close()
continue
p.screenshot(path="docs/screenshots/" + name)
print("%-12s %-22s items/rows %s" % (name, route, n))
p.close()
if bad:
print("не сняты из-за секретов:", bad)
return 1
return 0
if __name__ == "__main__":
sys.exit(main())