Files
felhom.eu/documentation/audits/selfhst-survey-2026-10-12/fetch.py
T
admin a7f897a7dd
gates / gates (push) Successful in 6m24s
Audit: selfh.st survey 2023-2025 read against Felhom; R-989 filed
Read-only. fetch.py + tables.py (stdlib), TABLE.md (45 charts, % of
respondents), FELHOM.md (apps, features, reasons, hardware, trends, ten
ranked recommendations), METHOD.md (hashes, counts, matching, MIT licence,
limits). Survey files are not committed. One register row (R-989) and one
STATUS line ask the operator to rule on the recommendations.
2026-10-12 22:09:10 +02:00

43 lines
1.4 KiB
Python

#!/usr/bin/env python3
"""Download the selfh.st annual survey results (2023-2025) to a cache outside every repo.
Prints bytes and SHA-256 for each file. The files are not committed (spec §9.2).
"""
import hashlib
import os
import sys
import urllib.request
BASE = "https://raw.githubusercontent.com/selfhst/cdn/main/assets/surveys/annual/{}-results.json"
CACHE = os.path.expanduser("~/research-cache/selfhst-survey")
# Prefixes/suffixes of the hashes the reviewer recorded on 2026-10-12.
EXPECTED = {
2023: ("714350e5e4b8f3cc", "f03f", 10362),
2024: ("289c5161e5b6b568", "4832", 14290),
2025: ("e083094ad7f8cb67", "229e", 20428),
}
def main():
os.makedirs(CACHE, exist_ok=True)
rc = 0
for year, (pre, suf, size) in EXPECTED.items():
url = BASE.format(year)
try:
with urllib.request.urlopen(url, timeout=30) as r:
data = r.read()
except Exception as e: # continue with the years that can be read (spec §13)
print(f"{year} FETCH FAILED {url}: {e}")
rc = 1
continue
with open(os.path.join(CACHE, f"{year}-results.json"), "wb") as f:
f.write(data)
h = hashlib.sha256(data).hexdigest()
ok = h.startswith(pre) and h.endswith(suf) and len(data) == size
print(f"{year} bytes={len(data)} sha256={h} {'MATCH' if ok else 'DIFFERS from spec'}")
return rc
if __name__ == "__main__":
sys.exit(main())