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