fix: fallback manual navigation to /v2/ URL when headless browser does not auto-redirect after auth

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ValueOn AG 2026-02-16 16:01:10 +01:00
parent c9a11e9c82
commit 537975723e
2 changed files with 46 additions and 4 deletions

View file

@ -15,12 +15,14 @@ export class JoinProcedure {
private _logger: Logger;
private _botName: string;
private _isAuthenticated: boolean;
private _meetingUrl: string;
constructor(page: Page, logger: Logger, botName: string, isAuthenticated: boolean = false) {
constructor(page: Page, logger: Logger, botName: string, isAuthenticated: boolean = false, meetingUrl: string = '') {
this._page = page;
this._logger = logger;
this._botName = botName;
this._isAuthenticated = isAuthenticated;
this._meetingUrl = meetingUrl;
}
/**
@ -175,7 +177,47 @@ export class JoinProcedure {
}
}
this._logger.warn('Could not confirm authenticated pre-join page after all retries. Proceeding anyway...');
// Fallback: The automatic redirect to /v2/ did not happen (common in headless browsers).
// Manually navigate to the /v2/ authenticated pre-join URL with auth cookies.
// Format: https://teams.microsoft.com/v2/?meetingjoin=true#/meet/{meetingId}?p={passcode}
if (this._meetingUrl) {
const v2Url = this._buildV2MeetingUrl(this._meetingUrl);
this._logger.info(`Redirect to /v2/ did not happen. Navigating manually to: ${v2Url}`);
await this._page.goto(v2Url, { waitUntil: 'domcontentloaded', timeout: 30000 });
// Wait for the /v2/ page to load and check again
for (let attempt = 1; attempt <= 3; attempt++) {
await this._page.waitForTimeout(5000);
const hasNameInput = await this._page.$('input[placeholder="Type your name"]');
const hasJoinButton = await this._page.$('#prejoin-join-button, button[data-tid="prejoin-join-button"], button:has-text("Join now")');
const url = this._page.url();
if (hasJoinButton && !hasNameInput) {
this._logger.info(`Authenticated pre-join page confirmed after manual nav (attempt ${attempt}/3). URL: ${url.substring(0, 100)}`);
return;
}
this._logger.info(`After manual nav (attempt ${attempt}/3): hasJoin=${!!hasJoinButton}, hasName=${!!hasNameInput}. URL: ${url.substring(0, 100)}`);
}
}
this._logger.warn('Could not confirm authenticated pre-join page. Proceeding anyway...');
}
/**
* Build the authenticated /v2/ meeting URL from the original meeting URL.
* Input: https://teams.microsoft.com/meet/36438888781520?p=5fGqrujxzewPFjJacW
* Output: https://teams.microsoft.com/v2/?meetingjoin=true#/meet/36438888781520?p=5fGqrujxzewPFjJacW
*/
private _buildV2MeetingUrl(meetingUrl: string): string {
try {
const url = new URL(meetingUrl);
const pathAndQuery = url.pathname + url.search;
return `https://teams.microsoft.com/v2/?meetingjoin=true#${pathAndQuery}`;
} catch {
this._logger.warn(`Could not parse meeting URL: ${meetingUrl}`);
return `https://teams.microsoft.com/v2/?meetingjoin=true`;
}
}
/**

View file

@ -133,8 +133,8 @@ export class BotOrchestrator {
// Launch browser
await this._launchBrowser();
// Update JoinProcedure with correct auth state
this._joinProcedure = new JoinProcedure(this._page!, this._logger, this._botName, authenticate);
// Update JoinProcedure with correct auth state and meeting URL
this._joinProcedure = new JoinProcedure(this._page!, this._logger, this._botName, authenticate, this._meetingUrl);
this._setState('navigating');