121 lines
4.4 KiB
Python
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 |