Browse Source

Files del Alexa Skill para ordenar

pablo.loyola 3 years ago
parent
commit
b6373c5bb9

+ 177
- 0
Ordenar_Alexa/interactionModels/custom/en-US.json View File

@@ -0,0 +1,177 @@
1
+{
2
+  "interactionModel": {
3
+    "languageModel": {
4
+      "invocationName": "linguini order",
5
+      "intents": [
6
+        {
7
+          "name": "AMAZON.CancelIntent",
8
+          "samples": []
9
+        },
10
+        {
11
+          "name": "AMAZON.HelpIntent",
12
+          "samples": []
13
+        },
14
+        {
15
+          "name": "AMAZON.StopIntent",
16
+          "samples": []
17
+        },
18
+        {
19
+          "name": "HelloWorldIntent",
20
+          "slots": [],
21
+          "samples": [
22
+            "hello",
23
+            "how are you",
24
+            "say hi world",
25
+            "say hi",
26
+            "hi",
27
+            "say hello world",
28
+            "say hello"
29
+          ]
30
+        },
31
+        {
32
+          "name": "AMAZON.NavigateHomeIntent",
33
+          "samples": []
34
+        },
35
+        {
36
+          "name": "LinguiniOrderFoodIntent",
37
+          "slots": [
38
+            {
39
+              "name": "food_type",
40
+              "type": "food_type"
41
+            },
42
+            {
43
+              "name": "food_category",
44
+              "type": "food_category"
45
+            }
46
+          ],
47
+          "samples": [
48
+            "add {food_type} {food_category}",
49
+            "{food_type} {food_category}",
50
+            "order {food_type} {food_category}",
51
+            "add a {food_type} {food_category}",
52
+            "order a {food_type} {food_category}"
53
+          ]
54
+        },
55
+        {
56
+          "name": "LinguiniOrderDrinkIntent",
57
+          "slots": [
58
+            {
59
+              "name": "drink_type",
60
+              "type": "drink_type"
61
+            }
62
+          ],
63
+          "samples": [
64
+            "{drink_type}",
65
+            "add {drink_type}",
66
+            "order {drink_type}",
67
+            "add a {drink_type}",
68
+            "order a {drink_type}"
69
+          ]
70
+        },
71
+        {
72
+          "name": "LinguiniOrderReviewIntent",
73
+          "slots": [],
74
+          "samples": [
75
+            "review please",
76
+            "review"
77
+          ]
78
+        },
79
+        {
80
+          "name": "LinguiniOrderFinishIntent",
81
+          "slots": [],
82
+          "samples": [
83
+            "Finish"
84
+          ]
85
+        },
86
+        {
87
+          "name": "LinguiniOrderNothingIntent",
88
+          "slots": [],
89
+          "samples": [
90
+            "that is all",
91
+            "that\u0027s all",
92
+            "nothing else",
93
+            "nothing"
94
+          ]
95
+        }
96
+      ],
97
+      "types": [
98
+        {
99
+          "values": [
100
+            {
101
+              "name": {
102
+                "value": "pizzetta"
103
+              }
104
+            },
105
+            {
106
+              "name": {
107
+                "value": "pasta"
108
+              }
109
+            }
110
+          ],
111
+          "name": "food_category"
112
+        },
113
+        {
114
+          "values": [
115
+            {
116
+              "name": {
117
+                "value": "chicken alfredo"
118
+              }
119
+            },
120
+            {
121
+              "name": {
122
+                "value": "gardenia"
123
+              }
124
+            },
125
+            {
126
+              "name": {
127
+                "value": "carnivore"
128
+              }
129
+            },
130
+            {
131
+              "name": {
132
+                "value": "pepperoni"
133
+              }
134
+            },
135
+            {
136
+              "name": {
137
+                "value": "plain cheese"
138
+              }
139
+            }
140
+          ],
141
+          "name": "food_type"
142
+        },
143
+        {
144
+          "values": [
145
+            {
146
+              "name": {
147
+                "value": "beer"
148
+              }
149
+            },
150
+            {
151
+              "name": {
152
+                "value": "wine"
153
+              }
154
+            },
155
+            {
156
+              "name": {
157
+                "value": "juice"
158
+              }
159
+            },
160
+            {
161
+              "name": {
162
+                "value": "soda"
163
+              }
164
+            },
165
+            {
166
+              "name": {
167
+                "value": "water"
168
+              }
169
+            }
170
+          ],
171
+          "name": "drink_type"
172
+        }
173
+      ]
174
+    }
175
+  },
176
+  "version": "32"
177
+}

