-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlambda_function.py
More file actions
316 lines (271 loc) · 12.3 KB
/
Copy pathlambda_function.py
File metadata and controls
316 lines (271 loc) · 12.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
"""Functions to build out Alexa Intelligent Messaging Skill."""
import boto3
import datetime
def lambda_handler(event, context):
"""Parse out event type and the object, aka context."""
if (event["session"]["application"]["applicationId"] !=
"amzn1.ask.skill.ff117040-72fc-409a-a82f-cdba631d7f2d"): # pragma: no cover
raise ValueError("Invalid Application ID")
if event["session"]["new"]:
on_session_started({"requestId": event["request"]["requestId"]},
event["session"])
try:
if event["request"]["type"] == "LaunchRequest":
return on_launch(event["request"], event["session"])
elif event["request"]["type"] == "IntentRequest":
return on_intent(event["request"], event["session"])
elif event["request"]["type"] == "SessionEndedRequest":
return on_session_ended(event["request"], event["session"])
except:
return unsure_response(event["request"]["intent"], event["session"])
def on_session_started(session_started_request, session):
"""Handle any initiation on new session."""
print("Starting new session.")
def on_launch(launch_request, session):
"""Handle the launch request function and the session object."""
return get_welcome_response()
def on_intent(intent_request, session):
"""Conditional logic of series of Alexa skill intents."""
intent = intent_request["intent"]
intent_name = intent_request["intent"]["name"]
if intent_name == "EstablishRecipient":
return get_recipient(intent, session)
elif intent_name == "ReceiveMessage":
return receive_message(intent, session)
elif intent_name == "VerifyMessage":
return verification_of_message(intent, session)
elif intent_name == "DeleteMessage":
return delete_message(intent, session)
elif intent_name == "AMAZON.HelpIntent":
return get_help_response()
elif intent_name == "AMAZON.CancelIntent" or intent_name == "AMAZON.StopIntent":
return on_session_ended()
elif intent_name == "AMAZON.YesIntent":
return handle_verification(intent, session)
elif intent_name == "AMAZON.NoIntent":
return handle_nointent(intent, session)
elif intent_name == "ReplayMessage":
return replay_message(intent, session)
else:
raise ValueError("Invalid intent") # pragma: no cover
def handle_nointent(intent, session):
"""Handle reprompts if not repeated exactly."""
if "message_body" in session["attributes"]:
return re_prompt_message(intent, session)
else:
return re_prompt_name(intent, session)
def re_prompt_message(intent, session):
"""Reprompt for message when not repeated to user exactly."""
session["attributes"]["message_body"] = ""
session_attributes = session["attributes"]
reprompt_text = ""
card_title = "AIM"
should_end_session = False
speech_output = "OK, what is the message?"
return build_response(session_attributes, build_speechlet_response(
card_title, speech_output, reprompt_text, should_end_session))
def re_prompt_name(intent, session):
"""Reprompt for name if not repeated to user exactly."""
session_attributes = {}
reprompt_text = ""
card_title = "AIM"
should_end_session = False
speech_output = "OK, who am I sending the message to?"
return build_response(session_attributes, build_speechlet_response(
card_title, speech_output, reprompt_text, should_end_session))
def handle_verification(intent, session):
"""Handle verification of name or user when not repeated exactly."""
if "message_body" in session["attributes"]:
return save_msg_to_db(session)
else:
return what_is_your_message(intent, session)
def what_is_your_message(intent, session):
"""Repeat function the message that was saved to the database."""
receiver_name = session["attributes"]["receiver_name"]
session_attributes = {"receiver_name": receiver_name}
card_title = "what is your message"
speech_output = "OK, what is your message to {}?".format(receiver_name)
reprompt_text = ""
should_end_session = False
return build_response(session_attributes, build_speechlet_response(
card_title, speech_output, reprompt_text, should_end_session))
def get_recipient(intent, session):
"""Repeat function the message that was saved to the database."""
receiver_name = intent["slots"]["ForName"]["value"]
session_attributes = {"receiver_name": receiver_name}
card_title = "AIM"
speech_output = "OK, send a message to {}, right?".format(receiver_name)
reprompt_text = ""
should_end_session = False
return build_response(session_attributes, build_speechlet_response(
card_title, speech_output, reprompt_text, should_end_session))
def verification_of_message(intent, session):
"""Verify that message is properly formatted."""
message_body = intent["slots"]["Message"]["value"]
session["attributes"]["message_body"] = message_body
card_title = "AIM"
speech_output = "OK. Your message to {} is, {}, right?".format(session["attributes"]["receiver_name"], message_body)
reprompt_text = ""
should_end_session = False
return build_response(session["attributes"], build_speechlet_response(
card_title, speech_output, reprompt_text, should_end_session))
def save_msg_to_db(session):
"""Save individual message to the database."""
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
table = dynamodb.Table('aim_messages')
db_response = table.scan()
next_index = 1 + sorted(db_response["Items"], key=lambda x: x['id'])[-1]['id']
print(sorted(db_response["Items"], key=lambda x: x['id'])[-1]['id'])
table.put_item(Item={
'id': next_index,
'receiver_name': session["attributes"]["receiver_name"],
'date': datetime.datetime.now().strftime('%m/%d/%y'),
'message': session["attributes"]["message_body"],
'heard': False
})
card_title = "AIM"
speech_output = "OK. Your message is saved."
reprompt_text = ""
should_end_session = True
return build_response(session["attributes"], build_speechlet_response(
card_title, speech_output, reprompt_text, should_end_session))
def receive_message(intent, session):
"""Return the messages based on receiver name."""
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
table = dynamodb.Table('aim_messages')
db_response = table.scan()
session_attributes = {}
receiver_name = intent["slots"]["ForName"]["value"].lower()
message = []
speech_output = ""
for index, row in enumerate(db_response["Items"]):
if row['receiver_name'].lower() == receiver_name and not row['heard']:
session_attributes["receiver_name"] = row["receiver_name"]
session_attributes["id"] = row["id"]
message.append(row["message"])
table.update_item(
Key={
"id": row["id"],
"receiver_name": row["receiver_name"]
},
UpdateExpression="SET heard = :bool",
ExpressionAttributeValues={
":bool": "true"
})
card_title = "AIM"
number_of_messages = len(message)
if not number_of_messages:
speech_output = "There are no messages for {}. ".format(receiver_name)
elif number_of_messages == 1:
speech_output = "Here is your message for {}. {} ".format(receiver_name, message[0])
else:
speech_output = "Here are the messages for {}. ".format(receiver_name)
for index, value in enumerate(message):
speech_output += "Message {}. {}. ".format(index + 1, value)
reprompt_text = ""
if not number_of_messages:
should_end_session = True
else:
should_end_session = False
session_attributes["message_body"] = speech_output
return build_response(session_attributes, build_speechlet_response(
card_title, speech_output, reprompt_text, should_end_session))
def replay_message(intent, session):
"""Replay the last heard message or messages."""
speech_output = session["attributes"]["message_body"]
reprompt_text = ""
card_title = "AIM"
should_end_session = False
return build_response(session["attributes"], build_speechlet_response(
card_title, speech_output, reprompt_text, should_end_session))
def delete_message(intent, session):
"""Delete message from database."""
session_attributes = {}
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
table = dynamodb.Table('aim_messages')
db_response = table.scan()
receiver_name = intent["slots"]["ForName"]["value"].lower()
receivers_last_message = sorted(db_response["Items"], key=lambda x: x['id'])
card_title = "Delete Message"
speech_output = "Your message has been deleted."
reprompt_text = ""
should_end_session = True
for i in receivers_last_message[::-1]:
if receiver_name == i["receiver_name"].lower():
table.delete_item(
Key={
"id": i["id"],
"receiver_name": i["receiver_name"]
})
return build_response(session_attributes, build_speechlet_response(
card_title, speech_output, reprompt_text, should_end_session))
speech_output = "You don't have any messages."
return build_response(session_attributes, build_speechlet_response(
card_title, speech_output, reprompt_text, should_end_session))
def on_session_ended():
"""Close session, aka the skill is not active."""
session_attributes = {}
card_title = "AIM - Thanks"
speech_output = "Thank you for using AIM. See you next time!"
reprompt_text = ""
should_end_session = True
return build_response(session_attributes, build_speechlet_response(
card_title, speech_output, reprompt_text, should_end_session))
def get_welcome_response():
"""Introduce the skill's title and function."""
session_attributes = {}
card_title = "AIM"
speech_output = "Welcome to AIM messaging"
reprompt_text = "Do you want to send or receive a message."
should_end_session = False
return build_response(session_attributes, build_speechlet_response(
card_title, speech_output, reprompt_text, should_end_session))
def get_help_response():
"""Introduce the skill's functionality."""
session_attributes = {}
card_title = "AIM"
speech_output = "Here's how to use AIM messaging. For example to send a \
message to Bob, say, send a message to Bob. And then \
follow the prompts. To receive a message, say, play \
messages for Bob. To replay a message, say, replay.\
To delete a message, say, delete a message from Bob."
reprompt_text = "Do you want to send or receive a message."
should_end_session = False
return build_response(session_attributes, build_speechlet_response(
card_title, speech_output, reprompt_text, should_end_session))
def unsure_response(intent, session):
"""Will be returned to the user if Alexa was unsure about the intent."""
session_attributes = {}
card_title = "AIM - unsure response"
speech_output = "I'm sorry, I didn't get that. Say help if you need it."
reprompt_text = "Do you want to send or receive a message."
should_end_session = False
return build_response(session_attributes, build_speechlet_response(
card_title, speech_output, reprompt_text, should_end_session))
def build_speechlet_response(title, output, reprompt_text, should_end_session):
"""Build custom object to be returned and sent to Alexa."""
return {
"outputSpeech": {
"type": "PlainText",
"text": output
},
"card": {
"type": "Simple",
"title": title,
"content": output
},
"reprompt": {
"outputSpeech": {
"type": "PlainText",
"text": reprompt_text
}
},
"shouldEndSession": should_end_session
}
def build_response(session_attributes, speechlet_response):
"""Return any data to persist throughout the session."""
return {
"version": "1.0",
"sessionAttributes": session_attributes,
"response": speechlet_response
}