diff --git a/src/bot/orchestrator.ts b/src/bot/orchestrator.ts index 75de834..b6e3711 100644 --- a/src/bot/orchestrator.ts +++ b/src/bot/orchestrator.ts @@ -318,28 +318,67 @@ export class BotOrchestrator { */ private async _ensureCameraOn(): Promise { try { - // Look for camera toggle button - const cameraBtn = await this._page!.$('button[data-tid="toggle-video"], button[aria-label*="camera" i], button[aria-label*="Camera" i], button[aria-label*="Video" i]'); - if (cameraBtn) { - // Check if camera is currently off (aria-pressed="false" or similar) - const isOff = await cameraBtn.evaluate((el) => { - return el.getAttribute('aria-pressed') === 'false' || - el.getAttribute('aria-checked') === 'false' || - el.classList.contains('is-off') || - el.querySelector('.fui-Icon-regular') !== null; - }); - if (isOff) { - await cameraBtn.click(); - this._logger.info('Camera toggled ON'); - await this._page!.waitForTimeout(1000); - } else { - this._logger.info('Camera already ON'); + // Try multiple selectors for the camera toggle + const cameraSelectors = [ + 'button[data-tid="toggle-video"]', + 'button[aria-label*="camera" i]', + 'button[aria-label*="Camera" i]', + 'button[aria-label*="Video" i]', + '#video-toggle-button', + '[data-tid="prejoin-camera-toggle"]', + ]; + + let cameraBtn = null; + let matchedSelector = ''; + for (const sel of cameraSelectors) { + cameraBtn = await this._page!.$(sel); + if (cameraBtn) { + matchedSelector = sel; + break; } + } + + if (!cameraBtn) { + this._logger.warn('Camera toggle button not found with any selector'); + return; + } + + // Log button details for debugging + const btnInfo = await cameraBtn.evaluate((el) => { + return { + ariaLabel: el.getAttribute('aria-label') || '', + ariaPressed: el.getAttribute('aria-pressed'), + ariaChecked: el.getAttribute('aria-checked'), + dataTid: el.getAttribute('data-tid') || '', + className: el.className?.substring(0, 80) || '', + title: el.getAttribute('title') || '', + innerText: el.innerText?.trim()?.substring(0, 30) || '', + }; + }); + this._logger.info(`Camera button found: ${matchedSelector} | aria-label="${btnInfo.ariaLabel}" | aria-pressed=${btnInfo.ariaPressed} | title="${btnInfo.title}"`); + + // Determine if camera is off — click to turn it ON + // In Teams pre-join: aria-pressed="false" means camera is OFF + const shouldClick = btnInfo.ariaPressed === 'false' || btnInfo.ariaChecked === 'false'; + + if (shouldClick) { + await cameraBtn.click(); + this._logger.info('Camera toggled ON (was off)'); + await this._page!.waitForTimeout(2000); + + // Verify the toggle worked + const afterState = await cameraBtn.evaluate((el) => el.getAttribute('aria-pressed')); + this._logger.info(`Camera state after toggle: aria-pressed=${afterState}`); + } else if (btnInfo.ariaPressed === null && btnInfo.ariaChecked === null) { + // No aria state — click anyway to turn camera on (safe default) + await cameraBtn.click(); + this._logger.info('Camera clicked (no aria state detected, assuming toggle)'); + await this._page!.waitForTimeout(2000); } else { - this._logger.warn('Camera toggle button not found'); + this._logger.info('Camera already ON (aria-pressed=true)'); } } catch (err) { - this._logger.warn('Could not toggle camera:', err); + this._logger.warn(`Could not toggle camera: ${err}`); } }