File size: 6,031 Bytes
3dc9da2
 
 
 
 
 
 
bf9bea9
3dc9da2
 
 
 
 
bf9bea9
3dc9da2
 
 
 
 
 
 
 
 
 
bf9bea9
 
 
3dc9da2
 
 
 
bf9bea9
 
3dc9da2
 
 
 
 
bf9bea9
 
3dc9da2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bf9bea9
3dc9da2
 
 
 
 
bf9bea9
3dc9da2
 
 
 
bf9bea9
3dc9da2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# db.py
import aiosqlite
import uuid
import os
import colorlog
from typing import List, Optional, Dict, Any

# Se usarán placehoders para los imports de app.py para evitar errores
logger = colorlog.getLogger("OMEGA_DB")
logger.setLevel(colorlog.logging.INFO) 
DB_PATH = "data/omega_modular_argentina.db"

class AsyncDatabase:
    """Clase central para interactuar con SQLite."""
    def __init__(self, db_path: str = DB_PATH):
        self.db_path = db_path
        os.makedirs(os.path.dirname(db_path), exist_ok=True)

    async def init(self):
        logger.info("🛠️ Base de Datos: Verificando tablas y consistencia.")
        async with aiosqlite.connect(self.db_path) as db:
            await db.execute("PRAGMA journal_mode=WAL;") 
            await db.execute("""
                CREATE TABLE IF NOT EXISTS souls (
                    uuid TEXT PRIMARY KEY, username TEXT UNIQUE, password_hash TEXT,
                    role TEXT DEFAULT 'INICIADO', karma INTEGER DEFAULT 100, 
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, is_banned BOOLEAN DEFAULT 0
                )
            """)
            await db.execute("""
                CREATE TABLE IF NOT EXISTS codex (
                    id INTEGER PRIMARY KEY AUTOINCREMENT, uuid TEXT UNIQUE,
                    title TEXT, content TEXT, principle TEXT, author_id TEXT,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                )
            """)
            await db.execute("""
                CREATE TABLE IF NOT EXISTS audit_logs (
                    id INTEGER PRIMARY KEY AUTOINCREMENT, user_id TEXT,
                    action TEXT, details TEXT, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                )
            """)
            await db.commit()
        await self.log_event(None, "SYSTEM_DB_INIT", "Base de Datos en línea. ¡Fierro!")

    async def create_soul_transactional(self, username: str, pass_hash: str, role: str) -> str:
        soul_uuid = str(uuid.uuid4())
        try:
            async with aiosqlite.connect(self.db_path) as db:
                await db.execute(
                    "INSERT INTO souls (uuid, username, password_hash, role) VALUES (?, ?, ?, ?)",
                    (soul_uuid, username, pass_hash, role)
                )
                await db.commit()
            return soul_uuid
        except aiosqlite.IntegrityError:
            class DatabaseIntegrityError(Exception): pass # Placeholder
            raise DatabaseIntegrityError("Ese usuario ya existe.")
        except Exception as e:
            logger.error(f"Quilombo al crear alma: {e}")
            raise

    async def get_soul_by_username(self, username: str) -> Optional[Dict[str, Any]]:
        async with aiosqlite.connect(self.db_path) as db:
            db.row_factory = aiosqlite.Row
            async with db.execute("SELECT * FROM souls WHERE username = ?", (username,)) as cursor:
                row = await cursor.fetchone()
                return dict(row) if row else None

    async def get_all_souls_data(self) -> List[Dict[str, Any]]:
        async with aiosqlite.connect(self.db_path) as db:
            db.row_factory = aiosqlite.Row
            async with db.execute("SELECT * FROM souls ORDER BY karma DESC") as cursor:
                rows = await cursor.fetchall()
                return [dict(r) for r in rows]
    
    async def update_ban_status_db(self, username: str, is_banned: bool):
        async with aiosqlite.connect(self.db_path) as db:
            await db.execute("UPDATE souls SET is_banned = ? WHERE username = ?", (1 if is_banned else 0, username))
            await db.commit()

    async def write_law_and_reward(self, title: str, content: str, principle: str, author_uuid: str):
        law_uuid = str(uuid.uuid4())
        async with aiosqlite.connect(self.db_path) as db:
            await db.execute(
                "INSERT INTO codex (uuid, title, content, principle, author_id) VALUES (?, ?, ?, ?, ?)",
                (law_uuid, title, content, principle, author_uuid)
            )
            await db.execute("UPDATE souls SET karma = karma + 20 WHERE uuid = ?", (author_uuid,))
            await db.commit()

    async def get_codex_feed_data(self, limit: int = 25) -> List[dict]:
        async with aiosqlite.connect(self.db_path) as db:
            db.row_factory = aiosqlite.Row
            query = """
                SELECT c.*, s.username as author_name, s.role 
                FROM codex c 
                LEFT JOIN souls s ON c.author_id = s.uuid 
                ORDER BY c.created_at DESC LIMIT ?
            """
            async with db.execute(query, (limit,)) as cursor:
                rows = await cursor.fetchall()
                return [dict(r) for r in rows]

    async def search_context_rag(self, query: str) -> str:
        async with aiosqlite.connect(self.db_path) as db:
            db.row_factory = aiosqlite.Row
            async with db.execute("SELECT title, content FROM codex ORDER BY RANDOM() LIMIT 2") as cursor:
                rows = await cursor.fetchall()
                context = "\n".join([f"PRECEDENTE [{r['title']}]: {r['content']}" for r in rows])
                return context if context else "No hay precedentes cargados."

    async def log_event(self, user_id: Optional[str], action: str, details: str):
        async with aiosqlite.connect(self.db_path) as db:
            await db.execute(
                "INSERT INTO audit_logs (user_id, action, details) VALUES (?, ?, ?)",
                (user_id, action, details)
            )
            await db.commit()
        
    async def get_recent_audit_logs(self, limit: int = 20) -> List[Dict[str, Any]]:
        async with aiosqlite.connect(self.db_path) as db:
            db.row_factory = aiosqlite.Row
            async with db.execute("SELECT * FROM audit_logs ORDER BY timestamp DESC LIMIT ?", (limit,)) as cursor:
                rows = await cursor.fetchall()
                return [dict(r) for r in rows]

DB = AsyncDatabase()