-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.py
152 lines (117 loc) · 4.31 KB
/
app.py
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
# -*- coding: utf-8 -*-
"""
AWS Lambda function for handling Alexa skill requests.
Copyright (c) 2022 AListair J. R. Young
"""
import json
import logging
import os
import sys
import urllib3
debug = bool(os.environ.get('DEBUG'))
base_url = os.environ.get('BASE_URL')
verify_ssl = not bool(os.environ.get('DO_NOT_VERIFY_SSL'))
logger = logging.getLogger('Ariadne-Lambda')
logger.setLevel (logging.DEBUG if debug else logging.INFO)
def smart_home_handler (event, context):
"""Handle requests intended for the Smart Home skill."""
directive = event.get ('directive')
assert directive is not None, 'Malformed request (missing directive).'
assert directive.get('header', {}).get('payloadVersion') == '3', 'Unsupported request (only support payloadVersion == 3).'
scope = directive.get('endpoint', {}).get('scope')
if scope is None:
# token is in grantee for Linking directive
scope = directive.get('payload', {}).get('grantee')
if scope is None:
# token is in payload for Discovery directive
scope = directive.get('payload', {}).get('scope')
assert scope is not None, 'Malformed request (missing endpoint.scope).'
assert scope.get('type') == 'BearerToken', 'Unsupported request (only support BearerToken).'
token = scope.get('token')
if token is None and debug:
token = os.environ.get('LONG_LIVED_ACCESS_TOKEN') # only for debug purposes
assert token, 'Configuration error (could not get access token.)'
http = urllib3.PoolManager(
cert_reqs='CERT_REQUIRED' if verify_ssl else 'CERT_NONE',
timeout=urllib3.Timeout(connect=2.0, read=10.0)
)
response = http.request(
'POST',
'{}/api/alexa/smart_home'.format(base_url),
headers={
'Authorization': 'Bearer {}'.format(token),
'Content-Type': 'application/json',
},
body=json.dumps(event).encode('utf-8'),
)
if response.status >= 400:
return {
'event': {
'payload': {
'type': 'INVALID_AUTHORIZATION_CREDENTIAL'
if response.status in (401, 403) else 'INTERNAL_ERROR',
'message': response.data.decode("utf-8"),
}
}
}
return json.loads(response.data.decode("utf-8"))
def custom_handler (event, context):
"""Handle requests intended for the Custom skill."""
try:
token = event.get('session', {}).get('user', {}).get('accessToken')
except AttributeError:
token = None
if token is None and _debug:
token = os.environ.get('LONG_LIVED_ACCESS_TOKEN')
assert token, 'Configuration error (could not get access token.)'
if token is None and debug:
token = os.environ.get('LONG_LIVED_ACCESS_TOKEN') # only for debug purposes
assert token, 'Configuration error (could not get access token.)'
http = urllib3.PoolManager(
cert_reqs='CERT_REQUIRED' if verify_ssl else 'CERT_NONE',
timeout=urllib3.Timeout(connect=2.0, read=10.0)
)
response = http.request(
'POST',
'{}/api/alexa'.format(base_url),
headers={
'Authorization': 'Bearer {}'.format(token),
'Content-Type': 'application/json',
},
body=json.dumps(event).encode('utf-8'),
)
if response.status >= 400:
return {
'event': {
'payload': {
'type': 'INVALID_AUTHORIZATION_CREDENTIAL'
if response.status in (401, 403) else 'INTERNAL_ERROR',
'message': response.data.decode("utf-8"),
}
}
}
return json.loads(response.data.decode("utf-8"))
def test_handler (event, context):
"""Handle requests intended for the test function."""
return "Hello from Ariadne Lambda function, using Python " + sys.version + "!"
def handler (event, context):
"""Handle incoming requests."""
# Assert that we have the necessary information.
assert base_url is not None, 'Please set BASE_URL environment variable.'
logger.debug ('Context: %s', context)
logger.debug ('Event: %s', event)
if context.function_name == 'ariadneSmartHome':
# Execute Smart Home Skill function.
return smart_home_handler(event, context)
elif context.function_name == 'ariadneCustom':
# Execute Custom Skill function.
return custom_handler(event, context)
elif context.function_name == 'ariadneTest':
# Execute test function.
return test_handler(event, context)
else:
# Bugger.
return {
'statusCode': 418,
'body': "Sorry, Dave, I'm afraid I can't do that."
}