Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions bots/google_meet_bot_adapter/google_meet_ui_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ def click_captions_button(self):
self.look_for_denied_your_request_element("click_captions_button")
self.click_this_meeting_is_being_recorded_join_now_button("click_captions_button")
self.click_others_may_see_your_meeting_differently_button("click_captions_button")
self.look_for_incoming_video_is_disabled_element()
self.check_if_waiting_room_timeout_exceeded(waiting_room_timeout_started_at, "click_captions_button")

last_check_timed_out = attempt_to_look_for_captions_button_index == num_attempts_to_look_for_captions_button - 1
Expand Down Expand Up @@ -644,11 +645,19 @@ def attempt_to_turn_off_reactions(self):
logger.info("Clicking the close button")
self.click_element(close_button, "close_button")

def look_for_incoming_video_is_disabled_element(self):
if not self.disable_incoming_video or self.confirmed_incoming_video_is_disabled:
return
incoming_video_is_set_to_audio_only_element = self.find_element_by_selector(By.XPATH, '//*[contains(text(), "Incoming video is set to audio only")]')
if incoming_video_is_set_to_audio_only_element:
logger.info("Confirmed incoming video is disabled")
self.confirmed_incoming_video_is_disabled = True

def disable_incoming_video_in_ui(self):
# First check if incoming video is already disabled. This is what we expect because
# we are disabling it via setting localstorage.
incoming_video_is_set_to_audio_only_element = self.find_element_by_selector(By.XPATH, '//*[contains(text(), "Incoming video is set to audio only")]')
if incoming_video_is_set_to_audio_only_element:
self.look_for_incoming_video_is_disabled_element()
if self.confirmed_incoming_video_is_disabled:
logger.info("No need to disable incoming video via the UI. It is already disabled.")
return

Expand Down Expand Up @@ -1143,6 +1152,8 @@ def position_mouse_for_humanized_interaction(self):

# returns nothing if succeeded, raises an exception if failed
def attempt_to_join_meeting(self):
self.confirmed_incoming_video_is_disabled = False

if self.google_meet_bot_login_is_available and self.google_meet_bot_login_should_be_used:
self.login_to_google_meet_account_with_retries()

Expand Down
2 changes: 1 addition & 1 deletion bots/teams_bot_adapter/teams_chromedriver_payload.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
(function () {
const CONV_HOST_REGEX = /(^|\.)teams\.microsoft\.(com|us)$/;
const CONV_HOST_REGEX = /(^|\.)(teams\.microsoft\.(com|us)|skype\.com)$/;
const CONV_PATH_REGEX = /\/conv\/[^/]+\/?$/;

let installed = false;
Expand Down
28 changes: 10 additions & 18 deletions bots/tests/test_teams_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -1814,17 +1814,19 @@ def test_domain_allow_list_violation_raises_error(
# Create bot controller
controller = BotController(self.bot.id)

# Mock the attempt_to_join_meeting to succeed immediately
# Mock the attempt_to_join_meeting to stay in the joining phase until allowed to finish
allow_join = threading.Event()
with patch("bots.teams_bot_adapter.teams_ui_methods.TeamsUIMethods.attempt_to_join_meeting") as mock_attempt_to_join:
mock_attempt_to_join.return_value = None # Successful join
mock_attempt_to_join.side_effect = lambda *args, **kwargs: allow_join.wait(timeout=30)

# Run the bot in a separate thread since it has an event loop
bot_thread = threading.Thread(target=controller.run)
bot_thread.daemon = True
bot_thread.start()

# Wait for the bot to join and adapter to be created
# Wait for the adapter to be created and start joining
time.sleep(3)
self.assertIsNone(controller.adapter.joined_at)

# Verify the listener subscribed over the driver's BiDi websocket
self.assertEqual(MockBiDiConnect.call_args[0][0], mock_driver.capabilities["webSocketUrl"])
Expand All @@ -1836,7 +1838,7 @@ def test_domain_allow_list_violation_raises_error(
# and mock open() to capture what would be written without touching filesystem
m = mock_open()
with patch("bots.web_bot_adapter.web_bot_adapter.os.path.islink", return_value=True):
with patch("builtins.open", m):
with patch("bots.web_bot_adapter.web_bot_adapter.open", m, create=True):
controller.adapter.write_chrome_policies_file()

# Verify open was called with the correct path
Expand Down Expand Up @@ -1867,9 +1869,6 @@ def test_domain_allow_list_violation_raises_error(

# --- Now test the domain allow list violation detection ---

# Simulate the bot having joined and being in the meeting
controller.adapter.joined_at = time.time()

# Sanity check the allow list matching that backs the history and iframe checks:
# allowed domains and their subdomains pass, look-alike domains do not
blocked_url = "https://badmicrosoft.com/some-path"
Expand All @@ -1893,7 +1892,7 @@ def execute_cdp_cmd_side_effect(cmd, params):
# Reset the last check time so the check runs immediately
controller.adapter.last_domain_allow_list_violation_check_time = 0

# Verify that check_domain_allow_list_violation raises an exception
# While the bot is still joining, check_domain_allow_list_violation raises an exception
with self.assertRaises(Exception) as context:
controller.adapter.check_domain_allow_list_violation()

Expand All @@ -1905,18 +1904,11 @@ def execute_cdp_cmd_side_effect(cmd, params):
mock_driver.execute_cdp_cmd.side_effect = None
mock_driver.execute_cdp_cmd.return_value = {}

# Clean up: simulate meeting ending to trigger cleanup
controller.adapter.left_meeting = True
controller.adapter.send_message_callback({"message": controller.adapter.Messages.MEETING_ENDED})
time.sleep(1)

# Now wait for the thread to finish naturally
# Cleanup
controller.cleanup()
allow_join.set()
bot_thread.join(timeout=5)

# If thread is still running after timeout, that's a problem to report
if bot_thread.is_alive():
print("WARNING: Bot thread did not terminate properly after cleanup")

# Close the database connection since we're in a thread
connection.close()

Expand Down
2 changes: 2 additions & 0 deletions bots/web_bot_adapter/web_bot_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1288,6 +1288,8 @@ def check_domain_allow_list_violation(self):
return
if not self.driver:
return
if self.joined_at:
return
if time.time() - self.last_domain_allow_list_violation_check_time < 30:
return

Expand Down
2 changes: 1 addition & 1 deletion version.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": "1.82.6"
"version": "1.82.7"
}
Loading