#!/usr/bin/env python3 """Sync vault hack notes with placed RomM library paths (2026-06-23 batch).""" import re from pathlib import Path VAULT = Path(r"C:\Users\MattC\Documents\Obsidian Vault\Pokémon ROM Hacks\Hacks") # RomM filename stem (without Pokemon - / (Hack) / variant) -> note stem PLACED = { # windows primary + variants "Alchemist": ("PC", "roms/windows/Pokemon - Alchemist (Hack).zip", "Complete"), "Abstract": ("PC", "roms/windows/Pokemon - Abstract (Hack).zip", "Complete"), "Awakening ENG": ("PC", "roms/windows/Pokemon - Awakening ENG (Hack).zip", "Complete"), "Bizarre ENGLISH": ("PC", "roms/windows/Pokemon - Bizarre ENGLISH (Hack).zip", "Complete"), "Concealed 2.1": ("PC", "roms/windows/Pokemon - Concealed 2.1 (Hack).zip", "Complete"), "Consonancia 1.2": ("PC", "roms/windows/Pokemon - Consonancia 1.2 (Hack).zip", "Complete"), "Eon Guardians": ("PC", "roms/windows/Pokemon - Eon Guardians (Hack).zip", "Complete"), "Fire Ash": ("PC", "roms/windows/Pokemon - Fire Ash (Hack).zip", "Complete"), "Floral Tempus": ("GBA", "roms/windows/Pokemon - Floral Tempus (Hack).zip", "Complete"), "HGSS Sevii": ("NDS", "roms/windows/Pokemon - HGSS Sevii (Hack).zip", "Complete"), "Hero Legacy": ("PC", "roms/windows/Pokemon - Hero Legacy (Hack).zip", "Complete"), "Jam Festival": ("PC", "roms/windows/Pokemon - Jam Festival (Hack).zip", "Complete"), "Legends of the Arena": ("PC", "roms/windows/Pokemon - Legends of the Arena (Hack).zip", "Complete"), "Mega Adventures": ("PC", "roms/windows/Pokemon - Mega Adventures (Hack).zip", "Complete"), "Nightmare 1.3.0": ("PC", "roms/windows/Pokemon - Nightmare 1.3.0 (Hack).zip", "Complete"), "Poketale": ("PC", "roms/windows/Pokemon - Poketale (Hack).zip", "Complete"), "Prisme": ("PC", "roms/windows/Pokemon - Prisme (Hack) [Installer].zip", "Complete"), "Shattered Light": ("PC", "roms/windows/Pokemon - Shattered Light (Hack).zip", "Ongoing"), "Tectonic 3.3.1": ("PC", "roms/windows/Pokemon - Tectonic 3.4.1 (Hack).zip", "Ongoing"), "Tectonic 3.4.1": ("PC", "roms/windows/Pokemon - Tectonic 3.4.1 (Hack).zip", "Ongoing"), "Uranium": ("PC", "roms/windows/Pokemon - Uranium (Hack) [Installer].zip", "Complete"), "InfiniteFusion": ("PC", "roms/windows/Pokemon - InfiniteFusion (Hack) [Full].zip", "Complete"), "Infinity 3.3.1": ("PC", "roms/windows/Pokemon - Infinity 3.3.1 (Hack).zip", "Complete"), "Rejuvenation": ("PC", "roms/windows/Pokemon - Rejuvenation (Hack).zip", "Ongoing"), "Itinerant": ("GBA", "roms/windows/Pokemon - Itinerant (Hack).zip", "Ongoing"), "Relict": ("PC", "roms/windows/Pokemon - Relict (Hack).zip", "Complete"), "Reminiscencia": ("PC", "roms/windows/Pokemon - Reminiscencia (Hack).zip", "Complete"), "Vanguard": ("PC", "roms/windows/Pokemon - Vanguard (Hack).zip", "Ongoing"), "Xenoverse": ("PC", "roms/windows/Pokemon - Xenoverse (Hack).zip", "Complete"), "Reborn": ("PC", "roms/windows/Pokemon - Reborn (Hack).zip", "Complete"), "Coral": ("GBC", "roms/gbc/Hacks/Pokemon - Coral (Hack).gbc", "Beta"), "Giratina Strikes Back Full": ("GBA", "roms/gba/Hacks/Pokemon - Giratina Strikes Back Full (Hack).gba", "Complete"), "Sienna Complete": ("GBA", "roms/gba/Hacks/Pokemon - Sienna Complete (Hack).gba", "Complete"), "Spades and Clubs": ("GBA", "roms/gba/Hacks/Pokemon - Spades and Clubs (Hack).gba", "Beta"), "Emerald Seaglass": ("GBA", "roms/gba/Hacks/Pokemon - Emerald Seaglass (Hack).gba", "Complete"), } NOTE_MAP = { "Awakening ENG": "Awakening", "Bizarre ENGLISH": "Bizarre", "Concealed 2.1": "Concealed", "Consonancia 1.2": "Consonancia", "Nightmare 1.3.0": "Nightmare", "Tectonic 3.4.1": "Tectonic", "Tectonic 3.3.1": "Tectonic", "Giratina Strikes Back Full": "Giratina Strikes Back", "Sienna Complete": "Sienna", "Infinity 3.3.1": "Infinity", "InfiniteFusion": "Infinite Fusion", "Reminiscencia": "Reminiscencia", } VARIANTS_BLOCK = """## Alternate builds (RomM) | Variant | Path | |---|---| {rows} > Windows zip is the Playnite primary unless noted. Joiplay/Android/Linux/macOS builds are separate RomM download entries. """ def patch_fm(text, key, val): if re.search(rf"^{key}:", text, re.M): return re.sub(rf"^{key}:.*$", f'{key}: {val}', text, count=1, flags=re.M) # insert after title return re.sub(r"(^title:.*\n)", rf"\1{key}: {val}\n", text, count=1, flags=re.M) def main(): updated = [] for rom_key, (plat, lp, status) in PLACED.items(): stem = NOTE_MAP.get(rom_key, rom_key) p = VAULT / f"{stem}.md" if not p.exists(): print(f"SKIP no note: {stem}") continue text = p.read_text(encoding="utf-8") text = patch_fm(text, "platform", plat) text = patch_fm(text, "status", status) text = patch_fm(text, "library_path", f'"{lp}"') if rom_key == "Infinity" or rom_key == "Infinity 3.3.1": text = patch_fm(text, "version", '"3.3.1"') if rom_key == "Nightmare 1.3.0": text = patch_fm(text, "version", '"1.3.0"') if rom_key == "Tectonic 3.4.1": text = patch_fm(text, "version", '"3.4.1"') # normalize In the library section if "## In the library" in text: text = re.sub( r"(?ms)^## In the library\s*\n.*?(?=^## |\n\[\[Index|\Z)", f"## In the library\n\n> Placed in RomM library (`{lp}`).\n\n", text, count=1, ) p.write_text(text, encoding="utf-8") updated.append(stem) print(f"Updated {len(updated)} notes: {', '.join(sorted(updated))}") if __name__ == "__main__": main()