scripts/check-instances.py
55 lines · 1492 bytes · executable
1#!/usr/bin/env python3
2"""Check every clearnet instance in instances.json.
3
4Fetches /api/instance from each and prints one line per instance. Exits 1 if
5any is down, so a scheduled CI job turns red and INSTANCES.md does not keep
6listing dead links. Tor, I2P and Yggdrasil addresses are skipped: the runner
7cannot reach them.
8"""
9
10import json
11import sys
12import urllib.error
13import urllib.request
14
15TIMEOUT = 15
16
17
18def check(url):
19 req = urllib.request.Request(
20 url.rstrip("/") + "/api/instance",
21 headers={"User-Agent": "skunkyart-instance-check"},
22 )
23 try:
24 with urllib.request.urlopen(req, timeout=TIMEOUT) as resp:
25 info = json.load(resp)
26 except (urllib.error.URLError, json.JSONDecodeError, TimeoutError) as err:
27 return None, str(err)
28 return info.get("version", "?"), None
29
30
31def main():
32 with open("instances.json", encoding="utf-8") as f:
33 instances = json.load(f)["instances"]
34
35 failed = 0
36 for inst in instances:
37 url = inst.get("urls", {}).get("clearnet")
38 if not url:
39 print(f"{inst['title']}: no clearnet url, skipped")
40 continue
41 version, err = check(url)
42 if err:
43 failed += 1
44 print(f"{inst['title']}: DOWN {url} ({err})")
45 else:
46 print(f"{inst['title']}: ok {url} v{version}")
47
48 if failed:
49 print(f"{failed} instance(s) down")
50 return 1
51 return 0
52
53
54if __name__ == "__main__":
55 sys.exit(main())