diff --git a/README.md b/README.md index 3fced45..a00b2d9 100644 --- a/README.md +++ b/README.md @@ -292,6 +292,7 @@ timeouts: captcha_detection: 2.0 # Timeout for captcha iframe detection sms_verification: 4.0 # Timeout for SMS verification banners gdpr_prompt: 10.0 # Timeout when handling GDPR dialogs + login_detection: 10.0 # Timeout for detecting existing login session via DOM elements publishing_result: 300.0 # Timeout for publishing status checks publishing_confirmation: 20.0 # Timeout for publish confirmation redirect image_upload: 30.0 # Timeout for image upload and server-side processing diff --git a/docs/BROWSER_TROUBLESHOOTING.md b/docs/BROWSER_TROUBLESHOOTING.md index ba977d3..7ed5bd6 100644 --- a/docs/BROWSER_TROUBLESHOOTING.md +++ b/docs/BROWSER_TROUBLESHOOTING.md @@ -71,6 +71,29 @@ The bot will also provide specific instructions on how to fix your configuration 2. Override specific keys under `timeouts` (e.g. `pagination_initial: 20.0`) if only a single selector is problematic. 3. Keep `retry_enabled` on so that DOM lookups are retried with exponential backoff. +### Issue: Bot fails to detect existing login session + +**Symptoms:** +- Bot re-logins despite being already authenticated +- Intermittent (50/50) login detection behavior +- More common with profiles unused for 20+ days + +**What `login_detection` controls:** +- Maximum time (seconds) to wait for user profile DOM elements when checking if already logged in +- Default: `10.0` seconds (provides ~22.5s total with retry/backoff) +- Used at startup before attempting login + +**When to increase `login_detection`:** +- Frequent unnecessary re-logins despite being authenticated +- Slow or unstable network connection +- Using browser profiles that haven't been active for weeks + +**Example:** +```yaml +timeouts: + login_detection: 15.0 # For slower networks or old sessions +``` + ## Common Issues and Solutions ### Issue 1: "Failed to connect to browser" with "root" error diff --git a/schemas/config.schema.json b/schemas/config.schema.json index b0621bc..d432e15 100644 --- a/schemas/config.schema.json +++ b/schemas/config.schema.json @@ -403,6 +403,13 @@ "title": "Gdpr Prompt", "type": "number" }, + "login_detection": { + "default": 10.0, + "description": "Timeout for detecting existing login session via DOM elements.", + "minimum": 1.0, + "title": "Login Detection", + "type": "number" + }, "publishing_result": { "default": 300.0, "description": "Timeout for publishing result checks.", diff --git a/src/kleinanzeigen_bot/__init__.py b/src/kleinanzeigen_bot/__init__.py index 92f175f..d7b74e0 100644 --- a/src/kleinanzeigen_bot/__init__.py +++ b/src/kleinanzeigen_bot/__init__.py @@ -595,6 +595,8 @@ class KleinanzeigenBot(WebScrapingMixin): async def login(self) -> None: LOG.info("Checking if already logged in...") await self.web_open(f"{self.root_url}") + if getattr(self, "page", None) is not None: + LOG.debug(_("Current page URL after opening homepage: %s"), self.page.url) if await self.is_logged_in(): LOG.info("Already logged in as [%s]. Skipping login.", self.config.login.username) @@ -608,9 +610,15 @@ class KleinanzeigenBot(WebScrapingMixin): # Sometimes a second login is required if not await self.is_logged_in(): + LOG.debug(_("First login attempt did not succeed, trying second login attempt")) await self.fill_login_data_and_send() await self.handle_after_login_logic() + if await self.is_logged_in(): + LOG.debug(_("Second login attempt succeeded")) + else: + LOG.warning(_("Second login attempt also failed - login may not have succeeded")) + async def fill_login_data_and_send(self) -> None: LOG.info("Logging in as [%s]...", self.config.login.username) await self.web_input(By.ID, "login-email", self.config.login.username) @@ -646,19 +654,34 @@ class KleinanzeigenBot(WebScrapingMixin): pass async def is_logged_in(self) -> bool: + # Use login_detection timeout (10s default) instead of default (5s) + # to allow sufficient time for client-side JavaScript rendering after page load. + # This is especially important for older sessions (20+ days) that require + # additional server-side validation time. + login_check_timeout = self._timeout("login_detection") + effective_timeout = self._effective_timeout("login_detection") + username = self.config.login.username.lower() + LOG.debug(_("Starting login detection (timeout: %.1fs base, %.1fs effective with multiplier/backoff)"), login_check_timeout, effective_timeout) + + # Try to find the standard element first try: - # Try to find the standard element first - user_info = await self.web_text(By.CLASS_NAME, "mr-medium") - if self.config.login.username.lower() in user_info.lower(): + user_info = await self.web_text(By.CLASS_NAME, "mr-medium", timeout = login_check_timeout) + if username in user_info.lower(): + LOG.debug(_("Login detected via .mr-medium element")) return True except TimeoutError: - try: - # If standard element not found, try the alternative - user_info = await self.web_text(By.ID, "user-email") - if self.config.login.username.lower() in user_info.lower(): - return True - except TimeoutError: - return False + LOG.debug(_("Timeout waiting for .mr-medium element after %.1fs"), effective_timeout) + + # If standard element not found or didn't contain username, try the alternative + try: + user_info = await self.web_text(By.ID, "user-email", timeout = login_check_timeout) + if username in user_info.lower(): + LOG.debug(_("Login detected via #user-email element")) + return True + except TimeoutError: + LOG.debug(_("Timeout waiting for #user-email element after %.1fs"), effective_timeout) + + LOG.debug(_("No login detected - neither .mr-medium nor #user-email found with username")) return False async def delete_ads(self, ad_cfgs:list[tuple[str, Ad, dict[str, Any]]]) -> None: diff --git a/src/kleinanzeigen_bot/model/config_model.py b/src/kleinanzeigen_bot/model/config_model.py index 1e224ab..5506f14 100644 --- a/src/kleinanzeigen_bot/model/config_model.py +++ b/src/kleinanzeigen_bot/model/config_model.py @@ -125,6 +125,7 @@ class TimeoutConfig(ContextualModel): captcha_detection:float = Field(default = 2.0, ge = 0.1, description = "Timeout for captcha iframe detection.") sms_verification:float = Field(default = 4.0, ge = 0.1, description = "Timeout for SMS verification prompts.") gdpr_prompt:float = Field(default = 10.0, ge = 1.0, description = "Timeout for GDPR/consent dialogs.") + login_detection:float = Field(default = 10.0, ge = 1.0, description = "Timeout for detecting existing login session via DOM elements.") publishing_result:float = Field(default = 300.0, ge = 10.0, description = "Timeout for publishing result checks.") publishing_confirmation:float = Field(default = 20.0, ge = 1.0, description = "Timeout for publish confirmation redirect.") image_upload:float = Field(default = 30.0, ge = 5.0, description = "Timeout for image upload and server-side processing.") diff --git a/src/kleinanzeigen_bot/resources/translations.de.yaml b/src/kleinanzeigen_bot/resources/translations.de.yaml index 55827e4..b91b8c4 100644 --- a/src/kleinanzeigen_bot/resources/translations.de.yaml +++ b/src/kleinanzeigen_bot/resources/translations.de.yaml @@ -61,8 +61,20 @@ kleinanzeigen_bot/__init__.py: login: "Checking if already logged in...": "Überprüfe, ob bereits eingeloggt..." + "Current page URL after opening homepage: %s": "Aktuelle Seiten-URL nach dem Öffnen der Startseite: %s" "Already logged in as [%s]. Skipping login.": "Bereits eingeloggt als [%s]. Überspringe Anmeldung." "Opening login page...": "Öffne Anmeldeseite..." + "First login attempt did not succeed, trying second login attempt": "Erster Anmeldeversuch war nicht erfolgreich, versuche zweiten Anmeldeversuch" + "Second login attempt succeeded": "Zweiter Anmeldeversuch erfolgreich" + "Second login attempt also failed - login may not have succeeded": "Zweiter Anmeldeversuch ebenfalls fehlgeschlagen - Anmeldung möglicherweise nicht erfolgreich" + + is_logged_in: + "Starting login detection (timeout: %.1fs base, %.1fs effective with multiplier/backoff)": "Starte Login-Erkennung (Timeout: %.1fs Basis, %.1fs effektiv mit Multiplikator/Backoff)" + "Login detected via .mr-medium element": "Login erkannt über .mr-medium Element" + "Timeout waiting for .mr-medium element after %.1fs": "Timeout beim Warten auf .mr-medium Element nach %.1fs" + "Login detected via #user-email element": "Login erkannt über #user-email Element" + "Timeout waiting for #user-email element after %.1fs": "Timeout beim Warten auf #user-email Element nach %.1fs" + "No login detected - neither .mr-medium nor #user-email found with username": "Kein Login erkannt - weder .mr-medium noch #user-email mit Benutzername gefunden" handle_after_login_logic: "# Device verification message detected. Please follow the instruction displayed in the Browser.": "# Nachricht zur Geräteverifizierung erkannt. Bitte den Anweisungen im Browser folgen."