125 lines
3.8 KiB
Python
125 lines
3.8 KiB
Python
#!/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())
|