import aiosqlite import logging from typing import List, Dict, Optional from config import DB_PATH logger = logging.getLogger(__name__) class Database: def __init__(self): self.db_path = DB_PATH async def init_db(self): async with aiosqlite.connect(self.db_path) as db: await db.execute(""" CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, telegram_id INTEGER UNIQUE NOT NULL, telegram_username TEXT, full_name TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) """) await db.execute(""" CREATE TABLE IF NOT EXISTS sip_accounts ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, extension_number TEXT UNIQUE NOT NULL, sip_secret TEXT, username TEXT, email TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users (id) ) """) await db.commit() logger.info("Database initialized") async def add_user(self, telegram_id: int, username: str = None, full_name: str = None) -> int: async with aiosqlite.connect(self.db_path) as db: cursor = await db.execute( "INSERT OR IGNORE INTO users (telegram_id, telegram_username, full_name) VALUES (?, ?, ?)", (telegram_id, username, full_name) ) await db.commit() if cursor.lastrowid == 0: # User already exists, get their id cursor = await db.execute( "SELECT id FROM users WHERE telegram_id = ?", (telegram_id,) ) row = await cursor.fetchone() return row[0] if row else None return cursor.lastrowid async def get_user(self, telegram_id: int) -> Optional[Dict]: async with aiosqlite.connect(self.db_path) as db: cursor = await db.execute( "SELECT * FROM users WHERE telegram_id = ?", (telegram_id,) ) row = await cursor.fetchone() if row: return { "id": row[0], "telegram_id": row[1], "telegram_username": row[2], "full_name": row[3], "created_at": row[4] } return None async def add_sip_account(self, user_id: int, extension_number: str, sip_secret: str = None, username: str = None, email: str = None) -> int: async with aiosqlite.connect(self.db_path) as db: cursor = await db.execute( """INSERT INTO sip_accounts (user_id, extension_number, sip_secret, username, email) VALUES (?, ?, ?, ?, ?)""", (user_id, extension_number, sip_secret, username, email) ) await db.commit() return cursor.lastrowid async def get_user_sip_accounts(self, telegram_id: int) -> List[Dict]: async with aiosqlite.connect(self.db_path) as db: cursor = await db.execute(""" SELECT sa.* FROM sip_accounts sa JOIN users u ON sa.user_id = u.id WHERE u.telegram_id = ? ORDER BY sa.created_at DESC """, (telegram_id,)) rows = await cursor.fetchall() return [ { "id": row[0], "user_id": row[1], "extension_number": row[2], "sip_secret": row[3], "username": row[4], "email": row[5], "created_at": row[6] } for row in rows ] async def get_all_sip_accounts(self) -> List[Dict]: async with aiosqlite.connect(self.db_path) as db: cursor = await db.execute(""" SELECT sa.*, u.telegram_id, u.telegram_username, u.full_name FROM sip_accounts sa JOIN users u ON sa.user_id = u.id ORDER BY sa.created_at DESC """) rows = await cursor.fetchall() return [ { "id": row[0], "user_id": row[1], "extension_number": row[2], "sip_secret": row[3], "username": row[4], "email": row[5], "created_at": row[6], "telegram_id": row[7], "telegram_username": row[8], "full_name": row[9] } for row in rows ] async def update_sip_secret(self, extension_number: str, new_secret: str) -> bool: async with aiosqlite.connect(self.db_path) as db: cursor = await db.execute( "UPDATE sip_accounts SET sip_secret = ? WHERE extension_number = ?", (new_secret, extension_number) ) await db.commit() return cursor.rowcount > 0 async def update_extension_number(self, old_number: str, new_number: str) -> bool: async with aiosqlite.connect(self.db_path) as db: cursor = await db.execute( "UPDATE sip_accounts SET extension_number = ? WHERE extension_number = ?", (new_number, old_number) ) await db.commit() return cursor.rowcount > 0 async def delete_sip_account(self, extension_number: str) -> bool: async with aiosqlite.connect(self.db_path) as db: cursor = await db.execute( "DELETE FROM sip_accounts WHERE extension_number = ?", (extension_number,) ) await db.commit() return cursor.rowcount > 0 async def get_sip_account_by_number(self, number: str) -> Optional[Dict]: async with aiosqlite.connect(self.db_path) as db: cursor = await db.execute( "SELECT * FROM sip_accounts WHERE extension_number = ?", (number,) ) row = await cursor.fetchone() if row: return { "id": row[0], "user_id": row[1], "extension_number": row[2], "sip_secret": row[3], "username": row[4], "email": row[5], "created_at": row[6] } return None