8000 Added 03.welcome-user sample (#365) · rusty0209/botbuilder-python@ef3ef4b · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit ef3ef4b

Browse files
tracyboehreraxelsrz
authored andcommitted
Added 03.welcome-user sample (microsoft#365)
* Added 03.welcome-user sample * Removed LUIS keys from settings. * Updated on_error messages, standardized app.py * Corrected README
1 parent bfe2669 commit ef3ef4b

File tree

8 files changed

+298
-0
lines changed

8 files changed

+298
-0
lines changed

samples/03.welcome-user/README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# welcome users
2+
3+
4+
Bot Framework v4 welcome users bot sample
5+
6+
This bot has been created using [Bot Framework](https://dev.botframework.com), is shows how to welcome users when they join the conversation.
7+
8+
## Running the sample
9+
- Clone the repository
10+
```bash
11+
git clone https://github.com/Microsoft/botbuilder-python.git
12+
```
13+
- Activate your desired virtual environment
14+
- Bring up a terminal, navigate to `botbuilder-python\samples\03.welcome-user` folder
15+
- In the terminal, type `pip install -r requirements.txt`
16+
- In the terminal, type `python app.py`
17+
18+
## Testing the bot using Bot Framework Emulator
19+
[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.
20+
21+
- Install the Bot Framework emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases)
22+
23+
### Connect to bot using Bot Framework Emulator
24+
- Launch Bot Framework Emulator
25+
- Paste this URL in the emulator window - http://localhost:3978/api/messages
26+
27+
28+
## Welcoming Users
29+
30+
The primary goal when creating any bot is to engag 8000 e your user in a meaningful conversation. One of the best ways to achieve this goal is to ensure that from the moment a user first connects, they understand your bot’s main purpose and capabilities, the reason your bot was created. See [Send welcome message to users](https://aka.ms/botframework-welcome-instructions) for additional information on how a bot can welcome users to a conversation.
31+
32+
## Further reading
33+
34+
- [Bot Framework Documentation](https://docs.botframework.com)
35+
- [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0)
36+
- [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?view=azure-bot-service-4.0)

samples/03.welcome-user/app.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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 (
11+
BotFrameworkAdapter,
12+
BotFrameworkAdapterSettings,
13+
MemoryStorage,
14+
TurnContext,
15+
UserState,
16+
)
17+
from botbuilder.schema import Activity, ActivityTypes
18+
19+
from bots import WelcomeUserBot
20+
21+
# Create the loop and Flask app
22+
LOOP = asyncio.get_event_loop()
23+
APP = Flask(__name__, instance_relative_config=True)
24+
APP.config.from_object("config.DefaultConfig")
25+
26+
# Create adapter.
27+
# See https://aka.ms/about-bot-adapter to learn more about how bots work.
28+
SETTINGS = BotFrameworkAdapterSettings(APP.config["APP_ID"], APP.config["APP_PASSWORD"])
29+
ADAPTER = BotFrameworkAdapter(SETTINGS)
30+
31+
32+
# Catch-all for errors.
33+
async def on_error(self, context: TurnContext, error: Exception):
34+
# This check writes out errors to console log .vs. app insights.
35+
# NOTE: In production environment, you should consider logging this to Azure
36+
# application insights.
37+
print(f"\n [on_turn_error] unhandled error: {error}", file=sys.stderr)
38+
39+
# Send a message to the user
40+
await context.send_activity("The bot encountered an error or bug.")
41+
await context.send_activity("To continue to run this bot, please fix the bot source code.")
42+
# Send a trace activity if we're talking to the Bot Framework Emulator
43+
if context.activity.channel_id == 'emulator':
44+
# Create a trace activity that contains the error object
45+
trace_activity = Activity(
46+
label="TurnError",
47+
name="on_turn_error Trace",
48+
timestamp=datetime.utcnow(),
49+
type=ActivityTypes.trace,
50+
value=f"{error}",
51+
value_type="https://www.botframework.com/schemas/error"
52+
)
53+
# Send a trace activity, which will be displayed in Bot Framework Emulator
54+
await context.send_activity(trace_activity)
55+
56+
ADAPTER.on_turn_error = MethodType(on_error, ADAPTER)
57+
58+
# Create MemoryStorage, UserState
59+
MEMORY = MemoryStorage()
60+
USER_STATE = UserState(MEMORY)
61+
62+
# Create the Bot
63+
BOT = WelcomeUserBot(USER_STATE)
64+
65+
# Listen for incoming requests on /api/messages.
66+
@APP.route("/api/messages", methods=["POST"])
67+
def messages():
68+
# Main bot message handler.
69+
if "application/json" in request.headers["Content-Type"]:
70+
body = request.json
71+
else:
72+
return Response(status=415)
73+
74+
activity = Activity().deserialize(body)
75+
auth_header = (
76+
request.headers["Authorization"] if "Authorization" in request.headers else ""
77+
)
78+
79+
try:
80+
task = LOOP.create_task(
81+
ADAPTER.process_activity(activity, auth_header, BOT.on_turn)
82+
)
83+
LOOP.run_until_complete(task)
84+
return Response(status=201)
85+
except Exception as exception:
86+
raise exception
87+
88+
89+
if __name__ == "__main__":
90+
try:
91+
APP.run(debug=False, port=APP.config["PORT"]) # nosec debug
92+
except Exception as exception:
93+
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 .welcome_user_bot import WelcomeUserBot
5+
6+
__all__ = ["WelcomeUserBot"]
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
4+
from botbuilder.core import ActivityHandler, TurnContext, UserState, CardFactory, MessageFactory
5+
from botbuilder.schema import ChannelAccount, HeroCard, CardImage, CardAction, ActionTypes
6+
7+
from data_models import WelcomeUserState
8+
9+
10+
class WelcomeUserBot(ActivityHandler):
11+
def __init__(self, user_state: UserState):
12+
if user_state is None:
13+
raise TypeError(
14+
"[WelcomeUserBot]: Missing parameter. user_state is required but None was given"
15+
)
16+
17+
self.user_state = user_state
18+
19+
self.user_state_accessor = self.user_state.create_property("WelcomeUserState")
20+
21+
self.WELCOME_MESSAGE = """This is a simple Welcome Bot sample. This bot will introduce you
22+
to welcoming and greeting users. You can say 'intro' to see the
23+
introduction card. If you are running this bot in the Bot Framework
24+
Emulator, press the 'Restart Conversation' button to simulate user joining
25+
a bot or a channel"""
26+
27+
async def on_turn(self, turn_context: TurnContext):
28+
await super().on_turn(turn_context)
29+
30+
# save changes to WelcomeUserState after each turn
31+
await self.user_state.save_changes(turn_context)
32+
33+
"""
34+
Greet when users are added to the conversation.
35+
Note that all channels do not send the conversation update activity.
36+
If you find that this bot works in the emulator, but does not in
37+
another channel the reason is most likely that the channel does not
38+
send this activity.
39+
"""
40+
41+
async def on_members_added_activity(
42+
self, members_added: [ChannelAccount], turn_context: TurnContext
43+
):
44+
for member in members_added:
45+
if member.id != turn_context.activity.recipient.id:
46+
await turn_context.send_activity(
47+
f"Hi there { member.name }. " + self.WELCOME_MESSAGE
48+
)
49+
50+
await turn_context.send_activity("""You are seeing this message because the bot received at least one
51+
'ConversationUpdate' event, indicating you (and possibly others)
52+
joined the conversation. If you are using the emulator, pressing
53+
the 'Start Over' button to trigger this event again. The specifics
54+
of the 'ConversationUpdate' event depends on the channel. You can
55+
read more information at: https://aka.ms/about-botframework-welcome-user"""
56+
)
57+
58+
await turn_context.send_activity("""It is a good pattern to use this event to send general greeting
59+
to user, explaining what your bot can do. In this example, the bot
60+
handles 'hello', 'hi', 'help' and 'intro'. Try it now, type 'hi'"""
61+
)
62+
63+
"""
64+
Respond to messages sent from the user.
65+
"""
66+
67+
async def on_message_activity(self, turn_context: TurnContext):
68+
# Get the state properties from the turn context.
69+
welcome_user_state = await self.user_state_accessor.get(turn_context, WelcomeUserState)
70+
71+
if not welcome_user_state.did_welcome_user:
72+
welcome_user_state.did_welcome_user = True
73+
74+
await turn_context.send_activity(
75+
"You are seeing this message because this was your first message ever to this bot."
76+
)
77+
78+
name = turn_context.activity.from_property.name
79+
await turn_context.send_activity(
80+
f"It is a good practice to welcome the user and provide personal greeting. For exampl 1241 e: Welcome { name }"
81+
)
82+
83+
else:
84+
# This example hardcodes specific utterances. You should use LUIS or QnA for more advance language
85+
# understanding.
86+
text = turn_context.activity.text.lower()
87+
if text in ("hello", "hi"):
88+
await turn_context.send_activity(
89+
f"You said { text }"
90+
)
91+
elif text in ("intro", "help"):
92+
await self.__send_intro_card(turn_context)
93+
else:
94+
await turn_context.send_activity(self.WELCOME_MESSAGE)
95+
96+
async def __send_intro_card(self, turn_context: TurnContext):
97+
card = HeroCard(
98+
title="Welcome to Bot Framework!",
99+
text="Welcome to Welcome Users bot sample! This Introduction card "
100+
"is a great way to introduce your Bot to the user and suggest "
101+
"some things to get them started. We use this opportunity to "
102+
"recommend a few next steps for learning more creating and deploying bots.",
103+
images=[
104+
CardImage(
105+
url="https://aka.ms/bf-welcome-card-image"
106+
)
107+
],
108+
buttons=[
109+
CardAction(
110+
type=ActionTypes.open_url,
111+
title="Get an overview",
112+
text="Get an overview",
113+
display_text="Get an overview",
114+
value="https://docs.microsoft.com/en-us/azure/bot-service/?view=azure-bot-service-4.0"
115+
),
116+
CardAction(
117+
type=ActionTypes.open_url,
118+
title="Ask a question",
119+
text="Ask a question",
120+
display_text="Ask a question",
121+
value="https://stackoverflow.com/questions/tagged/botframework"
122+
),
123+
CardAction(
124+
type=ActionTypes.open_url,
125+
title="Learn how to deploy",
126+
text="Learn how to deploy",
127+
display_text="Learn how to deploy",
128+
value="https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-howto-deploy-azure?view=azure-bot-service-4.0"
129+
)
130+
]
131+
)
132+
133+
return await turn_context.send_activity(MessageFactory.attachment(CardFactory.hero_card(card)))

samples/03.welcome-user/config.py

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: 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 .welcome_user_state import WelcomeUserState
5+
6+
__all__ = ["WelcomeUserState"]
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
4+
5+
class WelcomeUserState:
6+
def __init__(self, did_welcome: bool = False):
7+
self.did_welcome_user = did_welcome
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