""" Account Repository - Zugriff auf Account-Daten in der Datenbank """ import sqlite3 import json from typing import List, Dict, Any, Optional from datetime import datetime from infrastructure.repositories.base_repository import BaseRepository class AccountRepository(BaseRepository): """Repository für Account-Datenzugriff""" def get_by_id(self, account_id: int) -> Optional[Dict[str, Any]]: """ Holt einen Account nach ID. Args: account_id: Account ID Returns: Dict mit Account-Daten oder None """ # Sichere Abfrage die mit verschiedenen Schema-Versionen funktioniert query = "SELECT * FROM accounts WHERE id = ?" rows = self._execute_query(query, (account_id,)) if not rows: return None return self._row_to_account(rows[0]) def get_by_username(self, username: str, platform: str = None) -> Optional[Dict[str, Any]]: """ Holt einen Account nach Username. Args: username: Username platform: Optional platform filter Returns: Dict mit Account-Daten oder None """ if platform: query = "SELECT * FROM accounts WHERE username = ? AND platform = ?" params = (username, platform) else: query = "SELECT * FROM accounts WHERE username = ?" params = (username,) rows = self._execute_query(query, params) if not rows: return None return self._row_to_account(rows[0]) def get_all(self, platform: str = None, status: str = None) -> List[Dict[str, Any]]: """ Holt alle Accounts mit optionalen Filtern. Args: platform: Optional platform filter status: Optional status filter Returns: Liste von Account-Dicts """ query = "SELECT * FROM accounts WHERE 1=1" params = [] if platform: query += " AND platform = ?" params.append(platform) if status: query += " AND status = ?" params.append(status) query += " ORDER BY created_at DESC" rows = self._execute_query(query, params) return [self._row_to_account(row) for row in rows] def update_fingerprint_id(self, account_id: int, fingerprint_id: str) -> bool: """ Aktualisiert die Fingerprint ID eines Accounts. Args: account_id: Account ID fingerprint_id: Neue Fingerprint ID Returns: True bei Erfolg, False bei Fehler """ query = "UPDATE accounts SET fingerprint_id = ? WHERE id = ?" return self._execute_update(query, (fingerprint_id, account_id)) > 0 def update_session_id(self, account_id: int, session_id: str) -> bool: """ Aktualisiert die Session ID eines Accounts. Args: account_id: Account ID session_id: Neue Session ID Returns: True bei Erfolg, False bei Fehler """ query = """ UPDATE accounts SET session_id = ?, last_session_update = datetime('now') WHERE id = ? """ return self._execute_update(query, (session_id, account_id)) > 0 def update_status(self, account_id: int, status: str) -> bool: """ Aktualisiert den Status eines Accounts. Args: account_id: Account ID status: Neuer Status Returns: True bei Erfolg, False bei Fehler """ query = "UPDATE accounts SET status = ? WHERE id = ?" return self._execute_update(query, (status, account_id)) > 0 def _row_to_account(self, row) -> Dict[str, Any]: """Konvertiert eine Datenbankzeile zu einem Account-Dict""" # sqlite3.Row unterstützt dict() Konvertierung direkt if hasattr(row, 'keys'): # Es ist ein sqlite3.Row Objekt account = dict(row) else: # Fallback für normale Tuples # Hole die tatsächlichen Spaltennamen aus der Datenbank conn = sqlite3.connect(self.db_path) cursor = conn.cursor() cursor.execute("PRAGMA table_info(accounts)") columns_info = cursor.fetchall() conn.close() # Extrahiere Spaltennamen columns = [col[1] for col in columns_info] # Erstelle Dict mit vorhandenen Spalten account = {} for i, value in enumerate(row): if i < len(columns): account[columns[i]] = value # Parse metadata wenn vorhanden und die Spalte existiert if 'metadata' in account and account.get('metadata'): try: metadata = json.loads(account['metadata']) account['metadata'] = metadata # Extrahiere platform aus metadata wenn vorhanden if isinstance(metadata, dict) and 'platform' in metadata: account['platform'] = metadata['platform'] except: account['metadata'] = {} # Setze Standardwerte für fehlende Felder if 'platform' not in account: # Standardmäßig auf instagram setzen account['platform'] = 'instagram' # Stelle sicher dass wichtige Felder existieren for field in ['fingerprint_id', 'metadata']: if field not in account: account[field] = None return account