chore: initialize homebrew-magic-rpg monorepo

Consolidates the HbM: RPG project (formerly the loose hbm-books
working folder) into a single repo. ObsidianNotes, foundry-lore, and
foundry-system are wired in as submodules pointing at their existing
Gitea repos. Loose tooling scripts are organized under tools/,
obsolete/one-off scripts (fix_vault.py, generate_mocs.py, debug-*.ts,
write_file_helper.py) and _books/ (superseded by ObsidianNotes) are
excluded via .gitignore rather than deleted. foundryvtt-admin is
excluded pending its own separate repo.
This commit is contained in:
Octoturge
2026-08-17 21:28:50 +02:00
commit a4f8941fca
25 changed files with 3702 additions and 0 deletions
+113
View File
@@ -0,0 +1,113 @@
import os
import re
from pathlib import Path
# --- CONFIGURATION ---
ROOT_DIR = Path(__file__).parent.parent
VAULT_DIR = ROOT_DIR / "ObsidianNotes"
OUTPUT_DIR = ROOT_DIR / "NotebookLM_Uploads"
# Folders to completely ignore
IGNORE_FOLDERS = {".obsidian", "_assets", "_templates", "revisions", "tabletop-cards"}
# Thematic mapping: Which Obsidian folders go into which macro file
THEME_MAP = {
"01_System_Rules_and_Mechanics.txt": ["rules", "disciplines", "spells", "items", "races"],
"02_World_Lore_and_NPCs.txt": ["concepts", "npcs", "organizations", "lore"],
"03_Atlas_and_Locations.txt": ["locations"],
"04_Campaigns_and_Characters.txt": ["classes", "player-characters", "conflicts"]
}
# --- REGEX UTILITIES ---
FRONTMATTER_RE = re.compile(r"^---\s*\n(.*?)\n---\s*\n", re.DOTALL)
def parse_md_file(file_path, relative_path):
"""Reads a file, extracts YAML, cleans structure, and returns format text."""
try:
content = file_path.read_text(encoding="utf-8-sig")
except Exception as e:
return f"\n\n[ERROR READING FILE {relative_path}: {str(e)}]\n\n"
# Separate Frontmatter and Content
frontmatter = ""
match = FRONTMATTER_RE.match(content)
if match:
frontmatter = match.group(1).strip()
body = content[match.end():].strip()
else:
body = content.strip()
# Format the file section so NotebookLM sees it as a discrete structured document
builder = []
builder.append("\n" + "="*80)
builder.append(f"START_FILE: {relative_path}")
builder.append(f"FILENAME: {file_path.name}")
builder.append("="*80)
if frontmatter:
builder.append("\n--- METADATA ---")
builder.append(frontmatter)
builder.append("----------------\n")
builder.append(body)
builder.append(f"\nEND_FILE: {relative_path}\n")
return "\n".join(builder)
def main():
if not VAULT_DIR.exists():
print(f"[-] Error: Vault directory not found at {VAULT_DIR}")
return
OUTPUT_DIR.mkdir(exist_ok=True)
print(f"[+] Initializing vault compilation from: {VAULT_DIR}")
# Initialize empty text collectors for our themes
compiled_data = {filename: [] for filename in THEME_MAP.keys()}
# Walk through the entire Obsidian Vault
for root, dirs, files in os.walk(VAULT_DIR):
# In-place filtering to skip ignored root directories
dirs[:] = [d for d in dirs if d not in IGNORE_FOLDERS]
for file in files:
if not file.endswith(".md"):
continue
file_path = Path(root) / file
# Calculate path relative to the Vault root (e.g., 'spells/academic/fire-magic/fireball.md')
rel_path = file_path.relative_to(VAULT_DIR)
root_parent_folder = rel_path.parts[0] # The first subfolder name
# Find which macro file this note belongs to based on its root parent folder
target_macro = None
for macro_file, monitored_folders in THEME_MAP.items():
if root_parent_folder in monitored_folders:
target_macro = macro_file
break
# If it's a loose markdown file in the root vault or unmapped, default to Lore
if not target_macro:
target_macro = "02_World_Lore_and_NPCs.txt"
# Parse and append
formatted_note = parse_md_file(file_path, rel_path)
compiled_data[target_macro].append(formatted_note)
# Write the master compiled macro files
for filename, pieces in compiled_data.items():
if not pieces:
print(f"[!] Target file {filename} is empty. Skipping output.")
continue
out_path = OUTPUT_DIR / filename
# Combine all files with clear division
final_content = f"MASTER COMPILATION FOR CATEGORY: {filename}\n" + "\n".join(pieces)
out_path.write_text(final_content, encoding="utf-8")
print(f"[+] Successfully wrote {len(pieces)} files to -> {out_path.name}")
print("\n[+] Done! Drag the contents of 'NotebookLM_Uploads' straight into NotebookLM.")
if __name__ == "__main__":
main()