149 lines
5.1 KiB
Python
149 lines
5.1 KiB
Python
import os
|
|
import sqlite3
|
|
import json
|
|
from datetime import datetime, timezone
|
|
from app.config import DB_PATH
|
|
|
|
|
|
def _conn():
|
|
conn = sqlite3.connect(DB_PATH)
|
|
conn.row_factory = sqlite3.Row
|
|
return conn
|
|
|
|
|
|
def init_db():
|
|
os.makedirs(os.path.dirname(os.path.abspath(DB_PATH)), exist_ok=True)
|
|
conn = _conn()
|
|
conn.executescript('''
|
|
CREATE TABLE IF NOT EXISTS players (
|
|
id INTEGER PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
online INTEGER NOT NULL DEFAULT 0,
|
|
last_seen TEXT,
|
|
updating INTEGER NOT NULL DEFAULT 0,
|
|
registered INTEGER NOT NULL DEFAULT 0,
|
|
workspace_name TEXT,
|
|
player_type TEXT,
|
|
updated_at TEXT NOT NULL,
|
|
last_pushed TEXT,
|
|
last_ip_address TEXT,
|
|
status_last_updated TEXT,
|
|
screen_resolution TEXT,
|
|
hardware_version TEXT,
|
|
hostname TEXT,
|
|
eth0_ip TEXT
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS logs (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
timestamp TEXT NOT NULL,
|
|
event_type TEXT NOT NULL,
|
|
message TEXT NOT NULL,
|
|
details TEXT
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_logs_ts ON logs(timestamp DESC);
|
|
''')
|
|
# Migrate existing databases that predate the new columns
|
|
new_cols = [
|
|
('last_pushed', 'TEXT'),
|
|
('last_ip_address', 'TEXT'),
|
|
('status_last_updated', 'TEXT'),
|
|
('screen_resolution', 'TEXT'),
|
|
('hardware_version', 'TEXT'),
|
|
('hostname', 'TEXT'),
|
|
('eth0_ip', 'TEXT'),
|
|
]
|
|
for col, typ in new_cols:
|
|
try:
|
|
conn.execute(f'ALTER TABLE players ADD COLUMN {col} {typ}')
|
|
except Exception:
|
|
pass # column already exists
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
|
|
def upsert_player(p):
|
|
state = p.get('state', {})
|
|
workspace = p.get('workspace', {})
|
|
ps = p.get('player_status') or {}
|
|
res = ps.get('screen_resolution')
|
|
eth0 = (ps.get('public_ip') or {}).get('eth0') or {}
|
|
now = datetime.now(timezone.utc).isoformat()
|
|
conn = _conn()
|
|
conn.execute('''
|
|
INSERT INTO players (id, name, online, last_seen, updating, registered,
|
|
workspace_name, player_type, updated_at,
|
|
last_pushed, last_ip_address, status_last_updated,
|
|
screen_resolution, hardware_version, hostname, eth0_ip)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
ON CONFLICT(id) DO UPDATE SET
|
|
name = excluded.name,
|
|
online = excluded.online,
|
|
last_seen = excluded.last_seen,
|
|
updating = excluded.updating,
|
|
registered = excluded.registered,
|
|
workspace_name = excluded.workspace_name,
|
|
player_type = excluded.player_type,
|
|
updated_at = excluded.updated_at,
|
|
last_pushed = excluded.last_pushed,
|
|
last_ip_address = excluded.last_ip_address,
|
|
status_last_updated = excluded.status_last_updated,
|
|
screen_resolution = excluded.screen_resolution,
|
|
hardware_version = excluded.hardware_version,
|
|
hostname = excluded.hostname,
|
|
eth0_ip = excluded.eth0_ip
|
|
''', (
|
|
p['id'],
|
|
p['name'],
|
|
1 if state.get('online') else 0,
|
|
state.get('last_seen'),
|
|
1 if state.get('updating') else 0,
|
|
1 if state.get('registered') else 0,
|
|
workspace.get('name'),
|
|
p.get('player_type'),
|
|
now,
|
|
p.get('last_pushed'),
|
|
p.get('last_ip_address'),
|
|
ps.get('status_last_updated'),
|
|
f"{res[0]}x{res[1]}" if isinstance(res, list) and len(res) == 2 else None,
|
|
ps.get('hardware_version'),
|
|
ps.get('hostname'),
|
|
eth0.get('ip_v4'),
|
|
))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
|
|
def get_all_players():
|
|
conn = _conn()
|
|
rows = conn.execute('SELECT * FROM players ORDER BY name').fetchall()
|
|
conn.close()
|
|
return [dict(r) for r in rows]
|
|
|
|
|
|
def get_player_counts():
|
|
conn = _conn()
|
|
total = conn.execute('SELECT COUNT(*) FROM players').fetchone()[0]
|
|
online = conn.execute('SELECT COUNT(*) FROM players WHERE online = 1').fetchone()[0]
|
|
conn.close()
|
|
return total, online
|
|
|
|
|
|
def add_log(event_type, message, details=None):
|
|
now = datetime.now(timezone.utc).isoformat()
|
|
conn = _conn()
|
|
conn.execute(
|
|
'INSERT INTO logs (timestamp, event_type, message, details) VALUES (?, ?, ?, ?)',
|
|
(now, event_type, message, json.dumps(details) if details else None),
|
|
)
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
|
|
def get_recent_logs(limit=200):
|
|
conn = _conn()
|
|
rows = conn.execute('SELECT * FROM logs ORDER BY id DESC LIMIT ?', (limit,)).fetchall()
|
|
conn.close()
|
|
return [dict(r) for r in rows]
|