109 lines
3.6 KiB
Python
109 lines
3.6 KiB
Python
"""Ingest clrmamepro .dat files into the SQLite library database.
|
|
|
|
Usage::
|
|
|
|
python -m app.ingest [--dats data/dats] [--db data/library.sqlite]
|
|
"""
|
|
import argparse
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
from . import config, matcher
|
|
from .dat_parser import parse_dat_file
|
|
from .db import get_connection, init_db
|
|
|
|
|
|
def _norm_hex(value):
|
|
if not value:
|
|
return None
|
|
return str(value).strip().upper()
|
|
|
|
|
|
def detect_system(dat_name):
|
|
if "UMD Video" in dat_name:
|
|
return "videos"
|
|
if "PlayStation Portable" in dat_name:
|
|
return "games"
|
|
return "unknown"
|
|
|
|
|
|
def ingest_dat(conn, path):
|
|
header, entries = parse_dat_file(path)
|
|
dat_name = header.get("name") if header else path.stem
|
|
version = header.get("version") if header else None
|
|
description = header.get("description") if header else None
|
|
system = detect_system(dat_name)
|
|
|
|
existing = conn.execute("SELECT id FROM dats WHERE name = ?", (dat_name,)).fetchone()
|
|
if existing:
|
|
dat_id = existing["id"]
|
|
conn.execute("DELETE FROM roms WHERE release_id IN (SELECT id FROM releases WHERE dat_id = ?)", (dat_id,))
|
|
conn.execute("DELETE FROM releases WHERE dat_id = ?", (dat_id,))
|
|
conn.execute(
|
|
"UPDATE dats SET version=?, description=?, system=?, source_path=?, ingested_at=datetime('now') WHERE id=?",
|
|
(version, description, system, str(path), dat_id),
|
|
)
|
|
else:
|
|
cur = conn.execute(
|
|
"INSERT INTO dats (name, version, description, system, source_path, ingested_at) VALUES (?,?,?,?,?,datetime('now'))",
|
|
(dat_name, version, description, system, str(path)),
|
|
)
|
|
dat_id = cur.lastrowid
|
|
|
|
release_count = 0
|
|
rom_count = 0
|
|
for entry in entries:
|
|
cur = conn.execute(
|
|
"INSERT INTO releases (dat_id, name, description, region, serial) VALUES (?,?,?,?,?)",
|
|
(dat_id, entry.get("name"), entry.get("description"), entry.get("region"), entry.get("serial")),
|
|
)
|
|
release_id = cur.lastrowid
|
|
release_count += 1
|
|
for rom in entry.get("rom", []):
|
|
size = rom.get("size")
|
|
conn.execute(
|
|
"INSERT INTO roms (release_id, name, size, crc32, md5, sha1, serial) VALUES (?,?,?,?,?,?,?)",
|
|
(
|
|
release_id,
|
|
rom.get("name"),
|
|
int(size) if size else None,
|
|
_norm_hex(rom.get("crc")),
|
|
_norm_hex(rom.get("md5")),
|
|
_norm_hex(rom.get("sha1")),
|
|
rom.get("serial"),
|
|
),
|
|
)
|
|
rom_count += 1
|
|
|
|
matcher.clear_cache()
|
|
return dat_name, system, release_count, rom_count
|
|
|
|
|
|
def main(argv=None):
|
|
parser = argparse.ArgumentParser(description="Ingest clrmamepro DAT files into SQLite")
|
|
parser.add_argument("--dats", help="directory containing .dat files (default: data/dats)")
|
|
parser.add_argument("--db", help="SQLite database path (default: data/library.sqlite)")
|
|
args = parser.parse_args(argv)
|
|
|
|
dats_dir = Path(args.dats) if args.dats else config.DATS_DIR
|
|
db_path = Path(args.db) if args.db else config.DB_PATH
|
|
|
|
conn = init_db(db_path)
|
|
files = sorted(dats_dir.glob("*.dat"))
|
|
if not files:
|
|
print(f"No .dat files found in {dats_dir}", file=sys.stderr)
|
|
return 1
|
|
|
|
for path in files:
|
|
dat_name, system, releases, roms = ingest_dat(conn, path)
|
|
print(f"{dat_name} [{system}] -> {releases} releases, {roms} roms")
|
|
|
|
conn.commit()
|
|
conn.close()
|
|
print(f"\nLibrary written to {db_path}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|