diff --git a/src/bot/orchestrator.ts b/src/bot/orchestrator.ts index 43d21b3..86c414a 100644 --- a/src/bot/orchestrator.ts +++ b/src/bot/orchestrator.ts @@ -250,40 +250,51 @@ export class BotOrchestrator { timeout: 30000, }); - // Teams might show a "Continue on this browser" interstitial or redirect - // Wait for the page to settle - await this._page!.waitForTimeout(3000); + // Teams may show interstitials before the pre-join screen. + // Poll for ALL possible next-step buttons simultaneously so we don't + // miss one if it appears slowly. const currentUrl = this._page!.url(); this._logger.info(`Auth join: URL after meeting navigation: ${currentUrl.substring(0, 150)}`); - // Handle "Continue on this browser" if shown (same as anonymous flow) - try { - const continueBtn = await this._page!.$('button:has-text("Continue on this browser"), button:has-text("In diesem Browser fortfahren")'); - if (continueBtn) { - await continueBtn.click(); - this._logger.info('Clicked "Continue on this browser"'); - await this._page!.waitForTimeout(3000); - } - } catch { /* not shown for auth users — expected */ } - - // Handle "Join" button if Teams shows the chat view first - // (some meeting URLs redirect to the chat thread with a Join button) - const chatJoinSelectors = [ + // Race: wait for whichever button appears first (interstitial OR pre-join) + const interstitialSelectors = [ + 'button:has-text("Continue on this browser")', + 'button:has-text("In diesem Browser fortfahren")', + 'button:has-text("Weiter in diesem Browser")', 'button[data-tid="chat-join-button"]', 'button[data-tid="join-call-button"]', ]; - let chatJoinClicked = false; - for (const selector of chatJoinSelectors) { - try { - const btn = await this._page!.$(selector); - if (btn) { - await btn.click(); - chatJoinClicked = true; - this._logger.info(`Clicked chat "Join" button: ${selector}`); + const preJoinSelectors = [ + 'button:has-text("Join now")', + 'button:has-text("Jetzt teilnehmen")', + 'button[data-tid="prejoin-join-button"]', + ]; + const allSelectors = [...interstitialSelectors, ...preJoinSelectors].join(', '); + + // Poll up to 30s for ANY of these buttons + this._logger.info('Waiting for interstitial or pre-join button...'); + try { + const firstBtn = await this._page!.waitForSelector(allSelectors, { + timeout: 30000, state: 'visible', + }); + if (firstBtn) { + const btnText = await firstBtn.textContent().catch(() => ''); + const btnTid = await firstBtn.getAttribute('data-tid').catch(() => ''); + this._logger.info(`First visible button: "${btnText?.trim()}" (data-tid="${btnTid}")`); + + // If it's an interstitial button (not pre-join), click it and wait for the next screen + const isPreJoin = preJoinSelectors.some(s => + s.includes(btnTid || '__none__') || (btnText && s.includes(btnText.trim())) + ); + if (!isPreJoin) { + await firstBtn.click(); + this._logger.info('Clicked interstitial button, waiting for pre-join screen...'); await this._page!.waitForTimeout(3000); - break; } - } catch { /* continue */ } + } + } catch { + this._logger.warn('No interstitial or pre-join button found within 30s'); + await this._takeScreenshot('auth-no-buttons'); } // STEP 5: Pre-Join screen → Click "Join now"