diff --git a/src/bot/chatProcedure.ts b/src/bot/chatProcedure.ts index a6670c4..ea2261c 100644 --- a/src/bot/chatProcedure.ts +++ b/src/bot/chatProcedure.ts @@ -124,89 +124,44 @@ export class ChatProcedure { } const chatButtonSelectors = [ + '#chat-button', 'button[id="chat-button"]', - 'button[data-tid="chat-button"]', + 'button[aria-label="Chat"]', 'button[aria-label*="Chat" i]', - 'button[aria-label*="chat" i]', 'button[aria-label*="Unterhaltung" i]', 'button[aria-label*="Besprechungschat" i]', 'button[aria-label*="Meeting chat" i]', - 'button[aria-label*="conversation" i]', - '#chat-button', - // New Teams: toolbar buttons with data-cid - 'button[data-cid="chat-button"]', - '[data-tid="chat-button"]', ]; - for (const selector of chatButtonSelectors) { - try { - const button = await this._page.$(selector); - if (button) { - const isVisible = await button.isVisible().catch(() => false); - if (!isVisible) continue; - await button.click(); - this._logger.info(`Opened chat panel via selector: ${selector}`); - await this._page.waitForTimeout(1500); - if (await this._isChatPanelOpen()) return; - this._logger.info(`Clicked ${selector} but panel not detected as open, continuing search`); + // Poll for the chat button (toolbar renders asynchronously after join) + const maxAttempts = 10; + const pollIntervalMs = 1500; + + for (let attempt = 1; attempt <= maxAttempts; attempt++) { + for (const selector of chatButtonSelectors) { + try { + const button = await this._page.$(selector); + if (button) { + const isVisible = await button.isVisible().catch(() => false); + if (!isVisible) continue; + await button.click(); + this._logger.info(`Opened chat panel via: ${selector} (attempt ${attempt}/${maxAttempts})`); + await this._page.waitForTimeout(1500); + if (await this._isChatPanelOpen()) return; + this._logger.info(`Clicked ${selector} but panel not detected as open yet`); + } + } catch { + // Continue } - } catch { - // Continue + } + + if (attempt < maxAttempts) { + this._logger.info(`Chat button not found yet, retry ${attempt}/${maxAttempts} in ${pollIntervalMs}ms`); + await this._page.waitForTimeout(pollIntervalMs); } } - // Fallback: find chat-like toolbar buttons by scanning all toolbar buttons - const toolbarFound = await this._page.evaluate(() => { - const allButtons = document.querySelectorAll( - '[data-tid*="toolbar"] button, [role="toolbar"] button, ' + - '#calling-unified-bar button, [data-tid="call-controls"] button, ' + - 'button[data-tid]' - ); - for (const btn of Array.from(allButtons) as HTMLElement[]) { - const label = ( - btn.getAttribute('aria-label') || btn.getAttribute('title') || - btn.innerText || '' - ).toLowerCase(); - if ( - label.includes('chat') || label.includes('unterhaltung') || - label.includes('besprechungschat') || label.includes('meeting chat') || - label.includes('conversation') - ) { - btn.click(); - return `toolbar-scan: "${label}"`; - } - } - return null; - }); - - if (toolbarFound) { - this._logger.info(`Opened chat panel via ${toolbarFound}`); - await this._page.waitForTimeout(1500); - if (await this._isChatPanelOpen()) return; - } - - // Log all toolbar buttons for diagnostics - const toolbarDiag = await this._page.evaluate(() => { - const btns = document.querySelectorAll( - '[data-tid*="toolbar"] button, [role="toolbar"] button, ' + - '#calling-unified-bar button, button[data-tid]' - ); - return Array.from(btns).slice(0, 20).map((b) => { - const el = b as HTMLElement; - return { - tid: el.getAttribute('data-tid') || '', - label: el.getAttribute('aria-label') || '', - title: el.getAttribute('title') || '', - text: (el.innerText || '').substring(0, 40), - visible: el.offsetHeight > 0, - }; - }); - }).catch(() => []); - - this._logger.warn( - `Could not find chat button - chat will not work. ` + - `Toolbar buttons found: ${JSON.stringify(toolbarDiag)}` - ); + this._logger.warn('Could not find chat button after polling - chat will not work'); } /**