mikrotik-bot/db.py

121 lines
4.4 KiB
Python

import aiosqlite
import asyncio
from datetime import datetime
DB_PATH = 'mikrotik_bot.db'
CREATE_CLIENTS = '''
CREATE TABLE IF NOT EXISTS clients (
mac TEXT PRIMARY KEY,
name TEXT,
custom_name TEXT,
last_seen DATETIME
);
'''
CREATE_SESSIONS = '''
CREATE TABLE IF NOT EXISTS sessions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
mac TEXT,
ip TEXT,
start_time DATETIME,
end_time DATETIME,
rx_bytes INTEGER,
tx_bytes INTEGER,
source TEXT,
last_update DATETIME,
FOREIGN KEY(mac) REFERENCES clients(mac)
);
'''
async def init_db():
async with aiosqlite.connect(DB_PATH) as db:
await db.execute(CREATE_CLIENTS)
await db.execute(CREATE_SESSIONS)
await db.commit()
async def upsert_client(mac, name=None, custom_name=None):
async with aiosqlite.connect(DB_PATH) as db:
await db.execute('''
INSERT INTO clients (mac, name, custom_name, last_seen)
VALUES (?, ?, ?, ?)
ON CONFLICT(mac) DO UPDATE SET
name=excluded.name,
last_seen=excluded.last_seen
''', (mac, name, custom_name, datetime.now()))
await db.commit()
async def start_session(mac, ip, rx_bytes=0, tx_bytes=0, source='api'):
async with aiosqlite.connect(DB_PATH) as db:
await db.execute('''
INSERT INTO sessions (mac, ip, start_time, rx_bytes, tx_bytes, source, last_update)
VALUES (?, ?, ?, ?, ?, ?, ?)
''', (mac, ip, datetime.now(), rx_bytes, tx_bytes, source, datetime.now()))
await db.commit()
async def update_session(mac, rx_bytes, tx_bytes):
async with aiosqlite.connect(DB_PATH) as db:
await db.execute('''
UPDATE sessions SET rx_bytes=?, tx_bytes=?, last_update=?
WHERE mac=? AND end_time IS NULL
''', (rx_bytes, tx_bytes, datetime.now(), mac))
await db.commit()
async def close_session(mac):
async with aiosqlite.connect(DB_PATH) as db:
await db.execute('''
UPDATE sessions SET end_time=?
WHERE mac=? AND end_time IS NULL
''', (datetime.now(), mac))
await db.commit()
async def get_history(period_days=30, page=1, page_size=10):
async with aiosqlite.connect(DB_PATH) as db:
since = datetime.now().timestamp() - period_days*86400
offset = (page - 1) * page_size
async with db.execute('''
SELECT s.*, c.name, c.custom_name FROM sessions s
LEFT JOIN clients c ON s.mac = c.mac
WHERE s.start_time > datetime(?, 'unixepoch')
ORDER BY s.start_time DESC
LIMIT ? OFFSET ?
''', (since, page_size, offset)) as cursor:
rows = await cursor.fetchall()
# Получаем общее количество
async with db.execute('''
SELECT COUNT(*) FROM sessions WHERE start_time > datetime(?, 'unixepoch')
''', (since,)) as cursor:
total = (await cursor.fetchone())[0]
return rows, total
async def get_clients(page=1, page_size=10):
async with aiosqlite.connect(DB_PATH) as db:
offset = (page - 1) * page_size
async with db.execute('''
SELECT * FROM clients ORDER BY last_seen DESC LIMIT ? OFFSET ?
''', (page_size, offset)) as cursor:
rows = await cursor.fetchall()
async with db.execute('SELECT COUNT(*) FROM clients') as cursor:
total = (await cursor.fetchone())[0]
return rows, total
async def get_stats(period_days=30, page=1, page_size=10):
async with aiosqlite.connect(DB_PATH) as db:
since = datetime.now().timestamp() - period_days*86400
offset = (page - 1) * page_size
async with db.execute('''
SELECT s.mac, c.name, c.custom_name, SUM(s.rx_bytes), SUM(s.tx_bytes), COUNT(s.id)
FROM sessions s
LEFT JOIN clients c ON s.mac = c.mac
WHERE s.start_time > datetime(?, 'unixepoch')
GROUP BY s.mac
ORDER BY SUM(s.rx_bytes + s.tx_bytes) DESC
LIMIT ? OFFSET ?
''', (since, page_size, offset)) as cursor:
rows = await cursor.fetchall()
# Получаем общее количество клиентов за период
async with db.execute('''
SELECT COUNT(DISTINCT mac) FROM sessions WHERE start_time > datetime(?, 'unixepoch')
''', (since,)) as cursor:
total = (await cursor.fetchone())[0]
return rows, total