Files
meshcore-bot/migrate_webviewer_db.py
T
Stacy Olivas 7679eb7e2c fix: ruff and mypy compliance across utility scripts and tests
Fix ruff violations (import sort, unused imports, whitespace) in
backup_database.py, generate_website.py, meshcore_bot.py,
migrate_webviewer_db.py, packet_capture_service.py, version_info.py,
scripts/config_tui.py, scripts/update_todos.py, and validate_config.py.

Fix mypy stale type-ignore and remove unused imports in test files.
Add is_radio_zombie/is_radio_offline mock attributes to command_manager
test fixtures to prevent truthy Mock early returns.
2026-04-14 10:02:36 -07:00

89 lines
3.0 KiB
Python

#!/usr/bin/env python3
"""
One-off migration: copy packet_stream from a separate web viewer database
(e.g. bot_data.db) into the main bot database (e.g. meshcore_bot.db).
Use this when switching from split databases to the shared database so you
don't lose packet stream history. Run with bot and web viewer stopped.
Usage:
python3 migrate_webviewer_db.py <source_db> <target_db>
Example:
python3 migrate_webviewer_db.py bot_data.db meshcore_bot.db
"""
import sqlite3
import sys
from contextlib import closing
def main() -> int:
if len(sys.argv) != 3:
print("Usage: python3 migrate_webviewer_db.py <source_db> <target_db>", file=sys.stderr)
print("Example: python3 migrate_webviewer_db.py bot_data.db meshcore_bot.db", file=sys.stderr)
return 1
source_path = sys.argv[1]
target_path = sys.argv[2]
if source_path == target_path:
print("Source and target must be different files.", file=sys.stderr)
return 1
try:
with closing(sqlite3.connect(target_path, timeout=30.0)) as conn:
conn.execute("ATTACH DATABASE ? AS src", (source_path,))
# Ensure packet_stream exists in target (same schema as web viewer)
conn.execute("""
CREATE TABLE IF NOT EXISTS packet_stream (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp REAL NOT NULL,
data TEXT NOT NULL,
type TEXT NOT NULL
)
""")
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_packet_stream_timestamp ON packet_stream(timestamp)"
)
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_packet_stream_type ON packet_stream(type)"
)
# Check that source has packet_stream
cur = conn.execute(
"SELECT name FROM src.sqlite_master WHERE type='table' AND name='packet_stream'"
)
if cur.fetchone() is None:
conn.execute("DETACH DATABASE src")
print("Source database has no packet_stream table; nothing to migrate.", file=sys.stderr)
return 0
# Copy rows from source; skip ids that already exist in target (INSERT OR IGNORE)
before = conn.total_changes
conn.execute(
"""
INSERT OR IGNORE INTO main.packet_stream (id, timestamp, data, type)
SELECT id, timestamp, data, type FROM src.packet_stream
"""
)
inserted = conn.total_changes - before
conn.commit()
conn.execute("DETACH DATABASE src")
print(f"Migrated {inserted} packet_stream row(s) from {source_path} to {target_path}.")
return 0
except sqlite3.OperationalError as e:
print(f"Database error: {e}", file=sys.stderr)
return 1
except OSError as e:
print(f"File error: {e}", file=sys.stderr)
return 1
if __name__ == "__main__":
sys.exit(main())