+ 373
- 0
Ordenar_Alexa/lambda/lambda_function.py View File

@@ -0,0 +1,373 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+# This sample demonstrates handling intents from an Alexa skill using the Alexa Skills Kit SDK for Python.
4
+# Please visit https://alexa.design/cookbook for additional examples on implementing slots, dialog management,
5
+# session persistence, api calls, and more.
6
+# This sample is built using the handler classes approach in skill builder.
7
+import logging
8
+import requests
9
+import ask_sdk_core.utils as ask_utils
10
+
11
+#from ask_sdk_s3.adapter import S3Adapter
12
+#s3_adapter = S3Adapter(bucket_name=os.environ["S3_PERSISTENCE_BUCKET"])
13
+
14
+from ask_sdk_core.skill_builder import SkillBuilder
15
+from ask_sdk_core.dispatch_components import AbstractRequestHandler
16
+from ask_sdk_core.dispatch_components import AbstractExceptionHandler
17
+from ask_sdk_core.handler_input import HandlerInput
18
+
19
+from ask_sdk_model import Response
20
+
21
+logger = logging.getLogger(__name__)
22
+logger.setLevel(logging.INFO)
23
+
24
+ordernum = 0
25
+
26
+
27
+
28
+
29
+class LaunchRequestHandler(AbstractRequestHandler):
30
+    """Handler for Skill Launch."""
31
+    def can_handle(self, handler_input):
32
+        # type: (HandlerInput) -> bool
33
+
34
+        return ask_utils.is_request_type("LaunchRequest")(handler_input)
35
+
36
+    def handle(self, handler_input):
37
+        # type: (HandlerInput) -> Response
38
+        speak_output = "What would you like to order?"
39
+
40
+        return (
41
+            handler_input.response_builder
42
+                .speak(speak_output)
43
+                .ask(speak_output)
44
+                .response
45
+        )
46
+
47
+
48
+class HelloWorldIntentHandler(AbstractRequestHandler):
49
+    """Handler for Hello World Intent."""
50
+    def can_handle(self, handler_input):
51
+        # type: (HandlerInput) -> bool
52
+        return ask_utils.is_intent_name("HelloWorldIntent")(handler_input)
53
+
54
+    def handle(self, handler_input):
55
+        # type: (HandlerInput) -> Response
56
+        speak_output = "Hello World!"
57
+
58
+        return (
59
+            handler_input.response_builder
60
+                .speak(speak_output)
61
+                # .ask("add a reprompt if you want to keep the session open for the user to respond")
62
+                .response
63
+        )
64
+
65
+
66
+class LinguiniOrderFoodIntentHandler(AbstractRequestHandler):
67
+    """Handler for Linguini Order Food Intent."""
68
+    global ordernum 
69
+    ordernum = ordernum + 1
70
+    global food_dict
71
+    global order
72
+    def can_handle(self, handler_input):
73
+        # type: (HandlerInput) -> bool
74
+        return ask_utils.is_intent_name("LinguiniOrderFoodIntent")(handler_input)
75
+
76
+    def handle(self, handler_input):
77
+        # type: (HandlerInput) -> Response
78
+        slots = handler_input.request_envelope.request.intent.slots
79
+        food_type = slots["food_type"].value
80
+        food_category = slots["food_category"].value
81
+        speak_output = f"One {food_type} {food_category} added to your order. What else would you like to add?"
82
+        food = f"{food_type} {food_category}"
83
+        
84
+        if food == "gardenia pasta":
85
+            orderstr = 'orden' + str(ordernum)
86
+            order[orderstr] = 2
87
+        else:
88
+            orderstr = 'orden' + str(ordernum)
89
+            order[ordernum] = 1
90
+        
91
+        if food in order_names:
92
+            order_names[food] += 1
93
+        else:
94
+            order_names[food] = 1
95
+        
96
+        handler_input.response_builder.speak(speak_output).ask("What else would you like to add?")
97
+        return (handler_input.response_builder.response)
98
+
99
+
100
+class LinguiniOrderDrinkIntentHandler(AbstractRequestHandler):
101
+    """Handler for Linguini Order Drink Intent."""
102
+    global ordernum
103
+    ordernum = ordernum + 1
104
+    global drink_dict
105
+    global order
106
+    global order_names
107
+    def can_handle(self, handler_input):
108
+        # type: (HandlerInput) -> bool
109
+        return ask_utils.is_intent_name("LinguiniOrderDrinkIntent")(handler_input)
110
+
111
+    def handle(self, handler_input):
112
+        # type: (HandlerInput) -> Response
113
+        slots = handler_input.request_envelope.request.intent.slots
114
+        drink_type = slots["drink_type"].value
115
+        speak_output = f"One {drink_type} added to your order. What else would you like to add?"
116
+        
117
+        if drink_type == "water":
118
+            orderstr = 'orden' + str(ordernum)
119
+            order[orderstr] = 10
120
+        else:
121
+            orderstr = 'orden' + str(ordernum)
122
+            order[orderstr] = 9
123
+        
124
+        if drink_type in order_names:
125
+            order_names[drink_type] += 1
126
+        else:
127
+            order_names[drink_type] = 1
128
+        handler_input.response_builder.speak(speak_output).ask("What else would you like to add?")
129
+        return (handler_input.response_builder.response)
130
+
131
+
132
+class HelpIntentHandler(AbstractRequestHandler):
133
+    """Handler for Help Intent."""
134
+    def can_handle(self, handler_input):
135
+        # type: (HandlerInput) -> bool
136
+        return ask_utils.is_intent_name("AMAZON.HelpIntent")(handler_input)
137
+
138
+    def handle(self, handler_input):
139
+        # type: (HandlerInput) -> Response
140
+        speak_output = "You can say hello to me! How can I help?"
141
+
142
+        return (
143
+            handler_input.response_builder
144
+                .speak(speak_output)
145
+                .ask(speak_output)
146
+                .response
147
+        )
148
+
149
+
150
+class CancelIntentHandler(AbstractRequestHandler):
151
+    """Handler for Cancel Intent."""
152
+    global order
153
+    global order_names
154
+    def can_handle(self, handler_input):
155
+        # type: (HandlerInput) -> bool
156
+        return (ask_utils.is_intent_name("AMAZON.CancelIntent")(handler_input))
157
+
158
+    def handle(self, handler_input):
159
+        # type: (HandlerInput) -> Response
160
+        speak_output = "Your order has been canceled."
161
+        order.clear()
162
+        order_names.clear()
163
+        return (
164
+            handler_input.response_builder
165
+                .speak(speak_output)
166
+                .ask("reprompt")
167
+                .response
168
+        )
169
+
170
+
171
+class StopIntentHandler(AbstractRequestHandler):
172
+    """Handler for Stop Intent."""
173
+    def can_handle(self, handler_input):
174
+        # type: (HandlerInput) -> bool
175
+        return (ask_utils.is_intent_name("AMAZON.StopIntent")(handler_input))
176
+
177
+    def handle(self, handler_input):
178
+        # type: (HandlerInput) -> Response
179
+        speak_output = "Alright! Your order is complete. Would you like to review, finish, or cancel your order?"
180
+
181
+        return (
182
+            handler_input.response_builder
183
+                .speak(speak_output)
184
+                .ask(speak_output)
185
+                .response
186
+        )
187
+
188
+class LinguiniOrderNothingIntentHandler(AbstractRequestHandler):
189
+    """Handler for Stop Intent."""
190
+    def can_handle(self, handler_input):
191
+        # type: (HandlerInput) -> bool
192
+        return (ask_utils.is_intent_name("LinguiniOrderNothingIntent")(handler_input))
193
+
194
+    def handle(self, handler_input):
195
+        # type: (HandlerInput) -> Response
196
+        speak_output = "Alright! Your order is complete. Would you like to review, finish, or cancel your order"
197
+
198
+        return (
199
+            handler_input.response_builder
200
+                .speak(speak_output)
201
+                .ask(speak_output)
202
+                .response
203
+        )
204
+
205
+
206
+class LinguiniOrderReviewIntentHandler(AbstractRequestHandler):
207
+    global order
208
+    """Handler for Hello World Intent."""
209
+    def can_handle(self, handler_input):
210
+        # type: (HandlerInput) -> bool
211
+        return ask_utils.is_intent_name("LinguiniOrderReviewIntent")(handler_input)
212
+
213
+    def handle(self, handler_input):
214
+        # type: (HandlerInput) -> Response
215
+        speak_output = "You have "
216
+        for i in order_names:
217
+            speak_output += f"{order_names[i]} {i}, "
218
+        speak_output = speak_output[:-2]
219
+        speak_output += ". If everything seems okay, say finish to submit order or say cancel to cancel and restart order." 
220
+        
221
+
222
+        return (
223
+            handler_input.response_builder
224
+                .speak(speak_output)
225
+                .ask("add a reprompt if you want to keep the session open for the user to respond")
226
+                .response
227
+        )
228
+
229
+
230
+class LinguiniOrderFinishIntentHandler(AbstractRequestHandler):
231
+    global order
232
+    global order_names
233
+    """Handler for Hello World Intent."""
234
+    def can_handle(self, handler_input):
235
+        # type: (HandlerInput) -> bool
236
+        return ask_utils.is_intent_name("LinguiniOrderFinishIntent")(handler_input)
237
+
238
+    def handle(self, handler_input):
239
+        # type: (HandlerInput) -> Response
240
+        #Send order to Restaurant lmao
241
+        
242
+        full_order = [{'nombre': 'Aranpompano','celular': '(555)-555-5555', 'ordenCompleta': order, 'peticiones': {}}]
243
+        #full_order = [{'nombre': 'Scott Pilgrim','celular': '(555)-555-5555', 'ordenCompleta': {'orden1':1, 'orden2': 10}, 'peticiones': {}}]
244
+        
245
+        try:
246
+            r = requests.post('http://136.145.231.48:5000/papelonDeComida', json=full_order)
247
+        except:
248
+            r = None
249
+        
250
+        if r == None:
251
+            speak_output = "Sorry, I couldn't connect to the restaurant. Please try again later."
252
+        
253
+        elif(r.status_code == 200):
254
+            speak_output = f'Alright! {r.text}'
255
+        else:
256
+            speak_output = "Uh oh! I couldn't place your order, please try again later."
257
+        
258
+        #REPLACE THIS WHEN API IS IMPLEMENTED
259
+        order.clear()
260
+        order_names.clear()
261
+        #REPLACE THIS WHEN API IS IMPLEMENTED
262
+
263
+        return (
264
+            handler_input.response_builder
265
+                .speak(speak_output)
266
+                # .ask("add a reprompt if you want to keep the session open for the user to respond")
267
+                .response
268
+        )
269
+
270
+
271
+class SessionEndedRequestHandler(AbstractRequestHandler):
272
+    """Handler for Session End."""
273
+    def can_handle(self, handler_input):
274
+        # type: (HandlerInput) -> bool
275
+        return ask_utils.is_request_type("SessionEndedRequest")(handler_input)
276
+
277
+    def handle(self, handler_input):
278
+        # type: (HandlerInput) -> Response
279
+
280
+        # Any cleanup logic goes here.
281
+
282
+        return handler_input.response_builder.response
283
+
284
+
285
+class IntentReflectorHandler(AbstractRequestHandler):
286
+    """The intent reflector is used for interaction model testing and debugging.
287
+    It will simply repeat the intent the user said. You can create custom handlers
288
+    for your intents by defining them above, then also adding them to the request
289
+    handler chain below.
290
+    """
291
+    def can_handle(self, handler_input):
292
+        # type: (HandlerInput) -> bool
293
+        return ask_utils.is_request_type("IntentRequest")(handler_input)
294
+
295
+    def handle(self, handler_input):
296
+        # type: (HandlerInput) -> Response
297
+        intent_name = ask_utils.get_intent_name(handler_input)
298
+        speak_output = "You just triggered " + intent_name + "."
299
+
300
+        return (
301
+            handler_input.response_builder
302
+                .speak(speak_output)
303
+                # .ask("add a reprompt if you want to keep the session open for the user to respond")
304
+                .response
305
+        )
306
+
307
+
308
+class CatchAllExceptionHandler(AbstractExceptionHandler):
309
+    """Generic error handling to capture any syntax or routing errors. If you receive an error
310
+    stating the request handler chain is not found, you have not implemented a handler for
311
+    the intent being invoked or included it in the skill builder below.
312
+    """
313
+    def can_handle(self, handler_input, exception):
314
+        # type: (HandlerInput, Exception) -> bool
315
+        return True
316
+
317
+    def handle(self, handler_input, exception):
318
+        # type: (HandlerInput, Exception) -> Response
319
+        logger.error(exception, exc_info=True)
320
+
321
+        speak_output = "Sorry, I had trouble doing what you asked. Please try again."
322
+
323
+        return (
324
+            handler_input.response_builder
325
+                .speak(speak_output)
326
+                .ask(speak_output)
327
+                .response
328
+        )
329
+
330
+# The SkillBuilder object acts as the entry point for your skill, routing all request and response
331
+# payloads to the handlers above. Make sure any new handlers or interceptors you've
332
+# defined are included below. The order matters - they're processed top to bottom.
333
+
334
+
335
+sb = SkillBuilder()
336
+try:
337
+    resp = requests.get('http://136.145.231.48:5000/retrieveMenu')
338
+    if resp.status_code == 200:
339
+        menu_full = resp.json()
340
+        food_dict = menu_full['comidas']
341
+        pasta_dict = comida['Pasta']
342
+        drink_dict = menu_full['bebidas']
343
+    else:
344
+        menu_full = {}
345
+        food_dict = {}
346
+        pasta_dict = {}
347
+        drink_dict = {}
348
+except:
349
+    menu_full = {}
350
+    food_dict = {}
351
+    pasta_dict = {}
352
+    drink_dict = {}
353
+    
354
+
355
+order = {}
356
+order_names = {}
357
+
358
+sb.add_request_handler(LaunchRequestHandler())
359
+#sb.add_request_handler(HelloWorldIntentHandler())
360
+#sb.add_request_handler(HelpIntentHandler())
361
+sb.add_request_handler(LinguiniOrderFoodIntentHandler())
362
+sb.add_request_handler(LinguiniOrderDrinkIntentHandler())
363
+sb.add_request_handler(LinguiniOrderNothingIntentHandler())
364
+sb.add_request_handler(CancelIntentHandler())
365
+sb.add_request_handler(StopIntentHandler())
366
+sb.add_request_handler(LinguiniOrderReviewIntentHandler())
367
+sb.add_request_handler(LinguiniOrderFinishIntentHandler())
368
+sb.add_request_handler(SessionEndedRequestHandler())
369
+sb.add_request_handler(IntentReflectorHandler()) # make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers
370
+
371
+sb.add_exception_handler(CatchAllExceptionHandler())
372
+
373
+lambda_handler = sb.lambda_handler()

