Skip to content

Merging Teams in so far #454

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 98 commits into from
Nov 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
1890b76
initial commit for Teams work
Virtual-Josh Nov 1, 2019
dfe267d
initial commit for Teams
Virtual-Josh Nov 1, 2019
1b60528
Merge pull request #410 from microsoft/josh/activityHandler
Virtual-Josh Nov 1, 2019
140372d
adding teams activity handler, team info, and teams channel account c…
Virtual-Josh Nov 5, 2019
21876ca
adding conversation update scenario
Virtual-Josh Nov 7, 2019
96f262d
fixing linting issues
Virtual-Josh Nov 11, 2019
2b3f2bf
updating classes to use standard attrs
Virtual-Josh Nov 12, 2019
a5c2ef7
cleaning up PR feedback
Virtual-Josh Nov 13, 2019
e4d6fd1
adding line
Virtual-Josh Nov 13, 2019
f8f3ea5
adding another blank line
Virtual-Josh Nov 13, 2019
a590910
Merge pull request #431 from microsoft/josh/ActivityHandler
Virtual-Josh Nov 13, 2019
2e4d8c9
adding mentions bot and fixing bug for resource response IDs
Virtual-Josh Nov 19, 2019
ebbb4f7
Threading helper workaround
axelsrz Nov 20, 2019
48c71ff
Corrected case of "teams" folder name in core. Corrected __init__.py…
Nov 20, 2019
97f543a
Merge pull request #444 from microsoft/trboehre/lib-fixes
tracyboehrer Nov 20, 2019
2e82d95
adding mention bot
Virtual-Josh Nov 18, 2019
388ac11
resolving merge conflict
Virtual-Josh Nov 20, 2019
5090f95
adding mention bot
Virtual-Josh Nov 20, 2019
9c027af
updating linting
Virtual-Josh Nov 20, 2019
46e8b25
adding mention bot
Virtual-Josh Nov 18, 2019
40b32ab
resolving merge conflict
Virtual-Josh Nov 20, 2019
a4f8688
adding mention bot
Virtual-Josh Nov 20, 2019
1daeb43
updating linting
Virtual-Josh Nov 20, 2019
8c38c37
Merge branch 'josh/mentions' of https://github.com/microsoft/botbuild…
Virtual-Josh Nov 20, 2019
b5e355a
adding activity update and delete
Virtual-Josh Nov 20, 2019
b84ac37
adding list for activities
Virtual-Josh Nov 20, 2019
abb8894
cleaning up config
Virtual-Josh Nov 20, 2019
7114798
Added 43.complex-dialog
Oct 31, 2019
2b2d747
Pinned dependencies in all libraries
Nov 1, 2019
177b5a3
Pinned dependencies in libraries (missed some setup.py)
Nov 1, 2019
f2958da
Added 47.inspection (#381)
tracyboehrer Nov 5, 2019
fa3831f
ChoiceFactory.for_channel was erroneously returning a List instead of…
tracyboehrer Nov 5, 2019
5f0bf23
Refactored to unbound on_error methods when accessing outer app.py va…
tracyboehrer Nov 5, 2019
6cc29c7
Added 16.proactive-messages (#413)
tracyboehrer Nov 5, 2019
9abc76d
Added 19.custom-dialogs (#411)
tracyboehrer Nov 5, 2019
f74138a
modify echo to work out of the box w/ ARM template
stevengum Nov 4, 2019
cffd9cb
Fix ChoicePrompt ListStyle.none when set via PromptOptions (#373)
mdrichardson Nov 5, 2019
7ea7439
Added 18.bot-authentication (#419)
tracyboehrer Nov 5, 2019
4210be8
Added 23.facebook-events sample
Nov 11, 2019
6b065e1
23.facebook-events: on_error is now an unbound function
Nov 11, 2019
196de7c
Added 17.multilingual-bot
Nov 8, 2019
685b33e
17.multilingual-bot suggested corrections
Nov 11, 2019
f3a48e1
Partial 15.handling-attachments
Nov 7, 2019
393bcb9
Removing unnecesary encoding
axelsrz Nov 7, 2019
09a9422
Added 15.handling-attachments
Nov 8, 2019
2d340ed
15.handling-attachments suggested corrections
Nov 11, 2019
b1d97a6
pylint and black, suggested corrections.
Nov 12, 2019
11d244a
pylint and black changes. No logic changes. (#427)
tracyboehrer Nov 12, 2019
ef5ec6f
Fixes #425: Using incorrect BotState (#426)
tracyboehrer Nov 12, 2019
d303cda
Added send_activities and updated the logic
axelsrz Nov 14, 2019
0256c1f
pylint: Added send_activities and updated the logic
axelsrz Nov 14, 2019
92a9170
pylint: Added send_activities and updated the logic
axelsrz Nov 14, 2019
2f1f4ea
black formatter: Added send_activities and updated the logic
axelsrz Nov 14, 2019
f34d85a
Added 11.qnamaker (#429)
tracyboehrer Nov 14, 2019
7809974
Added 40.timex resolution (#430)
tracyboehrer Nov 14, 2019
52eee33
Added 42.scaleout (#435)
tracyboehrer Nov 14, 2019
7c939a2
Pinned pytest version (#438)
axelsrz Nov 15, 2019
f7424fd
updating linting
Virtual-Josh Nov 20, 2019
86ff943
fixing linting
Virtual-Josh Nov 20, 2019
94865bd
initial commit for Teams
Virtual-Josh Nov 1, 2019
3a5245f
initial commit for Teams work
Virtual-Josh Nov 1, 2019
a852776
adding teams activity handler, team info, and teams channel account c…
Virtual-Josh Nov 5, 2019
ad2b0ca
adding conversation update scenario
Virtual-Josh Nov 7, 2019
e15d868
fixing linting issues
Virtual-Josh Nov 11, 2019
623ac7a
updating classes to use standard attrs
Virtual-Josh Nov 12, 2019
503f5bb
cleaning up PR feedback
Virtual-Josh Nov 13, 2019
3616fd2
adding line
Virtual-Josh Nov 13, 2019
2f11383
adding another blank line
Virtual-Josh Nov 13, 2019
6352cb5
Corrected case of "teams" folder name in core. Corrected __init__.py…
Nov 20, 2019
0a80d56
removing extension file
Virtual-Josh Nov 21, 2019
5f9f1b3
Merge branch 'Teams' into josh/mentions
tracyboehrer Nov 21, 2019
0b15c44
Merge pull request #441 from microsoft/josh/mentions
tracyboehrer Nov 21, 2019
afd131c
Merge pull request #445 from microsoft/josh/activityUpdate
tracyboehrer Nov 21, 2019
3c1ef1f
Merge branch 'Teams' into josh/reactions
tracyboehrer Nov 21, 2019
9d5e95e
Merge pull request #442 from microsoft/josh/reactions
tracyboehrer Nov 21, 2019
0e9d642
resovling conflict
Virtual-Josh Nov 21, 2019
62d0739
more merge conflict resolution
Virtual-Josh Nov 21, 2019
55eae2c
fixing linting
Virtual-Josh Nov 20, 2019
23d260a
fixing conflicts
Virtual-Josh Nov 21, 2019
774ef48
adding updated teams activity handler
Virtual-Josh Nov 26, 2019
8406606
updating None check
Virtual-Josh Nov 26, 2019
877ac82
Merge pull request #448 from microsoft/josh/teamsActivitiyHandler
tracyboehrer Nov 26, 2019
9f109c2
updating activity handler and fixing spacing issue
Virtual-Josh Nov 26, 2019
c156c96
updating activity handler and tests
Virtual-Josh Nov 26, 2019
26be1f1
updating teams activity handler
Virtual-Josh Nov 26, 2019
5342892
removing constant
Virtual-Josh Nov 26, 2019
a0ccb8c
Merge pull request #452 from microsoft/josh/teamsActivitiyHandler
tracyboehrer Nov 26, 2019
22da668
resolving merge conflict
Virtual-Josh Nov 26, 2019
865a7fd
Merge remote-tracking branch 'origin' into Teams
Virtual-Josh Nov 26, 2019
91029c2
adding tests and removing constant
Virtual-Josh Nov 26, 2019
c0e0ede
Merge remote-tracking branch 'origin' into Teams
Virtual-Josh Nov 26, 2019
c83d60e
moving scenarios to root
Virtual-Josh Nov 26, 2019
98cea4f
updating attr check, using .seralize(), removing return
Virtual-Josh Nov 26, 2019
e296e02
rerunnign black
Virtual-Josh Nov 26, 2019
887cf66
updating names
Virtual-Josh Nov 26, 2019
ed9ddd6
updating loop to downcast
Virtual-Josh Nov 26, 2019
7ad027e
member not memeber
Virtual-Josh Nov 26, 2019
f5b1912
adding s
Virtual-Josh Nov 26, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
ConversationAccount,
ConversationParameters,
ConversationReference,
ResourceResponse,
TokenResponse,
ResourceResponse,
)
from botframework.connector import Channels, EmulatorApiClient
from botframework.connector.aio import ConnectorClient
Expand Down
10 changes: 10 additions & 0 deletions libraries/botbuilder-core/botbuilder/core/teams/__init__.py
Original file line number Diff line number Diff line change
@@ -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"]

Large diffs are not rendered by default.

100 changes: 100 additions & 0 deletions libraries/botbuilder-core/tests/teams/test_teams_activity_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
from typing import List

import aiounittest
from botbuilder.core import BotAdapter, TurnContext
from botbuilder.core.teams import TeamsActivityHandler
from botbuilder.schema import (
Activity,
ActivityTypes,
ChannelAccount,
ConversationReference,
MessageReaction,
ResourceResponse,
)


class TestingTeamsActivityHandler(TeamsActivityHandler):
def __init__(self):
self.record: List[str] = []

async def on_message_activity(self, turn_context: TurnContext):
self.record.append("on_message_activity")
return await super().on_message_activity(turn_context)

async def on_members_added_activity(
self, members_added: ChannelAccount, turn_context: TurnContext
):
self.record.append("on_members_added_activity")
return await super().on_members_added_activity(members_added, turn_context)

async def on_members_removed_activity(
self, members_removed: ChannelAccount, turn_context: TurnContext
):
self.record.append("on_members_removed_activity")
return await super().on_members_removed_activity(members_removed, turn_context)

async def on_message_reaction_activity(self, turn_context: TurnContext):
self.record.append("on_message_reaction_activity")
return await super().on_message_reaction_activity(turn_context)

async def on_reactions_added(
self, message_reactions: List[MessageReaction], turn_context: TurnContext
):
self.record.append("on_reactions_added")
return await super().on_reactions_added(message_reactions, turn_context)

async def on_reactions_removed(
self, message_reactions: List[MessageReaction], turn_context: TurnContext
):
self.record.append("on_reactions_removed")
return await super().on_reactions_removed(message_reactions, turn_context)

async def on_token_response_event(self, turn_context: TurnContext):
self.record.append("on_token_response_event")
return await super().on_token_response_event(turn_context)

async def on_event(self, turn_context: TurnContext):
self.record.append("on_event")
return await super().on_event(turn_context)

async def on_unrecognized_activity_type(self, turn_context: TurnContext):
self.record.append("on_unrecognized_activity_type")
return await super().on_unrecognized_activity_type(turn_context)


class NotImplementedAdapter(BotAdapter):
async def delete_activity(
self, context: TurnContext, reference: ConversationReference
):
raise NotImplementedError()

async def send_activities(
self, context: TurnContext, activities: List[Activity]
) -> List[ResourceResponse]:
raise NotImplementedError()

async def update_activity(self, context: TurnContext, activity: Activity):
raise NotImplementedError()


class TestTeamsActivityHandler(aiounittest.AsyncTestCase):
async def test_message_reaction(self):
# Note the code supports multiple adds and removes in the same activity though
# a channel may decide to send separate activities for each. For example, Teams
# sends separate activities each with a single add and a single remove.

# Arrange
activity = Activity(
type=ActivityTypes.message_reaction,
reactions_added=[MessageReaction(type="sad")],
)
turn_context = TurnContext(NotImplementedAdapter(), activity)

# Act
bot = TestingTeamsActivityHandler()
await bot.on_turn(turn_context)

# Assert
assert len(bot.record) == 2
assert bot.record[0] == "on_message_reaction_activity"
assert bot.record[1] == "on_reactions_added"
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class ActivityTypes(str, Enum):
end_of_conversation = "endOfConversation"
event = "event"
invoke = "invoke"
invoke_response = "invokeResponse"
delete_user_data = "deleteUserData"
message_update = "messageUpdate"
message_delete = "messageDelete"
Expand Down
15 changes: 15 additions & 0 deletions libraries/botbuilder-schema/botbuilder/schema/teams/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from .team_info import TeamInfo
from .notification_info import NotificationInfo
from .tenant_info import TenantInfo
from .channel_info import ChannelInfo
from .teams_channel_data import TeamsChannelData
from .teams_channel_account import TeamsChannelAccount

__all__ = [
"TeamInfo",
"ChannelInfo",
"TeamsChannelData",
"TeamsChannelAccount",
"TenantInfo",
"NotificationInfo",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# 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 ChannelInfo(object):
def __init__(self, id="", name=""):
self.id = id
self.name = name
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# 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 NotificationInfo:
def __init__(self, alert: bool = False):
self.alert = alert
14 changes: 14 additions & 0 deletions libraries/botbuilder-schema/botbuilder/schema/teams/team_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# 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="", name="", aadGroupId=""):
self.id = id
self.name = name
self.aad_group_id = aadGroupId
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# 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(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}
)
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# 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.teams import ChannelInfo, TeamInfo, NotificationInfo, TenantInfo


class TeamsChannelData:
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()
# 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 = (
NotificationInfo(**notification)
if notification is not None
else NotificationInfo()
)
self.tenant = TenantInfo(**tenant) if tenant is not None else TenantInfo()
12 changes: 12 additions & 0 deletions libraries/botbuilder-schema/botbuilder/schema/teams/tenant_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# 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 TenantInfo:
def __init__(self, id=""):
self._id = id
30 changes: 30 additions & 0 deletions scenarios/activity-update-and-delete/README.md
Original file line number Diff line number Diff line change
@@ -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)
92 changes: 92 additions & 0 deletions scenarios/activity-update-and-delete/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# 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 ActivitiyUpdateAndDeleteBot

# 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( # 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.
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)
ACTIVITY_IDS = []
# Create the Bot
BOT = ActivitiyUpdateAndDeleteBot(ACTIVITY_IDS)

# 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
6 changes: 6 additions & 0 deletions scenarios/activity-update-and-delete/bots/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from .activity_update_and_delete_bot import ActivitiyUpdateAndDeleteBot

__all__ = ["ActivitiyUpdateAndDeleteBot"]
Loading