def remote_endpoint( self, endpoint_url: str, endpoint_method: str = RemoteEndpoint.METHOD_POST) -> None: raise_if_variable_not_expected_type(value=endpoint_url, expected_type=endpoint_url, variable_name="endpoint_url") raise_if_value_not_in_list( value=endpoint_method, list_object=self.RemoteEndpoint.AVAILABLE_METHODS, variable_name="endpoint_method") self._remote_endpoint = self.RemoteEndpoint
def playerActivity(self, playerActivity: str) -> None: raise_if_value_not_in_list( value=playerActivity, list_object=self.AVAILABLE_PLAYER_ACTIVITIES, variable_name="playerActivity") self._playerActivity = playerActivity
def clearBehavior(self, clearBehavior: str) -> None: raise_if_value_not_in_list(value=clearBehavior, list_object=self.AVAILABLE_CLEAR_BEHAVIORS, variable_name="clearBehavior") self._clearBehavior = clearBehavior
def playBehavior(self, playBehavior: str) -> None: raise_if_value_not_in_list(value=playBehavior, list_object=self.AVAILABLE_PLAY_BEHAVIORS, variable_name="playBehavior") self._playBehavior = playBehavior
def type(self, type_value: str) -> None: raise_if_value_not_in_list(value=type_value, list_object=self.AVAILABLE_TYPES, variable_name="type") self._type = type_value
def process_request(self): output_event = None handler_to_use = None handler_is_an_alone_callback_function = False handler_is_an_audioplayer_handlers_group = False handler_is_a_then_state_handler = False handler_is_a_request_handler = False # Steps of priority # First, if the request is an interactive option made by the user if self.handler_input.is_option_select_request: # todo: rename is_option_select_request to need_to_be_handled_by_callback infos_callback_function_to_use = self.handler_input.interactivity_callback_functions.get( self.handler_input.selected_option_identifier).to_safedict( default=None) if infos_callback_function_to_use is not None: from inoft_vocal_framework.skill_builder.utils import get_function_or_class_from_file_and_path handler_to_use = get_function_or_class_from_file_and_path( file_filepath=infos_callback_function_to_use.get( "file_filepath_containing_callback").to_str(), path_qualname=infos_callback_function_to_use.get( "callback_function_path").to_str()) if handler_to_use is not None: handler_is_an_alone_callback_function = True # Second, Alexa Audio Player if self.handler_input.is_alexa_v1: if self.handler_input.alexaHandlerInput.context.audioPlayer.token is not None: last_used_audioplayer_handlers_group_infos = self.handler_input.alexaHandlerInput.get_last_used_audioplayer_handlers_group( ) from inoft_vocal_framework.skill_builder.utils import get_function_or_class_from_file_and_path audioplayer_handlers_group_class_type = get_function_or_class_from_file_and_path( file_filepath=last_used_audioplayer_handlers_group_infos. get("fileFilepathContainingClass").to_str(), path_qualname=last_used_audioplayer_handlers_group_infos. get("classPath").to_str()) if audioplayer_handlers_group_class_type is not None: raise_if_value_not_in_list( value=InoftHandlersGroup, list_object=list( audioplayer_handlers_group_class_type.__bases__), variable_name="audioplayer_handlers_group_class_type") class_kwargs = last_used_audioplayer_handlers_group_infos.get( "classKwargs").to_dict() class_kwargs["parent_handler"] = self handler_to_use = audioplayer_handlers_group_class_type( **class_kwargs) # When using an audioplayer handlers group, we will call its handle function (it will try every one of its # handler, until he found one that return an output). If the output is None (no function out of every function # of the audioplayer handlers group has returned something), then we will set back the handler_to_use to None, # so that the others more traditional handlers can have a chance to be use (if we did not do that, and that # no event was returned, the response would be the default fallback right away). # The reason we do all of that, is that if the AudioPlayer object is present, but not in a state that is # supported by the app trough a can_handle function (like if it is stopped, and no can_handle function of # any class is triggered by the current state of the AudioPlayer), then we will not be able to give an # interactive experience with the AudioPlayer, which translate into our output_event being None. output_event = handler_to_use.handle() if output_event is not None: handler_is_an_audioplayer_handlers_group = True else: handler_to_use = None # Third, if the invocation is a new session, and a session can be resumed, we resume the last intent of the previous session if self.handler_input.is_invocation_new_session is True and self.handler_input.session_been_resumed is True: last_intent_handler_class_key_name = self.handler_input.session_remember( "lastIntentHandler") if last_intent_handler_class_key_name in self.request_handlers_chain.keys( ): handler_to_use = self.request_handlers_chain[ last_intent_handler_class_key_name] elif last_intent_handler_class_key_name in self.state_handlers_chain.keys( ): handler_to_use = self.state_handlers_chain[ last_intent_handler_class_key_name] # Fourth, loading of the then_state in the session if handler_to_use is None: last_then_state_class_name = self.handler_input.remember_session_then_state( ) if last_then_state_class_name is not None: if last_then_state_class_name in self.state_handlers_chain.keys( ): handler_to_use = self.state_handlers_chain[ last_then_state_class_name] handler_is_a_then_state_handler = True self.handler_input.forget_session_then_state() else: logging.warning( f"A thenState class name ({last_then_state_class_name}) was not None and has" f" not been found in the available classes : {self.state_handlers_chain}" ) # Fifth, classical requests handlers if handler_to_use is None: for request_handler in self.request_handlers_chain.values(): if request_handler.can_handle() is True: handler_to_use = request_handler handler_is_a_request_handler = True break else: logging.debug( f"Not handled by : {request_handler.__class__}") if handler_to_use is not None: if handler_is_an_alone_callback_function is True: output_event = handler_to_use( self.handler_input, self.handler_input.selected_option_identifier) if output_event is not None: logging.debug( f"Successfully resumed by {handler_to_use} which returned {output_event}" ) else: logging.info( f"A callback function has been found {handler_to_use}. But nothing was returned," f" did you called the return self.to_platform_dict() function ?" ) if output_event is None and self.handler_input.session_been_resumed is True: logging.debug( f"Handled and resumed by : {handler_to_use.__class__}") output_event = handler_to_use.handle_resume() if output_event is None: logging.debug( f"Handled classically by : {handler_to_use.__class__}") output_event = handler_to_use.handle() if handler_is_a_then_state_handler is True and output_event is None: # If the handle function of the a then_state handler do not return anything, we call its fallback # function, and we set back the then_state to the session attributes (we do so before calling # the fallback, in case the fallback function changed the then_state) self.handler_input.memorize_session_then_state( state_handler_class_type_or_name= last_then_state_class_name) output_event = handler_to_use.fallback() if output_event is not None: if handler_is_an_alone_callback_function is False and handler_is_an_audioplayer_handlers_group is False: # If the response is handled by a function, we do not save it as the last intent (we cannot actually, # and it would not make sense anyway). So we will keep the previous last intent as the new last intent. # We do the same thing it is handler by an audioplayer handlers group (since it is used to handle interactions too) self.handler_input.memorize_session_last_intent_handler( handler_class_type_instance_name=handler_to_use) else: logging.debug( f"Handler by default fallback : {self.default_fallback_handler}" ) output_event = self.default_fallback_handler.handle() self.handler_input.save_attributes_if_need_to() print(f"output_event = {output_event}") wrapped_output_event = LambdaResponseWrapper( response_dict=output_event).get_wrapped( handler_input=self.handler_input) return wrapped_output_event