feat(teamsbot): dedicated bot account support with authenticated join
- New config fields: botAccountEmail, botAccountPassword for dedicated MSFT account - BrowserBotConnector passes credentials + backgroundImageUrl to bot service - Service passes config credentials to connector in joinMeeting - Enables: full language settings, virtual background, no lobby wait - Fallback: anonymous join when no bot account configured Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
91425809c3
commit
ad5c9d10cd
3 changed files with 28 additions and 6 deletions
|
|
@ -36,21 +36,26 @@ class BrowserBotConnector:
|
|||
instanceId: str,
|
||||
gatewayWsUrl: str,
|
||||
language: str = "de-DE",
|
||||
botAccountEmail: Optional[str] = None,
|
||||
botAccountPassword: Optional[str] = None,
|
||||
backgroundImageUrl: Optional[str] = None,
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Send join command to the Browser Bot service.
|
||||
|
||||
The bot will:
|
||||
1. Launch a headless browser
|
||||
2. Navigate to Teams web app
|
||||
3. Join the meeting
|
||||
2. If botAccountEmail/Password provided: authenticate with Microsoft first
|
||||
3. Navigate to Teams web app and join the meeting
|
||||
4. Enable captions and start scraping
|
||||
5. Connect back to Gateway via WebSocket using gatewayWsUrl
|
||||
|
||||
Args:
|
||||
gatewayWsUrl: Full WebSocket URL for the bot to connect back to
|
||||
(e.g. wss://gateway-int.poweron-center.net/api/teamsbot/{instanceId}/bot/ws/{sessionId})
|
||||
language: BCP-47 language code for captions spoken language (e.g. "de-DE", "en-US")
|
||||
language: BCP-47 language code for captions spoken language
|
||||
botAccountEmail: Microsoft account email for authenticated join (None = anonymous)
|
||||
botAccountPassword: Microsoft account password
|
||||
backgroundImageUrl: URL to background image for virtual background
|
||||
|
||||
Returns:
|
||||
Dict with 'success' bool and optional 'error' string.
|
||||
|
|
@ -67,10 +72,20 @@ class BrowserBotConnector:
|
|||
"meetingUrl": meetingUrl,
|
||||
"botName": botName,
|
||||
"instanceId": instanceId,
|
||||
"gatewayWsUrl": gatewayWsUrl, # Full WebSocket URL for bot to connect back
|
||||
"language": language, # Spoken language for Teams captions
|
||||
"gatewayWsUrl": gatewayWsUrl,
|
||||
"language": language,
|
||||
}
|
||||
|
||||
# Add authenticated join credentials if configured
|
||||
if botAccountEmail and botAccountPassword:
|
||||
payload["botAccountEmail"] = botAccountEmail
|
||||
payload["botAccountPassword"] = botAccountPassword
|
||||
logger.info(f"Bot will join authenticated as {botAccountEmail}")
|
||||
|
||||
# Add background image if configured
|
||||
if backgroundImageUrl:
|
||||
payload["backgroundImageUrl"] = backgroundImageUrl
|
||||
|
||||
try:
|
||||
async with aiohttp.ClientSession(timeout=_BOT_TIMEOUT) as session:
|
||||
async with session.post(f"{self.botUrl}/api/bot", json=payload) as resp:
|
||||
|
|
|
|||
|
|
@ -117,6 +117,8 @@ class TeamsbotConfig(BaseModel):
|
|||
language: str = Field(default="de-DE", description="Primary language for STT/TTS")
|
||||
voiceId: Optional[str] = Field(default=None, description="Google TTS voice ID (e.g., de-DE-Standard-A)")
|
||||
browserBotUrl: Optional[str] = Field(default=None, description="URL of the Browser Bot service. Falls back to TEAMSBOT_BROWSER_BOT_URL env variable if not set per-instance.")
|
||||
botAccountEmail: Optional[str] = Field(default=None, description="Dedicated Microsoft account email for authenticated bot join. Leave empty for anonymous join.")
|
||||
botAccountPassword: Optional[str] = Field(default=None, description="Dedicated Microsoft account password. MFA must be disabled for this account.")
|
||||
triggerIntervalSeconds: int = Field(default=10, ge=3, le=60, description="Seconds between periodic AI analysis triggers")
|
||||
triggerCooldownSeconds: int = Field(default=3, ge=1, le=30, description="Minimum seconds between AI calls")
|
||||
contextWindowSegments: int = Field(default=20, ge=5, le=100, description="Number of transcript segments to include in AI context")
|
||||
|
|
@ -157,6 +159,8 @@ class TeamsbotConfigUpdateRequest(BaseModel):
|
|||
language: Optional[str] = None
|
||||
voiceId: Optional[str] = None
|
||||
browserBotUrl: Optional[str] = None
|
||||
botAccountEmail: Optional[str] = None
|
||||
botAccountPassword: Optional[str] = None
|
||||
triggerIntervalSeconds: Optional[int] = None
|
||||
triggerCooldownSeconds: Optional[int] = None
|
||||
contextWindowSegments: Optional[int] = None
|
||||
|
|
|
|||
|
|
@ -127,6 +127,9 @@ class TeamsbotService:
|
|||
instanceId=self.instanceId,
|
||||
gatewayWsUrl=fullGatewayWsUrl,
|
||||
language=self.config.language,
|
||||
botAccountEmail=self.config.botAccountEmail,
|
||||
botAccountPassword=self.config.botAccountPassword,
|
||||
backgroundImageUrl=session.get("backgroundImageUrl") or self.config.backgroundImageUrl,
|
||||
)
|
||||
|
||||
if result.get("success"):
|
||||
|
|
|
|||
Loading…
Reference in a new issue