8000 Added 08.suggested-actions (#372) · sherlock666/botbuilder-python@bfe2669 · GitHub
[go: up one dir, main page]

Skip to content

Commit bfe2669

Browse files
tracyboehreraxelsrz
authored andcommitted
Added 08.suggested-actions (microsoft#372)
* Added 08.suggested-actions * Removed LUIS keys from settings. * Updated on_error messages, standardized app.py * Removed adapter_with_error_handler (migrated into app.py), corrected README.
1 parent 84b3a09 commit bfe2669

File tree

6 files changed

+223
-0
lines changed

6 files changed

+223
-0
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# suggested actions
2+
3+
Bot Framework v4 using adaptive cards bot sample
4+
5+
This bot has been created using [Bot Framework](https://dev.botframework.com), it shows how to use suggested actions. Suggested actions enable your bot to present buttons that the user can tap to provide input.
6+
7+
## Running the sample
8+
- Clone the repository
9+
```bash
10+
git clone https://github.com/Microsoft/botbuilder-python.git
11+
```
12+
- Bring up a terminal, navigate to `botbuilder-python\samples\08.suggested-actions` folder
13+
- In the terminal, type `pip install -r requirements.txt`
14+
- In the terminal, type `python app.py`
15+
16+
## Testing the bot using Bot Framework Emulator
17+
[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.
18+
19+
- Install the Bot Framework emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
20+
21+
### Connect to bot using Bot Framework Emulator
22+
- Launch Bot Framework Emulator
23+
- File -> Open Bot
24+
- Paste this URL in the emulator window - http://localhost:3978/api/messages
25+
26+
## Suggested actions
27+
28+
Suggested actions enable your bot to present buttons that the user can tap to provide input. Suggested actions appear close to the composer and enhance user experience.

samples/08.suggested-actions/app.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
4+
import asyncio
5+
import sys
6+
from datetime import datetime
7+
from types import MethodType
8+
9+
from flask import Flask, request, Response
10+
from botbuilder.core import BotFrameworkAdapterSettings, BotFrameworkAdapter, TurnContext
11+
from botbuilder.schema import Activity, ActivityTypes
12+
13+
from bots import SuggestActionsBot
14+
15+
# Create the loop and Flask app
16+
LOOP = asyncio.get_event_loop()
17+
APP = Flask(__name__, instance_relative_config=True)
18+
APP.config.from_object("config.DefaultConfig")
19+
20+
# Create adapter.
21+
# See https://aka.ms/about-bot-adapter to learn more about how bots work.
22+
SETTINGS = BotFrameworkAdapterSettings(APP.config["APP_ID"], APP.config["APP_PASSWORD"])
23+
ADAPTER = BotFrameworkAdapter(SETTINGS)
24+
25+
26+
# Catch-all for errors.
27+
async def on_error(self, context: TurnContext, error: Exception):
28+
# This check writes out errors to console log .vs. app insights.
29+
# NOTE: In production environment, you should consider logging this to Azure
30+
# application insights.
31+
print(f"\n [on_turn_error] unhandled error: {error}", file=sys.stderr)
32+
33+
# Send a message to the user
34+
await context.send_activity("The bot encountered an error or bug.")
35+
await context.send_activity("To continue to run this bot, please fix the bot source code.")
36+
# Send a trace activity if we're talking to the Bot Framework Emulator
37+
if context.activity.channel_id == 'emulator':
38+
# Create a trace activity that contains the error object
39+
trace_activity = Activity(
40+
label="TurnError",
41+
name="on_turn_error Trace",
42+
timestamp=datetime.utcnow(),
43+
type=ActivityTypes.trace,
44+
value=f"{error}",
45+
value_type="https://www.botframework.com/schemas/error"
46+
)
47+
# Send a trace activity, which will be displayed in Bot Framework Emulator
48+
await context.send_activity(trace_activity)
49+
50+
ADAPTER.on_turn_error = MethodType(on_error, ADAPTER)
51+
52+
# Create Bot
53+
BOT = SuggestActionsBot()
54+
55+
56+
# Listen for incoming requests on /api/messages.
57+
@APP.route("/api/messages", methods=["POST"])
58+
def messages():
59+
# Main bot message handler.
60+
if "application/json" < 28BE span class=pl-c1>in request.headers["Content-Type"]:
61+
body = request.json
62+
else:
63+
return Response(status=415)
64+
65+
activity = Activity().deserialize(body)
66+
auth_header = (
67+
F438 request.headers["Authorization"] if "Authorization" in request.headers else ""
68+
)
69+
70+
try:
71+
task = LOOP.create_task(
72+
ADAPTER.process_activity(activity, auth_header, BOT.on_turn)
73+
)
74+
LOOP.run_until_complete(task)
75+
return Response(status=201)
76+
except Exception as exception:
77+
raise exception
78+
79+
80+
if __name__ == "__main__":
81+
try:
82+
APP.run(debug=False, port=APP.config["PORT"]) # nosec debug
83+
except Exception as exception:
84+
raise exception
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
4+
from .suggested_actions_bot import SuggestActionsBot
5+
6+
__all__ = ["SuggestActionsBot"]
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
4+
from botbuilder.core import ActivityHandler, MessageFactory, TurnContext
5+
from botbuilder.schema import ChannelAccount, CardAction, ActionTypes, SuggestedActions
6+
7+
"""
8+
This bot will respond to the user's input with suggested actions.
9+
Suggested actions enable your bot to present buttons that the user
10+
can tap to provide input.
11+
"""
12+
13+
14+
class SuggestActionsBot(ActivityHandler):
15+
async def on_members_added_activity(self, members_added: [ChannelAccount], turn_context: TurnContext):
16+
"""
17+
Send a welcome message to the user and tell them what actions they may perform to use this bot
18+
"""
19+
20+
return await self._send_welcome_message(turn_context)
21+
22+
async def on_message_activity(self, turn_context: TurnContext):
23+
"""
24+
Respond to the users choice and display the suggested actions again.
25+
"""
26+
27+
text = turn_context.activity.text.lower()
28+
response_text = self._process_input(text)
29+
30+
await turn_context.send_activity(MessageFactory.text(response_text))
31+
32+
return await self._send_suggested_actions(turn_context)
33+
34+
async def _send_welcome_message(self, turn_context: TurnContext):
35+
for member in turn_context.activity.members_added:
36+
if member.id != turn_context.activity.recipient.id:
37+
await turn_context.send_activity(MessageFactory.text(
38+
f"Welcome to SuggestedActionsBot {member.name}. This bot will introduce you to suggestedActions. "
39+
f"Please answer the question: "
40+
))
41+
42+
await self._send_suggested_actions(turn_context)
43+
44+
def _process_input(self, text: str):
45+
color_text = "is the best color, I agree."
46+
47+
if text == "red":
48+
return f"Red {color_text}"
49+
50+
if text == "yellow":
51+
return f"Yellow {color_text}"
52+
53+
if text == "blue":
54+
return f"Blue {color_text}"
55+
56+
return "Please select a color from the suggested action choices"
57+
58+
async def _send_suggested_actions(self, turn_context: TurnContext):
59+
"""
60+
Creates and sends an activity with suggested actions to the user. When the user
61+
clicks one of the buttons the text value from the "CardAction" will be displayed
62+
in the channel just as if the user entered the text. There are multiple
63+
"ActionTypes" that may be used for different situations.
64+
"""
65+
66+
reply = MessageFactory.text("What is your favorite color?")
67+
68+
reply.suggested_actions = SuggestedActions(
69+
actions=[
70+
CardAction(
71+
title="Red",
72+
type=ActionTypes.im_back,
73+
value="Read"
74+
),
75+
CardAction(
76+
title="Yellow",
77+
type=ActionTypes.im_back,
78+
value="Yellow"
79+
),
80+
CardAction(
81+
title="Blue",
82+
type=ActionTypes.im_back,
83+
value="Blue"
84+
)
85+
]
86+
)
87+
88+
return await turn_context.send_activity(reply)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) Microsoft Corporation. All rights reserved.
3+
# Licensed under the MIT License.
4+
5+
import os
6+
7+
""" Bot Configuration """
8+
9+
10+
class DefaultConfig:
11+
""" Bot Configuration """
12+
13+
PORT = 3978
14+
APP_ID = os.environ.get("MicrosoftAppId", "")
15+
APP_PASSWORD = os.environ.get("MicrosoftAppPassword", "")
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
botbuilder-core>=4.4.0b1
2+
flask>=1.0.3

0 commit comments

Comments
 (0)
0