#!/usr/bin/env python3 # /// script # requires-python = ">=3.11" # dependencies = ["pyyaml"] # /// """Migrate reminders from reminder.yaml to SQLite. Reads reminder.yaml, inserts into reminders.sqlite, then renames YAML to .bak. """ from __future__ import annotations import sys from datetime import datetime, timezone from os import environ from pathlib import Path # db.py lives in skills/remind/scripts/ SCRIPTS_DIR = Path(__file__).resolve().parent.parent / "skills" / "remind" / "scripts" sys.path.insert(0, str(SCRIPTS_DIR)) import yaml from db import get_db, init_db WORKSPACE = Path(__file__).resolve().parent.parent YAML_PATH = WORKSPACE / "reminder.yaml" DEFAULT_DB_PATH = WORKSPACE / "db" / "reminders.sqlite" DB_PATH = Path(environ.get("REMIND_DB", str(DEFAULT_DB_PATH))) def _now() -> str: return datetime.now(timezone.utc).isoformat(timespec="seconds") def _parse_window(window: str) -> tuple[int, int]: start_str, end_str = window.split("-", 1) start = _hhmm_to_minutes(start_str.strip()) end = _hhmm_to_minutes(end_str.strip()) return start, end def _hhmm_to_minutes(value: str) -> int: h, m = value.split(":") return int(h) * 60 + int(m) def main() -> int: if not YAML_PATH.exists(): print("No reminder.yaml found — nothing to migrate.") return 0 data = yaml.safe_load(YAML_PATH.read_text(encoding="utf-8")) or {} reminders = data.get("reminders", []) if not reminders: print("reminder.yaml is empty — nothing to migrate.") return 0 init_db(DB_PATH) conn = get_db(DB_PATH) try: conn.execute("BEGIN") for item in reminders: text = (item.get("text") or "").strip() if not text: continue now = _now() cur = conn.execute( "INSERT INTO reminders (text, enabled, timezone, created_at, updated_at) VALUES (?, 1, 'Europe/Prague', ?, ?)", (text, now, now), ) rid = cur.lastrowid at = item.get("at") at_times = item.get("at_times", []) if at: at_times = [at] + list(at_times) for at_str in at_times: conn.execute( "INSERT INTO schedule_at (reminder_id, at_datetime) VALUES (?, ?)", (rid, at_str), ) for expr in item.get("cron_exprs", []): conn.execute( "INSERT INTO schedule_cron (reminder_id, cron_expr) VALUES (?, ?)", (rid, expr), ) random_cfg = item.get("random") if random_cfg: start, end = _parse_window(random_cfg["window"]) conn.execute( """ INSERT INTO schedule_random (reminder_id, times_per_day, window_start, window_end, days_filter, from_date, until_date) VALUES (?, ?, ?, ?, ?, ?, ?) """, ( rid, random_cfg["times_per_day"], start, end, random_cfg.get("days"), random_cfg.get("from"), random_cfg.get("until"), ), ) conn.execute("COMMIT") backup = YAML_PATH.with_suffix(".yaml.bak") YAML_PATH.rename(backup) print(f"Migrated {len(reminders)} reminders to {DB_PATH}") print(f"Renamed {YAML_PATH} to {backup}") return 0 except Exception as exc: conn.execute("ROLLBACK") print(f"Migration failed: {exc}", file=sys.stderr) return 1 finally: conn.close() if __name__ == "__main__": sys.exit(main())