Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ask/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from . import alexa_io
from alexa_io import InvalidAppIdException

'''
Setting up some nice abstractions around good object oritented code.
Expand Down
29 changes: 27 additions & 2 deletions ask/alexa_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,20 @@
}"""


class InvalidAppIdException(Exception):
pass


class Request(object):
"""
Simple wrapper around the JSON request
received by the module
"""
def __init__(self, request_dict, metadata=None):
def __init__(self, request_dict, metadata=None, supported_app_ids=None):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't it make more sense to do the supported app IDs verification in the VoiceHandler object?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry for late reply, been really busy, but yes it does i just made this on the quickness, didnt really think about it too much, ill make the changes.

self.request = request_dict
self.metadata = metadata or {}
self.session = self.request.get('session', {}).get('attributes', {})
self.supported_app_ids = supported_app_ids
if self.intent_name():
self.slots = self.get_slot_map()

Expand Down Expand Up @@ -50,6 +55,19 @@ def access_token(self):
def session_id(self):
return self.request["session"]["sessionId"]

def application_id(self):
try:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please replace the generic exception handling with an explicit check, or at least catch the specific exception

return self.request['session']['application']['applicationId']
except:
return None

def has_valid_app_id(self):
if not self.supported_app_ids:
return True
if not self.application_id():
return False
return self.application_id() in self.supported_app_ids

def get_slot_value(self, slot_name):
try:
return self.request["request"]["intent"]["slots"][slot_name]["value"]
Expand Down Expand Up @@ -192,11 +210,18 @@ def _handler(func):

return _handler

def route_request(self, request_json, metadata=None):
def route_request(self, request_json, metadata=None, app_ids=None):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to me that having the app_ids as a construction parameter for the 'alexa' makes more sense than passing it into a parameter for route_request

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i agree, should i add it to the constructor somehow? or do alexa.app_ids = [...] in lambda_handler?


''' Route the request object to the right handler function '''
request = Request(request_json)
request.supported_app_ids = app_ids
request.metadata = metadata

# before we do anything, lets verify the application id
# if app_ids is not passed in, verification does not occur
if not request.has_valid_app_id():
raise InvalidAppIdException('Invalid ApplicationId: %s' % request.application_id())

# add reprompt handler or some such for default?
handler_fn = self._handlers[self._default] # Set default handling for noisy requests

Expand Down
13 changes: 12 additions & 1 deletion tests/test_alexa.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from nose.tools import assert_equal, assert_dict_equal, assert_true
from nose.tools import assert_equal, assert_dict_equal, assert_true, raises

from .context import ask
from .fixtures.requests import (TEST_SESSION_ENDED_REQUEST, TEST_LAUNCH_REQUEST,
Expand Down Expand Up @@ -83,3 +83,14 @@ def test_routes_to_request_handler(self):

response = ask.alexa.route_request(req_json)
assert_true(response['request_handler_called'])

@raises(ask.InvalidAppIdException)
def test_raises_invalid_app_id(self):
req_json = TEST_INTENT_REQUEST
ids = ['supported_id', 'another_bad_id']
ask.alexa.route_request(req_json, app_ids=ids)

def test_valid_app_id(self):
req_json = TEST_INTENT_REQUEST
ids = ['amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe']
ask.alexa.route_request(req_json, app_ids=ids)
21 changes: 21 additions & 0 deletions tests/test_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,27 @@ def test_request_returns_session_id(self):

assert_equal(session_id, "SessionId.d461672c-2997-4d9d-9a8c-a67834acb9aa")

def test_request_returns_application_id(self):
application_id = self.example.application_id()

assert_equal(application_id, "amzn1.echo-sdk-ams.app.a306b3a3-3331-43c1-87bd-87d29d16fac8")

def test_request_has_valid_application_id_empty_app_ids(self):
assert_true(self.example.has_valid_app_id())

def test_request_has_valid_application_id(self):
self.example.supported_app_ids = ['amzn1.echo-sdk-ams.app.a306b3a3-3331-43c1-87bd-87d29d16fac8']

assert_true(self.example.has_valid_app_id())

def test_request_has_invalid_application_id(self):
def app_id_mock():
return 'bad_app_id'

self.example.supported_app_ids = ['amzn1.echo-sdk-ams.app.a306b3a3-3331-43c1-87bd-87d29d16fac8']
self.example.application_id = app_id_mock
assert_false(self.example.has_valid_app_id())

def test_request_returns_slot_value(self):
val1 = self.example.get_slot_value("example1")
val2 = self.example.get_slot_value("example2")
Expand Down