From 3e445a6a6b798d3de39f2d2e1c8574203074bab5 Mon Sep 17 00:00:00 2001 From: Noah Duncan Date: Wed, 7 Oct 2026 22:53:32 -0500 Subject: [PATCH 1/3] tc --- .../teams_chromedriver_payload.js | 92 +++++++++++++++++++ bots/teams_bot_adapter/teams_ui_methods.py | 11 +++ 2 files changed, 103 insertions(+) diff --git a/bots/teams_bot_adapter/teams_chromedriver_payload.js b/bots/teams_bot_adapter/teams_chromedriver_payload.js index 693b516bf..a4bb0cb3a 100644 --- a/bots/teams_bot_adapter/teams_chromedriver_payload.js +++ b/bots/teams_bot_adapter/teams_chromedriver_payload.js @@ -1,3 +1,95 @@ +(function () { + const CONV_HOST_REGEX = /(^|\.)teams\.microsoft\.(com|us)$/; + const CONV_PATH_REGEX = /\/conv\/[^/]+\/?$/; + + let installed = false; + let done = false; + + function isTargetUrl(input) { + try { + const raw = typeof input === 'string' ? input : (input instanceof Request ? input.url : String(input)); + const url = new URL(raw, window.location.href); + return CONV_HOST_REGEX.test(url.hostname) && CONV_PATH_REGEX.test(url.pathname); + } catch (_) { + return false; + } + } + + // Telemetry must never break the intercepted fetch. + function safeSendJson(message) { + try { window.ws?.sendJson(message); } catch (_) {} + } + + function getMethod(input, init) { + if (init?.method) return String(init.method).toUpperCase(); + if (input instanceof Request) return input.method.toUpperCase(); + return 'GET'; + } + + // Returns the rewritten body string, or null if the body isn't a conversation join request. + function rewriteBody(bodyText) { + let parsed; + try { parsed = JSON.parse(bodyText); } catch (_) { return null; } + if (!parsed?.conversationRequest) return null; + const v = parsed.participantPropertyBag?.participantScreening?.value; + if (!v) return null; + + const shouldOverrideIsBot = v.isBot === true && v.source === 'JoinShield'; + if (shouldOverrideIsBot) { + v.isBot = false; + } + safeSendJson({ + type: 'JoinShieldBypassActivated', + value: v, + wasIsBotOverridden: shouldOverrideIsBot, + }); + return shouldOverrideIsBot ? JSON.stringify(parsed) : bodyText; + } + + window.installJoinShieldBypass = function () { + if (done || installed) return true; + installed = true; + + const previousFetch = window.fetch; + + function uninstall() { + done = true; + // If something wrapped fetch after us, we can't unwind it; the wrapper becomes a passthrough. + if (window.fetch === joinShieldBypassFetch) { + window.fetch = previousFetch; + } + } + + function joinShieldBypassFetch(input, init) { + if (done || getMethod(input, init) !== 'POST' || !isTargetUrl(input)) { + return previousFetch.apply(this, arguments); + } + + // Only synchronous string bodies are rewritten; anything else (e.g. a Request object) + // passes through untouched so the original fetch timing and semantics are preserved. + if (typeof init?.body !== 'string') { + return previousFetch.apply(this, arguments); + } + + let newBody = null; + try { newBody = rewriteBody(init.body); } catch (err) { reportError(err); } + if (newBody === null) return previousFetch.apply(this, arguments); + uninstall(); + return previousFetch.call(this, input, { ...init, body: newBody }); + } + + function reportError(err) { + safeSendJson({ + type: 'JoinShieldBypassError', + error: err?.message || String(err), + }); + } + + window.fetch = joinShieldBypassFetch; + return true; + }; + })(); + (() => { let PAYLOAD = null; diff --git a/bots/teams_bot_adapter/teams_ui_methods.py b/bots/teams_bot_adapter/teams_ui_methods.py index 8abe6f92f..fdf363d08 100644 --- a/bots/teams_bot_adapter/teams_ui_methods.py +++ b/bots/teams_bot_adapter/teams_ui_methods.py @@ -129,6 +129,16 @@ def set_display_name_to_allow(self, display_name): # Tell the injected payload to allow this exact display name through Teams' validation regex. self.driver.execute_script("return window.setDisplayNameToAllowForTeamsNameValidationBypass?.(arguments[0]);", display_name) + def install_join_shield_bypass(self): + if self.teams_bot_login_is_available and self.teams_bot_login_should_be_used: + logger.info("Not installing JoinShield bypass because we are signed in") + return + + if self.driver.execute_script("return window.installJoinShieldBypass?.();"): + logger.info("Installed JoinShield bypass") + else: + logger.warning("Could not install JoinShield bypass") + def fill_out_name_input(self): num_attempts = 60 logger.info("Waiting for the name input field...") @@ -526,6 +536,7 @@ def attempt_to_join_meeting(self): logger.info("Waiting for the Join now button...") join_button = self.locate_element(step="join_button", condition=EC.presence_of_element_located((By.CSS_SELECTOR, '[data-tid="prejoin-join-button"]')), wait_time_seconds=10) logger.info("Clicking the Join now button...") + self.install_join_shield_bypass() self.click_element(join_button, "join_button") # Start polling participants From fc3bce6bd17b3ebce5dbfe59ce9977df7410d55c Mon Sep 17 00:00:00 2001 From: Noah Duncan Date: Wed, 7 Oct 2026 23:22:09 -0500 Subject: [PATCH 2/3] check for meeting not found in name input loop --- bots/google_meet_bot_adapter/google_meet_ui_methods.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bots/google_meet_bot_adapter/google_meet_ui_methods.py b/bots/google_meet_bot_adapter/google_meet_ui_methods.py index a76cf0811..0452f8093 100644 --- a/bots/google_meet_bot_adapter/google_meet_ui_methods.py +++ b/bots/google_meet_bot_adapter/google_meet_ui_methods.py @@ -491,6 +491,7 @@ def fill_out_name_input(self): except TimeoutException as e: self.look_for_blocked_element("name_input") self.look_for_login_required_element("name_input") + self.check_if_meeting_is_found() if self.google_meet_bot_login_session and self.join_now_button_is_present(): logger.info("This is a signed in bot and name input is not present but the join now button is present. Assuming name input is not present because we don't need to fill it out, so returning.") From 8140fcaac455db34fc85c4f672f578859c25eeae Mon Sep 17 00:00:00 2001 From: Noah Duncan Date: Wed, 7 Oct 2026 23:22:21 -0500 Subject: [PATCH 3/3] vbump --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index c153d5f30..21dff1d57 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "1.82.5" + "version": "1.82.6" }