Files
Alchemist/scripts/cucholix/format_contents_repo.py
2025-05-24 16:35:18 -07:00

101 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
import os
import re
import sys
import shutil
import tempfile
import subprocess
import unicodedata
def sanitize_name(name):
"""Normalize game names: remove symbols, accents, and replace ' - ' with space."""
n = unicodedata.normalize('NFKD', name).encode('ascii','ignore').decode('ascii')
n = n.replace("'", "").replace("", "").replace("`", "").replace('"', '')
n = n.replace(" - ", " ") # Replace problematic ' - ' only in the game name
return ' '.join(n.split()).strip()
def title_case_preserve_numbers(name):
"""Capitalize words while preserving full-uppercase acronyms."""
return ' '.join(w.capitalize() if not w.isupper() else w for w in name.split())
def find_title_id(path):
"""Look for 16-character Title ID under any 'contents/' directory."""
for root, dirs, _ in os.walk(path):
if os.path.basename(root).lower() == 'contents':
for d in dirs:
if re.fullmatch(r'[0-9A-Fa-f]{16}', d):
return d
return None
def extract_with_7z(rar_path, tmpdir):
"""Extract only atmosphere/contents/* using 7z."""
cmd = [
"7z", "x", "-y",
rar_path,
f"-o{tmpdir}",
"atmosphere/contents/*"
]
proc = subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return proc.returncode == 0 or find_title_id(tmpdir) is not None
def process_rar(root_folder, rar_relpath, output_root):
subdir, file = os.path.split(rar_relpath)
version_match = re.match(r"release_(.+)\.rar$", file, re.I)
if not version_match:
print(f"❌ Invalid release name: {file}")
return
version = version_match.group(1)
raw_game_name = os.path.basename(subdir)
# Clean and normalize game name (remove " - ", keep suffix clean)
cleaned_name = sanitize_name(raw_game_name)
game_name = title_case_preserve_numbers(cleaned_name)
pack_label = f"{game_name} - Graphics Pack" # Final folder
rar_path = os.path.join(root_folder, rar_relpath)
with tempfile.TemporaryDirectory() as tmp:
ok = extract_with_7z(rar_path, tmp)
if not ok:
print(f"❌ Extraction error (7z) on {rar_relpath}")
return
title_id = find_title_id(tmp)
if not title_id:
print(f"❌ No Title ID found in {rar_relpath}")
return # Skip making directory if no Title ID found
version_dir = os.path.join(output_root, pack_label, version)
os.makedirs(version_dir, exist_ok=True)
src = os.path.join(tmp, "atmosphere", "contents", title_id)
dst = os.path.join(version_dir, title_id)
try:
shutil.copytree(src, dst, dirs_exist_ok=True)
print(f"{rar_relpath}{os.path.join(pack_label, version, title_id)}")
except Exception as e:
print(f"❌ Copy failed for {rar_relpath}: {e}")
def main():
if len(sys.argv) != 2:
print("Usage: python collect_content_mods.py /path/to/root")
sys.exit(1)
root = sys.argv[1]
output = os.path.join(root, "format2")
os.makedirs(output, exist_ok=True)
tasks = []
for dirpath, _, files in os.walk(root):
for fn in files:
if re.match(r"release_.*\.rar$", fn, re.I):
rel = os.path.relpath(os.path.join(dirpath, fn), root)
tasks.append(rel)
for relpath in tasks:
process_rar(root, relpath, output)
print("✅ Done.")
if __name__ == "__main__":
main()