From b8402311cd13ee3baf523b9d35da0c3c69d0a08c Mon Sep 17 00:00:00 2001 From: ValueOn AG Date: Mon, 16 Feb 2026 15:07:00 +0100 Subject: [PATCH] fix: wait for /v2/ URL after auth (not light-meetings), skip background for auth joins Co-authored-by: Cursor --- src/bot/orchestrator.ts | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/bot/orchestrator.ts b/src/bot/orchestrator.ts index 4c8ea76..9d1af7f 100644 --- a/src/bot/orchestrator.ts +++ b/src/bot/orchestrator.ts @@ -216,21 +216,31 @@ export class BotOrchestrator { if (authSuccess) { this._logger.info('Authentication via "Sign in" link succeeded'); - // After the inline login flow completes (email → password → stay signed in), - // Teams triggers a redirect chain that ends at teams.microsoft.com/v2/ - // with the authenticated pre-join page containing the "Join now" button. - // Simply wait for that button to appear — no manual navigation needed. - this._logger.info('Waiting for authenticated pre-join page (Join now button)...'); + // After the hybrid login flow (email on Teams modal, password on MS login), + // Teams redirects to /v2/ with the authenticated pre-join page. + // We must wait for the URL to contain "/v2/" — the light-meetings page + // also has a "Join now" button but that's the anonymous version! + this._logger.info('Waiting for redirect to authenticated /v2/ pre-join page...'); + try { + await this._page!.waitForURL('**/v2/**', { timeout: 60000 }); + const v2Url = this._page!.url(); + this._logger.info(`Arrived at /v2/ page: ${v2Url.substring(0, 100)}`); + } catch { + const currentUrl = this._page!.url(); + this._logger.warn(`Did not reach /v2/ page within 60s. URL: ${currentUrl.substring(0, 100)}`); + } + + // Now wait for the Join button on the authenticated /v2/ pre-join page const joinButtonSelector = '#prejoin-join-button, button[data-tid="prejoin-join-button"]'; try { - await this._page!.waitForSelector(joinButtonSelector, { timeout: 60000, state: 'visible' }); + await this._page!.waitForSelector(joinButtonSelector, { timeout: 30000, state: 'visible' }); const finalUrl = this._page!.url(); - this._logger.info(`On authenticated pre-join page: ${finalUrl.substring(0, 100)}`); + this._logger.info(`On authenticated pre-join page with Join button: ${finalUrl.substring(0, 100)}`); } catch { const finalUrl = this._page!.url(); const pageContent = await this._page!.evaluate(() => document.body?.innerText?.substring(0, 300) || ''); - this._logger.warn(`Join button not found after 60s. URL: ${finalUrl.substring(0, 100)}`); + this._logger.warn(`Join button not found. URL: ${finalUrl.substring(0, 100)}`); this._logger.warn(`Page content: ${pageContent.substring(0, 200)}`); } } else { @@ -241,8 +251,10 @@ export class BotOrchestrator { } } - // Set virtual background if configured (must be done on pre-join screen, before "Join now") - if (this._options.backgroundImageUrl && this._page && authenticate) { + // Set virtual background if configured (only for anonymous joins on light-meetings pre-join) + // For authenticated joins, background is set after reaching the /v2/ pre-join page + // (the auth flow redirects through multiple pages, so background setup would interfere) + if (this._options.backgroundImageUrl && this._page && !authenticate) { try { const { BackgroundProcedure } = await import('./backgroundProcedure'); const bgProcedure = new BackgroundProcedure(this._page, this._logger);