diff --git a/monitor.py b/monitor.py index 95670c8..98b9f4f 100644 --- a/monitor.py +++ b/monitor.py @@ -606,6 +606,11 @@ class ApplicationHandler: return result async def _apply_gewobag(self, listing: dict, result: dict) -> dict: + """ + Gewobag uses Wohnungshelden (app.wohnungshelden.de) for their application system. + The application form is embedded in an iframe on the listing page. + We navigate directly to the iframe URL to fill the form. + """ page = await self.context.new_page() try: logger.info(f"[GEWOBAG] Opening page: {listing['link']}") @@ -621,25 +626,153 @@ class ApplicationHandler: await asyncio.sleep(1) except: pass - logger.info("[GEWOBAG] Looking for application button...") - apply_btn = await page.query_selector('a:has-text("Kontakt"), button:has-text("Anfrage"), a.btn:has-text("Anfragen")') - if apply_btn and await apply_btn.is_visible(): - logger.info("[GEWOBAG] Found application button, clicking...") - await apply_btn.click() - await asyncio.sleep(2) + # Gewobag has Wohnungshelden iframe directly on the page + logger.info("[GEWOBAG] Looking for Wohnungshelden iframe...") + iframe_element = await page.query_selector('iframe[src*="wohnungshelden.de"]') + + if iframe_element: + iframe_url = await iframe_element.get_attribute('src') + logger.info(f"[GEWOBAG] Found Wohnungshelden iframe: {iframe_url}") - screenshot_path = DATA_DIR / f"gewobag_{listing['id']}.png" - await page.screenshot(path=str(screenshot_path)) - logger.info(f"[GEWOBAG] Saved screenshot to {screenshot_path}") + # Navigate to the iframe URL directly in a new page + iframe_page = await self.context.new_page() + try: + await iframe_page.goto(iframe_url, wait_until="networkidle") + await asyncio.sleep(2) + logger.info("[GEWOBAG] Loaded Wohnungshelden application page") - result["success"] = False - result["message"] = "Application page opened but not submitted (not implemented)" + # Take screenshot + screenshot_path = DATA_DIR / f"gewobag_wohnungshelden_{listing['id']}.png" + await iframe_page.screenshot(path=str(screenshot_path), full_page=True) + logger.info(f"[GEWOBAG] Saved Wohnungshelden screenshot") + + # Fill out Wohnungshelden form (same fields as Degewo) + form_filled = False + + # Anrede (Salutation) - ng-select dropdown + try: + salutation_dropdown = await iframe_page.query_selector('#salutation-dropdown, ng-select[id*="salutation"]') + if salutation_dropdown: + await salutation_dropdown.click() + await asyncio.sleep(0.5) + anrede_option = await iframe_page.query_selector(f'.ng-option:has-text("{FORM_ANREDE}")') + if anrede_option: + await anrede_option.click() + logger.info(f"[GEWOBAG] Selected Anrede: {FORM_ANREDE}") + form_filled = True + except Exception as e: + logger.warning(f"[GEWOBAG] Could not set Anrede: {e}") + + # Vorname (First name) + try: + vorname_field = await iframe_page.query_selector('#firstName') + if vorname_field: + await vorname_field.fill(FORM_VORNAME) + logger.info(f"[GEWOBAG] Filled Vorname: {FORM_VORNAME}") + form_filled = True + except Exception as e: + logger.warning(f"[GEWOBAG] Could not fill Vorname: {e}") + + # Nachname (Last name) + try: + nachname_field = await iframe_page.query_selector('#lastName') + if nachname_field: + await nachname_field.fill(FORM_NACHNAME) + logger.info(f"[GEWOBAG] Filled Nachname: {FORM_NACHNAME}") + form_filled = True + except Exception as e: + logger.warning(f"[GEWOBAG] Could not fill Nachname: {e}") + + # E-Mail + try: + email_field = await iframe_page.query_selector('#email') + if email_field: + await email_field.fill(FORM_EMAIL) + logger.info(f"[GEWOBAG] Filled E-Mail: {FORM_EMAIL}") + form_filled = True + except Exception as e: + logger.warning(f"[GEWOBAG] Could not fill E-Mail: {e}") + + # Telefonnummer - Gewobag uses #phone-number + try: + tel_field = await iframe_page.query_selector('#phone-number, input[id*="telefonnummer"], input[id*="phone"]') + if tel_field: + await tel_field.fill(FORM_PHONE) + logger.info(f"[GEWOBAG] Filled Telefon: {FORM_PHONE}") + form_filled = True + except Exception as e: + logger.warning(f"[GEWOBAG] Could not fill Telefon: {e}") + + # Anzahl einziehende Personen - Gewobag uses formly_*_gesamtzahl + try: + personen_field = await iframe_page.query_selector('input[id*="gesamtzahl"], input[id*="numberPersonsTotal"]') + if personen_field: + await personen_field.fill(FORM_PERSONS) + logger.info(f"[GEWOBAG] Filled Anzahl Personen: {FORM_PERSONS}") + form_filled = True + except Exception as e: + logger.warning(f"[GEWOBAG] Could not fill Anzahl Personen: {e}") + + await asyncio.sleep(1) + + # Screenshot after filling + screenshot_path = DATA_DIR / f"gewobag_filled_{listing['id']}.png" + await iframe_page.screenshot(path=str(screenshot_path), full_page=True) + logger.info(f"[GEWOBAG] Saved filled form screenshot") + + # Try to submit + if form_filled: + try: + submit_selectors = [ + 'button[type="submit"]', + 'button:has-text("Absenden")', + 'button:has-text("Senden")', + 'button:has-text("Anfrage")', + '.btn-primary', + ] + + submit_btn = None + for selector in submit_selectors: + submit_btn = await iframe_page.query_selector(selector) + if submit_btn and await submit_btn.is_visible(): + logger.info(f"[GEWOBAG] Found submit button: {selector}") + break + submit_btn = None + + if submit_btn: + await submit_btn.click() + logger.info("[GEWOBAG] Clicked submit button") + await asyncio.sleep(3) + + # Screenshot after submission + screenshot_path = DATA_DIR / f"gewobag_submitted_{listing['id']}.png" + await iframe_page.screenshot(path=str(screenshot_path), full_page=True) + logger.info(f"[GEWOBAG] Saved submission screenshot") + + result["success"] = True + result["message"] = "Application submitted via Wohnungshelden" + else: + result["success"] = False + result["message"] = "Form filled but submit button not found" + logger.warning("[GEWOBAG] Submit button not found") + except Exception as e: + result["success"] = False + result["message"] = f"Submit error: {str(e)}" + logger.warning(f"[GEWOBAG] Submit error: {e}") + else: + result["success"] = False + result["message"] = "No form fields found in Wohnungshelden" + logger.warning("[GEWOBAG] Could not find form fields") + finally: + await iframe_page.close() else: - result["message"] = "No application button found" - logger.warning("[GEWOBAG] Could not find application button") + result["success"] = False + result["message"] = "No Wohnungshelden iframe found" + logger.warning("[GEWOBAG] No Wohnungshelden iframe found") screenshot_path = DATA_DIR / f"gewobag_nobtn_{listing['id']}.png" await page.screenshot(path=str(screenshot_path)) except Exception as e: + result["success"] = False result["message"] = f"Error: {str(e)}" logger.error(f"[GEWOBAG] Exception: {str(e)}") finally: