import sqlite3 import os DB_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "busylight.db") def get_db(): conn = sqlite3.connect(DB_PATH) conn.row_factory = sqlite3.Row conn.execute("PRAGMA journal_mode=WAL") conn.execute("PRAGMA foreign_keys=ON") return conn def init_db(): conn = get_db() conn.executescript(""" CREATE TABLE IF NOT EXISTS settings ( key TEXT PRIMARY KEY, value TEXT NOT NULL DEFAULT '' ); CREATE TABLE IF NOT EXISTS users ( azure_id TEXT PRIMARY KEY, display_name TEXT NOT NULL DEFAULT '', email TEXT DEFAULT '', personal_nr TEXT DEFAULT '', phone_extension TEXT DEFAULT '', active INTEGER NOT NULL DEFAULT 0 ); CREATE TABLE IF NOT EXISTS wled_devices ( id INTEGER PRIMARY KEY AUTOINCREMENT, hostname TEXT NOT NULL UNIQUE, name TEXT DEFAULT '', segment_count INTEGER NOT NULL DEFAULT 2, online INTEGER DEFAULT 0, leds INTEGER DEFAULT 0, version TEXT DEFAULT '', last_check TIMESTAMP ); CREATE TABLE IF NOT EXISTS assignments ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_azure_id TEXT NOT NULL REFERENCES users(azure_id) ON DELETE CASCADE, wled_device_id INTEGER NOT NULL REFERENCES wled_devices(id) ON DELETE CASCADE, segment INTEGER NOT NULL DEFAULT 0, UNIQUE(wled_device_id, segment), UNIQUE(user_azure_id) ); CREATE TABLE IF NOT EXISTS color_rules ( status TEXT PRIMARY KEY, r INTEGER NOT NULL DEFAULT 0, g INTEGER NOT NULL DEFAULT 0, b INTEGER NOT NULL DEFAULT 0, effect TEXT DEFAULT '' ); CREATE TABLE IF NOT EXISTS state ( user_azure_id TEXT PRIMARY KEY REFERENCES users(azure_id) ON DELETE CASCADE, last_aida_status TEXT DEFAULT '', last_teams_status TEXT DEFAULT '', phone_active INTEGER DEFAULT 0, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS activity_log ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, user_azure_id TEXT, user_name TEXT, aida_status TEXT, teams_status TEXT, wled_url TEXT, result TEXT ); """) # Migrate: add columns if missing (for existing databases) try: conn.execute("ALTER TABLE wled_devices ADD COLUMN online INTEGER DEFAULT 0") except Exception: pass try: conn.execute("ALTER TABLE wled_devices ADD COLUMN leds INTEGER DEFAULT 0") except Exception: pass try: conn.execute("ALTER TABLE wled_devices ADD COLUMN version TEXT DEFAULT ''") except Exception: pass try: conn.execute("ALTER TABLE wled_devices ADD COLUMN last_check TIMESTAMP") except Exception: pass try: conn.execute("ALTER TABLE wled_devices ADD COLUMN mac TEXT DEFAULT ''") except Exception: pass try: conn.execute("ALTER TABLE users ADD COLUMN phone_extension TEXT DEFAULT ''") except Exception: pass try: conn.execute("ALTER TABLE state ADD COLUMN phone_active INTEGER DEFAULT 0") except Exception: pass defaults = { "azure_client_id": "", "azure_client_secret": "", "azure_tenant_id": "", "azure_auth_tenant": "common", "azure_scopes": "User.Read User.Read.All Presence.Read Presence.Read.All", "azure_auth_record": "", "poll_interval": "15", "aida_csv_path": "", "aida_status_anwesend": "~~1~~", "aida_status_abwesend": "~~0~~", "aida_status_homeoffice": "~~2~~", } for key, value in defaults.items(): conn.execute( "INSERT OR IGNORE INTO settings (key, value) VALUES (?, ?)", (key, value), ) default_colors = [ ("abwesend", 0, 0, 0, ""), ("homeoffice", 255, 255, 0, ""), ("available", 0, 255, 0, ""), ("teams_available", 0, 255, 0, ""), ("teams_away", 0, 255, 0, ""), ("teams_busy", 255, 0, 0, ""), ("teams_donotdisturb", 255, 0, 255, ""), ("teams_inacall", 255, 0, 255, ""), ("teams_inameeting", 255, 0, 0, ""), ("teams_presenting", 200, 200, 200, ""), ("teams_inaconferencecall", 200, 200, 200, ""), ("teams_berightback", 0, 255, 0, ""), ("teams_offline", 0, 255, 0, ""), ("teams_inactive", 0, 255, 0, ""), ("teams_offwork", 0, 255, 0, ""), ("teams_outofoffice", 0, 255, 0, ""), ("phone_active", 255, 0, 0, ""), ] for status, r, g, b, effect in default_colors: conn.execute( "INSERT OR IGNORE INTO color_rules (status, r, g, b, effect) VALUES (?, ?, ?, ?, ?)", (status, r, g, b, effect), ) conn.commit() conn.close() def get_setting(key, default=""): conn = get_db() row = conn.execute("SELECT value FROM settings WHERE key = ?", (key,)).fetchone() conn.close() return row["value"] if row else default def set_setting(key, value): conn = get_db() conn.execute( "INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)", (key, str(value)), ) conn.commit() conn.close() def get_all_settings(): conn = get_db() rows = conn.execute("SELECT key, value FROM settings").fetchall() conn.close() return {row["key"]: row["value"] for row in rows} def log_activity(user_azure_id, user_name, aida_status, teams_status, wled_url, result): conn = get_db() conn.execute( """INSERT INTO activity_log (user_azure_id, user_name, aida_status, teams_status, wled_url, result) VALUES (?, ?, ?, ?, ?, ?)""", (user_azure_id, user_name, aida_status, teams_status, wled_url, result), ) conn.execute( "DELETE FROM activity_log WHERE id NOT IN (SELECT id FROM activity_log ORDER BY id DESC LIMIT 500)" ) conn.commit() conn.close()