@@ -470,6 +470,38 @@ async def _dismiss_dialog(self) -> None:
470470 except PlaywrightTimeoutError :
471471 pass
472472
473+ async def _open_more_menu (self ) -> bool :
474+ """Open the profile's More (three-dot) menu and check for Connect.
475+
476+ Uses ``aria-label`` to find the More button (language-independent)
477+ and ``[role="menu"]`` to detect the opened menu (structural).
478+ Returns True if the menu opened and contains a Connect option.
479+ """
480+ more_btn = self ._page .locator ("main button[aria-label*='More']" )
481+ try :
482+ if await more_btn .count () == 0 :
483+ return False
484+ await more_btn .first .click (timeout = 5000 )
485+ except Exception :
486+ logger .debug ("Could not click More button" , exc_info = True )
487+ return False
488+
489+ try :
490+ await self ._page .wait_for_selector ("[role='menu']" , timeout = 3000 )
491+ except PlaywrightTimeoutError :
492+ logger .debug ("More menu did not appear" )
493+ return False
494+
495+ # Check if Connect is in the menu
496+ menu_connect = (
497+ self ._page .locator ("[role='menu']" )
498+ .locator ("button, a, li, [role='menuitem'], [role='button']" )
499+ .filter (has_text = re .compile (r"^Connect$" ))
500+ )
501+ count = await menu_connect .count ()
502+ logger .debug ("More menu Connect matches: %d" , count )
503+ return count > 0
504+
473505 async def extract_page (
474506 self ,
475507 url : str ,
@@ -796,13 +828,20 @@ async def connect_with_person(
796828 "A connection request is already pending for this profile." ,
797829 profile = page_text ,
798830 )
831+ via_more_menu = False
799832 if state == "follow_only" :
800- return _connection_result (
801- url ,
802- "follow_only" ,
803- "This profile currently exposes Follow but not Connect." ,
804- profile = page_text ,
805- )
833+ # Connect may be hidden behind the More (three-dot) menu
834+ if await self ._open_more_menu ():
835+ state = "connectable"
836+ via_more_menu = True
837+ else :
838+ return _connection_result (
839+ url ,
840+ "follow_only" ,
841+ "This profile currently exposes Follow but not Connect." ,
842+ profile = page_text ,
843+ )
844+
806845 if state == "unavailable" :
807846 return _connection_result (
808847 url ,
@@ -821,7 +860,8 @@ async def connect_with_person(
821860 )
822861
823862 # Click the button (page is already loaded from scrape_person)
824- clicked = await self .click_button_by_text (button_text )
863+ click_scope = "[role='menu']" if via_more_menu else "main"
864+ clicked = await self .click_button_by_text (button_text , scope = click_scope )
825865 if not clicked :
826866 return _connection_result (
827867 url ,
0 commit comments