#!/usr/bin/env python3 """ build_botlinks.py -- AI / crawler discovery files for msosorg.com Generates two things from the pages that already exist on disk, so they stay current automatically whenever a page is added or removed: 1. /llms.txt an llmstxt.org-style Markdown index (English) 2. /links-for-bots/index.html a single, lightweight, fully-linked crawl hub covering EN / MK / SI Run after adding or removing pages: python tools/build_botlinks.py It only reads each page's and <meta name="description">, so it never depends on the visual markup and is safe to re-run (idempotent). """ import io, os, re ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE = "https://msosorg.com" LANGS = ("en", "mk", "si") LANG_LABEL = {"en": "English", "mk": "Македонски", "si": "Slovenščina"} # (top-level directory under a language, human label). Order = display order. SECTIONS = [ ("student-welcome-guide", "Student guide"), ("blog", "Blog"), ("news", "News"), ("projects", "Events & projects"), ("get-to-know-slovenia", "Get to know Slovenia"), ("get-to-know-macedonia", "Get to know Macedonia"), ] # Single top-level pages (their own index.html directly under the language dir). MAIN_PAGES = [ "about-us", "msos-hub", "become-a-member", "support", "gallery", "faq", "timeline-and-milestones", "legal", "privacy-policy", "cookie-policy", ] TITLE_RE = re.compile(r"<title>(.*?)", re.DOTALL | re.I) DESC_RE = re.compile(r'", ">") .replace('"', """)) def build_llms_txt(): """English llmstxt.org-style index.""" data = collect("en") lines = [] lines.append("# MSOS — Macedonian Student Organisation in Slovenia") lines.append("") lines.append("> MSOS is the first official Macedonian student organisation in Slovenia. " "This site helps Macedonian students move to and study in Slovenia — " "enrolment guides, events, community news and support. Content is " "student-written and informative; official sources should always be verified.") lines.append("") lines.append(f"Full multilingual crawl index (EN/MK/SI): {BASE}/links-for-bots/") lines.append("") # preferred section order for llms.txt order = ["Main pages", "Student guide", "Blog", "News", "Events & projects", "Get to know Slovenia", "Get to know Macedonia"] for label in order: rows = data.get(label) if not rows: continue lines.append(f"## {label}") for title, url, desc in rows: if desc: lines.append(f"- [{title}]({url}): {desc}") else: lines.append(f"- [{title}]({url})") lines.append("") txt = "\n".join(lines).rstrip() + "\n" io.open(os.path.join(ROOT, "llms.txt"), "w", encoding="utf-8", newline="\n").write(txt) return sum(len(v) for v in data.values()) def build_links_page(): """A single lightweight HTML hub linking every page, grouped by language + section.""" blocks = [] total = 0 for lang in LANGS: data = collect(lang) order = ["Main pages", "Student guide", "Blog", "News", "Events & projects", "Get to know Slovenia", "Get to know Macedonia"] secs = [] for label in order: rows = data.get(label) if not rows: continue items = "\n".join( f'
  • {esc(t)}{(" — " + esc(d)) if d else ""}
  • ' for t, u, d in rows ) total += len(rows) secs.append(f'

    {esc(label)}

    \n ') blocks.append( f'
    \n

    {LANG_LABEL[lang]} ({lang})

    \n' + "\n".join(secs) + "\n
    " ) body = "\n".join(blocks) html = f""" Links for bots — MSOS

    Links for bots

    A plain, fully-linked index of every page on msosorg.com, for search engines and AI crawlers. See also /llms.txt and /sitemap.xml.

    {body} """ out_dir = os.path.join(ROOT, "links-for-bots") os.makedirs(out_dir, exist_ok=True) io.open(os.path.join(out_dir, "index.html"), "w", encoding="utf-8", newline="\n").write(html) return total if __name__ == "__main__": n1 = build_llms_txt() n2 = build_links_page() print(f"llms.txt written ({n1} English pages listed)") print(f"links-for-bots/index.html ({n2} links across EN/MK/SI)")