33 KiB
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:
- Account-Erstellung gestartet → Polling alle 10-15 Sekunden
- Login-Versuch fehlgeschlagen (Code erwartet) → Sofort prüfen + alle 5 Sekunden
- Manueller Refresh-Button → Auf Knopfdruck
- Ö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ätigungscodesviews/tabs/- Tab-Integration in Hauptfenstercontrollers/- Controller für Code-Verwaltungdatabase/- Repository für Code-Speicherunglicensing/api_client.py- API-Calls für Code-Abruf (perspektivisch)
Datenbank-Schema
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 abrufenPOST /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
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-Buttonviews/dialogs/- Neue Export-Dialogscontrollers/- Export-Controllerutils/- Export-Service für Format-Generierungresources/icons/- Platform-Logos für PDF
Abhängigkeiten
- Python-Libraries:
csv- CSV-Export (Standard-Library)reportlaboderfpdf- PDF-Generierungzipfile- ZIP mit Passwortschutz (Standard-Library)secrets- Sichere Passwort-Generierung (Standard-Library)
Export-Service Struktur
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ügenviews/tabs/facebook_generator_tab.py- Facebook-spezifische UIviews/tabs/instagram_generator_tab.py- Instagram-spezifische UI (falls existent)social_networks/facebook/facebook_workflow.py- Privacy-Setting Flowsocial_networks/instagram/instagram_workflow.py- Privacy-Setting Flowsocial_networks/tiktok/tiktok_workflow.py- Privacy-Setting Flowsocial_networks/x/x_workflow.py- Privacy-Setting Flow
Implementierung pro Plattform
Neue Methoden in Workflow-Klassen:
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:
# 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 Selektoreninstagram_selectors.py- Privacy Settings Selektorentiktok_selectors.py- Privacy Settings Selektorenx_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_privateFlag 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:
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:
// 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
# 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
# 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:
# 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:
# 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):
# 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-Verwaltungutils/error_tracker.py- NEU - Fehler-Tracking mit Zwangspausebrowser/playwright_manager.py- Erweitern um Browser-Instanz-Zählercontrollers/*_controller.py- Alle Controller integrieren Lock-Prüfungviews/tabs/generator_tab*.py- UI-Updates für deaktivierte Buttonsviews/dialogs/- NEU - Pause-Warning Dialogmain.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