Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@
from botbuilder.core.turn_context import TurnContext
from botbuilder.core import ActivityHandler, InvokeResponse, BotFrameworkAdapter
from botbuilder.schema.teams import (
AppBasedLinkQuery,
TeamInfo,
ChannelInfo,
FileConsentCardResponse,
TeamsChannelData,
TeamsChannelAccount,
MessagingExtensionAction,
MessagingExtensionQuery,
O365ConnectorCardActionQuery,
TaskModuleRequest,
)
from botframework.connector import Channels

Expand Down Expand Up @@ -55,26 +61,28 @@ async def on_invoke_activity(self, turn_context: TurnContext):

if turn_context.activity.name == "fileConsent/invoke":
return await self.on_teams_file_consent(
turn_context, turn_context.activity.value
turn_context, FileConsentCardResponse(**turn_context.activity.value)
)

if turn_context.activity.name == "actionableMessage/executeAction":
await self.on_teams_o365_connector_card_action(
turn_context, turn_context.activity.value
turn_context,
O365ConnectorCardActionQuery(**turn_context.activity.value),
)
return self._create_invoke_response()

if turn_context.activity.name == "composeExtension/queryLink":
return self._create_invoke_response(
await self.on_teams_app_based_link_query(
turn_context, turn_context.activity.value
turn_context, AppBasedLinkQuery(**turn_context.activity.value)
)
)

if turn_context.activity.name == "composeExtension/query":
return self._create_invoke_response(
await self.on_teams_messaging_extension_query(
turn_context, turn_context.activity.value
turn_context,
MessagingExtensionQuery(**turn_context.activity.value),
)
)

Expand All @@ -88,21 +96,24 @@ async def on_invoke_activity(self, turn_context: TurnContext):
if turn_context.activity.name == "composeExtension/submitAction":
return self._create_invoke_response(
await self.on_teams_messaging_extension_submit_action_dispatch(
turn_context, turn_context.activity.value
turn_context,
MessagingExtensionAction(**turn_context.activity.value),
)
)

if turn_context.activity.name == "composeExtension/fetchTask":
return self._create_invoke_response(
await self.on_teams_messaging_extension_fetch_task(
turn_context, turn_context.activity.value
turn_context,
MessagingExtensionAction(**turn_context.activity.value),
)
)

if turn_context.activity.name == "composeExtension/querySettingUrl":
return self._create_invoke_response(
await self.on_teams_messaging_extension_configuration_query_settings_url(
turn_context, turn_context.activity.value
turn_context,
MessagingExtensionQuery(**turn_context.activity.value),
)
)

Expand All @@ -121,14 +132,14 @@ async def on_invoke_activity(self, turn_context: TurnContext):
if turn_context.activity.name == "task/fetch":
return self._create_invoke_response(
await self.on_teams_task_module_fetch(
turn_context, turn_context.activity.value
turn_context, TaskModuleRequest(**turn_context.activity.value)
)
)

if turn_context.activity.name == "task/submit":
return self._create_invoke_response(
await self.on_teams_task_module_submit(
turn_context, turn_context.activity.value
turn_context, TaskModuleRequest(**turn_context.activity.value)
)
)