+ 4
- 0
Ordenar_Alexa/lambda/requirements.txt View File

@@ -0,0 +1,4 @@
1
+boto3==1.9.216
2
+requests==2.25.1
3
+ask-sdk-core==1.11.0
4
+ask-sdk-s3-persistence-adapter

+ 27
- 0
Ordenar_Alexa/lambda/utils.py View File

@@ -0,0 +1,27 @@
1
+import logging
2
+import os
3
+import boto3
4
+from botocore.exceptions import ClientError
5
+
6
+
7
+def create_presigned_url(object_name):
8
+    """Generate a presigned URL to share an S3 object with a capped expiration of 60 seconds
9
+
10
+    :param object_name: string
11
+    :return: Presigned URL as string. If error, returns None.
12
+    """
13
+    s3_client = boto3.client('s3',
14
+                             region_name=os.environ.get('S3_PERSISTENCE_REGION'),
15
+                             config=boto3.session.Config(signature_version='s3v4',s3={'addressing_style': 'path'}))
16
+    try:
17
+        bucket_name = os.environ.get('S3_PERSISTENCE_BUCKET')
18
+        response = s3_client.generate_presigned_url('get_object',
19
+                                                    Params={'Bucket': bucket_name,
20
+                                                            'Key': object_name},
21
+                                                    ExpiresIn=60*1)
22
+    except ClientError as e:
23
+        logging.error(e)
24
+        return None
25
+
26
+    # The response contains the presigned URL
27
+    return response

