Awashes/coherence
0
1import sqlite32import datetime3import os4import json5import numpy as np6import io7from config import DB_NAME, HISTORY_DIR8 9# --- ADAPTERS (For saving Vectors in SQL) ---10def adapt_array(arr):11 out = io.BytesIO()12 np.save(out, arr)13 out.seek(0)14 return sqlite3.Binary(out.read())15 16def convert_array(text):17 out = io.BytesIO(text)18 out.seek(0)19 return np.load(out)20 21sqlite3.register_adapter(np.ndarray, adapt_array)22sqlite3.register_converter("ARRAY", convert_array)23 24def init_db():25 # Ensure history directory exists in Cloud26 if not os.path.exists(HISTORY_DIR):27 os.makedirs(HISTORY_DIR)28 29 conn = sqlite3.connect(DB_NAME, detect_types=sqlite3.PARSE_DECLTYPES)30 c = conn.cursor()31 32 # 1. Users33 c.execute('''CREATE TABLE IF NOT EXISTS users 34 (username TEXT PRIMARY KEY, 35 password TEXT, 36 contact_info TEXT, 37 last_active DATETIME, 38 created_at DATETIME)''')39 40 # 2. Sessions41 c.execute('''CREATE TABLE IF NOT EXISTS sessions 42 (cookie_id TEXT PRIMARY KEY, username TEXT)''')43 44 # 3. Connection Requests45 c.execute('''CREATE TABLE IF NOT EXISTS connection_requests 46 (sender TEXT, receiver TEXT, timestamp DATETIME, PRIMARY KEY (sender, receiver))''')47 48 # 4. CHAT INDEX49 c.execute('''CREATE TABLE IF NOT EXISTS chat_index 50 (session_id TEXT PRIMARY KEY, 51 username TEXT, 52 title TEXT, 53 last_updated DATETIME,54 current_vector ARRAY,55 msg_count INTEGER DEFAULT 0)''')56 57 # 5. Offline Notifications58 c.execute('''CREATE TABLE IF NOT EXISTS notifications 59 (id INTEGER PRIMARY KEY AUTOINCREMENT, 60 target_user TEXT, 61 type TEXT, 62 payload TEXT, 63 timestamp DATETIME)''')64 65 conn.commit()66 conn.close()67 68# --- VECTOR OPS ---69def save_session_vector(session_id, vector, count):70 conn = sqlite3.connect(DB_NAME, detect_types=sqlite3.PARSE_DECLTYPES)71 conn.execute("UPDATE chat_index SET current_vector = ?, msg_count = ? WHERE session_id = ?", 72 (vector, count, session_id))73 conn.commit()74 conn.close()75 76def load_session_data(session_id):77 conn = sqlite3.connect(DB_NAME, detect_types=sqlite3.PARSE_DECLTYPES)78 row = conn.execute("SELECT current_vector, msg_count FROM chat_index WHERE session_id = ?", (session_id,)).fetchone()79 conn.close()80 if row:81 return {"vector": row[0], "count": row[1] if row[1] is not None else 0}82 return None83 84def load_all_other_session_vectors(my_username):85 conn = sqlite3.connect(DB_NAME, detect_types=sqlite3.PARSE_DECLTYPES)86 sql = """87 SELECT username, current_vector 88 FROM chat_index 89 WHERE username != ? AND current_vector IS NOT NULL90 ORDER BY last_updated DESC91 """92 rows = conn.execute(sql, (my_username,)).fetchall()93 conn.close()94 return rows95 96# --- NOTIFICATIONS ---97def save_offline_notification(target_user, notif_type, payload):98 conn = sqlite3.connect(DB_NAME)99 conn.execute("INSERT INTO notifications (target_user, type, payload, timestamp) VALUES (?, ?, ?, ?)", 100 (target_user, notif_type, json.dumps(payload), datetime.datetime.now()))101 conn.commit()102 conn.close()103 104def get_and_clear_notifications(username):105 conn = sqlite3.connect(DB_NAME)106 rows = conn.execute("SELECT id, type, payload FROM notifications WHERE target_user = ?", (username,)).fetchall()107 alerts = []108 ids_to_delete = []109 for row in rows:110 ids_to_delete.append(row[0])111 try:112 data = json.loads(row[2])113 alerts.append({"type": row[1], **data})114 except: pass115 if ids_to_delete:116 placeholders = ','.join('?' * len(ids_to_delete))117 conn.execute(f"DELETE FROM notifications WHERE id IN ({placeholders})", ids_to_delete)118 conn.commit()119 conn.close()120 return alerts121 122# --- STANDARD OPS ---123def create_chat_entry(session_id, username, title="New Chat"):124 conn = sqlite3.connect(DB_NAME)125 conn.execute("INSERT OR REPLACE INTO chat_index (session_id, username, title, last_updated, msg_count) VALUES (?, ?, ?, ?, ?)", 126 (session_id, username, title, datetime.datetime.now(), 0))127 conn.commit()128 conn.close()129 130def update_chat_timestamp(session_id, title=None):131 conn = sqlite3.connect(DB_NAME)132 if title:133 conn.execute("UPDATE chat_index SET last_updated = ?, title = ? WHERE session_id = ?", (datetime.datetime.now(), title, session_id))134 else:135 conn.execute("UPDATE chat_index SET last_updated = ? WHERE session_id = ?", (datetime.datetime.now(), session_id))136 conn.commit()137 conn.close()138 139def list_user_chats(username):140 conn = sqlite3.connect(DB_NAME)141 rows = conn.execute("SELECT session_id, title FROM chat_index WHERE username = ? ORDER BY last_updated DESC", (username,)).fetchall()142 conn.close()143 return [{"id": r[0], "preview": r[1]} for r in rows]144 145def get_current_user(session_id: str):146 if not session_id: return None147 conn = sqlite3.connect(DB_NAME)148 res = conn.execute("SELECT username FROM sessions WHERE cookie_id = ?", (session_id,)).fetchone()149 conn.close()150 return res[0] if res else None151 152def get_user_contact(username: str):153 conn = sqlite3.connect(DB_NAME)154 res = conn.execute("SELECT contact_info FROM users WHERE username = ?", (username,)).fetchone()155 conn.close()156 return res[0] if res else "Hidden"157 158def update_last_active(username):159 conn = sqlite3.connect(DB_NAME)160 conn.execute("UPDATE users SET last_active = ? WHERE username = ?", (datetime.datetime.now(), username))161 conn.commit()162 conn.close()163 164def get_history_file(username, session_id):165 safe_id = "".join([c for c in session_id if c.isalnum() or c in "-_"])166 return os.path.join(HISTORY_DIR, f"{username}_{safe_id}.json")167 168def register_user(username, password, contact):169 from core.security import hash_pass170 conn = sqlite3.connect(DB_NAME)171 try:172 conn.execute("INSERT INTO users (username, password, contact_info, last_active, created_at) VALUES (?, ?, ?, ?, ?)", 173 (username, hash_pass(password), contact, datetime.datetime.now(), datetime.datetime.now()))174 conn.commit()175 return True176 except: return False177 finally: conn.close()178 179def authenticate_user(username, password):180 from core.security import hash_pass181 conn = sqlite3.connect(DB_NAME)182 row = conn.execute("SELECT password FROM users WHERE username = ?", (username,)).fetchone()183 conn.close()184 return row and row[0] == hash_pass(password)