#!/usr/bin/env python3 from __future__ import annotations import argparse import json import sqlite3 from datetime import datetime, timezone from pathlib import Path def _ensure_schema(conn: sqlite3.Connection) -> None: conn.execute( """ CREATE TABLE IF NOT EXISTS saint_du_jour ( id INTEGER PRIMARY KEY AUTOINCREMENT, mois INTEGER NOT NULL, jour INTEGER NOT NULL, saints_json TEXT NOT NULL, source_url TEXT, updated_at TEXT NOT NULL, UNIQUE(mois, jour) ) """ ) conn.execute( """ CREATE TABLE IF NOT EXISTS dicton ( id INTEGER PRIMARY KEY AUTOINCREMENT, mois INTEGER NOT NULL, jour INTEGER, texte TEXT NOT NULL, region TEXT ) """ ) conn.execute("CREATE INDEX IF NOT EXISTS idx_dicton_mois_jour ON dicton(mois, jour)") conn.execute("CREATE INDEX IF NOT EXISTS idx_saint_du_jour_mois_jour ON saint_du_jour(mois, jour)") def _load_json_rows(path: Path, required_key: str) -> list[dict]: raw = json.loads(path.read_text(encoding="utf-8")) if not isinstance(raw, list): raise ValueError(f"{path}: format JSON attendu = liste d'objets") rows: list[dict] = [] for item in raw: if not isinstance(item, dict): continue if required_key not in item: continue rows.append(item) return rows def _import_saints(conn: sqlite3.Connection, saints_rows: list[dict], mode: str) -> int: now = datetime.now(timezone.utc).isoformat() inserted = 0 if mode == "replace": conn.execute("DELETE FROM saint_du_jour") for row in saints_rows: mois = int(row["mois"]) jour = int(row["jour"]) saints = row.get("saints") or [] if not isinstance(saints, list): saints = [str(saints)] saints = [str(x).strip() for x in saints if str(x).strip()] if not saints: continue saints_json = json.dumps(saints, ensure_ascii=False) source_url = row.get("source_url") conn.execute( """ INSERT INTO saint_du_jour (mois, jour, saints_json, source_url, updated_at) VALUES (?, ?, ?, ?, ?) ON CONFLICT(mois, jour) DO UPDATE SET saints_json = excluded.saints_json, source_url = excluded.source_url, updated_at = excluded.updated_at """, (mois, jour, saints_json, source_url, now), ) inserted += 1 return inserted def _import_dictons(conn: sqlite3.Connection, dicton_rows: list[dict], mode: str, region: str | None) -> int: inserted = 0 if mode == "replace": if region: conn.execute("DELETE FROM dicton WHERE region = ?", (region,)) else: conn.execute("DELETE FROM dicton") for row in dicton_rows: mois = int(row["mois"]) jour = int(row["jour"]) dictons = row.get("dictons") or [] if not isinstance(dictons, list): dictons = [str(dictons)] dictons = [str(x).strip() for x in dictons if str(x).strip()] if not dictons: continue for texte in dictons: if mode == "append": exists = conn.execute( """ SELECT 1 FROM dicton WHERE mois = ? AND jour = ? AND texte = ? AND COALESCE(region, '') = COALESCE(?, '') LIMIT 1 """, (mois, jour, texte, region), ).fetchone() if exists: continue conn.execute( "INSERT INTO dicton (mois, jour, texte, region) VALUES (?, ?, ?, ?)", (mois, jour, texte, region), ) inserted += 1 return inserted def main() -> int: parser = argparse.ArgumentParser( description="Importe saints du jour + dictons dans SQLite (hors webapp)." ) parser.add_argument( "--db", default="data/jardin.db", help="Chemin SQLite cible", ) parser.add_argument( "--saints-json", default="calendrier_lunaire/saints_dictons/saints_du_jour.json", help="JSON saints_du_jour", ) parser.add_argument( "--dictons-json", default="calendrier_lunaire/saints_dictons/dictons_du_jour.json", help="JSON dictons_du_jour", ) parser.add_argument( "--mode", choices=["replace", "append"], default="replace", help="replace: purge puis recharge ; append: ajoute sans doublons", ) parser.add_argument( "--region", default="National", help="Région stockée dans table dicton (vide pour NULL)", ) args = parser.parse_args() db_path = Path(args.db) saints_path = Path(args.saints_json) dictons_path = Path(args.dictons_json) region = args.region.strip() or None saints_rows = _load_json_rows(saints_path, "saints") dicton_rows = _load_json_rows(dictons_path, "dictons") db_path.parent.mkdir(parents=True, exist_ok=True) conn = sqlite3.connect(db_path) try: _ensure_schema(conn) conn.execute("BEGIN") saints_count = _import_saints(conn, saints_rows, args.mode) dictons_count = _import_dictons(conn, dicton_rows, args.mode, region) conn.commit() except Exception: conn.rollback() raise finally: conn.close() print(f"Import terminé ({args.mode})") print(f" Saints importés: {saints_count}") print(f" Dictons importés: {dictons_count} (region={region!r})") print(f" Base: {db_path}") return 0 if __name__ == "__main__": raise SystemExit(main())