mirror of
https://github.com/Second-Hand-Friends/kleinanzeigen-bot.git
synced 2026-03-12 02:31:45 +01:00
fix: Handle email verification dialog (#782)
This commit is contained in:
@@ -317,6 +317,7 @@ timeouts:
|
||||
page_load: 15.0 # Timeout for web_open page loads
|
||||
captcha_detection: 2.0 # Timeout for captcha iframe detection
|
||||
sms_verification: 4.0 # Timeout for SMS verification banners
|
||||
email_verification: 4.0 # Timeout for email verification banners
|
||||
gdpr_prompt: 10.0 # Timeout when handling GDPR dialogs
|
||||
login_detection: 10.0 # Timeout for DOM-based login detection fallback (auth probe is tried first)
|
||||
publishing_result: 300.0 # Timeout for publishing status checks
|
||||
|
||||
@@ -518,6 +518,13 @@
|
||||
"title": "Sms Verification",
|
||||
"type": "number"
|
||||
},
|
||||
"email_verification": {
|
||||
"default": 4.0,
|
||||
"description": "Timeout for eMail verification prompts.",
|
||||
"minimum": 0.1,
|
||||
"title": "Email Verification",
|
||||
"type": "number"
|
||||
},
|
||||
"gdpr_prompt": {
|
||||
"default": 10.0,
|
||||
"description": "Timeout for GDPR/consent dialogs.",
|
||||
|
||||
@@ -863,11 +863,22 @@ class KleinanzeigenBot(WebScrapingMixin): # noqa: PLR0904
|
||||
LOG.warning("############################################")
|
||||
LOG.warning("# Device verification message detected. Please follow the instruction displayed in the Browser.")
|
||||
LOG.warning("############################################")
|
||||
await ainput("Press ENTER when done...")
|
||||
await ainput(_("Press ENTER when done..."))
|
||||
except TimeoutError:
|
||||
# No SMS verification prompt detected.
|
||||
pass
|
||||
|
||||
try:
|
||||
email_timeout = self._timeout("email_verification")
|
||||
await self.web_find(By.TEXT, "Um dein Konto zu schützen haben wir dir eine E-Mail geschickt", timeout = email_timeout)
|
||||
LOG.warning("############################################")
|
||||
LOG.warning("# Device verification message detected. Please follow the instruction displayed in the Browser.")
|
||||
LOG.warning("############################################")
|
||||
await ainput(_("Press ENTER when done..."))
|
||||
except TimeoutError:
|
||||
# No email verification prompt detected.
|
||||
pass
|
||||
|
||||
try:
|
||||
LOG.info("Handling GDPR disclaimer...")
|
||||
gdpr_timeout = self._timeout("gdpr_prompt")
|
||||
|
||||
@@ -153,6 +153,7 @@ class TimeoutConfig(ContextualModel):
|
||||
page_load:float = Field(default = 15.0, ge = 1.0, description = "Page load timeout for web_open.")
|
||||
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.")
|
||||
email_verification:float = Field(default = 4.0, ge = 0.1, description = "Timeout for email 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.")
|
||||
@@ -218,7 +219,7 @@ class DiagnosticsConfig(ContextualModel):
|
||||
|
||||
def _validate_glob_pattern(v:str) -> str:
|
||||
if not v.strip():
|
||||
raise ValueError("must be a non-empty, non-blank glob pattern")
|
||||
raise ValueError(_("must be a non-empty, non-blank glob pattern"))
|
||||
return v
|
||||
|
||||
|
||||
|
||||
@@ -603,6 +603,8 @@ kleinanzeigen_bot/model/config_model.py:
|
||||
"amount must be specified when auto_price_reduction is enabled": "amount muss angegeben werden, wenn auto_price_reduction aktiviert ist"
|
||||
"min_price must be specified when auto_price_reduction is enabled": "min_price muss angegeben werden, wenn auto_price_reduction aktiviert ist"
|
||||
"Percentage reduction amount must not exceed %s": "Prozentuale Reduktionsmenge darf %s nicht überschreiten"
|
||||
_validate_glob_pattern:
|
||||
"must be a non-empty, non-blank glob pattern": "muss ein nicht-leeres Glob-Muster sein"
|
||||
_validate_pause_requires_capture:
|
||||
"pause_on_login_detection_failure requires login_detection_capture to be enabled": "pause_on_login_detection_failure erfordert, dass login_detection_capture aktiviert ist"
|
||||
|
||||
|
||||
@@ -509,17 +509,21 @@ class TestKleinanzeigenBotAuthentication:
|
||||
# First login attempt:
|
||||
# 1. Captcha iframe found (in check_and_wait_for_captcha)
|
||||
# 2. Phone verification not found (in handle_after_login_logic)
|
||||
# 3. GDPR banner not found (in handle_after_login_logic)
|
||||
# 3. Email verification not found (in handle_after_login_logic)
|
||||
# 4. GDPR banner not found (in handle_after_login_logic)
|
||||
# Second login attempt:
|
||||
# 4. Captcha iframe found (in check_and_wait_for_captcha)
|
||||
# 5. Phone verification not found (in handle_after_login_logic)
|
||||
# 6. GDPR banner not found (in handle_after_login_logic)
|
||||
# 5. Captcha iframe found (in check_and_wait_for_captcha)
|
||||
# 6. Phone verification not found (in handle_after_login_logic)
|
||||
# 7. Email verification not found (in handle_after_login_logic)
|
||||
# 8. GDPR banner not found (in handle_after_login_logic)
|
||||
mock_find.side_effect = [
|
||||
AsyncMock(), # Captcha iframe (first login)
|
||||
TimeoutError(), # Phone verification (first login)
|
||||
TimeoutError(), # Email verification (first login)
|
||||
TimeoutError(), # GDPR banner (first login)
|
||||
AsyncMock(), # Captcha iframe (second login)
|
||||
TimeoutError(), # Phone verification (second login)
|
||||
TimeoutError(), # Email verification (second login)
|
||||
TimeoutError(), # GDPR banner (second login)
|
||||
]
|
||||
mock_ainput.return_value = ""
|
||||
@@ -529,7 +533,7 @@ class TestKleinanzeigenBotAuthentication:
|
||||
await test_bot.login()
|
||||
|
||||
# Verify the complete flow
|
||||
assert mock_find.call_count == 6 # Exactly 6 web_find calls
|
||||
assert mock_find.call_count == 8 # Exactly 8 web_find calls
|
||||
assert mock_ainput.call_count == 2 # Two captcha prompts
|
||||
assert mock_input.call_count == 6 # Two login attempts with username, clear password, and set password
|
||||
assert mock_click.call_count == 2 # Two submit button clicks
|
||||
@@ -583,13 +587,13 @@ class TestKleinanzeigenBotAuthentication:
|
||||
patch("kleinanzeigen_bot.ainput", new_callable = AsyncMock) as mock_ainput,
|
||||
):
|
||||
# Test case 1: No special handling needed
|
||||
mock_find.side_effect = [TimeoutError(), TimeoutError()] # No phone verification, no GDPR
|
||||
mock_find.side_effect = [TimeoutError(), TimeoutError(), TimeoutError()] # No phone verification, no email verification, no GDPR
|
||||
mock_click.return_value = AsyncMock()
|
||||
mock_ainput.return_value = ""
|
||||
|
||||
await test_bot.handle_after_login_logic()
|
||||
|
||||
assert mock_find.call_count == 2
|
||||
assert mock_find.call_count == 3
|
||||
assert mock_click.call_count == 0
|
||||
assert mock_ainput.call_count == 0
|
||||
|
||||
@@ -597,11 +601,11 @@ class TestKleinanzeigenBotAuthentication:
|
||||
mock_find.reset_mock()
|
||||
mock_click.reset_mock()
|
||||
mock_ainput.reset_mock()
|
||||
mock_find.side_effect = [AsyncMock(), TimeoutError()] # Phone verification found, no GDPR
|
||||
mock_find.side_effect = [AsyncMock(), TimeoutError(), TimeoutError()] # Phone verification found, no email verification, no GDPR
|
||||
|
||||
await test_bot.handle_after_login_logic()
|
||||
|
||||
assert mock_find.call_count == 2
|
||||
assert mock_find.call_count == 3
|
||||
assert mock_click.call_count == 0 # No click needed, just wait for user
|
||||
assert mock_ainput.call_count == 1 # Wait for user to complete verification
|
||||
|
||||
@@ -609,11 +613,11 @@ class TestKleinanzeigenBotAuthentication:
|
||||
mock_find.reset_mock()
|
||||
mock_click.reset_mock()
|
||||
mock_ainput.reset_mock()
|
||||
mock_find.side_effect = [TimeoutError(), AsyncMock()] # No phone verification, GDPR found
|
||||
mock_find.side_effect = [TimeoutError(), TimeoutError(), AsyncMock()] # No phone verification, no email verification, GDPR found
|
||||
|
||||
await test_bot.handle_after_login_logic()
|
||||
|
||||
assert mock_find.call_count == 2
|
||||
assert mock_find.call_count == 3
|
||||
assert mock_click.call_count == 2 # Click to accept GDPR and continue
|
||||
assert mock_ainput.call_count == 0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user