#!/usr/bin/env python3
"""Write docs/robots.txt and docs/sitemap.xml.
Both files were 404 before this, so nothing told a crawler where the site ends
or how often it changes. Everything here is derived from scripts/brand.py, so a
domain move is one edit rather than a hunt through the tree.
"""
from __future__ import annotations
import os
import sys
from datetime import datetime, timezone
ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir)
sys.path.insert(0, os.path.join(ROOT, "scripts"))
from brand import SITE
DOCS = os.path.join(ROOT, "docs")
ROBOTS = os.path.join(DOCS, "robots.txt")
SITEMAP = os.path.join(DOCS, "sitemap.xml")
# Googlebot renders the page before it indexes it, so anything the first paint
# needs has to stay crawlable. These three are small and carry the only server
# rendered content on the page, the trending table and the header counts.
RENDER_CRITICAL = ("trending_poc.json", "kev.json", "stats.json")
# These only feed the search box, which a crawler never types into. Together they
# are over 13 MB on the wire, which is crawl budget spent on nothing. Blocking
# them here does not touch curl: robots.txt binds crawlers, not clients.
BULK_PAYLOADS = (
"CVE_list.json",
"cve_metadata.json",
"epss.json",
"repo_meta.json",
"nuclei.json",
)
def robots() -> str:
lines = ["User-agent: *", "Allow: /"]
lines += [f"Disallow: /{name}" for name in BULK_PAYLOADS]
lines += ["", f"Sitemap: {SITE}/sitemap.xml", ""]
return "\n".join(lines)
def sitemap(urls: list[tuple[str, str]]) -> str:
body = "".join(
f" \n {loc}\n {lastmod}\n \n"
for loc, lastmod in urls
)
return (
'\n'
'\n'
f"{body}"
"\n"
)
def main() -> int:
today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
urls = [(f"{SITE}/", today)]
os.makedirs(DOCS, exist_ok=True)
with open(ROBOTS, "w", encoding="utf-8") as handle:
handle.write(robots())
with open(SITEMAP, "w", encoding="utf-8") as handle:
handle.write(sitemap(urls))
print(f"Wrote {ROBOTS} and {SITEMAP} ({len(urls)} URL) for {SITE}")
return 0
if __name__ == "__main__":
raise SystemExit(main())