NOC site for AS203496 served at noc.obr.sh

This commit is contained in:
olaf committed 2026-10-08 15:09:55 +02:00
commit 6758bda3cb
10 files changed
+102

No files matched your search

Executable
+52
View File
@@ -0,0 +1,52 @@
#!/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"<p>{e(l)}</p>" for l in (root / "content" / f"{name}.txt").read_text().splitlines() if l.strip())
def page(path, title, body):
nav = "".join(f'<a href="{u}">{t}</a>' for u, t in NAV)
doc = f"""<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>{e(title)} - {e(S['brand'])}</title><meta name="description" content="{e(S['asn'])} {e(S['tagline'])}">
<link rel="canonical" href="https://{S['domain']}{path}"><style>{CSS}</style></head><body>
<header><div class="w"><a class="b" href="/">{e(S['brand'])}</a><nav>{nav}</nav></div></header>
<main class="w">{body}</main><footer class="w">{e(S['brand'])} &middot; {e(S['asn'])} &middot; <a href="{S['peeringdb']}">PeeringDB</a></footer></body></html>"""
d = out / path.strip("/"); d.mkdir(parents=True, exist_ok=True)
(d / "index.html").write_text(doc)
ups = "".join(f"<li>{e(u['asn'])} {e(u['name'])} ({e(u['site'])})</li>" for u in S["upstreams"])
facts = f"""<table>
<tr><th>ASN</th><td>{e(S['asn'])}</td></tr>
<tr><th>Prefix</th><td><code>{e(S['prefix'])}</code> (IPv6 only)</td></tr>
<tr><th>Upstreams</th><td><ul>{ups}</ul></td></tr>
<tr><th>AS-SET</th><td><code>{e(S['as_set'])}</code> (RIPE)</td></tr>
<tr><th>RPKI</th><td>ROA {e(S['prefix'])}, origin {e(S['asn'])}, maxLength 48; ASPA providers AS41051, AS6517</td></tr>
<tr><th>PeeringDB</th><td><a href="{S['peeringdb']}">{S['peeringdb']}</a></td></tr>
<tr><th>Policy</th><td>Open, IPv6 preferred</td></tr></table>"""
page("/", S["tagline"], f"<h1>{e(S['brand'])}</h1><p><strong>{e(S['tagline'])}</strong></p>{paras('home')}<h2>Network facts</h2>{facts}")
page("/peering/", "Peering", f"<h1>Peering</h1>{paras('peering')}{facts}")
keys = "".join(f"<tr><th>{e(a)}</th><td><code>{e(f)}</code></td></tr>" for a, f in S["pgp"])
page("/pgp/", "PGP keys", f"<h1>PGP keys</h1>{paras('pgp')}<table>{keys}</table>")
c = S["contacts"]
cbody = f"""<h1>Contact</h1>{paras('contact')}<table>
<tr><th>NOC for {e(S['asn'])}</th><td><a href="mailto:{c['noc']}">{c['noc']}</a></td></tr>
<tr><th>Abuse</th><td><a href="mailto:{c['abuse']}">{c['abuse']}</a></td></tr>
<tr><th>Emergency</th><td>{e(c['phone'])}</td></tr>
<tr><th>Threema</th><td>{e(c['threema'])}<br><img src="/threema-{c['threema']}.jpg" alt="Threema QR code" width="160"></td></tr></table>"""
page("/contact/", "Contact", cbody)
(out / "robots.txt").write_text(f"User-agent: *\nAllow: /\nSitemap: https://{S['domain']}/sitemap.xml\n")
urls = "".join(f"<url><loc>https://{S['domain']}{u}</loc></url>" for u, _ in NAV)
(out / "sitemap.xml").write_text(f'<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">{urls}</urlset>')
print("built", S["domain"])