Expand All @@ -143,7 +154,9 @@ async def on_teams_signin_verify_state(self, turn_context: TurnContext):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_file_consent(
self, turn_context: TurnContext, file_consent_card_response
self,
turn_context: TurnContext,
file_consent_card_response: FileConsentCardResponse,
):
if file_consent_card_response.action == "accept":
await self.on_teams_file_consent_accept_activity(
Expand All @@ -163,27 +176,31 @@ async def on_teams_file_consent(
)

async def on_teams_file_consent_accept_activity( # pylint: disable=unused-argument
self, turn_context: TurnContext, file_consent_card_response
self,
turn_context: TurnContext,
file_consent_card_response: FileConsentCardResponse,
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_file_consent_decline_activity( # pylint: disable=unused-argument
self, turn_context: TurnContext, file_consent_card_response
self,
turn_context: TurnContext,
file_consent_card_response: FileConsentCardResponse,
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_o365_connector_card_action( # pylint: disable=unused-argument
self, turn_context: TurnContext, query
self, turn_context: TurnContext, query: O365ConnectorCardActionQuery
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_app_based_link_query( # pylint: disable=unused-argument
self, turn_context: TurnContext, query
self, turn_context: TurnContext, query: AppBasedLinkQuery
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_messaging_extension_query( # pylint: disable=unused-argument
self, turn_context: TurnContext, query
self, turn_context: TurnContext, query: MessagingExtensionQuery
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

Expand All @@ -193,9 +210,9 @@ async def on_teams_messaging_extension_select_item( # pylint: disable=unused-ar
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_messaging_extension_submit_action_dispatch(
self, turn_context: TurnContext, action
self, turn_context: TurnContext, action: MessagingExtensionAction
):
if not action:
if not action.bot_message_preview_action:
return await self.on_teams_messaging_extension_submit_action_activity(
turn_context, action
)
Expand Down Expand Up @@ -226,17 +243,17 @@ async def on_teams_messaging_extension_bot_message_send_activity( # pylint: dis
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_messaging_extension_submit_action_activity( # pylint: disable=unused-argument
self, turn_context: TurnContext, action
self, turn_context: TurnContext, action: MessagingExtensionAction
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_messaging_extension_fetch_task( # pylint: disable=unused-argument
self, turn_context: TurnContext, task_module_request
self, turn_context: TurnContext, action: MessagingExtensionAction
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_messaging_extension_configuration_query_settings_url( # pylint: disable=unused-argument
self, turn_context: TurnContext, query
self, turn_context: TurnContext, query: MessagingExtensionQuery
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

Expand All @@ -251,19 +268,19 @@ async def on_teams_messaging_extension_card_button_clicked( # pylint: disable=u
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_task_module_fetch( # pylint: disable=unused-argument
self, turn_context: TurnContext, task_module_request
self, turn_context: TurnContext, task_module_request: TaskModuleRequest
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_teams_task_module_submit( # pylint: disable=unused-argument
self, turn_context: TurnContext, task_module_request
self, turn_context: TurnContext, task_module_request: TaskModuleRequest
):
raise _InvokeResponseException(status_code=HTTPStatus.NOT_IMPLEMENTED)

async def on_conversation_update_activity(self, turn_context: TurnContext):

if turn_context.activity.channel_id == Channels.ms_teams:
channel_data = TeamsChannelData(**turn_context.activity.channel_data)

if turn_context.activity.members_added:
return await self.on_teams_members_added_dispatch_activity(
turn_context.activity.members_added, channel_data.team, turn_context
Expand All @@ -279,7 +296,9 @@ async def on_conversation_update_activity(self, turn_context: TurnContext):
if channel_data:
if channel_data.event_type == "channelCreated":
return await self.on_teams_channel_created_activity(
channel_data.channel, channel_data.team, turn_context
ChannelInfo(**channel_data.channel),
channel_data.team,
turn_context,
)
if channel_data.event_type == "channelDeleted":
return await self.on_teams_channel_deleted_activity(
Expand Down Expand Up @@ -337,17 +356,26 @@ async def on_teams_members_added_dispatch_activity( # pylint: disable=unused-ar

return await self.on_teams_members_added_activity(teams_members_added, team_info, turn_context)
"""
team_accounts_added = []
for member in members_added:
new_account_json = member.serialize()
del new_account_json["additional_properties"]
if "additional_properties" in new_account_json:
del new_account_json["additional_properties"]
member = TeamsChannelAccount(**new_account_json)
return await self.on_teams_members_added_activity(members_added, turn_context)
team_accounts_added.append(member)
return await self.on_teams_members_added_activity(
team_accounts_added, turn_context
)

async def on_teams_members_added_activity(
self, teams_members_added: [TeamsChannelAccount], turn_context: TurnContext
):
teams_members_added = [ChannelAccount(member) for member in teams_members_added]
return super().on_members_added_activity(teams_members_added, turn_context)
teams_members_added = [
ChannelAccount(**member.serialize()) for member in teams_members_added
]
return await super().on_members_added_activity(
teams_members_added, turn_context
)

async def on_teams_members_removed_dispatch_activity( # pylint: disable=unused-argument
self,
Expand All @@ -358,7 +386,8 @@ async def on_teams_members_removed_dispatch_activity( # pylint: disable=unused-
teams_members_removed = []
for member in members_removed:
new_account_json = member.serialize()
del new_account_json["additional_properties"]
if "additional_properties" in new_account_json:
del new_account_json["additional_properties"]
teams_members_removed.append(TeamsChannelAccount(**new_account_json))

return await self.on_teams_members_removed_activity(
Expand All @@ -368,8 +397,10 @@ async def on_teams_members_removed_dispatch_activity( # pylint: disable=unused-
async def on_teams_members_removed_activity(
self, teams_members_removed: [TeamsChannelAccount], turn_context: TurnContext
):
members_removed = [ChannelAccount(member) for member in teams_members_removed]
return super().on_members_removed_activity(members_removed, turn_context)
members_removed = [
ChannelAccount(**member.serialize()) for member in teams_members_removed
]
return await super().on_members_removed_activity(members_removed, turn_context)

async def on_teams_channel_deleted_activity( # pylint: disable=unused-argument
self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext
Expand Down
60 changes: 60 additions & 0 deletions libraries/botbuilder-core/tests/teams/simple_adapter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

import unittest
from typing import List
from botbuilder.core import BotAdapter, TurnContext
from botbuilder.schema import Activity, ConversationReference, ResourceResponse


class SimpleAdapter(BotAdapter):
# pylint: disable=unused-argument

def __init__(self, call_on_send=None, call_on_update=None, call_on_delete=None):
super(SimpleAdapter, self).__init__()
self.test_aux = unittest.TestCase("__init__")
self._call_on_send = call_on_send
self._call_on_update = call_on_update
self._call_on_delete = call_on_delete

async def delete_activity(
self, context: TurnContext, reference: ConversationReference
):
self.test_aux.assertIsNotNone(
reference, "SimpleAdapter.delete_activity: missing reference"
)
if self._call_on_delete is not None:
self._call_on_delete(reference)

async def send_activities(
self, context: TurnContext, activities: List[Activity]
) -> List[ResourceResponse]:
self.test_aux.assertIsNotNone(
activities, "SimpleAdapter.delete_activity: missing reference"
)
self.test_aux.assertTrue(
len(activities) > 0,
"SimpleAdapter.send_activities: empty activities array.",
)

if self._call_on_send is not None:
self._call_on_send(activities)
responses = []

for activity in activities:
responses.append(ResourceResponse(id=activity.id))

return responses

async def update_activity(self, context: TurnContext, activity: Activity):
self.test_aux.assertIsNotNone(
activity, "SimpleAdapter.update_activity: missing activity"
)
if self._call_on_update is not None:
self._call_on_update(activity)

return ResourceResponse(activity.id)

async def process_request(self, activity, handler):
context = TurnContext(self, activity)
return self.run_pipeline(context, handler)
Loading