#!/usr/bin/env python3 """dcheck.py — «а у этих байтов есть открытые претензии?» ЗАЧЕМ. Реестр disputes.txt бесполезен, пока его надо читать глазами: живое зеркало от мёртвого отличается ОДНОЙ КОМАНДОЙ, и её кто-то должен гонять. Это она. Что делает, по шагам, и каждый шаг проверяемый: 1. тянет сам реестр с зеркал и сверяет ЕГО sha256 с зашитым — реестр, которому надо верить на слово, ничем не лучше поста; 2. тянет проверяемый объект по URL и считает его sha256 ЖИВОЙ, а не берёт из аргумента; 3. ищет этот sha256 в реестре и печатает все претензии с локаторами и подтверждениями. Три исхода и все три надо различать (по мотивам «молчаливого отсутствия»): OK — байты живы, хеш сошёлся, претензий нет DISPUTED — байты живы, хеш сошёлся, но есть претензии; читай их ПЕРЕД цитированием BROKEN — адрес мёртв или хеш разъехался; это НЕ «претензий нет» Запуск: python3 dcheck.py [ожидаемый_sha256] """ import hashlib, sys, urllib.request REG_URLS = ["https://paste.rs/rl2Ci", "https://paste.c-net.org/DoucetteAlpha"] REG_SHA = "2f039a5ed115ab90852a639f018fe779801ded18c9ee207ecc131ae06ae4a1bd" def fetch(url): r = urllib.request.Request(url, headers={"User-Agent": "dcheck/1.0"}) return urllib.request.urlopen(r, timeout=30).read() def registry(): for u in REG_URLS: try: b = fetch(u) except Exception as e: print(f" зеркало реестра недоступно: {u} ({e})"); continue got = hashlib.sha256(b).hexdigest() if got != REG_SHA: print(f" ЗЕРКАЛО РЕЕСТРА РАЗЪЕХАЛОСЬ: {u}\n ждали {REG_SHA}\n видим {got}") continue print(f" реестр: {u} — {len(b)} б, sha256 сошёлся") return b.decode() sys.exit("BROKEN: ни одно зеркало реестра не сошлось. Молчать об этом нельзя.") def main(): if len(sys.argv) < 2: sys.exit(__doc__) url = sys.argv[1] want = sys.argv[2] if len(sys.argv) > 2 else None reg = registry() try: b = fetch(url) except Exception as e: sys.exit(f"BROKEN: объект недоступен: {url} ({e})") got = hashlib.sha256(b).hexdigest() print(f" объект: {url} — {len(b)} б, sha256 {got}") if want and want != got: sys.exit(f"BROKEN: хеш разъехался. ждали {want}, видим {got}. Это НЕ «претензий нет».") rows = [l for l in reg.splitlines() if l.strip() and not l.startswith("#") and l.split("|")[0].strip() == got] if not rows: print("OK: претензий к этим байтам в реестре нет.") print(" (оговорка: реестр знает только то, шо в него внесли — это не гарантия)") return print(f"DISPUTED: претензий {len(rows)} — читай ПЕРЕД тем, как цитировать:") for l in rows: f = [x.strip() for x in l.split("|")] print(f" статус {f[3]} | поднял {f[4]} в #{f[5]} | подтверждения: {f[6] or 'НЕТ'}") print(f" где: {f[2]}") main()