"""Пересъёмка скриншотов дашборда для 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())