# Register intent request handlers cls_members = inspect.getmembers(owl_skill.request_handlers, inspect.isclass) for member in cls_members: cls = member[1] if issubclass(cls, AbstractRequestHandler) and \ cls is not AbstractRequestHandler: sb.add_request_handler(cls()) # Register exception handlers cls_members = inspect.getmembers(owl_skill.exception_handlers, inspect.isclass) for member in cls_members: cls = member[1] if issubclass(cls, AbstractExceptionHandler) and \ cls is not AbstractExceptionHandler: sb.add_exception_handler(cls()) # request interceptors cls_members = inspect.getmembers(owl_skill.interceptors, inspect.isclass) for memeber in cls_members: cls = memeber[1] if issubclass(cls, AbstractRequestInterceptor) and \ cls is not AbstractRequestInterceptor: sb.add_global_request_interceptor(cls()) if issubclass(cls, AbstractResponseInterceptor) and \ cls is not AbstractResponseInterceptor: sb.add_global_response_interceptor(cls()) lambda_handler = sb.lambda_handler()
logger.debug("Alexa Request: {}".format( handler_input.request_envelope.request)) class ResponseLogger(AbstractResponseInterceptor): """Log the alexa responses.""" def process(self, handler_input, response): # type: (HandlerInput, Response) -> None logger.debug("Alexa Response: {}".format(response)) # Register intent handlers sb.add_request_handler(GetRandomFactHandler()) sb.add_request_handler(GetSpecificSpeciesFactHandler()) sb.add_request_handler(LaunchRequestHandler()) sb.add_request_handler(YesHandler()) sb.add_request_handler(NoHandler()) sb.add_request_handler(HelpIntentHandler()) sb.add_request_handler(CancelOrStopIntentHandler()) sb.add_request_handler(FallbackIntentHandler()) sb.add_request_handler(SessionEndedRequestHandler()) # Register exception handlers sb.add_exception_handler(CatchAllExceptionHandler()) # Uncomment the following lines of code for request, response logs. sb.add_global_request_interceptor(RequestLogger()) sb.add_global_response_interceptor(ResponseLogger()) # Handler name that is used on AWS lambda main = sb.lambda_handler()
logger.info("Response: {}".format(response)) # Add all request handlers to the skill. sb.add_request_handler(LaunchRequestHandler()) sb.add_request_handler(RepeatHandler()) sb.add_request_handler(HelpIntentHandler()) sb.add_request_handler(ExitIntentHandler()) sb.add_request_handler(SessionEndedRequestHandler()) sb.add_request_handler(FallbackIntentHandler()) # Add all request handlers to the skill. sb.add_request_handler(ListShipsHandler()) sb.add_request_handler(NewGameHandler()) sb.add_request_handler(SetupBoardHandler()) sb.add_request_handler(PlayGameHandler()) # Add exception handler to the skill. sb.add_exception_handler(CatchAllExceptionHandler()) # Add response interceptor to the skill. sb.add_global_response_interceptor(CacheResponseForRepeatInterceptor()) sb.add_global_request_interceptor(RequestLogger()) sb.add_global_response_interceptor(ResponseLogger()) # Expose the lambda handler to register in AWS Lambda. lambda_handler = sb.lambda_handler()
#Clase que detecta la localización del usuario class LocalizationInterceptor(AbstractRequestInterceptor): """Add function to request attributes, that can load locale specific data.""" def process(self, handler_input): # type: (HandlerInput) -> None locale = handler_input.request_envelope.request.locale logger.info("Locale is {}".format(locale)) i18n = gettext.translation('data', localedir='locales', languages=[locale], fallback=True) handler_input.attributes_manager.request_attributes["_"] = i18n.gettext # sb.add_request_handler(LaunchRequestHandler()) #sb.add_request_handler(EJEMPLOIntentHandler()) sb.add_request_handler(RecetaIntentHandler()) sb.add_request_handler(HelpIntentHandler()) sb.add_request_handler(RepeatIntentHandler()) sb.add_request_handler(CancelOrStopIntentHandler()) sb.add_request_handler(FallbackIntentHandler()) sb.add_request_handler(SessionEndedRequestHandler()) sb.add_exception_handler(CatchAllExceptionHandler()) sb.add_global_request_interceptor(LocalizationInterceptor()) sb.add_global_response_interceptor(CacheSpeechForRepeatInterceptor()) lambda_handler = sb.lambda_handler()
class TestSkillBuilder(unittest.TestCase): def setUp(self): self.sb = SkillBuilder() def test_add_null_request_handler_throw_error(self): with self.assertRaises(SkillBuilderException) as exc: self.sb.add_request_handler(request_handler=None) assert "Valid Request Handler instance to be provided" in str( exc.exception ), ("Add Request Handler method didn't throw exception when a null " "request handler is added") def test_add_invalid_request_handler_throw_error(self): invalid_request_handler = mock.Mock() with self.assertRaises(SkillBuilderException) as exc: self.sb.add_request_handler( request_handler=invalid_request_handler) assert "Input should be a RequestHandler instance" in str( exc.exception), ( "Add Request Handler method didn't throw exception when an " "invalid request handler is added") def test_add_valid_request_handler(self): mock_request_handler = mock.MagicMock(spec=AbstractRequestHandler) self.sb.add_request_handler(request_handler=mock_request_handler) assert self.sb.request_handlers[0] == mock_request_handler, ( "Add Request Handler method didn't add valid request handler to " "Skill Builder Request Handlers list") def test_add_null_exception_handler_throw_error(self): with self.assertRaises(SkillBuilderException) as exc: self.sb.add_exception_handler(exception_handler=None) assert "Valid Exception Handler instance to be provided" in str( exc.exception ), ("Add Exception Handler method didn't throw exception when a null " "exception handler is added") def test_add_invalid_exception_handler_throw_error(self): invalid_exception_handler = mock.Mock() with self.assertRaises(SkillBuilderException) as exc: self.sb.add_exception_handler( exception_handler=invalid_exception_handler) assert "Input should be an ExceptionHandler instance" in str( exc.exception), ( "Add Exception Handler method didn't throw exception when an " "invalid exception handler is added") def test_add_valid_exception_handler(self): mock_exception_handler = mock.MagicMock(spec=AbstractExceptionHandler) self.sb.add_exception_handler(exception_handler=mock_exception_handler) assert self.sb.exception_handlers[0] == mock_exception_handler, ( "Add Exception Handler method didn't add valid exception handler " "to Skill Builder Exception Handlers list") def test_add_null_global_request_interceptor_throw_error(self): with self.assertRaises(SkillBuilderException) as exc: self.sb.add_global_request_interceptor(request_interceptor=None) assert "Valid Request Interceptor instance to be provided" in str( exc.exception), ( "Add Global Request Interceptor method didn't throw exception " "when a null request interceptor is added") def test_add_invalid_global_request_interceptor_throw_error(self): invalid_request_interceptor = mock.Mock() with self.assertRaises(SkillBuilderException) as exc: self.sb.add_global_request_interceptor( request_interceptor=invalid_request_interceptor) assert "Input should be a RequestInterceptor instance" in str( exc.exception), ( "Add Global Request Interceptor method didn't throw exception " "when an invalid request interceptor is added") def test_add_valid_global_request_interceptor(self): mock_request_interceptor = mock.MagicMock( spec=AbstractRequestInterceptor) self.sb.add_global_request_interceptor( request_interceptor=mock_request_interceptor) assert self.sb.global_request_interceptors[0] == \ mock_request_interceptor, ( "Add Global Request Interceptor method didn't add valid request " "interceptor to Skill Builder " "Request Interceptors list") def test_add_null_global_response_interceptor_throw_error(self): with self.assertRaises(SkillBuilderException) as exc: self.sb.add_global_response_interceptor(response_interceptor=None) assert "Valid Response Interceptor instance to be provided" in str( exc.exception ), ("Add Global Response Interceptor method didn't throw exception " "when a null response interceptor is added") def test_add_invalid_global_response_interceptor_throw_error(self): invalid_response_interceptor = mock.Mock() with self.assertRaises(SkillBuilderException) as exc: self.sb.add_global_response_interceptor( response_interceptor=invalid_response_interceptor) assert "Input should be a ResponseInterceptor instance" in str( exc.exception ), ("Add Global Response Interceptor method didn't throw exception " "when an invalid response interceptor " "is added") def test_add_valid_global_response_interceptor(self): mock_response_interceptor = mock.MagicMock( spec=AbstractResponseInterceptor) self.sb.add_global_response_interceptor( response_interceptor=mock_response_interceptor) assert self.sb.global_response_interceptors[0] == \ mock_response_interceptor, ( "Add Global Response Interceptor method didn't add valid response " "interceptor to Skill Builder " "Response Interceptors list") def test_skill_configuration_getter_no_registered_components(self): actual_config = self.sb.skill_configuration assert actual_config.request_mappers is not None, ( "Skill Configuration getter in Skill Builder didn't set request " "mappers correctly") assert actual_config.request_mappers[ 0].request_handler_chains is not None, ( "Skill Configuration getter in Skill Builder didn't set handler " "chains in request mappers correctly") assert len( actual_config.request_mappers[0].request_handler_chains) == 0, ( "Skill Configuration getter in Skill Builder added invalid " "handler in handler chain, " "when no request handlers are registered") assert actual_config.handler_adapters is not None, ( "Skill Configuration getter in Skill Builder didn't set handler " "adapters correctly") assert isinstance(actual_config.handler_adapters[0], HandlerAdapter), ( "Skill Configuration getter in Skill Builder didn't set default " "handler adapter") assert actual_config.exception_mapper is None, ( "Skill Configuration getter in Skill Builder created invalid " "exception mapper, " "when no exception handlers are registered") assert actual_config.request_interceptors == [], ( "Skill Configuration getter in Skill Builder created invalid " "request interceptors, " "when no global request interceptors are registered") assert actual_config.response_interceptors == [], ( "Skill Configuration getter in Skill Builder created invalid " "response interceptors, " "when no global response interceptors are registered") assert actual_config.custom_user_agent is None, ( "Skill Configuration getter in Skill Builder set invalid custom " "user agent") assert actual_config.skill_id is None, ( "Skill Configuration getter in Skill Builder set invalid skill id") def test_skill_configuration_getter_handlers_registered(self): mock_request_handler = mock.MagicMock(spec=AbstractRequestHandler) self.sb.add_request_handler(request_handler=mock_request_handler) mock_exception_handler = mock.MagicMock(spec=AbstractExceptionHandler) self.sb.add_exception_handler(exception_handler=mock_exception_handler) actual_config = self.sb.skill_configuration assert actual_config.request_mappers is not None, ( "Skill Configuration getter in Skill Builder didn't set request " "mappers correctly") assert actual_config.request_mappers[ 0].request_handler_chains is not None, ( "Skill Configuration getter in Skill Builder didn't set handler " "chains in request mappers correctly") assert len( actual_config.request_mappers[0].request_handler_chains) == 1, ( "Skill Configuration getter in Skill Builder didn't add valid " "handler in handler chain, " "when request handlers are registered") assert actual_config.request_mappers[0].request_handler_chains[ 0].request_handler == mock_request_handler, ( "Skill Configuration getter in Skill Builder added invalid " "handler in handler chain, " "when request handlers are registered") assert actual_config.exception_mapper is not None, ( "Skill Configuration getter in Skill Builder didn't create " "exception mapper, " "when exception handlers are registered") assert len(actual_config.exception_mapper.exception_handlers) == 1, ( "Skill Configuration getter in Skill Builder added additional " "exception handlers than the registered ones " "in exception mapper") assert actual_config.exception_mapper.exception_handlers[ 0] == mock_exception_handler, ( "Skill Configuration getter in Skill Builder added invalid " "handler in exception mapper, " "when exception handlers are registered") def test_create_skill(self): mock_request_handler = mock.MagicMock(spec=AbstractRequestHandler) self.sb.add_request_handler(request_handler=mock_request_handler) mock_exception_handler = mock.MagicMock(spec=AbstractExceptionHandler) self.sb.add_exception_handler(exception_handler=mock_exception_handler) actual_skill = self.sb.create() expected_skill = Skill(self.sb.skill_configuration) assert actual_skill.request_dispatcher.request_mappers[0].request_handler_chains[0].request_handler == \ expected_skill.request_dispatcher.request_mappers[0].request_handler_chains[0].request_handler, ( "Skill Builder created skill with incorrect request handlers when " "using create method") assert actual_skill.request_dispatcher.exception_mapper.exception_handlers[0] == \ expected_skill.request_dispatcher.exception_mapper.exception_handlers[0], ( "Skill Builder created skill with incorrect exception handlers " "when using create method") def test_lambda_handler_creation(self): handler_func = self.sb.lambda_handler() assert callable(handler_func), "Skill Builder Lambda Handler " \ "function returned an invalid object" actual_arg_spec = inspect.getargspec(handler_func) assert len(actual_arg_spec.args) == 2, ( "Skill Builder Lambda Handler function created a handler of " "different signature than AWS Lambda") assert "event" in actual_arg_spec.args, ( "Skill Builder Lambda Handler function created a handler without " "named parameter event") assert "context" in actual_arg_spec.args, ( "Skill Builder Lambda Handler function created a handler without " "named parameter context") def test_lambda_handler_invocation(self): mock_request_handler = mock.MagicMock(spec=AbstractRequestHandler) mock_request_handler.can_handle.return_value = True mock_response = Response() mock_response.output_speech = "test output speech" mock_request_handler.handle.return_value = mock_response self.sb.add_request_handler(request_handler=mock_request_handler) mock_request_envelope_payload = { "context": { "System": { "application": { "applicationId": "test" } } } } self.sb.skill_id = "test" lambda_handler = self.sb.lambda_handler() response_envelope = lambda_handler(event=mock_request_envelope_payload, context=None) assert response_envelope["version"] == RESPONSE_FORMAT_VERSION, ( "Response Envelope from lambda handler invocation has version " "different than expected") assert response_envelope["userAgent"] == user_agent_info( custom_user_agent=None ), ("Response Envelope from lambda handler invocation has user agent " "info different than expected") assert response_envelope["response"][ "outputSpeech"] == "test output speech", ( "Response Envelope from lambda handler invocation has incorrect " "response than built by skill") def test_request_handler_decorator_creation(self): request_handler_wrapper = self.sb.request_handler(can_handle_func=None) assert callable(request_handler_wrapper), ( "Skill Builder Request Handler decorator returned an invalid " "wrapper object") actual_arg_spec = inspect.getargspec(request_handler_wrapper) assert len(actual_arg_spec.args) == 1, ( "Skill Builder Request Handler decorator created a wrapper of " "different signature than expected") assert "handle_func" in actual_arg_spec.args, ( "Skill Builder Request Handler decorator created a wrapper " "without named parameter handler_func") def test_request_handler_decorator_invalid_can_handle_func(self): request_handler_wrapper = self.sb.request_handler(can_handle_func=None) with self.assertRaises(SkillBuilderException) as exc: request_handler_wrapper(handle_func=None) assert "can_handle_func and handle_func input parameters should be callable" in str( exc.exception), ( "Request Handler Decorator accepted invalid can_handle_func " "parameter") def test_request_handler_decorator_invalid_handle_func(self): request_handler_wrapper = self.sb.request_handler( can_handle_func=lambda x: True) with self.assertRaises(SkillBuilderException) as exc: request_handler_wrapper(handle_func=None) assert "can_handle_func and handle_func input parameters should be callable" in str( exc.exception), ( "Request Handler Decorator was decorated on an invalid object") def test_request_handler_decorator_on_valid_handle_func(self): def test_can_handle(input): return True def test_handle(input): return "something" self.sb.request_handler(can_handle_func=test_can_handle)( handle_func=test_handle) actual_request_handler = self.sb.request_handlers[0] assert actual_request_handler.__class__.__name__ == "RequestHandlerTestHandle", ( "Request Handler decorator created Request Handler of incorrect " "name") assert actual_request_handler.can_handle(None) is True, ( "Request Handler decorator created Request Handler with incorrect " "can_handle function") assert actual_request_handler.handle(None) == "something", ( "Request Handler decorator created Request Handler with incorrect " "handle function") def test_request_handler_decorator_on_can_handle_func_with_incorrect_params( self): def test_can_handle(): return True def test_handle(input): return "something" with self.assertRaises(SkillBuilderException) as exc: self.sb.request_handler(can_handle_func=test_can_handle)( handle_func=test_handle) assert "can_handle_func should only accept a single input arg, handler input" in str( exc.exception), ( "Request Handler Decorator accepted invalid can_handle_func " "parameter") def test_request_handler_decorator_on_handle_func_with_incorrect_params( self): def test_can_handle(input): return True def test_handle(*args, **kwargs): return "something" with self.assertRaises(SkillBuilderException) as exc: self.sb.request_handler(can_handle_func=test_can_handle)( handle_func=test_handle) assert "handle_func should only accept a single input arg, handler input" in str( exc.exception), ( "Request Handler Decorator was decorated with invalid " "handle_func which takes more than one input args") def test_exception_handler_decorator_creation(self): exception_handler_wrapper = self.sb.exception_handler( can_handle_func=None) assert callable(exception_handler_wrapper), ( "Skill Builder Exception Handler decorator returned an invalid " "wrapper object") actual_arg_spec = inspect.getargspec(exception_handler_wrapper) assert len(actual_arg_spec.args) == 1, ( "Skill Builder Exception Handler decorator created a wrapper of " "different signature than expected") assert "handle_func" in actual_arg_spec.args, ( "Skill Builder Exception Handler decorator created a wrapper " "without named parameter handler_func") def test_exception_handler_decorator_invalid_can_handle_func(self): exception_handler_wrapper = self.sb.exception_handler( can_handle_func=None) with self.assertRaises(SkillBuilderException) as exc: exception_handler_wrapper(handle_func=None) assert "can_handle_func and handle_func input parameters should be callable" in str( exc.exception), ( "Exception Handler Decorator accepted invalid can_handle_func " "parameter") def test_exception_handler_decorator_invalid_handle_func(self): exception_handler_wrapper = self.sb.exception_handler( can_handle_func=lambda x: True) with self.assertRaises(SkillBuilderException) as exc: exception_handler_wrapper(handle_func=None) assert "can_handle_func and handle_func input parameters should be callable" in str( exc.exception ), ("Exception Handler Decorator was decorated on an invalid object") def test_exception_handler_decorator_on_valid_handle_func(self): def test_can_handle(input, exc): return True def test_handle(input, exc): return "something" self.sb.exception_handler(can_handle_func=test_can_handle)( handle_func=test_handle) actual_exception_handler = self.sb.exception_handlers[0] assert actual_exception_handler.__class__.__name__ == "ExceptionHandlerTestHandle", ( "Exception Handler decorator created Exception Handler of incorrect name" ) assert actual_exception_handler.can_handle(None, None) is True, ( "Exception Handler decorator created Exception Handler with " "incorrect can_handle function") assert actual_exception_handler.handle(None, None) == "something", ( "Exception Handler decorator created Exception Handler with " "incorrect handle function") def test_exception_handler_decorator_on_can_handle_func_with_incorrect_params( self): def test_can_handle(*args): return True def test_handle(input, exc): return "something" with self.assertRaises(SkillBuilderException) as exc: self.sb.exception_handler(can_handle_func=test_can_handle)( handle_func=test_handle) assert "can_handle_func should only accept two input args, handler input and exception" in str( exc.exception), ( "Exception Handler Decorator accepted invalid can_handle_func " "parameter") def test_exception_handler_decorator_on_handle_func_with_incorrect_params( self): def test_can_handle(input, exc): return True def test_handle(exc, **kwargs): return "something" with self.assertRaises(SkillBuilderException) as exc: self.sb.exception_handler(can_handle_func=test_can_handle)( handle_func=test_handle) assert "handle_func should only accept two input args, handler input and exception" in str( exc.exception), ( "Exception Handler Decorator was decorated with invalid " "handle_func which takes more than two input args") def test_global_request_interceptor_decorator_creation(self): request_interceptor_wrapper = self.sb.global_request_interceptor() assert callable(request_interceptor_wrapper), ( "Skill Builder Global Request Interceptor decorator returned an " "invalid wrapper object") actual_arg_spec = inspect.getargspec(request_interceptor_wrapper) assert len(actual_arg_spec.args) == 1, ( "Skill Builder Global Request Interceptor decorator created a " "wrapper of different signature than expected") assert "process_func" in actual_arg_spec.args, ( "Skill Builder Global Request Interceptor decorator created a " "wrapper without named parameter process_func") def test_global_request_interceptor_decorator_invalid_process_func(self): request_interceptor_wrapper = self.sb.global_request_interceptor() with self.assertRaises(SkillBuilderException) as exc: request_interceptor_wrapper(process_func=None) assert "process_func input parameter should be callable" in str( exc.exception ), ("Global Request Interceptor Decorator accepted invalid process_func parameter" ) def test_global_request_interceptor_decorator_on_valid_process_func(self): def test_process(input): return "something" self.sb.global_request_interceptor()(process_func=test_process) actual_global_request_interceptor = self.sb.global_request_interceptors[ 0] assert actual_global_request_interceptor.__class__.__name__ == "RequestInterceptorTestProcess" assert actual_global_request_interceptor.process(None) == "something" def test_global_request_interceptor_on_process_func_with_incorrect_params( self): def test_process(**kwargs): return "something" with self.assertRaises(SkillBuilderException) as exc: self.sb.global_request_interceptor()(process_func=test_process) assert "process_func should only accept a single input arg, handler input" in str( exc.exception ), ("Global Request Interceptor Decorator was decorated with invalid " "process_func which takes more than " "one input args") def test_global_response_interceptor_decorator_creation(self): response_interceptor_wrapper = self.sb.global_response_interceptor() assert callable(response_interceptor_wrapper), ( "Skill Builder Global Request Interceptor decorator returned an " "invalid wrapper object") actual_arg_spec = inspect.getargspec(response_interceptor_wrapper) assert len(actual_arg_spec.args) == 1, ( "Skill Builder Global Response Interceptor decorator created a " "wrapper of different signature than " "expected") assert "process_func" in actual_arg_spec.args, ( "Skill Builder Global Response Interceptor decorator created a " "wrapper without named parameter " "process_func") def test_global_response_interceptor_decorator_invalid_process_func(self): response_interceptor_wrapper = self.sb.global_response_interceptor() with self.assertRaises(SkillBuilderException) as exc: response_interceptor_wrapper(process_func=None) assert "process_func input parameter should be callable" in str( exc.exception), ( "Global Response Interceptor Decorator accepted invalid " "process_func parameter") def test_global_response_interceptor_decorator_on_valid_process_func(self): def test_process(input, response): return "something" self.sb.global_response_interceptor()(process_func=test_process) actual_global_response_interceptor = self.sb.global_response_interceptors[ 0] assert actual_global_response_interceptor.__class__.__name__ == "ResponseInterceptorTestProcess" assert actual_global_response_interceptor.process(None, None) == "something" def test_global_response_interceptor_on_process_func_with_incorrect_params( self): def test_process(**kwargs): return "something" with self.assertRaises(SkillBuilderException) as exc: self.sb.global_response_interceptor()(process_func=test_process) assert "process_func should only accept two input args, handler input and response" in str( exc.exception ), ("Global Response Interceptor Decorator was decorated with invalid " "process_func which takes more than " "one input args")
speech = "Sorry, I didn't get it. Can you please say it again!!" handler_input.response_builder.speak(speech).ask(speech) return handler_input.response_builder.response class SaveSessionAttributesResponseInterceptor(AbstractResponseInterceptor): """ Response interceptors are invoked immediately after execution of the request handler for an incoming request. """ def process(self, handler_input, response): print("Response generated: {}".format(response)) handler_input.attributes_manager.session_attributes = categories.get_session_attributes() sb.add_request_handler(LaunchRequestHandler()) sb.add_request_handler(CountryIntentHandler()) sb.add_request_handler(HelpIntentHandler()) sb.add_request_handler(CancelAndStopIntentHandler()) sb.add_request_handler(SessionEndedRequestHandler()) sb.add_global_request_interceptor(SetupRequestInterceptor()) sb.add_global_response_interceptor(SaveSessionAttributesResponseInterceptor()) sb.add_exception_handler(AllExceptionHandler()) lambda_handler = sb.lambda_handler()
return # The SkillBuilder object acts as the entry point for your skill, routing all request and response # payloads to the handlers above. Make sure any new handlers or interceptors you've # defined are included below. The order matters - they're processed top to bottom. sb = SkillBuilder() sb = CustomSkillBuilder(persistence_adapter=dynamodb_adapter) # Interceptors sb.add_global_request_interceptor( LoadPersistenceAttributesRequestInterceptor()) sb.add_global_response_interceptor( SavePersistenceAttributesResponseInterceptor()) sb.add_request_handler(LaunchRequestHandler()) sb.add_request_handler(HelpIntentHandler()) sb.add_request_handler(AudioPlayIntentHandler()) sb.add_request_handler(AudioStopIntentHandler()) sb.add_request_handler(NextPlaybackHandler()) sb.add_request_handler(PreviousPlaybackHandler()) sb.add_request_handler(StartOverHandler()) # ########## AUDIOPLAYER INTERFACE HANDLERS ######################### sb.add_request_handler(PlaybackStartedHandler()) sb.add_request_handler(PlaybackFinishedHandler()) sb.add_request_handler(PlaybackStoppedHandler()) sb.add_request_handler(PlaybackNearlyFinishedHandler()) sb.add_request_handler(PlaybackFailedHandler())