Initial commit: Yodmon Yodeck→Zabbix bridge
- Yodeck API poller (every 10 min, paginated, 310 players) - SQLite persistence (players + activity logs) - SNMP v2c agent via net-snmp pass_persist - Zabbix API auto host creation/update (6.0+) - Flask web dashboard with live player status and log - Docker deployment with persistent volume - dev_server.py for local testing without Docker Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
107
app/database.py
Normal file
107
app/database.py
Normal file
@@ -0,0 +1,107 @@
|
||||
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
|
||||
);
|
||||
|
||||
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);
|
||||
''')
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
|
||||
def upsert_player(p):
|
||||
state = p.get('state', {})
|
||||
workspace = p.get('workspace', {})
|
||||
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)
|
||||
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
|
||||
''', (
|
||||
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,
|
||||
))
|
||||
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]
|
||||
Reference in New Issue
Block a user