1039 Zeilen
33 KiB
Markdown
1039 Zeilen
33 KiB
Markdown
# 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
|