fix: navigate to meeting URL after auth instead of waiting for chat Join button
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
bfabc3dbe9
commit
72f57f062d
1 changed files with 38 additions and 24 deletions
|
|
@ -179,7 +179,7 @@ export class BotOrchestrator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Join a meeting as authenticated user (System Bot or User Account).
|
* Join a meeting as authenticated user (System Bot or User Account).
|
||||||
* Flow: teams.microsoft.com → MS Login → Teams Chat → Join → Pre-Join → Join now
|
* Flow: teams.microsoft.com → MS Login → Navigate to meeting URL → Pre-Join → Join now
|
||||||
*/
|
*/
|
||||||
private async _attemptAuthJoin(): Promise<void> {
|
private async _attemptAuthJoin(): Promise<void> {
|
||||||
// Launch browser in headful mode with minimal args (Chromium Minimal)
|
// Launch browser in headful mode with minimal args (Chromium Minimal)
|
||||||
|
|
@ -187,7 +187,7 @@ export class BotOrchestrator {
|
||||||
|
|
||||||
this._setState('navigating');
|
this._setState('navigating');
|
||||||
|
|
||||||
// STEP 1: Navigate to teams.microsoft.com
|
// STEP 1: Navigate to teams.microsoft.com to trigger authentication
|
||||||
this._logger.info('Auth join: navigating to teams.microsoft.com');
|
this._logger.info('Auth join: navigating to teams.microsoft.com');
|
||||||
await this._page!.goto('https://teams.microsoft.com', {
|
await this._page!.goto('https://teams.microsoft.com', {
|
||||||
waitUntil: 'domcontentloaded',
|
waitUntil: 'domcontentloaded',
|
||||||
|
|
@ -225,51 +225,65 @@ export class BotOrchestrator {
|
||||||
}
|
}
|
||||||
this._logger.info('Authentication successful');
|
this._logger.info('Authentication successful');
|
||||||
|
|
||||||
// STEP 3: Wait for Teams chat page (landing page after auth)
|
// STEP 3: Wait for Teams to finish loading after auth
|
||||||
|
this._logger.info('Waiting for Teams to load after auth...');
|
||||||
try {
|
try {
|
||||||
await this._page!.waitForURL('**/teams.microsoft.com/**', { timeout: 30000 });
|
await this._page!.waitForURL('**/teams.microsoft.com/**', { timeout: 30000 });
|
||||||
} catch {
|
} catch {
|
||||||
// Also accept teams.cloud.microsoft
|
|
||||||
try {
|
try {
|
||||||
await this._page!.waitForURL('**/teams.cloud.microsoft/**', { timeout: 10000 });
|
await this._page!.waitForURL('**/teams.cloud.microsoft/**', { timeout: 10000 });
|
||||||
} catch {
|
} catch {
|
||||||
this._logger.warn(`Unexpected URL after auth: ${this._page!.url().substring(0, 150)}`);
|
this._logger.warn(`Unexpected URL after auth: ${this._page!.url().substring(0, 150)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Give Teams a moment to initialize (session cookies, service workers)
|
||||||
|
await this._page!.waitForTimeout(3000);
|
||||||
|
|
||||||
// Wait for "Join" button in chat header
|
// STEP 4: Navigate directly to the meeting URL (authenticated session)
|
||||||
|
// This is the key step: the previous flow waited for a "Join" button in
|
||||||
|
// the Teams chat header, which only works if the meeting chat happens to
|
||||||
|
// be visible. Navigating directly to the meeting URL reliably shows the
|
||||||
|
// pre-join screen for authenticated users.
|
||||||
|
this._logger.info(`Auth join: navigating to meeting URL: ${this._meetingUrl.substring(0, 80)}...`);
|
||||||
|
await this._page!.goto(this._meetingUrl, {
|
||||||
|
waitUntil: 'domcontentloaded',
|
||||||
|
timeout: 30000,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Teams might show a "Continue on this browser" interstitial or redirect
|
||||||
|
// Wait for the page to settle
|
||||||
|
await this._page!.waitForTimeout(3000);
|
||||||
|
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 {
|
try {
|
||||||
await this._page!.waitForSelector(
|
const continueBtn = await this._page!.$('button:has-text("Continue on this browser"), button:has-text("In diesem Browser fortfahren")');
|
||||||
'button[data-tid="chat-join-button"], button[data-tid="join-call-button"]',
|
if (continueBtn) {
|
||||||
{ timeout: 30000, state: 'visible' },
|
await continueBtn.click();
|
||||||
);
|
this._logger.info('Clicked "Continue on this browser"');
|
||||||
this._logger.info('Teams chat page loaded, "Join" button found');
|
await this._page!.waitForTimeout(3000);
|
||||||
} catch {
|
|
||||||
this._logger.warn('"Join" button not found in chat header');
|
|
||||||
await this._takeScreenshot('auth-no-join-button');
|
|
||||||
}
|
}
|
||||||
|
} catch { /* not shown for auth users — expected */ }
|
||||||
|
|
||||||
// STEP 4: Click "Join" in chat header → Pre-Join screen
|
// Handle "Join" button if Teams shows the chat view first
|
||||||
this._logger.info('Clicking "Join" in chat header');
|
// (some meeting URLs redirect to the chat thread with a Join button)
|
||||||
const chatJoinSelectors = [
|
const chatJoinSelectors = [
|
||||||
'button[data-tid="chat-join-button"]',
|
'button[data-tid="chat-join-button"]',
|
||||||
'button[data-tid="join-call-button"]',
|
'button[data-tid="join-call-button"]',
|
||||||
];
|
];
|
||||||
|
|
||||||
let chatJoinClicked = false;
|
let chatJoinClicked = false;
|
||||||
for (const selector of chatJoinSelectors) {
|
for (const selector of chatJoinSelectors) {
|
||||||
try {
|
try {
|
||||||
const btn = await this._page!.waitForSelector(selector, { timeout: 5000, state: 'visible' });
|
const btn = await this._page!.$(selector);
|
||||||
if (btn) {
|
if (btn) {
|
||||||
await btn.click();
|
await btn.click();
|
||||||
chatJoinClicked = true;
|
chatJoinClicked = true;
|
||||||
|
this._logger.info(`Clicked chat "Join" button: ${selector}`);
|
||||||
|
await this._page!.waitForTimeout(3000);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch { /* try next */ }
|
} catch { /* continue */ }
|
||||||
}
|
|
||||||
|
|
||||||
if (!chatJoinClicked) {
|
|
||||||
throw new Error('"Join" button in chat header not found');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// STEP 5: Pre-Join screen → Click "Join now"
|
// STEP 5: Pre-Join screen → Click "Join now"
|
||||||
|
|
@ -284,7 +298,6 @@ export class BotOrchestrator {
|
||||||
await this._takeScreenshot('auth-no-join-now');
|
await this._takeScreenshot('auth-no-join-now');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Camera stays OFF — no video injection, focus on communication stability
|
|
||||||
this._logger.info('Camera left OFF (video disabled for stability)');
|
this._logger.info('Camera left OFF (video disabled for stability)');
|
||||||
|
|
||||||
// Ensure microphone is ON (required for voice playback)
|
// Ensure microphone is ON (required for voice playback)
|
||||||
|
|
@ -311,6 +324,7 @@ export class BotOrchestrator {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!joinNowClicked) {
|
if (!joinNowClicked) {
|
||||||
|
await this._takeScreenshot('auth-no-join-now-final');
|
||||||
throw new Error('"Join now" button not found on pre-join screen');
|
throw new Error('"Join now" button not found on pre-join screen');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue