From d6e7cde9dccfd7570b99a392fd966dd8eac0a89e Mon Sep 17 00:00:00 2001 From: Oliver Hofmann Date: Sun, 17 May 2026 17:34:34 +0200 Subject: [PATCH] fix: traverse Shadow DOM of lpc-card to find mailto email link --- src/teampulse/resolver.py | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/teampulse/resolver.py b/src/teampulse/resolver.py index 30619d9..82c6aa9 100644 --- a/src/teampulse/resolver.py +++ b/src/teampulse/resolver.py @@ -111,26 +111,37 @@ class Resolver: return None try: - # Move mouse onto the card itself to keep it open while stage 2 loads + # Move mouse onto the card itself to keep it open while it loads card_el = self._page.query_selector(".lpc_ip_root_class") if card_el: card_el.hover() - # Stage 2: wait for the email link to appear (card expands) - self._page.wait_for_selector( - ".lpc_ip_root_class a[href*='mailto:']", timeout=8_000 + # Stage 2: card content is inside a Shadow DOM () + # Wait for the mailto link to appear inside the shadow root + self._page.wait_for_function( + """() => { + const lpcCard = document.querySelector('.lpc_ip_root_class lpc-card'); + if (!lpcCard || !lpcCard.shadowRoot) return false; + return !!lpcCard.shadowRoot.querySelector('a[href*="mailto:"]'); + }""", + timeout=10_000, ) - email_el = self._page.query_selector(".lpc_ip_root_class a[href*='mailto:']") - email = None - if email_el: - href = email_el.get_attribute("href") or "" - email = href.replace("mailto:", "").strip() or email_el.inner_text().strip() or None + email = self._page.evaluate("""() => { + const lpcCard = document.querySelector('.lpc_ip_root_class lpc-card'); + if (!lpcCard || !lpcCard.shadowRoot) return null; + const link = lpcCard.shadowRoot.querySelector('a[href*="mailto:"]'); + return link ? link.href.replace('mailto:', '').trim() : null; + }""") self._page.mouse.move(0, 0) time.sleep(0.3) - return email + return email or None except Exception: - card = self._page.query_selector(".lpc_ip_root_class") - card_text = card.inner_text().strip()[:200] if card else "(leer)" - print(f" Karte für '{display_name}' offen, E-Mail nicht gefunden. Inhalt: {card_text!r}") + # Diagnose: show shadow root text if available + card_text = self._page.evaluate("""() => { + const lpcCard = document.querySelector('.lpc_ip_root_class lpc-card'); + if (!lpcCard || !lpcCard.shadowRoot) return '(kein Shadow Root)'; + return lpcCard.shadowRoot.textContent.trim().substring(0, 200); + }""") or "(leer)" + print(f" Karte für '{display_name}' offen, E-Mail nicht im Shadow Root. Inhalt: {card_text!r}") self._page.mouse.move(0, 0) return None