Complete curated-list import automation and vault sync.
Adds list-import tooling, expands romhack-import for PC variants and patch batches, and syncs catalog with 2026-06-23 valhalla placements (Vanguard, Xenoverse, GBA patches, Infinity 3.3.1).
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Create vault notes for list-import hacks missing from catalog."""
|
||||
import json, re, textwrap, unicodedata
|
||||
from datetime import date
|
||||
from pathlib import Path
|
||||
|
||||
VAULT = Path(r"C:\Users\MattC\Documents\Obsidian Vault\Pokémon ROM Hacks\Hacks")
|
||||
CATALOG = Path(__file__).resolve().parents[1] / "wiki" / "catalog.json"
|
||||
|
||||
NEW = [
|
||||
("Alchemist", "GBA", "FireRed", "Complete", "https://www.pokecommunity.com/threads/pokémon-alchemist.378280/"),
|
||||
("Concealed", "PC", None, "Complete", "https://www.pokecommunity.com/threads/concealed.527325/"),
|
||||
("Consonancia", "PC", None, "Complete", "https://www.pokecommunity.com/threads/pokémon-consonancia-full-game.537329/"),
|
||||
("Crown", "PC", None, "Ongoing", "https://www.pokecommunity.com/threads/pokémon-crown.463821/"),
|
||||
("Eon Guardians", "GBA", "Emerald", "Complete", "https://www.pokecommunity.com/threads/pokémon-eon-guardians.527913/"),
|
||||
("Fire Ash", "GBA", "FireRed", "Complete", "https://www.pokecommunity.com/threads/pokémon-fire-ash.399096/"),
|
||||
("Floral Tempus", "GBA", "Emerald", "Complete", "https://www.pokecommunity.com/threads/pokémon-floral-tempus-ex-1-9-4-released-12-gym-badges-elite-4-champion.409175/"),
|
||||
("Hero Legacy", "PC", None, "Complete", "https://www.pokecommunity.com/threads/pokémon-hero-legacy-eng-de-now-with-new-game-mode.538518/"),
|
||||
("HGSS Sevii", "NDS", "HeartGold", "Complete", "https://www.pokecommunity.com/threads/pokémon-hgss-sevii-islands-hoenn-postgame.434636/"),
|
||||
("Itinerant", "GBA", "FireRed", "Ongoing", "https://www.pokecommunity.com/threads/pokemon-itinerant.528218/"),
|
||||
("Jam Festival", "PC", None, "Complete", "https://www.pokecommunity.com/threads/pkmn-jam-festival.536702/"),
|
||||
("Legends of the Arena", "GBA", "Emerald", "Complete", "https://www.pokecommunity.com/threads/pokémon-legends-of-the-arena.298738/"),
|
||||
("Mega Adventures", "GBA", "Ruby", "Complete", "https://www.pokecommunity.com/threads/pokemon-mega-adventure.362058/"),
|
||||
("Nightmare", "PC", None, "Complete", "https://www.pokecommunity.com/threads/pokémon-nightmare.504856/"),
|
||||
("Poketale", "PC", None, "Complete", "https://www.mediafire.com/file/n6yzxnclf2uys7c/Poketale.zip/file"),
|
||||
("Relict", "PC", None, "Complete", "https://phiongames.blogspot.com/2025/12/descarga-pokemon-relict.html"),
|
||||
("Shattered Light", "PC", None, "Ongoing", "https://eeveeexpo.com/shattered-light/"),
|
||||
("Sienna", "GBA", "Ruby", "Complete", "https://www.pokecommunity.com/threads/hack-of-the-year-2010-pokémon-sienna-complete-version-released.202372/"),
|
||||
("Spades and Clubs", "GBA", "FireRed", "Beta", "https://senta-storage-system.neocities.org/patchrelease"),
|
||||
("Tectonic", "PC", None, "Ongoing", "https://www.tectonic-game.com"),
|
||||
("Vega Fairy EX", "GBA", "FireRed", "Complete", "https://www.pokecommunity.com/threads/pokemon-vega-fairy-edition-ex-minus-v1-4-balance-updates-and-skarmory-evo.475538/"),
|
||||
]
|
||||
|
||||
UPDATES = {
|
||||
"Coral": "roms/gbc/Hacks/Pokemon - Coral (Hack).gbc",
|
||||
"Giratina Strikes Back": "roms/gba/Hacks/Pokemon - Giratina Strikes Back Full (Hack).gba",
|
||||
}
|
||||
|
||||
|
||||
def norm(s):
|
||||
s = unicodedata.normalize("NFKD", s).encode("ascii", "ignore").decode().lower()
|
||||
s = re.sub(r"^pokemon\s+", "", s)
|
||||
return re.sub(r"[^a-z0-9]+", " ", s).strip()
|
||||
|
||||
|
||||
def yaml_quote(s):
|
||||
if s is None:
|
||||
return '"—"'
|
||||
if any(c in s for c in ':"\\#[]{}'):
|
||||
return json.dumps(s)
|
||||
return s
|
||||
|
||||
|
||||
def note_body(title, source):
|
||||
return textwrap.dedent(f"""\
|
||||
# {title}
|
||||
|
||||
> [!info] From curated YouTube/pastebin list import (2026-06-23)
|
||||
> Added to catalog from community recommendation lists. Download may be gated — see [[Wanted]].
|
||||
|
||||
## Summary
|
||||
|
||||
Surfaced from external recommendation lists (pastebin / Google Doc). Not yet in the RomM library unless noted in frontmatter.
|
||||
|
||||
## Links
|
||||
|
||||
- Info / thread: {source}
|
||||
|
||||
## In the library
|
||||
|
||||
> [!note] See `library_path` in frontmatter.
|
||||
|
||||
[[Index|← back to directory]]
|
||||
""")
|
||||
|
||||
|
||||
def patch_library_path(path: Path, lp: str):
|
||||
text = path.read_text(encoding="utf-8")
|
||||
text = re.sub(r"^library_path:.*$", f'library_path: "{lp}"', text, count=1, flags=re.M)
|
||||
path.write_text(text, encoding="utf-8")
|
||||
|
||||
|
||||
def main():
|
||||
existing = {norm(p.stem) for p in VAULT.glob("*.md")}
|
||||
today = date.today().isoformat()
|
||||
created = []
|
||||
for name, platform, base, status, source in NEW:
|
||||
if norm(name) in existing:
|
||||
continue
|
||||
title = f"Pokémon {name}"
|
||||
tags = ["hack", f"platform/{platform.lower()}", f"status/{status.lower().replace(' ', '-')}"]
|
||||
if base:
|
||||
tags.append(f"base/{base.lower().replace(' ', '-')}")
|
||||
fm = [
|
||||
"---",
|
||||
f"title: {title}",
|
||||
f'platform: {platform}',
|
||||
f'base: {base or "—"}',
|
||||
'version: "—"',
|
||||
f"status: {status}",
|
||||
"type: [New Experience]",
|
||||
'generation: "—"',
|
||||
'library_path: "—"',
|
||||
f"source: {json.dumps(source)}",
|
||||
f"added: {today}",
|
||||
"play_status: Unplayed",
|
||||
"tags:",
|
||||
]
|
||||
fm += [f" - {t}" for t in tags]
|
||||
fm.append("---")
|
||||
body = note_body(title, source)
|
||||
out = VAULT / f"{name}.md"
|
||||
out.write_text("\n".join(fm) + "\n" + body, encoding="utf-8")
|
||||
created.append(name)
|
||||
for stem, lp in UPDATES.items():
|
||||
p = VAULT / f"{stem}.md"
|
||||
if p.exists():
|
||||
patch_library_path(p, lp)
|
||||
print(f"Created {len(created)} notes: {', '.join(created)}")
|
||||
print(f"Updated library_path: {', '.join(UPDATES)}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user