#!/usr/bin/env python3 """One-shot: migrate the SQLite voicemail store into MySQL. Reads the existing /var/lib/vm-transcribe/voicemail.db (sqlite) and inserts every message/setting/session row into the MySQL `asterisk` DB, skipping duplicates on (mailbox, origtime, callerid). Idempotent. Run as asterisk: sudo -u asterisk /opt/vm-transcribe/venv/bin/python3 /opt/vm-transcribe/vm_migrate_sqlite_to_mysql.py """ import json import os import sqlite3 import sys sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import vm_store SRC = os.environ.get("VM_DB", "/var/lib/vm-transcribe/voicemail.db") def main(): if not os.path.exists(SRC): print("no sqlite source at", SRC, "- nothing to migrate") return src = sqlite3.connect(SRC) src.row_factory = sqlite3.Row dst = vm_store.connect() # MySQL (via secret) print("migrating from", SRC, "-> MySQL") cols = [d[1] for d in src.execute("PRAGMA table_info(messages)")] n = 0 for r in src.execute("SELECT * FROM messages"): try: vals = [] for c in cols: v = r[c] if c in ("intents", "numbers") and isinstance(v, str): try: json.loads(v) except Exception: v = json.dumps([]) vals.append(v) ph = ",".join(["%s"] * len(cols)) dst.execute( "INSERT IGNORE INTO messages (%s) VALUES (%s)" % (",".join(cols), ph), vals) n += 1 except Exception as e: print(" skip msg id", r["id"], ":", e) dst.commit() print("messages scanned: %d" % n) for tbl in ("settings", "sessions"): try: c = [d[1] for d in src.execute("PRAGMA table_info(%s)" % tbl)] except Exception: continue k = 0 for r in src.execute("SELECT * FROM %s" % tbl): try: dst.execute( "INSERT IGNORE INTO %s (%s) VALUES (%s)" % (tbl, ",".join(c), ",".join(["%s"] * len(c))), [r[x] for x in c]) k += 1 except Exception as e: print(" skip %s row:" % tbl, e) dst.commit() print("%s migrated: %d" % (tbl, k)) # quick count check total = dst.execute("SELECT COUNT(*) c FROM messages").fetchone()["c"] print("MySQL messages total: %d" % total) if __name__ == "__main__": main()