Insta geht wieder, wegen dem Domain Umzug

Dieser Commit ist enthalten in:
Claude Project Manager
2025-11-27 21:17:32 +01:00
Ursprung 2d276f167c
Commit 8e4a052b6c
16 geänderte Dateien mit 208 neuen und 38 gelöschten Zeilen

Datei anzeigen

@ -1,13 +1,18 @@
{
"permissions": {
"allow": [
"Bash(python3:*)"
"Bash(python3:*)",
"Bash(tree:*)",
"Bash(git -C /mnt/a/GiTea/AccountForger log --oneline)",
"Bash(cat:*)",
"Bash(sqlite3:*)",
"Bash(find:*)"
],
"deny": [],
"ask": [],
"defaultMode": "acceptEdits",
"additionalDirectories": [
"/mnt/a/GiTea/Styleguide"
],
"ask": []
]
}
}

Datei anzeigen

@ -5,9 +5,9 @@
## Project Overview
- **Path**: `A:\GiTea\AccountForger`
- **Files**: 1393 files
- **Files**: 1394 files
- **Size**: 257.7 MB
- **Last Modified**: 2025-11-16 22:31
- **Last Modified**: 2025-11-27 19:34
## Technology Stack
@ -21,13 +21,13 @@
```
check_rotation_system.py
CLAUDE.md
CLAUDE_PROJECT_README.md
debug_video_issue.py
init
install_requirements.py
main.py
package.json
README.md
application/
│ ├── __init__.py
│ ├── services/
@ -436,3 +436,6 @@ This project is managed with Claude Project Manager. To work with this project:
- README updated on 2025-11-09 21:00:06
- README updated on 2025-11-16 22:31:39
- README updated on 2025-11-16 22:32:35
- README updated on 2025-11-27 19:33:36
- README updated on 2025-11-27 19:34:18
- README updated on 2025-11-27 19:41:04

Datei anzeigen

@ -1,6 +1,6 @@
{
"imap_server": "imap.ionos.de",
"imap_port": 993,
"imap_user": "info@z5m7q9dk3ah2v1plx6ju.com",
"imap_pass": "GZsg9:66@a@M%etP"
}
"imap_server": "imap.ionos.de",
"imap_port": 993,
"imap_user": "info@z5m7q9dk3ah2v1plx6ju.com",
"imap_pass": "GZsg9:66@a@M%etP"
}

Datei anzeigen

@ -280,3 +280,34 @@ class BasePlatformController(QObject):
# Standard-Implementierung - kann von Unterklassen erweitert werden
self.logger.info(f"Account erfolgreich erstellt für {self.platform_name}")
def stop_account_creation(self):
"""
Stoppt die Account-Erstellung (Default-Implementierung).
Diese Methode kann von Unterklassen überschrieben werden für spezielle Anforderungen.
Sie stellt sicher dass:
1. Der Process Guard freigegeben wird
2. Der Worker-Thread gestoppt wird
3. Die UI zurückgesetzt wird
4. Dialoge geschlossen werden
"""
# Guard-Freigabe (wichtig: VOR Worker-Stop)
from utils.process_guard import get_guard
guard = get_guard()
if guard.is_locked():
guard.end(success=False)
self.logger.info("Guard freigegeben bei Stop (BaseController)")
# Worker stoppen falls vorhanden
if self.worker_thread and self.worker_thread.isRunning():
self.worker_thread.stop()
generator_tab = self.get_generator_tab()
generator_tab.add_log(f"{self.platform_name}-Account-Erstellung wurde abgebrochen")
generator_tab.set_running(False)
generator_tab.set_progress(0)
# Forge-Dialog schließen falls vorhanden
if hasattr(self, 'forge_dialog') and self.forge_dialog:
self.forge_dialog.close()
self.forge_dialog = None

Datei anzeigen

@ -283,6 +283,24 @@ class BaseAccountCreationWorkerThread(QThread):
return save_result
def stop(self):
"""Stoppt den Thread"""
"""
Stoppt den Thread sauber mit Guard-Freigabe.
WICHTIG: Guard wird SOFORT freigegeben, da terminate() den finally-Block überspringt.
"""
import logging
logger = logging.getLogger(__name__)
self.running = False
# Guard SOFORT freigeben bevor terminate()
# Grund: terminate() überspringt den finally-Block in run()
from utils.process_guard import get_guard
guard = get_guard()
if guard.is_locked():
guard.end(success=False)
logger.info("Guard freigegeben bei Worker-Stop (vor terminate)")
# Jetzt Thread beenden
self.terminate()
self.wait(2000) # Warte max 2 Sekunden auf sauberes Ende

Datei anzeigen

@ -287,7 +287,15 @@ class FacebookController(BasePlatformController):
self.forge_dialog = None
def stop_account_creation(self):
"""Stoppt die Facebook-Account-Erstellung."""
"""Stoppt die Facebook-Account-Erstellung mit Guard-Freigabe."""
# Guard-Freigabe (wichtig: VOR Worker-Stop)
from utils.process_guard import get_guard
guard = get_guard()
if guard.is_locked():
guard.end(success=False)
self.logger.info("Guard freigegeben bei Facebook Stop")
# Worker stoppen
if self.worker_thread and self.worker_thread.isRunning():
self.worker_thread.stop()
generator_tab = self.get_generator_tab()

Datei anzeigen

@ -198,13 +198,22 @@ class GmailController(BasePlatformController):
logger.info(f"[GMAIL] start_account_creation abgeschlossen")
def stop_account_creation(self):
"""Stoppt die laufende Account-Erstellung"""
"""Stoppt die laufende Account-Erstellung mit Guard-Freigabe"""
logger.info("[GMAIL] Stoppe Account-Erstellung")
# Guard-Freigabe (wichtig: VOR Worker-Stop)
from utils.process_guard import get_guard
guard = get_guard()
if guard.is_locked():
guard.end(success=False)
logger.info("Guard freigegeben bei Gmail Stop")
# Worker stoppen
if self.worker_thread and self.worker_thread.isRunning():
self.worker_thread.stop()
self.worker_thread.wait()
# Dialog schließen
if hasattr(self, 'forge_dialog') and self.forge_dialog:
self.forge_dialog.close()

Datei anzeigen

@ -269,7 +269,15 @@ class InstagramController(BasePlatformController):
self.forge_dialog.show()
def stop_account_creation(self):
"""Stoppt die Instagram-Account-Erstellung."""
"""Stoppt die Instagram-Account-Erstellung mit Guard-Freigabe."""
# Guard-Freigabe (wichtig: VOR Worker-Stop)
from utils.process_guard import get_guard
guard = get_guard()
if guard.is_locked():
guard.end(success=False)
self.logger.info("Guard freigegeben bei Instagram Stop")
# Worker stoppen
if self.worker_thread and self.worker_thread.isRunning():
self.worker_thread.stop()
generator_tab = self.get_generator_tab()

Datei anzeigen

@ -131,7 +131,15 @@ class OkRuController(BasePlatformController):
self.forge_dialog.show()
def stop_account_creation(self):
"""Stoppt die OK.ru-Account-Erstellung."""
"""Stoppt die OK.ru-Account-Erstellung mit Guard-Freigabe."""
# Guard-Freigabe (wichtig: VOR Worker-Stop)
from utils.process_guard import get_guard
guard = get_guard()
if guard.is_locked():
guard.end(success=False)
self.logger.info("Guard freigegeben bei OK.ru Stop")
# Worker stoppen
if self.worker_thread and self.worker_thread.isRunning():
self.worker_thread.stop()
generator_tab = self.get_generator_tab()

Datei anzeigen

@ -273,7 +273,15 @@ class TikTokController(BasePlatformController):
self.forge_dialog.show()
def stop_account_creation(self):
"""Stoppt die TikTok-Account-Erstellung."""
"""Stoppt die TikTok-Account-Erstellung mit Guard-Freigabe."""
# Guard-Freigabe (wichtig: VOR Worker-Stop)
from utils.process_guard import get_guard
guard = get_guard()
if guard.is_locked():
guard.end(success=False)
self.logger.info("Guard freigegeben bei TikTok Stop")
# Worker stoppen
if self.worker_thread and self.worker_thread.isRunning():
self.worker_thread.stop()
generator_tab = self.get_generator_tab()

Datei anzeigen

@ -271,7 +271,15 @@ class XController(BasePlatformController):
self.forge_dialog.show()
def stop_account_creation(self):
"""Stoppt die X-Account-Erstellung."""
"""Stoppt die X-Account-Erstellung mit Guard-Freigabe."""
# Guard-Freigabe (wichtig: VOR Worker-Stop)
from utils.process_guard import get_guard
guard = get_guard()
if guard.is_locked():
guard.end(success=False)
self.logger.info("Guard freigegeben bei X Stop")
# Worker stoppen
if self.worker_thread and self.worker_thread.isRunning():
self.worker_thread.stop()
generator_tab = self.get_generator_tab()

Datei anzeigen

@ -129,18 +129,18 @@ class SessionController(QObject):
self.login_failed.emit(account_id, str(e))
def _cancel_login(self, account_id: str):
"""Bricht den Login-Prozess ab"""
"""Bricht den Login-Prozess ab mit Guard-Freigabe"""
logger.info(f"Login für Account {account_id} wurde abgebrochen")
# Feature 5: Guard freigeben bei Cancel
# HINWEIS: Worker Thread gibt Guard in seinem finally-Block frei
# Nur freigeben wenn Worker noch nicht gestartet (Guard locked aber kein Worker)
# Guard IMMER freigeben bei Cancel (einfacher + robuster)
# Doppelte Freigabe ist kein Problem (wird von ProcessGuard ignoriert)
from utils.process_guard import get_guard
guard = get_guard()
if guard.is_locked() and not (hasattr(self, 'login_worker') and self.login_worker and self.login_worker.isRunning()):
logger.warning("Guard war locked aber Worker nicht aktiv - gebe Guard frei")
if guard.is_locked():
guard.end(success=False)
logger.info("Guard freigegeben bei Login-Cancel")
# Dialog schließen
if hasattr(self, 'login_dialog') and self.login_dialog:
self.login_dialog.close()
self.login_dialog = None

Binäre Datei nicht angezeigt.

Datei anzeigen

@ -15,6 +15,7 @@ from email.header import decode_header
from datetime import datetime, timedelta
from utils.text_similarity import TextSimilarity
from config.paths import PathConfig
logger = logging.getLogger("email_handler")
@ -23,7 +24,7 @@ class EmailHandler:
Handler für den Zugriff auf E-Mail-Dienste und den Abruf von Bestätigungscodes.
"""
CONFIG_FILE = os.path.join("config", "email_config.json")
CONFIG_FILE = os.path.join(PathConfig.CONFIG_DIR, "email_config.json")
def __init__(self):
"""Initialisiert den EmailHandler und lädt die Konfiguration."""

Datei anzeigen

@ -31,6 +31,7 @@ class ProcessGuard:
# Konfiguration
MAX_FAILURES = 3
PAUSE_DURATION_HOURS = 1
LOCK_TIMEOUT_MINUTES = 10 # Auto-Unlock nach 10 Minuten bei hängenden Prozessen
def __init__(self):
"""Initialisiert den Process Guard."""
@ -38,6 +39,7 @@ class ProcessGuard:
self._is_locked = False
self._current_process = None
self._current_platform = None
self._lock_started_at = None # Timestamp für Auto-Timeout
# Error Tracking
self._failure_count = 0
@ -95,6 +97,7 @@ class ProcessGuard:
self._is_locked = True
self._current_process = process_type
self._current_platform = platform
self._lock_started_at = datetime.now() # Timestamp für Auto-Timeout
logger.info(f"Process locked: {process_type} ({platform})")
def end(self, success: bool):
@ -109,6 +112,7 @@ class ProcessGuard:
self._is_locked = False
self._current_process = None
self._current_platform = None
self._lock_started_at = None # Timestamp zurücksetzen
# Fehler-Tracking
if success:
@ -133,6 +137,7 @@ class ProcessGuard:
self._is_locked = False
self._current_process = None
self._current_platform = None
self._lock_started_at = None # Timestamp zurücksetzen
self._load_pause_state()
if self._is_paused():
@ -143,12 +148,31 @@ class ProcessGuard:
def is_locked(self) -> bool:
"""
Gibt zurück ob aktuell ein Prozess läuft.
Gibt zurück ob aktuell ein Prozess läuft (mit Auto-Timeout-Check).
Returns:
True wenn ein Prozess aktiv ist
"""
return self._is_locked
if not self._is_locked:
return False
# Auto-Timeout-Check: Unlock bei hängenden Prozessen
if self._lock_started_at:
elapsed_minutes = (datetime.now() - self._lock_started_at).total_seconds() / 60
if elapsed_minutes > self.LOCK_TIMEOUT_MINUTES:
logger.warning(
f"⏰ AUTO-TIMEOUT: Lock nach {int(elapsed_minutes)} Minuten freigegeben. "
f"Prozess: {self._current_process} ({self._current_platform})"
)
# Lock automatisch freigeben
self._is_locked = False
self._current_process = None
self._current_platform = None
self._lock_started_at = None
return False
return True
def is_paused(self) -> bool:
"""

Datei anzeigen

@ -11,7 +11,7 @@ from PyQt5.QtWidgets import (
QLabel, QPushButton, QStackedWidget, QTabWidget,
QAction, QMessageBox
)
from PyQt5.QtCore import Qt, pyqtSignal, QSize, QFile
from PyQt5.QtCore import Qt, pyqtSignal, QSize, QFile, QTimer
from PyQt5.QtGui import QIcon, QFont, QPixmap
from localization.language_manager import LanguageManager
@ -114,6 +114,14 @@ class MainWindow(QMainWindow):
# Verbinde Signale
self.connect_signals()
# Timer für periodische Guard-Status-Prüfung des Zurück-Buttons
self.guard_check_timer = QTimer()
self.guard_check_timer.timeout.connect(self._update_back_button_state)
self.guard_check_timer.start(1000) # Alle 1 Sekunde prüfen
# Initiale Button-Status-Prüfung
self._update_back_button_state()
def connect_signals(self):
"""Verbindet die internen Signale."""
# Platform-Selector-Signal verbinden
@ -267,6 +275,37 @@ class MainWindow(QMainWindow):
"""Setzt eine Nachricht in der Statusleiste."""
self.statusBar().showMessage(message)
def _update_back_button_state(self):
"""
Aktualisiert den Status des Zurück-Buttons basierend auf ProcessGuard.
Deaktiviert den Zurück-Button wenn ein Prozess läuft oder Pause aktiv ist,
um zu verhindern dass User während Account-Erstellung/Login navigieren.
"""
from utils.process_guard import get_guard
guard = get_guard()
# Prüfe ob blockiert
is_locked = guard.is_locked()
is_paused = guard.is_paused()
is_blocked = is_locked or is_paused
# Button entsprechend setzen (nur wenn auf Platform-View)
if self.stacked_widget.currentWidget() == self.platform_container:
self.back_button.setEnabled(not is_blocked)
# Tooltip setzen
if is_blocked:
status_msg = guard.get_status_message()
self.back_button.setToolTip(f"{status_msg}")
else:
# Reset Tooltip
if self.language_manager:
tooltip = self.language_manager.get_text("buttons.back", "↩ Zurück")
else:
tooltip = "↩ Zurück"
self.back_button.setToolTip(tooltip)
def add_log_widget(self, text_widget):
"""Fügt einen GUI-Handler zum Logger hinzu."""
add_gui_handler(logger, text_widget)