fix: parse meeting ID + passcode separately, fill both fields, click Join meeting

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ValueOn AG 2026-02-17 12:41:24 +01:00
parent 8ed183f13c
commit f7e0c194d5

View file

@ -363,37 +363,105 @@ async function _runVariant(
_log('warn', '"Join a meeting" button not found on landing page'); _log('warn', '"Join a meeting" button not found on landing page');
} }
// Wait for the resulting page to FULLY load // Wait for the "Join a meeting" form to FULLY load
_log('info', 'Waiting for resulting page to fully load...'); _log('info', 'Waiting for Join a meeting form to load...');
await page.waitForTimeout(5000); await page.waitForTimeout(5000);
try { try {
await page.waitForLoadState('networkidle', { timeout: 20000 }); await page.waitForLoadState('networkidle', { timeout: 20000 });
} catch { } catch {
_log('warn', 'networkidle timeout, continuing'); _log('warn', 'networkidle timeout, continuing');
} }
await page.waitForTimeout(5000); await page.waitForTimeout(3000);
await _screenshotStep('3 - Nach "Join a meeting"'); await _screenshotStep('3 - Join a meeting Formular');
// If there's an input for meeting URL, enter it // Parse meeting URL to extract Meeting ID and Passcode
_log('info', 'Looking for meeting URL input...'); // URL format: https://teams.microsoft.com/meet/36438888781520?p=5fGqrujxzewPFjJacW
const meetingInputSelectors = [ const { meetingId, passcode } = _parseMeetingUrl(meetingUrl);
'input[placeholder*="meeting" i]', _log('info', `Parsed meeting URL: ID="${meetingId}", Passcode="${passcode ? passcode.substring(0, 5) + '...' : 'none'}"`);
'input[placeholder*="code" i]',
'input[placeholder*="link" i]', // Fill Meeting ID field
'input[placeholder*="ID" i]', if (meetingId) {
'input[type="text"]', _log('info', 'Looking for Meeting ID input...');
'input[type="url"]', const idInputSelectors = [
'input[placeholder*="meeting" i]',
'input[placeholder*="Meeting ID" i]',
'input[placeholder*="ID" i]',
'input[aria-label*="Meeting ID" i]',
'input[type="text"]:first-of-type',
];
let idFilled = false;
for (const selector of idInputSelectors) {
try {
const input = await page.waitForSelector(selector, { timeout: 5000, state: 'visible' });
if (input) {
await input.fill(meetingId);
_log('info', `Entered Meeting ID in: ${selector}`);
idFilled = true;
await page.waitForTimeout(1000);
break;
}
} catch {
// Try next
}
}
if (!idFilled) {
_log('warn', 'Meeting ID input not found');
}
}
// Fill Passcode field
if (passcode) {
_log('info', 'Looking for Passcode input...');
const passcodeSelectors = [
'input[placeholder*="passcode" i]',
'input[placeholder*="Passcode" i]',
'input[placeholder*="password" i]',
'input[aria-label*="passcode" i]',
'input[aria-label*="Passcode" i]',
];
let passcodeFilled = false;
for (const selector of passcodeSelectors) {
try {
const input = await page.waitForSelector(selector, { timeout: 5000, state: 'visible' });
if (input) {
await input.fill(passcode);
_log('info', `Entered Passcode in: ${selector}`);
passcodeFilled = true;
await page.waitForTimeout(1000);
break;
}
} catch {
// Try next
}
}
if (!passcodeFilled) {
_log('warn', 'Passcode input not found');
}
}
await _screenshotStep('4 - Meeting-Daten eingegeben');
// Click "Join meeting" button
_log('info', 'Looking for "Join meeting" button...');
const joinBtnSelectors = [
'button:has-text("Join meeting")',
'button:has-text("Besprechung beitreten")',
'button:has-text("Join now")',
'button:has-text("Jetzt teilnehmen")',
'button[data-tid="joinMeetingButton"]',
'button[data-tid="join-meeting-button"]',
]; ];
let meetingInputFound = false; let joinClicked = false;
for (const selector of meetingInputSelectors) { for (const selector of joinBtnSelectors) {
try { try {
const input = await page.waitForSelector(selector, { timeout: 5000, state: 'visible' }); const btn = await page.waitForSelector(selector, { timeout: 5000, state: 'visible' });
if (input) { if (btn) {
await input.fill(meetingUrl); await btn.click();
_log('info', `Entered meeting URL in: ${selector}`); _log('info', `Clicked "Join meeting": ${selector}`);
meetingInputFound = true; joinClicked = true;
await page.waitForTimeout(3000);
break; break;
} }
} catch { } catch {
@ -401,12 +469,36 @@ async function _runVariant(
} }
} }
if (meetingInputFound) { if (!joinClicked) {
await page.waitForTimeout(5000); _log('warn', '"Join meeting" button not found — logging all visible buttons');
await _screenshotStep('4 - Meeting URL eingegeben'); try {
} else { const buttons = await page.evaluate(() => {
_log('warn', 'No meeting URL input field found'); const btns = document.querySelectorAll('button');
return Array.from(btns).slice(0, 20).map(b => {
const text = (b.textContent || '').trim().substring(0, 80);
const tid = b.getAttribute('data-tid') || '';
const disabled = b.disabled ? ' DISABLED' : '';
return `[BUTTON tid="${tid}"${disabled}] ${text}`;
});
});
buttons.forEach(b => _log('info', ` ${b}`));
} catch {
// Ignore
}
} }
// Wait for resulting page after clicking Join
if (joinClicked) {
_log('info', 'Waiting for page after Join meeting...');
await page.waitForTimeout(5000);
try {
await page.waitForLoadState('networkidle', { timeout: 30000 });
} catch {
_log('warn', 'networkidle timeout after Join, continuing');
}
await page.waitForTimeout(10000);
}
await _screenshotStep('5 - Nach Join meeting');
} }
// ===================================================================== // =====================================================================
@ -753,6 +845,39 @@ function _getDeviceSpoofScript(): void {
} }
} }
// ============================================================================
// MEETING URL PARSER
// ============================================================================
/**
* Parse a Teams meeting URL to extract Meeting ID and Passcode.
* URL format: https://teams.microsoft.com/meet/36438888781520?p=5fGqrujxzewPFjJacW
* Meeting ID: 36438888781520 (from path)
* Passcode: 5fGqrujxzewPFjJacW (from ?p= parameter)
*/
function _parseMeetingUrl(meetingUrl: string): { meetingId: string; passcode: string | null } {
try {
const parsed = new URL(meetingUrl.trim());
// Extract meeting ID from path: /meet/36438888781520
let meetingId = '';
if (parsed.pathname.includes('/meet/')) {
meetingId = parsed.pathname.split('/meet/')[1] || '';
// Remove trailing slashes
meetingId = meetingId.replace(/\/$/, '');
}
// Extract passcode from ?p= parameter
const passcode = parsed.searchParams.get('p') || null;
return { meetingId, passcode };
} catch {
// If URL parsing fails, try to extract digits as meeting ID
const digits = meetingUrl.replace(/\D/g, '');
return { meetingId: digits, passcode: null };
}
}
// ============================================================================ // ============================================================================
// URL RESOLUTION // URL RESOLUTION
// ============================================================================ // ============================================================================