# AccountForger - Roadmap Dieses Dokument enthält geplante Features und Verbesserungen für AccountForger. --- ## 🎯 Feature 1: Bestätigungscodes-Reiter **Priorität:** Hoch **Status:** Geplant **Geschätzter Aufwand:** 3-5 Tage ### Beschreibung Neuer Reiter "Bestätigungscodes" neben "Plattformen" und "Accounts" für die Verwaltung eingehender Verifizierungscodes. ### Funktionale Anforderungen #### UI/UX Design - **Chat-ähnliche Oberfläche** mit Liste aller eingehenden Codes - **Code-Anzeige Format:** ``` [Social Media Logo] username_123 Code: 456789 📧 example@domain.com ODER 📱 +49123456789 ⏱ Löscht sich in 5h 32min [Kopieren] [Ausblenden] ``` - **WICHTIG:** Keine Emojis für Logo-Platzhalter - echte Platform-Icons verwenden - **Sortierung:** Neueste Codes oben - **Leerer Zustand:** "Keine Bestätigungscodes vorhanden" #### Code-Status & Lebensdauer - **Automatische Löschung:** Codes werden nach **6 Stunden** automatisch entfernt - **Countdown-Timer:** Zeigt verbleibende Zeit bis zur Löschung - **Verwendete Codes:** Grau ausgegraut mit Hinweis "Verwendet" - **Ausblenden-Funktion:** Nutzer kann Codes manuell ausblenden (kein permanentes Löschen) #### Filter & Suche - **Filter-Optionen:** - Nach Plattform (Instagram, Facebook, TikTok, etc.) - Nach Account-Name - Nach Code-Typ (E-Mail vs SMS) - **Suchfeld:** Schnellsuche nach Account-Namen - **Filter kombinierbar:** Mehrere Filter gleichzeitig aktiv #### Copy-Funktion - **Copy-Button:** Kopiert Code mit einem Klick in Zwischenablage - **Visuelles Feedback:** "Kopiert!" kurz anzeigen nach Klick #### Code-Abfrage & Aktualisierung - **Automatische Abfrage erfolgt bei:** 1. **Account-Erstellung gestartet** → Polling alle 10-15 Sekunden 2. **Login-Versuch fehlgeschlagen** (Code erwartet) → Sofort prüfen + alle 5 Sekunden 3. **Manueller Refresh-Button** → Auf Knopfdruck 4. **Öffnen des Bestätigungscodes-Reiters** → Einmalig beim Laden - **Intelligentes Polling:** - Polling stoppt wenn kein aktiver Prozess läuft (Server-Schonung) - Status-Indikator zeigt Aktualisierungsstatus: - "Prüfe auf neue Codes..." (während Abfrage) - "Aktualisiert vor X Sekunden" (nach erfolgreicher Abfrage) #### Datenquellen - **E-Mail-Codes:** Abfrage über Server-API (perspektivisch, siehe Feature 3) - **SMS-Codes:** Abfrage über Server-API (perspektivisch) - Codes erscheinen automatisch wenn sie vom Server abgerufen werden ### Technische Umsetzung #### Betroffene Module - `views/components/` - Neuer Tab für Bestätigungscodes - `views/tabs/` - Tab-Integration in Hauptfenster - `controllers/` - Controller für Code-Verwaltung - `database/` - Repository für Code-Speicherung - `licensing/api_client.py` - API-Calls für Code-Abruf (perspektivisch) #### Datenbank-Schema ```sql CREATE TABLE verification_codes ( id INTEGER PRIMARY KEY, account_name TEXT NOT NULL, platform TEXT NOT NULL, code TEXT NOT NULL, source_type TEXT NOT NULL, -- 'email' oder 'sms' source_value TEXT NOT NULL, -- E-Mail-Adresse oder Telefonnummer received_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, expires_at TIMESTAMP NOT NULL, used BOOLEAN DEFAULT 0, hidden BOOLEAN DEFAULT 0, auto_used BOOLEAN DEFAULT 0 ); ``` #### API-Endpunkte (perspektivisch) - `GET /api/codes/poll` - Neue Codes abrufen - `POST /api/codes/mark-used` - Code als verwendet markieren ### Abhängigkeiten - Feature 3 (Server-seitige E-Mail/SMS-Abfrage) muss implementiert sein für vollständige Funktionalität - Bis dahin: Lokale E-Mail/SMS-Abfrage als Übergangslösung --- ## 📦 Feature 2: Profil-Export **Priorität:** Mittel **Status:** ✅ Abgeschlossen (2025-11-10) **Tatsächlicher Aufwand:** 1 Tag ### Beschreibung Export-Funktion für einzelne Account-Profile zur Weitergabe an andere Nutzer oder als Backup. ### Funktionale Anforderungen #### Export-Umfang **Exportierte Daten:** - ✓ Benutzername - ✓ Passwort - ✓ E-Mail-Adresse - ✓ Telefonnummer - ✓ Plattform - ✓ Vor-/Nachname - ✓ Geburtsdatum - ✓ Erstellungsdatum **NICHT exportiert:** - ✗ Browser-Cookies - ✗ Session Storage - ✗ Browser-Fingerprint - ✗ Proxy-Einstellungen #### Export-Formate ##### 1. CSV-Format ```csv Username,Passwort,E-Mail,Telefon,Plattform,Vorname,Nachname,Geburtsdatum,Erstellt_am waster_ha_948,P@ssw0rd123,waster@domain.com,+49123456789,Instagram,Max,Mustermann,15.03.1995,01.11.2025 ``` - **Trennzeichen:** Komma (,) - **Encoding:** UTF-8 - **Kopfzeile:** Ja (erste Zeile) - **Auch bei Einzelexport:** Nur eine Datenzeile ##### 2. TXT-Format ``` Username: waster_ha_948 Passwort: P@ssw0rd123 E-Mail: waster@domain.com Telefon: +49123456789 Plattform: Instagram Name: Max Mustermann Geburtsdatum: 15.03.1995 Erstellt am: 01.11.2025 ``` - **Struktur:** Key-Value Paare - **Encoding:** UTF-8 ##### 3. PDF-Format ``` ┌────────────────────────────────────────┐ │ [IntelSight Logo] │ │ │ │ Account-Profil: waster_ha_948 │ │ Plattform: [Instagram Logo] Instagram │ │ │ │ LOGIN-DATEN │ │ • Benutzername: waster_ha_948 │ │ • Passwort: P@ssw0rd123 │ │ • E-Mail: waster@domain.com │ │ • Telefon: +49123456789 │ │ │ │ PROFIL-INFORMATIONEN │ │ • Name: Max Mustermann │ │ • Geburtsdatum: 15.03.1995 │ │ • Erstellt am: 01.11.2025 │ │ │ │ Exportiert am: 09.11.2025 15:30 │ └────────────────────────────────────────┘ ``` - **Layout:** Schöne Übersicht mit Logos - **IntelSight-Logo:** Oben links - **Platform-Logo:** Bei Plattform-Angabe - **Fallback:** Text-Only PDF wenn Logos nicht verfügbar #### Mehrfach-Auswahl - **CSV + TXT + PDF** gleichzeitig auswählbar - Alle ausgewählten Formate werden in einem Vorgang exportiert #### Dateinamen-Konvention ``` {username}_{plattform}_{exportdatum}.{format} Beispiele: waster_ha_948_instagram_2025-11-09_15-30.csv waster_ha_948_instagram_2025-11-09_15-30.txt waster_ha_948_instagram_2025-11-09_15-30.pdf ``` - **Datumsformat:** `YYYY-MM-DD_HH-mm` - **Kleinschreibung:** Plattform-Name in Kleinbuchstaben #### Passwortschutz ##### Automatische Passwort-Generierung - **Aktivierung:** Optional per Checkbox im Export-Dialog - **Länge:** 10 Zeichen - **Zeichen:** Alphanumerisch + Sonderzeichen - **Beispiel:** `Xy7#mK9@pL` ##### Passwort-Anzeige Nach erfolgreichem Export wird Passwort angezeigt: ``` ┌─ Export erfolgreich ──────────────────┐ │ │ │ ✓ Profil exportiert! │ │ │ │ Datei: │ │ waster_ha_948_instagram_2025-...zip │ │ │ │ 🔒 Passwort: Xy7#mK9@pL │ │ [Kopieren] │ │ │ │ ⚠ Bitte Passwort speichern! │ │ │ │ [Ordner öffnen] [OK] │ └────────────────────────────────────────┘ ``` - **Kopieren-Button:** Kopiert Passwort in Zwischenablage - **Warnung:** Nutzer wird aufgefordert, Passwort zu speichern ##### Verschlüsselung **Mit Passwortschutz:** - Alle ausgewählten Formate werden in **eine ZIP-Datei** gepackt - ZIP-Datei wird mit generiertem Passwort verschlüsselt - Dateiname: `{username}_{plattform}_{exportdatum}.zip` - Enthält: CSV, TXT, PDF (je nach Auswahl) **Ohne Passwortschutz:** - Separate Dateien für jedes Format - Keine ZIP-Datei #### Export-Dialog ``` ┌─ Profil exportieren ──────────────┐ │ │ │ Format (mehrfach auswählbar): │ │ ☑ CSV │ │ ☑ TXT │ │ ☐ PDF │ │ │ │ ☑ Mit Passwort schützen │ │ (Wird automatisch generiert) │ │ │ │ [Abbrechen] [Exportieren] │ └────────────────────────────────────┘ ``` - **Mindestens ein Format** muss ausgewählt sein - Bei Passwortschutz: Keine manuelle Passworteingabe - Nach Klick auf "Exportieren": Save-Dialog öffnet sich #### Speicherort - **Nutzer wählt** Speicherort per Standard-Datei-Dialog - **Kein Standard-Ordner** vordefiniert - Letzte Auswahl wird **nicht** gespeichert #### UI-Integration - **Bestehender Button:** "Exportieren" im Accounts-Tab wird erweitert - **Einzelexport:** Nur der aktuell ausgewählte Account - **Kein Batch-Export:** Mehrfach-Export vorerst nicht implementiert #### Erfolgs-Feedback ``` ┌─ Export erfolgreich ──────────────────┐ │ │ │ ✓ Profil exportiert! │ │ │ │ Dateien: │ │ • waster_ha_948_instagram_2025-...csv │ │ • waster_ha_948_instagram_2025-...txt │ │ │ │ [MIT PASSWORT: Passwort-Anzeige] │ │ │ │ Gespeichert in: C:\Users\...\ │ │ │ │ [Ordner öffnen] [OK] │ └────────────────────────────────────────┘ ``` - **Dateiliste:** Alle exportierten Dateien anzeigen - **Ordner öffnen:** Button öffnet Zielordner im Explorer/Finder - **Passwort:** Nur wenn Passwortschutz aktiviert wurde #### Fehlerbehandlung - **Export fehlgeschlagen:** Fehlermeldung mit Grund - "Festplatte voll" - "Keine Schreibrechte" - "Datei bereits vorhanden und schreibgeschützt" - **Logo nicht gefunden:** PDF-Export mit Text-Only Fallback ### Technische Umsetzung #### Betroffene Module - `views/tabs/accounts_tab.py` - Erweiterung Export-Button - `views/dialogs/` - Neue Export-Dialogs - `controllers/` - Export-Controller - `utils/` - Export-Service für Format-Generierung - `resources/icons/` - Platform-Logos für PDF #### Abhängigkeiten - **Python-Libraries:** - `csv` - CSV-Export (Standard-Library) - `reportlab` oder `fpdf` - PDF-Generierung - `zipfile` - ZIP mit Passwortschutz (Standard-Library) - `secrets` - Sichere Passwort-Generierung (Standard-Library) #### Export-Service Struktur ```python class ProfileExportService: def export_to_csv(account_data) -> bytes def export_to_txt(account_data) -> bytes def export_to_pdf(account_data) -> bytes def generate_password() -> str def create_protected_zip(files, password) -> bytes ``` ### Ausschlüsse - **Kein Re-Import:** Import-Funktion wird NICHT implementiert - **Kein Batch-Export:** Nur Einzelexport - **Keine Verschlüsselung ohne Passwort:** Ungeschützte Dateien sind Plain-Text --- ## 📋 Weitere Features ### Feature 3: Server-seitige E-Mail/SMS-Abfrage **Status:** Geplant *Details folgen nach Abstimmung* --- ## 🔒 Feature 4: Privater Account erstellen **Priorität:** Mittel **Status:** Geplant **Geschätzter Aufwand:** 3-4 Tage ### Beschreibung Checkbox in der Account-Erstellungsmaske zum automatischen Setzen des Account-Privatsphäre-Modus auf "privat" während der Registrierung. ### Funktionale Anforderungen #### Unterstützte Plattformen - **Facebook** - Privacy Settings auf "Friends" - **Instagram** - Private Account aktivieren - **TikTok** - Private Account aktivieren - **X/Twitter** - Protect your posts aktivieren **NICHT unterstützt:** - Gmail (keine Privatsphäre-Einstellung in diesem Sinne) - VK, OK.ru (vorerst) #### UI-Integration **Checkbox in Account-Erstellungsmaske:** ``` ┌─ Account erstellen (Instagram) ────┐ │ │ │ Vorname: [_______________] │ │ Nachname: [_______________] │ │ Alter: [___] │ │ │ │ ☐ Privaten Account erstellen │ │ │ │ Registrierungsmethode: │ │ ○ E-Mail ○ Telefon │ │ │ │ [Abbrechen] [Erstellen] │ └─────────────────────────────────────┘ ``` - **Position:** Unterhalb der Basis-Daten (Name, Alter), oberhalb Registrierungsmethode - **Standard:** Deaktiviert (nicht angehakt) - **Sichtbarkeit:** Nur bei unterstützten Plattformen anzeigen - **Label:** "Privaten Account erstellen" #### Ablauf **Wenn Checkbox aktiviert:** ``` 1. Normale Account-Erstellung (wie bisher) - Registrierung - Profil-Daten eingeben - Verifizierung abschließen 2. Account erfolgreich erstellt ↓ 3. Navigiere zu Privacy-Settings ↓ 4. Setze Account auf "privat" - Instagram: Settings → Privacy → Private Account (Toggle ON) - Facebook: Settings → Privacy → Who can see posts → Friends - TikTok: Settings → Privacy → Private Account (Toggle ON) - X: Settings → Privacy and Safety → Protect your posts (Toggle ON) ↓ 5. Zurück zum Hauptbildschirm ``` **Timing:** Als **Teil des Registrierungs-Flows**, direkt nach erfolgreicher Verifizierung, bevor "Account erstellt"-Dialog erscheint. #### Erfolgs-/Fehler-Feedback **Bei Erfolg:** ``` ┌─ Account erstellt ────────────────┐ │ │ │ ✓ Account erstellt: waster_ha_948 │ │ ✓ Account auf privat gesetzt │ │ │ │ [OK] │ └────────────────────────────────────┘ ``` **Bei Fehler:** ``` ┌─ Account erstellt ────────────────┐ │ │ │ ✓ Account erstellt: waster_ha_948 │ │ │ │ ⚠ Account konnte nicht auf privat │ │ gesetzt werden │ │ │ │ Fehler: Timeout beim Laden der │ │ Privacy-Settings │ │ │ │ Bitte setzen Sie den Account │ │ manuell auf privat. │ │ │ │ [OK] │ └────────────────────────────────────┘ ``` - **Kein Retry:** Keine "Erneut versuchen" Option - **Account behalten:** Account wird auch bei Fehler gespeichert - **Nutzer-Aktion:** Hinweis dass manuelles Setzen erforderlich ist #### Keine Verifizierung - **Keine Prüfung** ob Account tatsächlich privat ist - Software versucht nur, Privacy-Setting zu setzen - Bei Erfolg (kein Fehler) → Annehmen dass es funktioniert hat ### Technische Umsetzung #### Betroffene Module - `views/tabs/generator_tab_factory.py` - Checkbox hinzufügen - `views/tabs/facebook_generator_tab.py` - Facebook-spezifische UI - `views/tabs/instagram_generator_tab.py` - Instagram-spezifische UI (falls existent) - `social_networks/facebook/facebook_workflow.py` - Privacy-Setting Flow - `social_networks/instagram/instagram_workflow.py` - Privacy-Setting Flow - `social_networks/tiktok/tiktok_workflow.py` - Privacy-Setting Flow - `social_networks/x/x_workflow.py` - Privacy-Setting Flow #### Implementierung pro Plattform **Neue Methoden in Workflow-Klassen:** ```python class FacebookWorkflow: def set_privacy_to_private(self) -> bool: """ Setzt Facebook-Account auf privat (Friends only). Returns: True bei Erfolg, False bei Fehler """ try: # 1. Navigiere zu Settings # 2. Öffne Privacy-Bereich # 3. Setze "Who can see posts" auf "Friends" # 4. Speichern return True except Exception as e: logger.error(f"Privacy-Setting fehlgeschlagen: {e}") return False ``` **Analoger Code für Instagram, TikTok, X** #### Workflow-Integration **In Account-Creation Workflow:** ```python # Nach erfolgreicher Verifizierung if registration_successful: # Account in DB speichern save_account_to_db(account_data) # Wenn "Privat"-Checkbox aktiviert war if create_private_account: try: privacy_success = workflow.set_privacy_to_private() if privacy_success: return { "success": True, "message": "Account erstellt und auf privat gesetzt", "privacy_set": True } else: return { "success": True, "message": "Account erstellt, aber Privacy-Setting fehlgeschlagen", "privacy_set": False, "privacy_error": "Konnte nicht auf privat gesetzt werden" } except Exception as e: return { "success": True, "message": "Account erstellt", "privacy_set": False, "privacy_error": str(e) } else: return { "success": True, "message": "Account erstellt", "privacy_set": None # Nicht versucht } ``` #### Selektoren (pro Plattform neu) **Neue Selector-Definitionen benötigt:** - `facebook_selectors.py` - Privacy Settings Selektoren - `instagram_selectors.py` - Privacy Settings Selektoren - `tiktok_selectors.py` - Privacy Settings Selektoren - `x_selectors.py` - Privacy Settings Selektoren ### Abhängigkeiten - **Playwright/Browser-Automatisierung** muss Privacy-Settings-Seiten navigieren können - **Plattform-spezifische Selektoren** müssen recherchiert und getestet werden - **Zeitverzögerung:** Rechne mit +10-20 Sekunden pro Account-Erstellung ### Risiken & Bekannte Probleme - **UI-Änderungen:** Wenn Plattformen Privacy-Settings-UI ändern, bricht Feature - **Rate-Limiting:** Zusätzliche Aktionen könnten Rate-Limits schneller erreichen - **A/B-Testing:** Manche Nutzer sehen andere UI-Varianten - **Keine Garantie:** Auch bei "Erfolg" könnte Setting nicht gesetzt sein (keine Verifizierung) ### Ausschlüsse - **Keine Verifizierung:** Wird nicht geprüft ob Account wirklich privat ist - **Kein Retry:** Bei Fehler keine automatische Wiederholung - **Keine Datenbank-Speicherung:** `is_private` Flag wird NICHT in DB gespeichert - **Keine nachträgliche Änderung:** Funktion nur während Erstellung, nicht nachträglich änderbar --- ## 🛡️ Feature 5: Software Missbrauch Schutz **Priorität:** Hoch **Status:** ✅ Abgeschlossen (2025-11-10) **Tatsächlicher Aufwand:** 2 Tage ### Beschreibung Schutzmaßnahmen gegen versehentlichen oder absichtlichen Missbrauch der Software durch parallele Prozesse, zu viele Browser-Instanzen oder wiederholte Fehlversuche. ### Funktionale Anforderungen #### 1. Process Lock Manager **Zentrale Steuerung für alle Prozesse:** - Nur **ein Vorgang gleichzeitig** erlaubt - Gilt für: Account-Erstellung, Login, Export (alle Prozess-Typen) - Plattform-übergreifend: Keine Instagram-Erstellung während Facebook-Login **Verhalten:** ``` Situation: Instagram-Account wird erstellt ↓ Nutzer versucht Facebook-Account zu erstellen ↓ ⚠️ Warnung: "Prozess läuft bereits" ↓ "Bitte warten Sie bis 'Account-Erstellung (Instagram)' abgeschlossen ist." ↓ Buttons ausgegraut + Tooltip ``` **UI-Feedback:** - Alle Prozess-Buttons werden **deaktiviert** (ausgegraut) - Tooltip zeigt: "Warten Sie bis aktueller Vorgang abgeschlossen ist" - Warnmeldung bei Klick-Versuch auf deaktivierten Button **Crash-Sicherheit:** - Bei Programm-Neustart: Lock wird **automatisch zurückgesetzt** - Keine persistente Speicherung des Lock-Status - Lock nur im Memory während Laufzeit #### 2. Browser-Instanz Schutz **Nur eine Playwright-Instanz gleichzeitig:** - Verhindert mehrere Browser-Fenster parallel - Ressourcen-Schonung (RAM, CPU) - Vermeidet Konflikte zwischen Browser-Instanzen **Implementierung:** ```python class PlaywrightManager: _active_browser_count = 0 _max_browsers = 1 def launch_browser(self): if self._active_browser_count >= self._max_browsers: raise Exception( "Browser bereits aktiv. " "Beenden Sie den aktuellen Prozess." ) self._active_browser_count += 1 # ... Browser starten def close_browser(self): self._active_browser_count -= 1 ``` **Fehlerbehandlung:** - Bei Absturz: Browser-Counter wird beim Neustart zurückgesetzt - Bei forciertem Schließen: Counter wird dekrementiert #### 3. Fehler-Tracking mit Zwangspause **Automatische Pause nach wiederholten Fehlschlägen:** - Nach **3 fehlgeschlagenen** Account-Erstellungen **hintereinander** - **Zwangspause von 1 Stunde** (nicht überspringbar) - Verhindert Rate-Limiting und IP-Sperren **Fehler-Zählung:** ``` Versuch 1: Instagram Account → Fehler ❌ (Zähler: 1) Versuch 2: Facebook Account → Fehler ❌ (Zähler: 2) Versuch 3: TikTok Account → Fehler ❌ (Zähler: 3) ↓ 🚫 ZWANGSPAUSE AKTIVIERT (1 Stunde) ``` **Reset-Bedingungen:** - Bei **Erfolg**: Fehler-Zähler wird auf 0 zurückgesetzt - Nach **Pause-Ende**: Fehler-Zähler wird auf 0 zurückgesetzt - Bei **Programm-Neustart**: Fehler-Zähler wird NICHT zurückgesetzt (persistiert) **UI während Zwangspause:** ``` ┌─ Automatische Pause aktiv ────────┐ │ │ │ ⏸️ Zwangspause wegen Fehlerrate │ │ │ │ Nach 3 fehlgeschlagenen Versuchen │ │ ist eine Pause erforderlich. │ │ │ │ ⏰ Verbleibende Zeit: 47 Min │ │ │ │ Empfehlung: │ │ • Proxy-Einstellungen prüfen │ │ • Internetverbindung prüfen │ │ • Plattform-Status überprüfen │ │ │ │ [Schließen] │ └────────────────────────────────────┘ ``` - **Countdown-Timer** zeigt verbleibende Zeit - Alle Prozess-Buttons **deaktiviert** - **Nicht überspringbar** - kein "Pause beenden" Button - Persistiert über Programm-Neustarts (in Datei gespeichert) **Persistierung:** ```json // config/.error_tracking { "consecutive_failures": 3, "pause_until": "2025-11-09T16:30:00", "last_failure_platform": "Instagram", "last_failure_reason": "Timeout bei Verifizierung" } ``` ### Technische Umsetzung #### Process Lock Manager Klasse ```python # utils/process_lock_manager.py import time from typing import Optional from datetime import datetime class ProcessLockManager: """ Zentrale Verwaltung für Prozess-Locks und Fehler-Tracking. Singleton-Pattern für globalen Zugriff. """ _instance = None _lock_active = False _current_process = None _current_platform = None def __new__(cls): if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance @classmethod def start_process(cls, process_type: str, platform: str) -> bool: """ Versucht einen Prozess zu starten. Args: process_type: Art des Prozesses ("Account-Erstellung", "Login", etc.) platform: Plattform (Instagram, Facebook, etc.) Returns: True wenn gestartet, False wenn blockiert """ if cls._lock_active: return False cls._lock_active = True cls._current_process = process_type cls._current_platform = platform return True @classmethod def end_process(cls, success: bool = True): """ Beendet den aktuellen Prozess. Args: success: Ob Prozess erfolgreich war """ cls._lock_active = False cls._current_process = None cls._current_platform = None # Fehler-Tracking aktualisieren if success: ErrorTracker.reset_failures() else: ErrorTracker.report_failure(cls._current_platform) @classmethod def is_locked(cls) -> bool: """Gibt zurück ob aktuell ein Prozess läuft""" return cls._lock_active @classmethod def get_current_process_info(cls) -> Optional[dict]: """Gibt Info über aktuellen Prozess zurück""" if not cls._lock_active: return None return { "type": cls._current_process, "platform": cls._current_platform } @classmethod def force_unlock(cls, reason: str = "Manuell"): """ Entsperrt zwangsweise (nur bei Absturz). Args: reason: Grund für Force-Unlock """ logger.warning(f"Process Lock wurde entsperrt: {reason}") cls._lock_active = False cls._current_process = None cls._current_platform = None @classmethod def reset_on_startup(cls): """Wird beim Programmstart aufgerufen""" cls.force_unlock("Programm-Neustart") ``` #### Error Tracker Klasse ```python # utils/error_tracker.py import json import os from datetime import datetime, timedelta from typing import Optional class ErrorTracker: """Tracking von fehlgeschlagenen Prozessen mit Zwangspause.""" CONFIG_FILE = os.path.join("config", ".error_tracking") MAX_FAILURES = 3 PAUSE_DURATION_HOURS = 1 _consecutive_failures = 0 _pause_until = None @classmethod def load_state(cls): """Lädt gespeicherten State beim Start""" if not os.path.exists(cls.CONFIG_FILE): return try: with open(cls.CONFIG_FILE, 'r') as f: data = json.load(f) cls._consecutive_failures = data.get('consecutive_failures', 0) pause_until_str = data.get('pause_until') if pause_until_str: cls._pause_until = datetime.fromisoformat(pause_until_str) # Prüfe ob Pause abgelaufen if datetime.now() > cls._pause_until: cls._pause_until = None cls._consecutive_failures = 0 cls._save_state() except Exception as e: logger.error(f"Fehler beim Laden von Error Tracking: {e}") @classmethod def _save_state(cls): """Speichert aktuellen State""" try: os.makedirs(os.path.dirname(cls.CONFIG_FILE), exist_ok=True) data = { 'consecutive_failures': cls._consecutive_failures, 'pause_until': cls._pause_until.isoformat() if cls._pause_until else None, 'last_update': datetime.now().isoformat() } with open(cls.CONFIG_FILE, 'w') as f: json.dump(data, f, indent=2) except Exception as e: logger.error(f"Fehler beim Speichern von Error Tracking: {e}") @classmethod def report_failure(cls, platform: str): """ Meldet einen Fehlschlag. Args: platform: Plattform auf der Fehler auftrat """ cls._consecutive_failures += 1 logger.warning(f"Fehlschlag #{cls._consecutive_failures} auf {platform}") if cls._consecutive_failures >= cls.MAX_FAILURES: # Aktiviere Zwangspause cls._pause_until = datetime.now() + timedelta(hours=cls.PAUSE_DURATION_HOURS) logger.error( f"Zwangspause aktiviert bis {cls._pause_until.strftime('%H:%M')} " f"nach {cls.MAX_FAILURES} Fehlschlägen" ) cls._save_state() @classmethod def reset_failures(cls): """Setzt Fehler-Zähler bei Erfolg zurück""" if cls._consecutive_failures > 0: logger.info("Fehler-Zähler zurückgesetzt nach Erfolg") cls._consecutive_failures = 0 cls._save_state() @classmethod def is_paused(cls) -> bool: """Gibt zurück ob aktuell Zwangspause aktiv ist""" if cls._pause_until is None: return False if datetime.now() > cls._pause_until: # Pause ist abgelaufen cls._pause_until = None cls._consecutive_failures = 0 cls._save_state() return False return True @classmethod def get_pause_remaining_seconds(cls) -> Optional[int]: """Gibt verbleibende Sekunden der Pause zurück""" if not cls.is_paused(): return None remaining = (cls._pause_until - datetime.now()).total_seconds() return max(0, int(remaining)) @classmethod def get_pause_info(cls) -> Optional[dict]: """Gibt Info über aktive Pause zurück""" if not cls.is_paused(): return None remaining_seconds = cls.get_pause_remaining_seconds() remaining_minutes = remaining_seconds // 60 return { 'active': True, 'remaining_seconds': remaining_seconds, 'remaining_minutes': remaining_minutes, 'pause_until': cls._pause_until.strftime('%H:%M'), 'consecutive_failures': cls._consecutive_failures } ``` #### Integration in bestehenden Code **In main.py beim Start:** ```python # Beim Programmstart ProcessLockManager.reset_on_startup() ErrorTracker.load_state() # Prüfe ob Pause aktiv if ErrorTracker.is_paused(): pause_info = ErrorTracker.get_pause_info() show_pause_dialog(pause_info) ``` **In allen Controller-Klassen:** ```python # facebook_controller.py, instagram_controller.py, etc. def create_account(self, account_data): # 1. Prüfe Zwangspause if ErrorTracker.is_paused(): pause_info = ErrorTracker.get_pause_info() show_pause_warning(pause_info) return # 2. Prüfe Process Lock if not ProcessLockManager.start_process("Account-Erstellung", "Instagram"): current = ProcessLockManager.get_current_process_info() show_warning( "Prozess läuft bereits", f"Bitte warten Sie bis '{current['type']} ({current['platform']})' " f"abgeschlossen ist." ) return try: # 3. Normaler Prozess self.show_modal() result = self._perform_account_creation(account_data) # 4. Lock freigeben mit Erfolgs-Status ProcessLockManager.end_process(success=result['success']) return result except Exception as e: # Bei Fehler: Lock freigeben mit Fehler-Status ProcessLockManager.end_process(success=False) raise ``` **In Generator Tabs (UI):** ```python # views/tabs/generator_tab.py def update_ui_state(self): """Aktualisiert Button-Status basierend auf Locks""" # Prüfe Zwangspause is_paused = ErrorTracker.is_paused() is_locked = ProcessLockManager.is_locked() # Deaktiviere Buttons wenn Pause oder Lock aktiv self.create_button.setEnabled(not is_paused and not is_locked) # Tooltip setzen if is_paused: pause_info = ErrorTracker.get_pause_info() tooltip = f"Zwangspause aktiv (noch {pause_info['remaining_minutes']} Min)" elif is_locked: current = ProcessLockManager.get_current_process_info() tooltip = f"Warten Sie bis '{current['type']}' abgeschlossen ist" else: tooltip = "Account erstellen" self.create_button.setToolTip(tooltip) ``` #### Betroffene Module - `utils/process_lock_manager.py` - **NEU** - Zentrale Lock-Verwaltung - `utils/error_tracker.py` - **NEU** - Fehler-Tracking mit Zwangspause - `browser/playwright_manager.py` - Erweitern um Browser-Instanz-Zähler - `controllers/*_controller.py` - Alle Controller integrieren Lock-Prüfung - `views/tabs/generator_tab*.py` - UI-Updates für deaktivierte Buttons - `views/dialogs/` - **NEU** - Pause-Warning Dialog - `main.py` - Startup-Initialisierung ### Abhängigkeiten - Bestehendes Modal-System (ProgressModal, AccountCreationModal, LoginProcessModal) - Logging-System für Error-Tracking - File-System für Persistierung (.error_tracking) ### Risiken & Edge Cases - **Browser-Absturz:** Counter könnte falsch sein → Reset bei Neustart - **Zwangspause zu streng:** Nutzer könnte frustriert sein → Klare Kommunikation wichtig - **Lock bleibt hängen:** Failsafe-Timer (5 Min) im Modal verhindert dies ### Ausschlüsse - **KEIN** Manual Override / Force-Unlock Button - **KEIN** Cooldown zwischen Account-Erstellungen - **KEINE** Plattform-spezifischen Rate-Limits - **KEINE** Pause-Überspringen-Funktion --- ## 📋 Weitere Features ### Feature 3: Server-seitige E-Mail/SMS-Abfrage **Status:** Geplant *Details folgen nach Abstimmung* --- **Letzte Aktualisierung:** 2025-11-09