From 140372d4561f89690c5e8c669734f7aba364e693 Mon Sep 17 00:00:00 2001 From: virtual-josh Date: Mon, 4 Nov 2019 17:20:36 -0800 Subject: [PATCH 1/7] adding teams activity handler, team info, and teams channel account classes --- .../core/Teams/teams_activity_handler.py | 238 ++++++++++++++++++ .../botbuilder-schema/teams/team_info.py | 20 ++ .../teams/teams_channel_account.py | 34 +++ 3 files changed, 292 insertions(+) create mode 100644 libraries/botbuilder-schema/teams/team_info.py create mode 100644 libraries/botbuilder-schema/teams/teams_channel_account.py diff --git a/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py b/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py index e69de29bb..2e6f7d71a 100644 --- a/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py +++ b/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py @@ -0,0 +1,238 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +from typing import List + +from botbuilder.schema import ActivityTypes, ChannelAccount, MessageReaction +from botbuilder.schema.teams import TeamInfo +from .turn_context import TurnContext +from activity_handler import ActivityHandler +from botframework.connector import Channels +from http import HTTPStatus +from botbuilder.core import InvokeResponse + + +class TeamsActivityHandler(ActivityHandler): + async def on_turn(self, turn_context: TurnContext): + if turn_context is None: + raise TypeError("ActivityHandler.on_turn(): turn_context cannot be None.") + + if hasattr(turn_context, "activity") and turn_context.activity is None: + raise TypeError( + "ActivityHandler.on_turn(): turn_context must have a non-None activity." + ) + + if ( + hasattr(turn_context.activity, "type") + and turn_context.activity.type is None + ): + raise TypeError( + "ActivityHandler.on_turn(): turn_context activity must have a non-None type." + ) + + if turn_context.activity.type == ActivityTypes.Invoke: + pass + else: + await super(on_turn(turn_context)) + + return + + async def on_invoke_activity_async(self, turn_context: TurnContext): + try: + if turn_context.activity.name == None and turn_context.activity.channel_id == Channels.ms_teams: + return await on_teams_card_action_invoke(turn_context) + else: + if turn_context.activity.name == "signin/verifyState": + await on_teams_signin_verify_state_async(turn_context) + return _create_invoke_response() + elif turn_context.activity.name == "fileConsent/invoke": + await on_teams_file_concent_async(turn_context, turn_context.activity.value) + return _create_invoke_response() + elif turn_context.activity.name == "actionableMessage/executeAction": + await on_teams_o365_connector_card_action_async(turn_context, turn_context.activity.value) + return _create_invoke_response() + elif turn_context.activity.name == "composeExtension/queryLink": + return createInvokeResponse(await on_teams_app_based_link_query_async(turn_context, turn_context.activity.value)) + elif turn_context.activity.name == "composeExtension/query": + return _create_invoke_response(await on_teams_messaging_extension_query_async(turn_context, turn_context.activity.value)) + elif turn_context.activity.name == "composeExtension/selectItem": + return _create_invoke_response(await on_teams_messaging_extension_select_item_async(turn_context, turn_context.activity.value)) + elif turn_context.activity.name == "composeExtension/submitAction": + return _create_invoke_response(await on_teams_messaging_extension_submit_action_dispatch_async(turn_context, turn_context.activity.value)) + elif turn_context.activity.name == "composeExtension/fetchTask": + return _create_invoke_response(await on_teams_messaging_extension_fetch_task_async(turn_context, turn_context.activity.value)) + elif turn_context.activity.name == "composeExtension/querySettingUrl": + return _create_invoke_response(await on_teams_messaging_extension_configuration_query_settings_url_async(turn_context, turn_context.activity.value)) + elif turn_context.acitivity.name == "composseExtension/settings": + await on_teams_messaging_extension_configuration_settings_async(turn_context, turn_context.activity.value) + return _create_invoke_response() + elif turn_context.acitivity.name == "composeExtension/onCardButtonClicked": + await on_teams_messaging_extension_card_button_clicked_async(turn_context, turn_context.acitivity.value) + return _create_invoke_response() + elif turn_context.acitivity.name == "task/fetch": + return _create_invoke_response(await on_teams_task_module_fetch_async(turn_context, turn_context.activity.value)) + elif turn_context.acitivity.name == "task/submit": + return _create_invoke_response(await on_teams_task_module_submit_async(turn_context, turn_context.activity.value)) + else: + raise invoke_response_exception(HTTPStatus.NOT_IMPLEMENTED) + except InvokeResponseException as e: + return e.CreateInvokeResponse() + + async def on_teams_card_action_invoke_async(self, turn_context: TurnContext): + raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) + + async def on_teams_singin_verify_state_async(self, turn_context: TurnContext): + raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) + + async def on_teams_file_concent_async(self, turn_context: TurnContext, file_consent_card_response: FileConcentCardResponse): + if file_consent_card_response.action == "accept": + await file_consent_card_response(turn_context, file_consent_card_response) + return _create_invoke_response() + elif file_consent_card_response.action == "decline": + await on_teams_file_consent_decline_async(turn_context, file_consent_card_response) + return _create_invoke_response() + else: + raise _InvokeResponseException(HTTPStatus.BAD_REQUEST, ("%s is not a supported action" % file_consent_card_response)) + + async def on_teams_file_consent_accept_async(self, turn_context: TurnContext, file_consent_card_response: FileConsentCardResponse): + raise _InvokeResponseException(HTTPStatus.NOT_IMPLMENENTED) + + async def on_teams_file_consent_decline_async(self, turn_context: TurnContext, file_consent_card_response: FileConsentCardResponse): + raise _InvokeResponseException(HTTPStatus.NOT_IMPLMENENTED) + + async def on_teams_messaging_extension_query_async(self, turn_context: TurnContext, query: MessagingExtensionQuery): + raise _InvokeResponseException(HTTPStatus.NOT_IMPLMENENTED) + + async def on_teams_o365_connector_card_action_async(self, turn_context: TurnContext, query: O365ConnectorCardActionQuery): + raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) + + async def on_teams_app_based_link_query_async(self, turn_context: TurnContext, query: AppBasedLinkQuery): + raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) + + async def on_teams_messaging_extension_select_item_async(self, turn_context: TurnContext, query: JObject): + raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) + + async def on_teams_messaging_extension_fetch_task_async(self, turn_context: TurnContext, action: MessagingExtensionAction): + raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) + + async def on_teams_messaging_extension_submit_action_dispatch_async(self, turn_context: TurnContext, action, MessagingExtensionAction): + if action.BotMessagePreviewAction != None: + if action.BotMessagePreviewAction == "edit": + return await on_teams_messaging_extension_bot_message_preview_edit_async(turn_context, action) + elif action.BotMessagePreview == "send": + return await on_teams_messaging_extension_bot_message_preview_send_async(turn_context, action) + else: + raise _InvokeResponseException(HTTPStatus.BAD_REQUEST, + ("%s is not a supported BotMessagePreviewAction" % action.BotMessagePreviewAction)) + else: + return await on_teams_messaging_extension_submit_action_async(turn_context, action) + + async def on_teams_messaging_extension_submit_action_async(self, turn_context: TurnContext, action: MEssagingExtensionAction): + raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) + + async def on_teams_messaging_extension_bot_message_preview_edit_async(self, turn_context: TurnContext, action: MessagingExtensionAction): + raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) + + async def on_teams_messaging_extension_bot_message_preview_send_async(self, turn_context: TurnContext, action: MessagingExtensionAction): + raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) + + async def on_teams_messaging_extension_configuration_query_setting_url_async(self, turn_context: TurnContext, query: MessagingExtensionQuery): + raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) + + async def on_teams_messaging_extension_configuration_setting_async(self, turn_context: TurnContext, settings: JObject): + raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) + + async def on_teams_messaging_extension_card_button_clicked_async(self, turn_context: TurnContext, cardData: JObject): + raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) + + async def on_teams_task_module_fetch_async(self, turn_context: TurnContext, taskModuleRequest: TaskModuleRequest): + raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) + + async def on_teams_task_module_submit_async(self, turn_context: TurnContext, task_module_request: TaskModuleRequest): + raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) + + async def on_conversation_update_activity_async(self, turn_context: TurnContext): + if turn_context.activity.channel_id == Channels.Msteams: + channel_data = turn_context.activity.get_channel_data() + if turn_context.activity.members_added != None: + return on_teams_members_added_dispatch_async(turn_context.activity.members_added, channel_data.team) + + if turn_context.activity.members_added != None: + return on_teams_members_removed_dispatched_async(turn_context.acitivity.members_removed, channel_data.team) + + if channel_data != None: + if channel_data.event_type == "channelCreated": + return on_teams_channel_created_async(channel_data.channel, channel_data.team, turn_context) + elif channel_data.event_type == "channelDeleted": + return on_teams_channel_deleted_async(channel_data.channel, channel_data.team, turn_context) + elif channel_data.event_type == "channelRenamed": + return on_teams_channel_renamed(channel_data.channel, channel_data.team, turn_context) + elif channel_data.event_type == "teamRenamed": + return self.on_teams_team_renamed_async(channel_data.team, turn_context) + else: + return super().on_conversation_update_activity(turn_context) + + return super().on_conversation_update_activity(turn_context) + + async def on_teams_member_added_dispatch(self, members_added: List, team_info: TeamInfo, turn_context: TurnContext): + team_members = {} + team_members_added = [] + for member_added in members_added: + if member_added.properties != None: + team_members_added.append(TeamsChannelAccount(member_added)) + else: + if team_members == {}: + result = await TeamInfo.get_members_async(turn_context) + team_members = { i.id : i for i in result } + + if member_added.id in team_members: + team_members_added.append(member_added) + else: + newTeamsChannelAccount = TeamsChannelAccount( + id=member_added.id, + name = member_added.name, + aad_object_id = member_added.aad_object_id, + role = member_added.role + ) + team_members_added.append(newTeamsChannelAccount) + + await self.on_teams_members_added_async(teams_members_added, team_info, turn_context) + + async def on_teams_members_removed_dispatch_async(self, membersRemoved: List, teamInfo: TeamInfo, turn_context: TurnContext): + teams_members_removed = [] + for member_removed in membersRemoved: + teams_members_removed.append(TeamsChannelAccount(member_removed)) + + return self.on_teams_members_removed_async(teams_members_removed, team_info, turn_context) + + async def on_teams_members_added_async(self, teams_members_added: List, team_info: TeamInfo, turn_context: TurnContext): + members_added = [ ChannelAccount(i) for i in teams_members_added ] + return super().on_members_added_activity(members_added, turn_context) + + async def on_teams_members_removed_async(self, teams_members_removed: List, team_info: TeamInfo, turn_context: TurnContext): + members_removed = [ ChannelAccount(i) for i in teams_members_removed ] + return super().on_members_removed_activity(members_removed, turn_context) + + async def on_teams_channel_created_async(self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context, TurnContext): + return #Task.CompleteTask + + async def on_teams_channel_deleted_async(self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext): + return #Task.CompleteTask + + async def on_teams_channel_renamed_async(self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext): + return #Task.CompleteTask + + async def on_teams_team_reanamed_async(self, teamInfo: TeamInfo, turn_context: TurnContext): + return #Task.CompleteTask + + @staticmethod + def _create_invoke_response(body: object = None) -> InvokeResponse: + return InvokeResponse(status = int(HTTPStatus.OK), body = body) + + class _InvokeResponseException(Exception): + def __init__(self, status_code: HTTPStatus, body: object = None): + self._statusCode = status_code + self._body = body + + def create_invoke_response() -> InvokeResponse: + return InvokeResponse(status= int(self._statusCode), body = self._body) \ No newline at end of file diff --git a/libraries/botbuilder-schema/teams/team_info.py b/libraries/botbuilder-schema/teams/team_info.py new file mode 100644 index 000000000..105dcaf77 --- /dev/null +++ b/libraries/botbuilder-schema/teams/team_info.py @@ -0,0 +1,20 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is +# regenerated. + +class TeamInfo: + def __init__(self, id: string = "", name: string = ""): + self.id = id + self.name = name + + @property + def id(): + return self.id + + @property + def name(): + return self.name \ No newline at end of file diff --git a/libraries/botbuilder-schema/teams/teams_channel_account.py b/libraries/botbuilder-schema/teams/teams_channel_account.py new file mode 100644 index 000000000..6e11ae058 --- /dev/null +++ b/libraries/botbuilder-schema/teams/teams_channel_account.py @@ -0,0 +1,34 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is +# regenerated. + +from botbuilder.schema import ChannelAccount + +class TeamsChannelAccount(ChanelAccount): + def __init__(self, id: string = "", name: string = "", given_name: string = "", surname: string = "", email: string = "", user_principal_name: string = ""): + self.id = id + self.name = name + self.given_name = given_name + self.surname = surname + self.email = email + self.user_principal_name = user_principal_name + + @property + def given_name(): + return self.given_name + + @property + def surname(): + return self.surname + + @property + def email(): + return self.email + + @property + def user_principal_name(): + return self.user_principal_name \ No newline at end of file From 21876ca45dd292150db15f2c875de0f4448a8729 Mon Sep 17 00:00:00 2001 From: virtual-josh Date: Wed, 6 Nov 2019 23:18:57 -0800 Subject: [PATCH 2/7] adding conversation update scenario --- .../botbuilder/core/Teams/__init__.py | 10 + .../core/Teams/teams_activity_handler.py | 227 ++++++------------ .../botbuilder/core/Teams/teams_info.py | 12 + .../tests/teams/conversation-update/README.md | 30 +++ .../tests/teams/conversation-update/app.py | 83 +++++++ .../conversation-update/bots/__init__.py | 6 + .../bots/conversation_update_bot.py | 36 +++ .../tests/teams/conversation-update/config.py | 15 ++ .../conversation-update/requirements.txt | 2 + .../teams_app_manifest/color.png | Bin 0 -> 1229 bytes .../teams_app_manifest/manifest.json | 43 ++++ .../teams_app_manifest/outline.png | Bin 0 -> 383 bytes .../botbuilder/schema/teams/__init__.py | 15 ++ .../botbuilder/schema/teams/channel_info.py | 28 +++ .../schema/teams/notification_info.py | 19 ++ .../botbuilder/schema/teams/team_info.py | 36 +++ .../schema/teams/teams_channel_account.py | 60 +++++ .../schema/teams/teams_channel_data.py | 59 +++++ .../schema/teams/tenant_info.py} | 19 +- .../teams/teams_channel_account.py | 34 --- samples/02.echo-bot/config.py | 4 +- 21 files changed, 536 insertions(+), 202 deletions(-) create mode 100644 libraries/botbuilder-core/botbuilder/core/Teams/__init__.py create mode 100644 libraries/botbuilder-core/tests/teams/conversation-update/README.md create mode 100644 libraries/botbuilder-core/tests/teams/conversation-update/app.py create mode 100644 libraries/botbuilder-core/tests/teams/conversation-update/bots/__init__.py create mode 100644 libraries/botbuilder-core/tests/teams/conversation-update/bots/conversation_update_bot.py create mode 100644 libraries/botbuilder-core/tests/teams/conversation-update/config.py create mode 100644 libraries/botbuilder-core/tests/teams/conversation-update/requirements.txt create mode 100644 libraries/botbuilder-core/tests/teams/conversation-update/teams_app_manifest/color.png create mode 100644 libraries/botbuilder-core/tests/teams/conversation-update/teams_app_manifest/manifest.json create mode 100644 libraries/botbuilder-core/tests/teams/conversation-update/teams_app_manifest/outline.png create mode 100644 libraries/botbuilder-schema/botbuilder/schema/teams/__init__.py create mode 100644 libraries/botbuilder-schema/botbuilder/schema/teams/channel_info.py create mode 100644 libraries/botbuilder-schema/botbuilder/schema/teams/notification_info.py create mode 100644 libraries/botbuilder-schema/botbuilder/schema/teams/team_info.py create mode 100644 libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_account.py create mode 100644 libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_data.py rename libraries/botbuilder-schema/{teams/team_info.py => botbuilder/schema/teams/tenant_info.py} (62%) delete mode 100644 libraries/botbuilder-schema/teams/teams_channel_account.py diff --git a/libraries/botbuilder-core/botbuilder/core/Teams/__init__.py b/libraries/botbuilder-core/botbuilder/core/Teams/__init__.py new file mode 100644 index 000000000..bad913500 --- /dev/null +++ b/libraries/botbuilder-core/botbuilder/core/Teams/__init__.py @@ -0,0 +1,10 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- + +from .teams_activity_handler import TeamsActivityHandler + +__all__ = ["TeamsActivityHandler"] \ No newline at end of file diff --git a/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py b/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py index 2e6f7d71a..8997ab4c8 100644 --- a/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py +++ b/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py @@ -4,19 +4,22 @@ from typing import List from botbuilder.schema import ActivityTypes, ChannelAccount, MessageReaction -from botbuilder.schema.teams import TeamInfo -from .turn_context import TurnContext -from activity_handler import ActivityHandler +from botbuilder.core.turn_context import TurnContext +from botbuilder.core import ActivityHandler, MessageFactory +from botbuilder.schema.teams import TeamInfo, ChannelInfo, TeamsChannelData, TenantInfo, TeamsChannelAccount from botframework.connector import Channels from http import HTTPStatus from botbuilder.core import InvokeResponse +from pprint import pprint +import jsonpickle class TeamsActivityHandler(ActivityHandler): async def on_turn(self, turn_context: TurnContext): if turn_context is None: raise TypeError("ActivityHandler.on_turn(): turn_context cannot be None.") + if hasattr(turn_context, "activity") and turn_context.activity is None: raise TypeError( "ActivityHandler.on_turn(): turn_context must have a non-None activity." @@ -30,196 +33,108 @@ async def on_turn(self, turn_context: TurnContext): "ActivityHandler.on_turn(): turn_context activity must have a non-None type." ) - if turn_context.activity.type == ActivityTypes.Invoke: - pass + if turn_context.activity.type == ActivityTypes.invoke: + invokeResponse = await on_invoke_activity(turn_context) else: - await super(on_turn(turn_context)) + await super().on_turn(turn_context) - return - async def on_invoke_activity_async(self, turn_context: TurnContext): + async def on_invoke_activity(turn_context: TurnContext): try: - if turn_context.activity.name == None and turn_context.activity.channel_id == Channels.ms_teams: - return await on_teams_card_action_invoke(turn_context) + if turn_context.activity.name == None and turn_context.activity.channel_id == Channels.Msteams: + return #await on_teams_card_action_invoke_activity(turn_context) else: - if turn_context.activity.name == "signin/verifyState": - await on_teams_signin_verify_state_async(turn_context) - return _create_invoke_response() - elif turn_context.activity.name == "fileConsent/invoke": - await on_teams_file_concent_async(turn_context, turn_context.activity.value) - return _create_invoke_response() - elif turn_context.activity.name == "actionableMessage/executeAction": - await on_teams_o365_connector_card_action_async(turn_context, turn_context.activity.value) - return _create_invoke_response() - elif turn_context.activity.name == "composeExtension/queryLink": - return createInvokeResponse(await on_teams_app_based_link_query_async(turn_context, turn_context.activity.value)) - elif turn_context.activity.name == "composeExtension/query": - return _create_invoke_response(await on_teams_messaging_extension_query_async(turn_context, turn_context.activity.value)) - elif turn_context.activity.name == "composeExtension/selectItem": - return _create_invoke_response(await on_teams_messaging_extension_select_item_async(turn_context, turn_context.activity.value)) - elif turn_context.activity.name == "composeExtension/submitAction": - return _create_invoke_response(await on_teams_messaging_extension_submit_action_dispatch_async(turn_context, turn_context.activity.value)) - elif turn_context.activity.name == "composeExtension/fetchTask": - return _create_invoke_response(await on_teams_messaging_extension_fetch_task_async(turn_context, turn_context.activity.value)) - elif turn_context.activity.name == "composeExtension/querySettingUrl": - return _create_invoke_response(await on_teams_messaging_extension_configuration_query_settings_url_async(turn_context, turn_context.activity.value)) - elif turn_context.acitivity.name == "composseExtension/settings": - await on_teams_messaging_extension_configuration_settings_async(turn_context, turn_context.activity.value) - return _create_invoke_response() - elif turn_context.acitivity.name == "composeExtension/onCardButtonClicked": - await on_teams_messaging_extension_card_button_clicked_async(turn_context, turn_context.acitivity.value) - return _create_invoke_response() - elif turn_context.acitivity.name == "task/fetch": - return _create_invoke_response(await on_teams_task_module_fetch_async(turn_context, turn_context.activity.value)) - elif turn_context.acitivity.name == "task/submit": - return _create_invoke_response(await on_teams_task_module_submit_async(turn_context, turn_context.activity.value)) - else: - raise invoke_response_exception(HTTPStatus.NOT_IMPLEMENTED) - except InvokeResponseException as e: - return e.CreateInvokeResponse() - - async def on_teams_card_action_invoke_async(self, turn_context: TurnContext): - raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) - - async def on_teams_singin_verify_state_async(self, turn_context: TurnContext): - raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) - - async def on_teams_file_concent_async(self, turn_context: TurnContext, file_consent_card_response: FileConcentCardResponse): - if file_consent_card_response.action == "accept": - await file_consent_card_response(turn_context, file_consent_card_response) - return _create_invoke_response() - elif file_consent_card_response.action == "decline": - await on_teams_file_consent_decline_async(turn_context, file_consent_card_response) - return _create_invoke_response() - else: - raise _InvokeResponseException(HTTPStatus.BAD_REQUEST, ("%s is not a supported action" % file_consent_card_response)) - - async def on_teams_file_consent_accept_async(self, turn_context: TurnContext, file_consent_card_response: FileConsentCardResponse): - raise _InvokeResponseException(HTTPStatus.NOT_IMPLMENENTED) - - async def on_teams_file_consent_decline_async(self, turn_context: TurnContext, file_consent_card_response: FileConsentCardResponse): - raise _InvokeResponseException(HTTPStatus.NOT_IMPLMENENTED) - - async def on_teams_messaging_extension_query_async(self, turn_context: TurnContext, query: MessagingExtensionQuery): - raise _InvokeResponseException(HTTPStatus.NOT_IMPLMENENTED) - - async def on_teams_o365_connector_card_action_async(self, turn_context: TurnContext, query: O365ConnectorCardActionQuery): - raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) - - async def on_teams_app_based_link_query_async(self, turn_context: TurnContext, query: AppBasedLinkQuery): - raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) - - async def on_teams_messaging_extension_select_item_async(self, turn_context: TurnContext, query: JObject): - raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) - - async def on_teams_messaging_extension_fetch_task_async(self, turn_context: TurnContext, action: MessagingExtensionAction): - raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) - - async def on_teams_messaging_extension_submit_action_dispatch_async(self, turn_context: TurnContext, action, MessagingExtensionAction): - if action.BotMessagePreviewAction != None: - if action.BotMessagePreviewAction == "edit": - return await on_teams_messaging_extension_bot_message_preview_edit_async(turn_context, action) - elif action.BotMessagePreview == "send": - return await on_teams_messaging_extension_bot_message_preview_send_async(turn_context, action) - else: - raise _InvokeResponseException(HTTPStatus.BAD_REQUEST, - ("%s is not a supported BotMessagePreviewAction" % action.BotMessagePreviewAction)) - else: - return await on_teams_messaging_extension_submit_action_async(turn_context, action) - - async def on_teams_messaging_extension_submit_action_async(self, turn_context: TurnContext, action: MEssagingExtensionAction): - raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) - - async def on_teams_messaging_extension_bot_message_preview_edit_async(self, turn_context: TurnContext, action: MessagingExtensionAction): - raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) - - async def on_teams_messaging_extension_bot_message_preview_send_async(self, turn_context: TurnContext, action: MessagingExtensionAction): - raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) - - async def on_teams_messaging_extension_configuration_query_setting_url_async(self, turn_context: TurnContext, query: MessagingExtensionQuery): - raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) - - async def on_teams_messaging_extension_configuration_setting_async(self, turn_context: TurnContext, settings: JObject): - raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) - - async def on_teams_messaging_extension_card_button_clicked_async(self, turn_context: TurnContext, cardData: JObject): - raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) - - async def on_teams_task_module_fetch_async(self, turn_context: TurnContext, taskModuleRequest: TaskModuleRequest): - raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) - - async def on_teams_task_module_submit_async(self, turn_context: TurnContext, task_module_request: TaskModuleRequest): - raise _InvokeResponseException(HTTPStatus.NOT_IMPLEMENTED) - - async def on_conversation_update_activity_async(self, turn_context: TurnContext): - if turn_context.activity.channel_id == Channels.Msteams: - channel_data = turn_context.activity.get_channel_data() - if turn_context.activity.members_added != None: - return on_teams_members_added_dispatch_async(turn_context.activity.members_added, channel_data.team) + turn_context.send_activity(MessageFactory.text("working")) + except: + return + + async def on_conversation_update_activity(self, turn_context: TurnContext): + print(turn_context.activity) + if turn_context.activity.channel_id == Channels.ms_teams: + channel_data = TeamsChannelData(**turn_context.activity.channel_data) if turn_context.activity.members_added != None: - return on_teams_members_removed_dispatched_async(turn_context.acitivity.members_removed, channel_data.team) + return await self.on_teams_members_added_dispatch_activity(turn_context.activity.members_added, channel_data.team, turn_context) + if turn_context.activity.members_removed != None: + return await self.on_teams_members_removed_dispatch_activity(turn_context.activity.members_removed, channel_data.team, turn_context) + if channel_data != None: if channel_data.event_type == "channelCreated": - return on_teams_channel_created_async(channel_data.channel, channel_data.team, turn_context) + return await self.on_teams_channel_created_activity(channel_data.channel, channel_data.team, turn_context) elif channel_data.event_type == "channelDeleted": - return on_teams_channel_deleted_async(channel_data.channel, channel_data.team, turn_context) + return await self.on_teams_channel_deleted_activity(channel_data.channel, channel_data.team, turn_context) elif channel_data.event_type == "channelRenamed": - return on_teams_channel_renamed(channel_data.channel, channel_data.team, turn_context) + return await self.on_teams_channel_renamed_activity(channel_data.channel, channel_data.team, turn_context) elif channel_data.event_type == "teamRenamed": - return self.on_teams_team_renamed_async(channel_data.team, turn_context) + return await self.on_teams_team_renamed_activity(channel_data.team, turn_context) else: - return super().on_conversation_update_activity(turn_context) + return await super().on_conversation_update_activity(turn_context) - return super().on_conversation_update_activity(turn_context) + return await super().on_conversation_update_activity(turn_context) + + async def on_teams_channel_created_activity(self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext): + return - async def on_teams_member_added_dispatch(self, members_added: List, team_info: TeamInfo, turn_context: TurnContext): + async def on_teams_team_renamed_activity(self, team_info: TeamInfo, turn_context: TurnContext): + return + + async def on_teams_members_added_dispatch_activity(self, members_added: [ChannelAccount], team_info: TeamInfo, turn_context: TurnContext): + """ team_members = {} team_members_added = [] - for member_added in members_added: - if member_added.properties != None: - team_members_added.append(TeamsChannelAccount(member_added)) + for member in members_added: + if member.additional_properties != {}: + team_members_added.append(TeamsChannelAccount(member)) else: if team_members == {}: - result = await TeamInfo.get_members_async(turn_context) + result = await TeamsInfo.get_members_async(turn_context) team_members = { i.id : i for i in result } - if member_added.id in team_members: - team_members_added.append(member_added) + if member.id in team_members: + team_members_added.append(member) else: newTeamsChannelAccount = TeamsChannelAccount( - id=member_added.id, - name = member_added.name, - aad_object_id = member_added.aad_object_id, - role = member_added.role + id=member.id, + name = member.name, + aad_object_id = member.aad_object_id, + role = member.role ) team_members_added.append(newTeamsChannelAccount) - await self.on_teams_members_added_async(teams_members_added, team_info, turn_context) + return await self.on_teams_members_added_activity(teams_members_added, team_info, turn_context) + """ + for member in members_added: + newAccountJson = member.__dict__ + del newAccountJson["additional_properties"] + member = TeamsChannelAccount(**newAccountJson) + return await self.on_teams_members_added_activity(members_added, turn_context) + + async def on_teams_members_added_activity(self, teams_members_added: [TeamsChannelAccount], turn_context: TurnContext): + for member in teams_members_added: + member = ChannelAccount(member) + return super().on_members_added_activity(members_added, turn_context) - async def on_teams_members_removed_dispatch_async(self, membersRemoved: List, teamInfo: TeamInfo, turn_context: TurnContext): + async def on_teams_members_removed_dispatch_activity(self, members_removed: List, team_info: TeamInfo, turn_context: TurnContext): teams_members_removed = [] - for member_removed in membersRemoved: - teams_members_removed.append(TeamsChannelAccount(member_removed)) - - return self.on_teams_members_removed_async(teams_members_removed, team_info, turn_context) + for member in members_removed: + newAccountJson = member.__dict__ + del newAccountJson["additional_properties"] + teams_members_removed.append(TeamsChannelAccount(**newAccountJson)) - async def on_teams_members_added_async(self, teams_members_added: List, team_info: TeamInfo, turn_context: TurnContext): - members_added = [ ChannelAccount(i) for i in teams_members_added ] - return super().on_members_added_activity(members_added, turn_context) + return await self.on_teams_members_removed_activity(teams_members_removed, turn_context) - async def on_teams_members_removed_async(self, teams_members_removed: List, team_info: TeamInfo, turn_context: TurnContext): + async def on_teams_members_removed_activity(self, teams_members_removed: [TeamsChannelAccount], turn_context: TurnContext): members_removed = [ ChannelAccount(i) for i in teams_members_removed ] return super().on_members_removed_activity(members_removed, turn_context) - async def on_teams_channel_created_async(self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context, TurnContext): - return #Task.CompleteTask + + - async def on_teams_channel_deleted_async(self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext): + async def on_teams_channel_deleted_activity(self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext): return #Task.CompleteTask - async def on_teams_channel_renamed_async(self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext): + async def on_teams_channel_renamed_activity(self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext): return #Task.CompleteTask async def on_teams_team_reanamed_async(self, teamInfo: TeamInfo, turn_context: TurnContext): diff --git a/libraries/botbuilder-core/botbuilder/core/Teams/teams_info.py b/libraries/botbuilder-core/botbuilder/core/Teams/teams_info.py index e69de29bb..9f5357985 100644 --- a/libraries/botbuilder-core/botbuilder/core/Teams/teams_info.py +++ b/libraries/botbuilder-core/botbuilder/core/Teams/teams_info.py @@ -0,0 +1,12 @@ +class TeamInfo: + def __init__(self, id = "", name = ""): + self.id = id + self.name = name + + @property + def id(): + return self.id + + @property + def name(): + return self.name \ No newline at end of file diff --git a/libraries/botbuilder-core/tests/teams/conversation-update/README.md b/libraries/botbuilder-core/tests/teams/conversation-update/README.md new file mode 100644 index 000000000..40e84f525 --- /dev/null +++ b/libraries/botbuilder-core/tests/teams/conversation-update/README.md @@ -0,0 +1,30 @@ +# EchoBot + +Bot Framework v4 echo bot sample. + +This bot has been created using [Bot Framework](https://dev.botframework.com), it shows how to create a simple bot that accepts input from the user and echoes it back. + +## Running the sample +- Clone the repository +```bash +git clone https://github.com/Microsoft/botbuilder-python.git +``` +- Activate your desired virtual environment +- Bring up a terminal, navigate to `botbuilder-python\samples\02.echo-bot` folder +- In the terminal, type `pip install -r requirements.txt` +- In the terminal, type `python app.py` + +## Testing the bot using Bot Framework Emulator +[Microsoft Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel. + +- Install the Bot Framework emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases) + +### Connect to bot using Bot Framework Emulator +- Launch Bot Framework Emulator +- Paste this URL in the emulator window - http://localhost:3978/api/messages + +## Further reading + +- [Bot Framework Documentation](https://docs.botframework.com) +- [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0) +- [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?view=azure-bot-service-4.0) diff --git a/libraries/botbuilder-core/tests/teams/conversation-update/app.py b/libraries/botbuilder-core/tests/teams/conversation-update/app.py new file mode 100644 index 000000000..1c3a74476 --- /dev/null +++ b/libraries/botbuilder-core/tests/teams/conversation-update/app.py @@ -0,0 +1,83 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +import asyncio +import sys +from datetime import datetime +from types import MethodType + +from flask import Flask, request, Response +from botbuilder.core import BotFrameworkAdapterSettings, TurnContext, BotFrameworkAdapter +from botbuilder.schema import Activity, ActivityTypes + +from bots import ConversationUpdateBot + +# Create the loop and Flask app +LOOP = asyncio.get_event_loop() +APP = Flask(__name__, instance_relative_config=True) +APP.config.from_object("config.DefaultConfig") + +# Create adapter. +# See https://aka.ms/about-bot-adapter to learn more about how bots work. +SETTINGS = BotFrameworkAdapterSettings(APP.config["APP_ID"], APP.config["APP_PASSWORD"]) +ADAPTER = BotFrameworkAdapter(SETTINGS) + + +# Catch-all for errors. +async def on_error(self, context: TurnContext, error: Exception): + # This check writes out errors to console log .vs. app insights. + # NOTE: In production environment, you should consider logging this to Azure + # application insights. + print(f"\n [on_turn_error] unhandled error: {error}", file=sys.stderr) + + # Send a message to the user + await context.send_activity("The bot encountered an error or bug.") + await context.send_activity("To continue to run this bot, please fix the bot source code.") + # Send a trace activity if we're talking to the Bot Framework Emulator + if context.activity.channel_id == 'emulator': + # Create a trace activity that contains the error object + trace_activity = Activity( + label="TurnError", + name="on_turn_error Trace", + timestamp=datetime.utcnow(), + type=ActivityTypes.trace, + value=f"{error}", + value_type="https://www.botframework.com/schemas/error" + ) + # Send a trace activity, which will be displayed in Bot Framework Emulator + await context.send_activity(trace_activity) + +ADAPTER.on_turn_error = MethodType(on_error, ADAPTER) + +# Create the Bot +BOT = ConversationUpdateBot() + +# Listen for incoming requests on /api/messages.s +@APP.route("/api/messages", methods=["POST"]) +def messages(): + # Main bot message handler. + if "application/json" in request.headers["Content-Type"]: + body = request.json + else: + return Response(status=415) + + activity = Activity().deserialize(body) + auth_header = ( + request.headers["Authorization"] if "Authorization" in request.headers else "" + ) + + try: + task = LOOP.create_task( + ADAPTER.process_activity(activity, auth_header, BOT.on_turn) + ) + LOOP.run_until_complete(task) + return Response(status=201) + except Exception as exception: + raise exception + + +if __name__ == "__main__": + try: + APP.run(debug=False, port=APP.config["PORT"]) # nosec debug + except Exception as exception: + raise exception diff --git a/libraries/botbuilder-core/tests/teams/conversation-update/bots/__init__.py b/libraries/botbuilder-core/tests/teams/conversation-update/bots/__init__.py new file mode 100644 index 000000000..f9e91a398 --- /dev/null +++ b/libraries/botbuilder-core/tests/teams/conversation-update/bots/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +from .conversation_update_bot import ConversationUpdateBot + +__all__ = ["ConversationUpdateBot"] diff --git a/libraries/botbuilder-core/tests/teams/conversation-update/bots/conversation_update_bot.py b/libraries/botbuilder-core/tests/teams/conversation-update/bots/conversation_update_bot.py new file mode 100644 index 000000000..e0b8098fd --- /dev/null +++ b/libraries/botbuilder-core/tests/teams/conversation-update/bots/conversation_update_bot.py @@ -0,0 +1,36 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +from botbuilder.core import ActivityHandler, MessageFactory, TurnContext, CardFactory +from botbuilder.core.teams import TeamsActivityHandler +from botbuilder.schema import ChannelAccount +from botbuilder.schema.teams import ChannelInfo, TeamInfo, TeamsChannelAccount + + +class ConversationUpdateBot(TeamsActivityHandler): + async def on_teams_channel_created_activity(self, channel_info: ChannelInfo, teamInfo: TeamInfo, turn_context: TurnContext): + return await turn_context.send_activity(MessageFactory.text(f"The new channel is {channel_info.name}. The channel id is {channel_info.id}")) + + async def on_teams_channel_deleted_activity(self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext): + return await turn_context.send_activity(MessageFactory.text(f"The deleted channel is {channel_info.name}")) + + async def on_teams_channel_renamed_activity(self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext): + return await turn_context.send_activity(MessageFactory.text(f"The new channel name is {channel_info.name}")) + + async def on_teams_team_renamed_activity(self, team_info: TeamInfo, turn_context: TurnContext): + return await turn_context.send_activity(MessageFactory.text(f"The new team name is {team_info.name}")) + + async def on_teams_members_added_activity(self, teams_members_added: [TeamsChannelAccount], turn_context: TurnContext): + for member in teams_members_added: + await turn_context.send_activity(MessageFactory.text(f"Welcome your new team member {member.id}")) + return + + async def on_teams_members_removed_activity(self, teams_members_removed: [TeamsChannelAccount], turn_context: TurnContext): + for member in teams_members_removed: + await turn_context.send_activity(MessageFactory.text(f"Say goodbye to your team member {member.id}")) + return + + + + + \ No newline at end of file diff --git a/libraries/botbuilder-core/tests/teams/conversation-update/config.py b/libraries/botbuilder-core/tests/teams/conversation-update/config.py new file mode 100644 index 000000000..762d93edf --- /dev/null +++ b/libraries/botbuilder-core/tests/teams/conversation-update/config.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +import os + +""" Bot Configuration """ + + +class DefaultConfig: + """ Bot Configuration """ + + PORT = 3978 + APP_ID = os.environ.get("MicrosoftAppId", "5396829c-e0a1-4698-9746-848ca0ba2892") + APP_PASSWORD = os.environ.get("MicrosoftAppPassword", "x@YOwxU3rqAPzc.nxdRx?Zc.Z96OiHt4") diff --git a/libraries/botbuilder-core/tests/teams/conversation-update/requirements.txt b/libraries/botbuilder-core/tests/teams/conversation-update/requirements.txt new file mode 100644 index 000000000..7e54b62ec --- /dev/null +++ b/libraries/botbuilder-core/tests/teams/conversation-update/requirements.txt @@ -0,0 +1,2 @@ +botbuilder-core>=4.4.0b1 +flask>=1.0.3 diff --git a/libraries/botbuilder-core/tests/teams/conversation-update/teams_app_manifest/color.png b/libraries/botbuilder-core/tests/teams/conversation-update/teams_app_manifest/color.png new file mode 100644 index 0000000000000000000000000000000000000000..48a2de13303e1e8a25f76391f4a34c7c4700fd3d GIT binary patch literal 1229 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGojKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCe1|JzX3_D&pSWuFnWfl{x;g|9jrEYf8Vqrkk2Ba|%ol3OT){=#|7ID~|e{ zODQ{kU&ME#@`*-tm%Tukt_gFr+`F?$dx9wg-jad`^gsMn2_%Kh%WH91&SjKq5 zgkdI|!exdOVgw@>>=!Tjnk6q)zV*T8$FdgRFYC{kQ7``NOcl@R(_%_8e5e0E;>v0G zEM9kb)2itgOTSfH7M=b3-S61B?PiazMdwXZwrS)^5UUS#HQjaoua5h_{Gx*_Zz|XK z$tf0mZ&=tpf2!!Q)!A_l&o_$g*|JM$VZa~F^0{x1T{=QFu*x$`=V%~jUW=G`iqqp=lquB-`P{Qjw`=zEu3cMc_x7m2f#9m}uoFBMMQ^+%cOL)F_)N@JZ}Axoxi1y= zeebq`y==e!nl+?cK-PhOec!3%|IupShHrcjW8sSt)F1>NW*{ zW%ljk2)nk%-}+F&?gi=7^$L#VeX3@kp%f{n}fR z`}uZPx$IY~r8R5%gMlrc`jP!L3IloKFoq~sFFH5|cdklX=R08T)}71BhaN8$`AsNf0_ zq>WNhAtCd|-nBlTU=y5zl_vXlXZ~bkuaYENMp>3QSQ_#zuYZ+eQh*OIHRxP~s(}ic zN2J4$u=AQcPt)|>F3zZLsjtP;Tajkugx;NcYED2~JVBlVO>{`uAY?Q4O|AA z=16}CJieK^5P_TKnou!zGR`$!PUC)DqtkO;?!`p!+9v3lP_mu=%Vt3BkoWsq%;FN1sp58w*zfr-z^7tIb*q>!yncCjrzLuOk3N+d&~^Cxd| z Date: Mon, 11 Nov 2019 09:53:10 -0800 Subject: [PATCH 3/7] fixing linting issues --- .../botbuilder/core/Teams/__init__.py | 2 +- .../core/Teams/teams_activity_handler.py | 183 +++++++++++------- .../botbuilder/core/Teams/teams_info.py | 12 -- .../tests/teams/conversation-update/app.py | 19 +- .../bots/conversation_update_bot.py | 68 ++++--- .../tests/teams/conversation-update/config.py | 6 +- .../botbuilder/schema/teams/__init__.py | 14 +- .../botbuilder/schema/teams/channel_info.py | 13 +- .../schema/teams/notification_info.py | 9 +- .../botbuilder/schema/teams/team_info.py | 14 +- .../schema/teams/teams_channel_account.py | 33 +++- .../schema/teams/teams_channel_data.py | 48 +++-- .../botbuilder/schema/teams/tenant_info.py | 11 +- 13 files changed, 252 insertions(+), 180 deletions(-) delete mode 100644 libraries/botbuilder-core/botbuilder/core/Teams/teams_info.py diff --git a/libraries/botbuilder-core/botbuilder/core/Teams/__init__.py b/libraries/botbuilder-core/botbuilder/core/Teams/__init__.py index bad913500..6683b49a0 100644 --- a/libraries/botbuilder-core/botbuilder/core/Teams/__init__.py +++ b/libraries/botbuilder-core/botbuilder/core/Teams/__init__.py @@ -7,4 +7,4 @@ from .teams_activity_handler import TeamsActivityHandler -__all__ = ["TeamsActivityHandler"] \ No newline at end of file +__all__ = ["TeamsActivityHandler"] diff --git a/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py b/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py index 8997ab4c8..9aa6c998a 100644 --- a/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py +++ b/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py @@ -1,25 +1,23 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -from typing import List - -from botbuilder.schema import ActivityTypes, ChannelAccount, MessageReaction +from http import HTTPStatus +from botbuilder.schema import ActivityTypes, ChannelAccount from botbuilder.core.turn_context import TurnContext -from botbuilder.core import ActivityHandler, MessageFactory -from botbuilder.schema.teams import TeamInfo, ChannelInfo, TeamsChannelData, TenantInfo, TeamsChannelAccount +from botbuilder.core import ActivityHandler, MessageFactory, InvokeResponse +from botbuilder.schema.teams import ( + TeamInfo, + ChannelInfo, + TeamsChannelData, + TeamsChannelAccount, +) from botframework.connector import Channels -from http import HTTPStatus -from botbuilder.core import InvokeResponse - -from pprint import pprint -import jsonpickle class TeamsActivityHandler(ActivityHandler): async def on_turn(self, turn_context: TurnContext): if turn_context is None: raise TypeError("ActivityHandler.on_turn(): turn_context cannot be None.") - if hasattr(turn_context, "activity") and turn_context.activity is None: raise TypeError( "ActivityHandler.on_turn(): turn_context must have a non-None activity." @@ -34,52 +32,74 @@ async def on_turn(self, turn_context: TurnContext): ) if turn_context.activity.type == ActivityTypes.invoke: - invokeResponse = await on_invoke_activity(turn_context) + invoke_response = await self.on_invoke_activity(turn_context) else: await super().on_turn(turn_context) - - async def on_invoke_activity(turn_context: TurnContext): + async def on_invoke_activity(self, turn_context: TurnContext): try: - if turn_context.activity.name == None and turn_context.activity.channel_id == Channels.Msteams: - return #await on_teams_card_action_invoke_activity(turn_context) - else: - turn_context.send_activity(MessageFactory.text("working")) + if ( + turn_context.activity.name is None + and turn_context.activity.channel_id == Channels.Msteams + ): + return # await on_teams_card_action_invoke_activity(turn_context) + + turn_context.send_activity(MessageFactory.text("working")) except: return - + async def on_conversation_update_activity(self, turn_context: TurnContext): - print(turn_context.activity) if turn_context.activity.channel_id == Channels.ms_teams: channel_data = TeamsChannelData(**turn_context.activity.channel_data) - if turn_context.activity.members_added != None: - return await self.on_teams_members_added_dispatch_activity(turn_context.activity.members_added, channel_data.team, turn_context) + if turn_context.activity.members_added is not None: + return await self.on_teams_members_added_dispatch_activity( + turn_context.activity.members_added, channel_data.team, turn_context + ) + + if turn_context.activity.members_removed is not None: + return await self.on_teams_members_removed_dispatch_activity( + turn_context.activity.members_removed, + channel_data.team, + turn_context, + ) - if turn_context.activity.members_removed != None: - return await self.on_teams_members_removed_dispatch_activity(turn_context.activity.members_removed, channel_data.team, turn_context) - - if channel_data != None: + if channel_data is not None: if channel_data.event_type == "channelCreated": - return await self.on_teams_channel_created_activity(channel_data.channel, channel_data.team, turn_context) - elif channel_data.event_type == "channelDeleted": - return await self.on_teams_channel_deleted_activity(channel_data.channel, channel_data.team, turn_context) - elif channel_data.event_type == "channelRenamed": - return await self.on_teams_channel_renamed_activity(channel_data.channel, channel_data.team, turn_context) - elif channel_data.event_type == "teamRenamed": - return await self.on_teams_team_renamed_activity(channel_data.team, turn_context) - else: - return await super().on_conversation_update_activity(turn_context) - + return await self.on_teams_channel_created_activity( + channel_data.channel, channel_data.team, turn_context + ) + if channel_data.event_type == "channelDeleted": + return await self.on_teams_channel_deleted_activity( + channel_data.channel, channel_data.team, turn_context + ) + if channel_data.event_type == "channelRenamed": + return await self.on_teams_channel_renamed_activity( + channel_data.channel, channel_data.team, turn_context) + if channel_data.event_type == "teamRenamed": + return await self.on_teams_team_renamed_activity( + channel_data.team, turn_context + ) + return await super().on_conversation_update_activity(turn_context) + return await super().on_conversation_update_activity(turn_context) - - async def on_teams_channel_created_activity(self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext): + + async def on_teams_channel_created_activity( # pylint: disable=unused-argument + self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext + ): return - - async def on_teams_team_renamed_activity(self, team_info: TeamInfo, turn_context: TurnContext): + + async def on_teams_team_renamed_activity( # pylint: disable=unused-argument + self, team_info: TeamInfo, turn_context: TurnContext + ): return - async def on_teams_members_added_dispatch_activity(self, members_added: [ChannelAccount], team_info: TeamInfo, turn_context: TurnContext): + async def on_teams_members_added_dispatch_activity( # pylint: disable=unused-argument + self, + members_added: [ChannelAccount], + team_info: TeamInfo, + turn_context: TurnContext, + ): """ team_members = {} team_members_added = [] @@ -90,64 +110,79 @@ async def on_teams_members_added_dispatch_activity(self, members_added: [Channel if team_members == {}: result = await TeamsInfo.get_members_async(turn_context) team_members = { i.id : i for i in result } - + if member.id in team_members: team_members_added.append(member) else: newTeamsChannelAccount = TeamsChannelAccount( - id=member.id, - name = member.name, + id=member.id, + name = member.name, aad_object_id = member.aad_object_id, role = member.role ) team_members_added.append(newTeamsChannelAccount) - + return await self.on_teams_members_added_activity(teams_members_added, team_info, turn_context) """ for member in members_added: - newAccountJson = member.__dict__ - del newAccountJson["additional_properties"] - member = TeamsChannelAccount(**newAccountJson) + new_account_json = member.__dict__ + del new_account_json["additional_properties"] + member = TeamsChannelAccount(**new_account_json) return await self.on_teams_members_added_activity(members_added, turn_context) - async def on_teams_members_added_activity(self, teams_members_added: [TeamsChannelAccount], turn_context: TurnContext): + async def on_teams_members_added_activity( + self, teams_members_added: [TeamsChannelAccount], turn_context: TurnContext + ): for member in teams_members_added: member = ChannelAccount(member) - return super().on_members_added_activity(members_added, turn_context) - - async def on_teams_members_removed_dispatch_activity(self, members_removed: List, team_info: TeamInfo, turn_context: TurnContext): + return super().on_members_added_activity(teams_members_added, turn_context) + + async def on_teams_members_removed_dispatch_activity( # pylint: disable=unused-argument + self, + members_removed: [ChannelAccount], + team_info: TeamInfo, + turn_context: TurnContext, + ): teams_members_removed = [] for member in members_removed: - newAccountJson = member.__dict__ - del newAccountJson["additional_properties"] - teams_members_removed.append(TeamsChannelAccount(**newAccountJson)) - - return await self.on_teams_members_removed_activity(teams_members_removed, turn_context) - - async def on_teams_members_removed_activity(self, teams_members_removed: [TeamsChannelAccount], turn_context: TurnContext): - members_removed = [ ChannelAccount(i) for i in teams_members_removed ] + new_account_json = member.__dict__ + del new_account_json["additional_properties"] + teams_members_removed.append(TeamsChannelAccount(**new_account_json)) + + return await self.on_teams_members_removed_activity( + teams_members_removed, turn_context + ) + + async def on_teams_members_removed_activity( + self, teams_members_removed: [TeamsChannelAccount], turn_context: TurnContext + ): + members_removed = [ChannelAccount(i) for i in teams_members_removed] return 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 + ): + return # Task.CompleteTask - async def on_teams_channel_deleted_activity(self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext): - return #Task.CompleteTask + async def on_teams_channel_renamed_activity( # pylint: disable=unused-argument + self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext + ): + return # Task.CompleteTask - async def on_teams_channel_renamed_activity(self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext): - return #Task.CompleteTask - - async def on_teams_team_reanamed_async(self, teamInfo: TeamInfo, turn_context: TurnContext): - return #Task.CompleteTask + async def on_teams_team_reanamed_async( # pylint: disable=unused-argument + self, team_info: TeamInfo, turn_context: TurnContext + ): + return # Task.CompleteTask @staticmethod def _create_invoke_response(body: object = None) -> InvokeResponse: - return InvokeResponse(status = int(HTTPStatus.OK), body = body) - + return InvokeResponse(status=int(HTTPStatus.OK), body=body) + class _InvokeResponseException(Exception): def __init__(self, status_code: HTTPStatus, body: object = None): - self._statusCode = status_code + super().__init__() + self._status_code = status_code self._body = body - def create_invoke_response() -> InvokeResponse: - return InvokeResponse(status= int(self._statusCode), body = self._body) \ No newline at end of file + def create_invoke_response(self) -> InvokeResponse: + return InvokeResponse(status=int(self._status_code), body=self._body) diff --git a/libraries/botbuilder-core/botbuilder/core/Teams/teams_info.py b/libraries/botbuilder-core/botbuilder/core/Teams/teams_info.py deleted file mode 100644 index 9f5357985..000000000 --- a/libraries/botbuilder-core/botbuilder/core/Teams/teams_info.py +++ /dev/null @@ -1,12 +0,0 @@ -class TeamInfo: - def __init__(self, id = "", name = ""): - self.id = id - self.name = name - - @property - def id(): - return self.id - - @property - def name(): - return self.name \ No newline at end of file diff --git a/libraries/botbuilder-core/tests/teams/conversation-update/app.py b/libraries/botbuilder-core/tests/teams/conversation-update/app.py index 1c3a74476..aa6b9adba 100644 --- a/libraries/botbuilder-core/tests/teams/conversation-update/app.py +++ b/libraries/botbuilder-core/tests/teams/conversation-update/app.py @@ -7,7 +7,11 @@ from types import MethodType from flask import Flask, request, Response -from botbuilder.core import BotFrameworkAdapterSettings, TurnContext, BotFrameworkAdapter +from botbuilder.core import ( + BotFrameworkAdapterSettings, + TurnContext, + BotFrameworkAdapter, +) from botbuilder.schema import Activity, ActivityTypes from bots import ConversationUpdateBot @@ -24,7 +28,9 @@ # Catch-all for errors. -async def on_error(self, context: TurnContext, error: Exception): +async def on_error( # pylint: disable=unused-argument + self, context: TurnContext, error: Exception +): # This check writes out errors to console log .vs. app insights. # NOTE: In production environment, you should consider logging this to Azure # application insights. @@ -32,9 +38,11 @@ async def on_error(self, context: TurnContext, error: Exception): # Send a message to the user await context.send_activity("The bot encountered an error or bug.") - await context.send_activity("To continue to run this bot, please fix the bot source code.") + await context.send_activity( + "To continue to run this bot, please fix the bot source code." + ) # Send a trace activity if we're talking to the Bot Framework Emulator - if context.activity.channel_id == 'emulator': + if context.activity.channel_id == "emulator": # Create a trace activity that contains the error object trace_activity = Activity( label="TurnError", @@ -42,11 +50,12 @@ async def on_error(self, context: TurnContext, error: Exception): timestamp=datetime.utcnow(), type=ActivityTypes.trace, value=f"{error}", - value_type="https://www.botframework.com/schemas/error" + value_type="https://www.botframework.com/schemas/error", ) # Send a trace activity, which will be displayed in Bot Framework Emulator await context.send_activity(trace_activity) + ADAPTER.on_turn_error = MethodType(on_error, ADAPTER) # Create the Bot diff --git a/libraries/botbuilder-core/tests/teams/conversation-update/bots/conversation_update_bot.py b/libraries/botbuilder-core/tests/teams/conversation-update/bots/conversation_update_bot.py index e0b8098fd..ec34da0f0 100644 --- a/libraries/botbuilder-core/tests/teams/conversation-update/bots/conversation_update_bot.py +++ b/libraries/botbuilder-core/tests/teams/conversation-update/bots/conversation_update_bot.py @@ -1,36 +1,56 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -from botbuilder.core import ActivityHandler, MessageFactory, TurnContext, CardFactory +from botbuilder.core import MessageFactory, TurnContext from botbuilder.core.teams import TeamsActivityHandler -from botbuilder.schema import ChannelAccount from botbuilder.schema.teams import ChannelInfo, TeamInfo, TeamsChannelAccount class ConversationUpdateBot(TeamsActivityHandler): - async def on_teams_channel_created_activity(self, channel_info: ChannelInfo, teamInfo: TeamInfo, turn_context: TurnContext): - return await turn_context.send_activity(MessageFactory.text(f"The new channel is {channel_info.name}. The channel id is {channel_info.id}")) - - async def on_teams_channel_deleted_activity(self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext): - return await turn_context.send_activity(MessageFactory.text(f"The deleted channel is {channel_info.name}")) - - async def on_teams_channel_renamed_activity(self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext): - return await turn_context.send_activity(MessageFactory.text(f"The new channel name is {channel_info.name}")) - - async def on_teams_team_renamed_activity(self, team_info: TeamInfo, turn_context: TurnContext): - return await turn_context.send_activity(MessageFactory.text(f"The new team name is {team_info.name}")) - - async def on_teams_members_added_activity(self, teams_members_added: [TeamsChannelAccount], turn_context: TurnContext): + async def on_teams_channel_created_activity( + self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext + ): + return await turn_context.send_activity( + MessageFactory.text( + f"The new channel is {channel_info.name}. The channel id is {channel_info.id}" + ) + ) + + async def on_teams_channel_deleted_activity( + self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext + ): + return await turn_context.send_activity( + MessageFactory.text(f"The deleted channel is {channel_info.name}") + ) + + async def on_teams_channel_renamed_activity( + self, channel_info: ChannelInfo, team_info: TeamInfo, turn_context: TurnContext + ): + return await turn_context.send_activity( + MessageFactory.text(f"The new channel name is {channel_info.name}") + ) + + async def on_teams_team_renamed_activity( + self, team_info: TeamInfo, turn_context: TurnContext + ): + return await turn_context.send_activity( + MessageFactory.text(f"The new team name is {team_info.name}") + ) + + async def on_teams_members_added_activity( + self, teams_members_added: [TeamsChannelAccount], turn_context: TurnContext + ): for member in teams_members_added: - await turn_context.send_activity(MessageFactory.text(f"Welcome your new team member {member.id}")) + await turn_context.send_activity( + MessageFactory.text(f"Welcome your new team member {member.id}") + ) return - - async def on_teams_members_removed_activity(self, teams_members_removed: [TeamsChannelAccount], turn_context: TurnContext): + + async def on_teams_members_removed_activity( + self, teams_members_removed: [TeamsChannelAccount], turn_context: TurnContext + ): for member in teams_members_removed: - await turn_context.send_activity(MessageFactory.text(f"Say goodbye to your team member {member.id}")) + await turn_context.send_activity( + MessageFactory.text(f"Say goodbye to your team member {member.id}") + ) return - - - - - \ No newline at end of file diff --git a/libraries/botbuilder-core/tests/teams/conversation-update/config.py b/libraries/botbuilder-core/tests/teams/conversation-update/config.py index 762d93edf..6b5116fba 100644 --- a/libraries/botbuilder-core/tests/teams/conversation-update/config.py +++ b/libraries/botbuilder-core/tests/teams/conversation-update/config.py @@ -4,12 +4,10 @@ import os -""" Bot Configuration """ - class DefaultConfig: """ Bot Configuration """ PORT = 3978 - APP_ID = os.environ.get("MicrosoftAppId", "5396829c-e0a1-4698-9746-848ca0ba2892") - APP_PASSWORD = os.environ.get("MicrosoftAppPassword", "x@YOwxU3rqAPzc.nxdRx?Zc.Z96OiHt4") + APP_ID = os.environ.get("MicrosoftAppId", "") + APP_PASSWORD = os.environ.get("MicrosoftAppPassword", "") diff --git a/libraries/botbuilder-schema/botbuilder/schema/teams/__init__.py b/libraries/botbuilder-schema/botbuilder/schema/teams/__init__.py index 00a4c1f01..81944aed3 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/teams/__init__.py +++ b/libraries/botbuilder-schema/botbuilder/schema/teams/__init__.py @@ -6,10 +6,10 @@ from .teams_channel_account import TeamsChannelAccount __all__ = [ - "TeamInfo", - "ChannelInfo", - "TeamsChannelData", - "TeamsChannelData", - "TenantInfo", - "NotificationInfo" - ] \ No newline at end of file + "TeamInfo", + "ChannelInfo", + "TeamsChannelData", + "TeamsChannelData", + "TenantInfo", + "NotificationInfo", +] diff --git a/libraries/botbuilder-schema/botbuilder/schema/teams/channel_info.py b/libraries/botbuilder-schema/botbuilder/schema/teams/channel_info.py index 78751d609..ea8c7b99c 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/teams/channel_info.py +++ b/libraries/botbuilder-schema/botbuilder/schema/teams/channel_info.py @@ -6,23 +6,24 @@ # Changes may cause incorrect behavior and will be lost if the code is # regenerated. + class ChannelInfo: - def __init__(self, id = "", name = ""): + def __init__(self, id="", name=""): self._id = id self._name = name - + @property def id(self): return self._id - + @id.setter def id(self, id): self._id = id - - @property + + @property def name(self): return self._name @name.setter def name(self, name): - self._name = name \ No newline at end of file + self._name = name diff --git a/libraries/botbuilder-schema/botbuilder/schema/teams/notification_info.py b/libraries/botbuilder-schema/botbuilder/schema/teams/notification_info.py index 0a43d709a..f3624a75d 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/teams/notification_info.py +++ b/libraries/botbuilder-schema/botbuilder/schema/teams/notification_info.py @@ -6,14 +6,15 @@ # Changes may cause incorrect behavior and will be lost if the code is # regenerated. -class NotificationInfo(): + +class NotificationInfo: def __init__(self, alert: bool = False): self._alert = alert - + @property def alert(): return self._alert - + @alert.setter def alert(alert): - self._alert = alert \ No newline at end of file + self._alert = alert diff --git a/libraries/botbuilder-schema/botbuilder/schema/teams/team_info.py b/libraries/botbuilder-schema/botbuilder/schema/teams/team_info.py index c0765322b..9675e750a 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/teams/team_info.py +++ b/libraries/botbuilder-schema/botbuilder/schema/teams/team_info.py @@ -6,31 +6,31 @@ # Changes may cause incorrect behavior and will be lost if the code is # regenerated. + class TeamInfo: - def __init__(self, id = "", name = "", aadGroupId = ""): + def __init__(self, id="", name="", aadGroupId=""): self._id = id self._name = name self._aad_group_id = aadGroupId def get_id(self): return self._id - + def set_id(self, id): self._id = id - + def get_name(self): return self._name - + def set_name(self, name): self._name = name def get_aad_group_id(self): return self._aad_group_id - + def set_aad_group_id(self, aad_group_id): - self._aad_group_id= aad_group_id + self._aad_group_id = aad_group_id id = property(get_id, set_id) name = property(get_name, set_name) aad_group_id = property(get_aad_group_id, set_aad_group_id) - \ No newline at end of file diff --git a/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_account.py b/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_account.py index 6a999d9b8..7cdd35d69 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_account.py +++ b/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_account.py @@ -8,9 +8,22 @@ from botbuilder.schema import ChannelAccount + class TeamsChannelAccount(ChannelAccount): - def __init__(self, id = "", name = "", aad_object_id = "", role ="", given_name = "", surname = "", email = "", userPrincipalName = ""): - super().__init__(**{"id":id, "name":name, "aad_object_id": aad_object_id, "role":role}) + def __init__( + self, + id="", + name="", + aad_object_id="", + role="", + given_name="", + surname="", + email="", + userPrincipalName="", + ): + super().__init__( + **{"id": id, "name": name, "aad_object_id": aad_object_id, "role": role} + ) self._given_name = given_name self._surname = surname self._email = email @@ -18,37 +31,37 @@ def __init__(self, id = "", name = "", aad_object_id = "", role ="", given_name def get_id(self): return self._id - + def set_id(self, id): self._id = id def get_name(self): return self._name - + def set_name(self, name): self._name = name def get_given_name(self): return self._given_name - + def set_given_name(self, given_name): self._given_name = given_name def get_surname(self): return self._surname - + def set_surname(self, surname): self._surname = surname def get_email(self): return self._email - + def set_email(self, email): self._email = email - + def get_user_principal_name(self): return self._user_principal_name - + def set_user_principal_name(self, user_principal_name): self._user_principal_name = user_principal_name @@ -57,4 +70,4 @@ def set_user_principal_name(self, user_principal_name): given_name = property(get_given_name, set_given_name) surname = property(get_surname, set_surname) email = property(get_email, set_email) - user_principal_name = property(get_user_principal_name, set_user_principal_name) \ No newline at end of file + user_principal_name = property(get_user_principal_name, set_user_principal_name) diff --git a/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_data.py b/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_data.py index ad4dea143..c983b82a4 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_data.py +++ b/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_data.py @@ -6,49 +6,55 @@ # Changes may cause incorrect behavior and will be lost if the code is # regenerated. -from botbuilder.schema.teams import ChannelInfo, TeamInfo, NotificationInfo, TenantInfo +from botbuilder.schema.teams import ChannelInfo, TeamInfo, NotificationInfo, TenantInfo + class TeamsChannelData: - def __init__(self, - channel: ChannelInfo = None, - eventType = "", - team: TeamInfo = None, - notification: NotificationInfo = None, - tenant: TenantInfo = None): + def __init__( + self, + channel: ChannelInfo = None, + eventType="", + team: TeamInfo = None, + notification: NotificationInfo = None, + tenant: TenantInfo = None, + ): self._channel = ChannelInfo(**channel) if channel is not None else ChannelInfo() - self._event_type = eventType + self._event_type = eventType self._team = TeamInfo(**team) if team is not None else TeamInfo() - self._notification = NotificationInfo(**notification) if notification is not None else NotificationInfo() + self._notification = ( + NotificationInfo(**notification) + if notification is not None + else NotificationInfo() + ) self._tenant = TenantInfo(**tenant) if tenant is not None else TenantInfo() - - + def get_channel(self): return self._channel - + def set_channel(self, channel): self._channel = channel - + def get_event_type(self): return self._event_type - + def set_event_type(event_type): self._event_type = event_type - + def get_team(self): return self._team - + def set_team(self, team): self._team = team - + def get_notification(self): return self._notification - + def set_notification(self, notification): self._notification = notification - + def get_tenant(self): return self._tenant - + def set_tenant(self): return self._tenant @@ -56,4 +62,4 @@ def set_tenant(self): channel = property(get_channel, set_channel) team = property(get_team, set_team) notification = property(get_notification, set_notification) - tenant = property(get_tenant, set_tenant) \ No newline at end of file + tenant = property(get_tenant, set_tenant) diff --git a/libraries/botbuilder-schema/botbuilder/schema/teams/tenant_info.py b/libraries/botbuilder-schema/botbuilder/schema/teams/tenant_info.py index 95408d5cb..0e0c7ffaf 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/teams/tenant_info.py +++ b/libraries/botbuilder-schema/botbuilder/schema/teams/tenant_info.py @@ -6,14 +6,15 @@ # Changes may cause incorrect behavior and will be lost if the code is # regenerated. -class TenantInfo(): - def __init__(self, id = ""): + +class TenantInfo: + def __init__(self, id=""): self._id = id - + @property def id(): return self._id - + @id.setter def id(self, id): - self._id = id \ No newline at end of file + self._id = id From 2b3f2bf63ae3e0bd936331430511e5a9c4fe56c4 Mon Sep 17 00:00:00 2001 From: virtual-josh Date: Tue, 12 Nov 2019 15:42:30 -0800 Subject: [PATCH 4/7] updating classes to use standard attrs --- .../core/Teams/teams_activity_handler.py | 1 + .../botbuilder/schema/teams/channel_info.py | 23 ++------- .../schema/teams/notification_info.py | 10 +--- .../botbuilder/schema/teams/team_info.py | 28 ++-------- .../schema/teams/teams_channel_account.py | 51 ++----------------- 5 files changed, 13 insertions(+), 100 deletions(-) diff --git a/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py b/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py index 9aa6c998a..d06448995 100644 --- a/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py +++ b/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py @@ -64,6 +64,7 @@ async def on_conversation_update_activity(self, turn_context: TurnContext): turn_context, ) + print(turn_context.activity) if channel_data is not None: if channel_data.event_type == "channelCreated": return await self.on_teams_channel_created_activity( diff --git a/libraries/botbuilder-schema/botbuilder/schema/teams/channel_info.py b/libraries/botbuilder-schema/botbuilder/schema/teams/channel_info.py index ea8c7b99c..f5f10eda3 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/teams/channel_info.py +++ b/libraries/botbuilder-schema/botbuilder/schema/teams/channel_info.py @@ -7,23 +7,8 @@ # regenerated. -class ChannelInfo: +class ChannelInfo(object): def __init__(self, id="", name=""): - self._id = id - self._name = name - - @property - def id(self): - return self._id - - @id.setter - def id(self, id): - self._id = id - - @property - def name(self): - return self._name - - @name.setter - def name(self, name): - self._name = name + self.id = id + self.name = name + \ No newline at end of file diff --git a/libraries/botbuilder-schema/botbuilder/schema/teams/notification_info.py b/libraries/botbuilder-schema/botbuilder/schema/teams/notification_info.py index f3624a75d..dd55a69c7 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/teams/notification_info.py +++ b/libraries/botbuilder-schema/botbuilder/schema/teams/notification_info.py @@ -9,12 +9,4 @@ class NotificationInfo: def __init__(self, alert: bool = False): - self._alert = alert - - @property - def alert(): - return self._alert - - @alert.setter - def alert(alert): - self._alert = alert + self.alert = alert diff --git a/libraries/botbuilder-schema/botbuilder/schema/teams/team_info.py b/libraries/botbuilder-schema/botbuilder/schema/teams/team_info.py index 9675e750a..33b956995 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/teams/team_info.py +++ b/libraries/botbuilder-schema/botbuilder/schema/teams/team_info.py @@ -9,28 +9,6 @@ class TeamInfo: def __init__(self, id="", name="", aadGroupId=""): - self._id = id - self._name = name - self._aad_group_id = aadGroupId - - def get_id(self): - return self._id - - def set_id(self, id): - self._id = id - - def get_name(self): - return self._name - - def set_name(self, name): - self._name = name - - def get_aad_group_id(self): - return self._aad_group_id - - def set_aad_group_id(self, aad_group_id): - self._aad_group_id = aad_group_id - - id = property(get_id, set_id) - name = property(get_name, set_name) - aad_group_id = property(get_aad_group_id, set_aad_group_id) + self.id = id + self.name = name + self.aad_group_id = aadGroupId \ No newline at end of file diff --git a/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_account.py b/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_account.py index 7cdd35d69..4bcf350f8 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_account.py +++ b/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_account.py @@ -24,50 +24,7 @@ def __init__( super().__init__( **{"id": id, "name": name, "aad_object_id": aad_object_id, "role": role} ) - self._given_name = given_name - self._surname = surname - self._email = email - self._user_principal_name = userPrincipalName - - def get_id(self): - return self._id - - def set_id(self, id): - self._id = id - - def get_name(self): - return self._name - - def set_name(self, name): - self._name = name - - def get_given_name(self): - return self._given_name - - def set_given_name(self, given_name): - self._given_name = given_name - - def get_surname(self): - return self._surname - - def set_surname(self, surname): - self._surname = surname - - def get_email(self): - return self._email - - def set_email(self, email): - self._email = email - - def get_user_principal_name(self): - return self._user_principal_name - - def set_user_principal_name(self, user_principal_name): - self._user_principal_name = user_principal_name - - id = property(get_id, set_id) - name = property(get_name, set_name) - given_name = property(get_given_name, set_given_name) - surname = property(get_surname, set_surname) - email = property(get_email, set_email) - user_principal_name = property(get_user_principal_name, set_user_principal_name) + self.given_name = given_name + self.surname = surname + self.email = email + self.user_principal_name = userPrincipalName From a5c2ef7574b376e7b3d264f88e830cc9367d699e Mon Sep 17 00:00:00 2001 From: virtual-josh Date: Tue, 12 Nov 2019 17:11:34 -0800 Subject: [PATCH 5/7] cleaning up PR feedback --- .../core/Teams/teams_activity_handler.py | 9 ++--- .../schema/teams/teams_channel_account.py | 1 + .../schema/teams/teams_channel_data.py | 39 +------------------ .../botbuilder/schema/teams/tenant_info.py | 10 +---- 4 files changed, 8 insertions(+), 51 deletions(-) diff --git a/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py b/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py index d06448995..a253c20c5 100644 --- a/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py +++ b/libraries/botbuilder-core/botbuilder/core/Teams/teams_activity_handler.py @@ -39,7 +39,7 @@ async def on_turn(self, turn_context: TurnContext): async def on_invoke_activity(self, turn_context: TurnContext): try: if ( - turn_context.activity.name is None + not turn_context.activity.name and turn_context.activity.channel_id == Channels.Msteams ): return # await on_teams_card_action_invoke_activity(turn_context) @@ -52,20 +52,19 @@ 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 is not None: + 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 ) - if turn_context.activity.members_removed is not None: + if turn_context.activity.members_removed: return await self.on_teams_members_removed_dispatch_activity( turn_context.activity.members_removed, channel_data.team, turn_context, ) - print(turn_context.activity) - if channel_data is not None: + 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 diff --git a/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_account.py b/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_account.py index 4bcf350f8..a2354effd 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_account.py +++ b/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_account.py @@ -27,4 +27,5 @@ def __init__( self.given_name = given_name self.surname = surname self.email = email + # This isn't camel_cased because the JSON that makes this object isn't camel_case self.user_principal_name = userPrincipalName diff --git a/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_data.py b/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_data.py index c983b82a4..10a9a2649 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_data.py +++ b/libraries/botbuilder-schema/botbuilder/schema/teams/teams_channel_data.py @@ -19,6 +19,7 @@ def __init__( tenant: TenantInfo = None, ): self._channel = ChannelInfo(**channel) if channel is not None else ChannelInfo() + # This is not camel case because the JSON that makes this object isn't self._event_type = eventType self._team = TeamInfo(**team) if team is not None else TeamInfo() self._notification = ( @@ -26,40 +27,4 @@ def __init__( if notification is not None else NotificationInfo() ) - self._tenant = TenantInfo(**tenant) if tenant is not None else TenantInfo() - - def get_channel(self): - return self._channel - - def set_channel(self, channel): - self._channel = channel - - def get_event_type(self): - return self._event_type - - def set_event_type(event_type): - self._event_type = event_type - - def get_team(self): - return self._team - - def set_team(self, team): - self._team = team - - def get_notification(self): - return self._notification - - def set_notification(self, notification): - self._notification = notification - - def get_tenant(self): - return self._tenant - - def set_tenant(self): - return self._tenant - - event_type = property(get_event_type, set_event_type) - channel = property(get_channel, set_channel) - team = property(get_team, set_team) - notification = property(get_notification, set_notification) - tenant = property(get_tenant, set_tenant) + self._tenant = TenantInfo(**tenant) if tenant is not None else TenantInfo() \ No newline at end of file diff --git a/libraries/botbuilder-schema/botbuilder/schema/teams/tenant_info.py b/libraries/botbuilder-schema/botbuilder/schema/teams/tenant_info.py index 0e0c7ffaf..03a2ca65a 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/teams/tenant_info.py +++ b/libraries/botbuilder-schema/botbuilder/schema/teams/tenant_info.py @@ -9,12 +9,4 @@ class TenantInfo: def __init__(self, id=""): - self._id = id - - @property - def id(): - return self._id - - @id.setter - def id(self, id): - self._id = id + self._id = id \ No newline at end of file From e4d6fd1353fb3fdd88e1a785b61c2dc1062e93f2 Mon Sep 17 00:00:00 2001 From: virtual-josh Date: Wed, 13 Nov 2019 13:08:10 -0800 Subject: [PATCH 6/7] adding line --- .../botbuilder-schema/botbuilder/schema/teams/tenant_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/botbuilder-schema/botbuilder/schema/teams/tenant_info.py b/libraries/botbuilder-schema/botbuilder/schema/teams/tenant_info.py index 03a2ca65a..2b47e81a0 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/teams/tenant_info.py +++ b/libraries/botbuilder-schema/botbuilder/schema/teams/tenant_info.py @@ -9,4 +9,4 @@ class TenantInfo: def __init__(self, id=""): - self._id = id \ No newline at end of file + self._id = id From f8f3ea5b7ef9edd967053733746d181b59ad36c1 Mon Sep 17 00:00:00 2001 From: virtual-josh Date: Wed, 13 Nov 2019 13:10:42 -0800 Subject: [PATCH 7/7] adding another blank line --- .../botbuilder-schema/botbuilder/schema/teams/team_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/botbuilder-schema/botbuilder/schema/teams/team_info.py b/libraries/botbuilder-schema/botbuilder/schema/teams/team_info.py index 33b956995..316ae89c2 100644 --- a/libraries/botbuilder-schema/botbuilder/schema/teams/team_info.py +++ b/libraries/botbuilder-schema/botbuilder/schema/teams/team_info.py @@ -11,4 +11,4 @@ class TeamInfo: def __init__(self, id="", name="", aadGroupId=""): self.id = id self.name = name - self.aad_group_id = aadGroupId \ No newline at end of file + self.aad_group_id = aadGroupId