From 24f8537d89286f1164a90c0e78211877b43de3bf Mon Sep 17 00:00:00 2001 From: Oliver Hofmann Date: Sun, 17 May 2026 17:21:47 +0200 Subject: [PATCH] fix: add aria-label hover strategy; log which strategy triggered --- src/teampulse/resolver.py | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/teampulse/resolver.py b/src/teampulse/resolver.py index 88e601a..30619d9 100644 --- a/src/teampulse/resolver.py +++ b/src/teampulse/resolver.py @@ -45,51 +45,62 @@ class Resolver: encoding="utf-8", ) - def _hover_sender(self, display_name: str) -> bool: - """Find the sender's avatar in the visible chat and hover to open the profile card.""" + def _hover_sender(self, display_name: str) -> str: + """Find the sender's avatar/name and hover to open the profile card. + Returns the strategy used, or '' if not found.""" - # Strategy 1: reply-message-header (channel meetings) — hover the avatar + # Strategy 1: reply-message-header (channel meetings) — avatar next to name for header in self._page.query_selector_all("[data-tid='reply-message-header']"): try: - # Quick check on full header text before iterating spans if display_name not in header.inner_text(): continue avatar = header.query_selector("[data-tid='reply-message-header-avatar']") if avatar: avatar.scroll_into_view_if_needed() avatar.hover() - return True - # Fallback: hover the name span + return "reply-avatar" for span in header.query_selector_all("span"): if span.inner_text().strip() == display_name: span.scroll_into_view_if_needed() span.hover() - return True + return "reply-span" except Exception: continue - # Strategy 2: message-author-name (private meeting chat) — hover the element + # Strategy 2: aria-label containing the name (Fluent UI persona elements) + safe_name = display_name.replace("'", "\\'") + for el in self._page.query_selector_all(f"[aria-label*='{safe_name}']"): + try: + if el.is_visible(): + el.scroll_into_view_if_needed() + el.hover() + return "aria-label" + except Exception: + continue + + # Strategy 3: message-author-name (private meeting chat) for el in self._page.query_selector_all("[data-tid='message-author-name']"): try: if el.inner_text().strip() == display_name: el.scroll_into_view_if_needed() el.hover() - return True + return "author-name" except Exception: continue - return False + return "" def _extract_email_from_profile(self, display_name: str) -> str | None: try: - hovered = self._hover_sender(display_name) + strategy = self._hover_sender(display_name) except Exception as e: print(f" Hover auf '{display_name}' fehlgeschlagen: {e}") return None - if not hovered: + if not strategy: print(f" '{display_name}' nicht im sichtbaren Chat gefunden.") return None + print(f" '{display_name}' via '{strategy}' gehovered...") try: # Stage 1: wait for card container to appear