+ 44
- 0
Ordenar_Alexa/skill.json View File

@@ -0,0 +1,44 @@
1
+{
2
+  "manifest": {
3
+    "apis": {
4
+      "custom": {
5
+        "endpoint": {
6
+          "uri": "arn:aws:lambda:us-east-1:952171653410:function:d09b2dda-6a62-40cf-99b4-68aad50c5297:Release_0"
7
+        },
8
+        "interfaces": [],
9
+        "regions": {
10
+          "NA": {
11
+            "endpoint": {
12
+              "uri": "arn:aws:lambda:us-east-1:952171653410:function:d09b2dda-6a62-40cf-99b4-68aad50c5297:Release_0"
13
+            }
14
+          },
15
+          "EU": {
16
+            "endpoint": {
17
+              "uri": "arn:aws:lambda:eu-west-1:952171653410:function:d09b2dda-6a62-40cf-99b4-68aad50c5297:Release_0"
18
+            }
19
+          },
20
+          "FE": {
21
+            "endpoint": {
22
+              "uri": "arn:aws:lambda:us-west-2:952171653410:function:d09b2dda-6a62-40cf-99b4-68aad50c5297:Release_0"
23
+            }
24
+          }
25
+        }
26
+      }
27
+    },
28
+    "permissions": [
29
+      {
30
+        "name": "alexa::profile:given_name:read"
31
+      },
32
+      {
33
+        "name": "alexa::profile:mobile_number:read"
34
+      }
35
+    ],
36
+    "publishingInformation": {
37
+      "locales": {
38
+        "en-US": {
39
+          "name": "Linguini_Order"
40
+        }
41
+      }
42
+    }
43
+  }
44
+}