#!/usr/bin/env python3 """Build the NOC site into ./public. Brand, domain and facts come from site.json; prose from content/*.txt.""" import json, html, shutil, pathlib root = pathlib.Path(__file__).parent S = json.load(open(root / "site.json")) out = root / "public" shutil.rmtree(out, ignore_errors=True) shutil.copytree(root / "static", out) e = html.escape CSS = """:root{--bg:#fff;--fg:#1c1f24;--mut:#5b6470;--ac:#0b5cad;--bd:#d9dee4} @media (prefers-color-scheme:dark){:root{--bg:#14171b;--fg:#e6e9ed;--mut:#9aa4b0;--ac:#6cb2ff;--bd:#2d333b}} body{margin:0;background:var(--bg);color:var(--fg);font:16px/1.6 system-ui,sans-serif} .w{max-width:46rem;margin:0 auto;padding:0 16px}header{border-bottom:1px solid var(--bd);padding:1rem 0} header a.b{font-weight:700;color:var(--fg);text-decoration:none}nav{margin-top:.4rem}nav a{margin-right:1rem} a{color:var(--ac)}h1{margin-top:2rem}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid var(--bd);padding:.4rem .5rem;text-align:left;vertical-align:top} th{color:var(--mut);font-weight:600;width:35%}code{word-break:break-all}footer{color:var(--mut);border-top:1px solid var(--bd);margin:3rem 0 2rem;padding-top:1rem;font-size:.9rem}""" NAV = [("/", "Home"), ("/peering/", "Peering"), ("/pgp/", "PGP keys"), ("/contact/", "Contact")] def paras(name): return "".join(f"

{e(l)}

" for l in (root / "content" / f"{name}.txt").read_text().splitlines() if l.strip()) def page(path, title, body): nav = "".join(f'{t}' for u, t in NAV) doc = f""" {e(title)} - {e(S['brand'])}
{e(S['brand'])}
{body}
""" d = out / path.strip("/"); d.mkdir(parents=True, exist_ok=True) (d / "index.html").write_text(doc) ups = "".join(f"
  • {e(u['asn'])} {e(u['name'])} ({e(u['site'])})
  • " for u in S["upstreams"]) facts = f"""
    ASN{e(S['asn'])}
    Prefix{e(S['prefix'])} (IPv6 only)
    Upstreams
      {ups}
    AS-SET{e(S['as_set'])} (RIPE)
    RPKIROA {e(S['prefix'])}, origin {e(S['asn'])}, maxLength 48; ASPA providers AS41051, AS6517
    PeeringDB{S['peeringdb']}
    PolicyOpen, IPv6 preferred
    """ page("/", S["tagline"], f"

    {e(S['brand'])}

    {e(S['tagline'])}

    {paras('home')}

    Network facts

    {facts}") page("/peering/", "Peering", f"

    Peering

    {paras('peering')}{facts}") keys = "".join(f"{e(a)}{e(f)}" for a, f in S["pgp"]) page("/pgp/", "PGP keys", f"

    PGP keys

    {paras('pgp')}{keys}
    ") c = S["contacts"] cbody = f"""

    Contact

    {paras('contact')}
    NOC for {e(S['asn'])}{c['noc']}
    Abuse{c['abuse']}
    Emergency{e(c['phone'])}
    Threema{e(c['threema'])}
    Threema QR code
    """ page("/contact/", "Contact", cbody) (out / "robots.txt").write_text(f"User-agent: *\nAllow: /\nSitemap: https://{S['domain']}/sitemap.xml\n") urls = "".join(f"https://{S['domain']}{u}" for u, _ in NAV) (out / "sitemap.xml").write_text(f'{urls}') print("built", S["domain"])