def iam_role(self) -> SafeDict: if self._iam_role is None: try: self._iam_role = SafeDict(self.iam.get_role(RoleName=self.role_name)["Role"]) except botocore.exceptions.ClientError: # If a ClientError happened while getting the role, it means he do not exist. logging.debug(f"Creating {self.role_name} IAM Role..") attach_policy_obj = json.loads(self.attach_policy) assume_policy_obj = json.loads(self.assume_policy) self._iam_role = SafeDict(self.iam.create_role(RoleName=self.role_name, AssumeRolePolicyDocument=self.assume_policy)["Role"]) # create or update the role's policies if needed policy = self.iam_resource.RolePolicy(self.role_name, "inoft-vocal-permissions") try: if policy.policy_document != attach_policy_obj: logging.debug(f"Updating inoft-vocal-permissions policy on {self.role_name} IAM Role.") policy.put(PolicyDocument=self.attach_policy) except botocore.exceptions.ClientError: logging.debug(f"Creating inoft-vocal-permissions policy on {self.role_name} IAM Role.") policy.put(PolicyDocument=self.attach_policy) role_policy_dict = self._iam_role.get("AssumeRolePolicyDocument").to_dict() if role_policy_dict != assume_policy_obj: if (SafeDict(role_policy_dict["Statement"][0]).get("Principal").get("Service").to_any() != assume_policy_obj["Statement"][0]["Principal"]["Service"]): logging.debug(f"Updating assume role policy on {self.role_name} IAM Role.") self.iam_client.update_assume_role_policy(RoleName=self.role_name, PolicyDocument=self.assume_policy) return self._iam_role
def create_and_setup_api_routes(self, api_id: str, lambda_arn: str): integration_creation_response = SafeDict(self.api_gateway_client.create_integration(ApiId=api_id, IntegrationType="AWS_PROXY", PayloadFormatVersion="2.0", IntegrationUri=lambda_arn, TimeoutInMillis=10000)) integration_id = integration_creation_response.get("IntegrationId").to_str(default=None) if integration_id is None: raise Exception(f"Error while creating the route integration of the api towards the lambda_function." f"The integration_id was not found in the integration creation response." f"Please delete the api and redo the deployment." f"If the issue persist, create an Issue topic on the github page of the framework.") route_names = ["amazonAlexaV1", "googleAssistantDialogflowV1", "samsungBixbyV1", "appleSiriV1"] route_names_to_settings_keys = {"amazonAlexaV1": "alexaApiEndpointUrlNotRecommendedToUse", "googleAssistantDialogflowV1": "googleAssistantApiEndointUrl", "samsungBixbyV1": "samsungBixbyApiEndointUrl", "appleSiriV1": "siriApiEndointUrl"} api_gateway_root_url = self.api_gateway_v2_url(api_id=api_id) for route_name in route_names: self.boto_session.get_credentials() response = self.api_gateway_client.create_route( ApiId=api_id, AuthorizationType="None", RouteKey=f"ANY /{route_name}", # A space is required between the HTTP method and the / Target=f"integrations/{integration_id}", ) self.add_lambda_permission_to_call_api_resource(lambda_arn=lambda_arn, api_id=api_id, route_key=route_name) api_route_url = f"{api_gateway_root_url}/{route_name}" click.echo(f"Api route {click.style(route_name, fg='green')} creation complete accessible on {api_route_url}") self.settings.settings.get_set("deployment", {}).get_set("endpoints", {}).put( route_names_to_settings_keys[route_name], api_route_url).reset_navigated_dict()
def session_attributes(self) -> SafeDict: if not isinstance(self._session_attributes, SafeDict): if isinstance(self.session.attributes, dict): self._session_attributes = SafeDict(self.session.attributes) else: self._session_attributes = SafeDict() return self._session_attributes
def create_api_gateway(self, lambda_arn: str, lambda_name: str, description: str = None) -> str: # todo: fix bug if id of api gateway is present in file, but the api has been deleted, it will not try to recreate it api_name = lambda_name or lambda_arn.split(":")[-1] api_creation_response = SafeDict(self.api_gateway_client.create_api(Name=api_name, Description=description or self.default_description, Target=lambda_arn, ProtocolType="HTTP")) api_id = api_creation_response.get("ApiId").to_str() self.create_and_setup_api_routes(api_id=api_id, lambda_arn=lambda_arn) return api_id
def _load_smart_session_user_data(self): # We use a separate function to load the smart session user data, and we do not include it in the property itself, # because this function can be called by the smart_session_user_data property or the session_been_resumed property. if self._smart_session_user_data is None: if self.sessions_users_data_disable_database is False: self._smart_session_user_data, self._session_been_resumed = self.dynamodb_adapter.get_smart_session_attributes( user_id=self.persistent_user_id, session_id=self.session_id, timeout_seconds=self.default_session_data_timeout) if not isinstance(self._smart_session_user_data, SafeDict): self._smart_session_user_data = SafeDict() else: self._smart_session_user_data = SafeDict() logging.debug(f"_smart_session_user_data = {self._smart_session_user_data}")
def persistent_user_data(self) -> SafeDict: if self._persistent_user_data is None: if self.sessions_users_data_disable_database is False: self._persistent_user_data = self.dynamodb_adapter.get_persistent_attributes(user_id=self.persistent_user_id) if not isinstance(self._persistent_user_data, SafeDict): self._persistent_user_data = SafeDict() logging.debug(f"_persistent_user_data = {self._persistent_user_data}") return self._persistent_user_data
def settings(self) -> SafeDict: if Settings.settings_loaded is not True: if self.raise_if_not_loaded is True: raise Exception( f"The settings have not yet been loaded and are : {Settings.settings}" ) else: Settings._settings = SafeDict() return Settings._settings
def simple_session_user_data(self) -> SafeDict: for output_context in self.request.queryResult.outputContexts: if isinstance(output_context, dict) and "name" in output_context.keys( ) and "parameters" in output_context.keys(): all_texts_after_slash = output_context["name"].split("/") last_text_after_slash = all_texts_after_slash[ len(all_texts_after_slash) - 1] if str(last_text_after_slash).lower() == "sessiondata": # We lower the text, to make sure that it will work even if the cases have been lowered. Because for some reasons, # google is lowering the keys, so even if the key in the framework os sessionData, google might return sessiondata. parameters_stringed_dict_or_dict = output_context[ "parameters"] if parameters_stringed_dict_or_dict is not None: if isinstance(parameters_stringed_dict_or_dict, str): parameters_stringed_dict_or_dict = json_loads( parameters_stringed_dict_or_dict) if isinstance(parameters_stringed_dict_or_dict, dict): # The data key contains an stringed dictionary of the data we are interested by. if "data" in parameters_stringed_dict_or_dict.keys( ): parameters_stringed_dict_or_dict = parameters_stringed_dict_or_dict[ "data"] if isinstance(parameters_stringed_dict_or_dict, str): parameters_stringed_dict_or_dict = json_loads( parameters_stringed_dict_or_dict) if isinstance(parameters_stringed_dict_or_dict, dict): self._simple_session_user_data = SafeDict( parameters_stringed_dict_or_dict) else: self._simple_session_user_data = SafeDict() else: raise Exception( f"parameters_stringed_dict_or_dict was nto None, not a str, dict and could" f"not be json converted to a dict : {parameters_stringed_dict_or_dict}" ) if not isinstance(self._simple_session_user_data, SafeDict): self._simple_session_user_data = SafeDict() return self._simple_session_user_data
def settings(self, settings_dict: dict): validator = self.ExtendedValidator() is_valid = validator.validate(settings_dict, self._settings_file_validator_schema) if is_valid is not True: raise Exception( f"The settings file was not valid. Please modify it or recreate it : {validator.errors}" ) else: Settings._settings = SafeDict(settings_dict) Settings.settings_loaded = True
def _fetch_attributes(self, user_id: str) -> SafeDict: try: response = self.dynamodb.get_item( TableName=self.table_name, Key={"id": self.utils.python_to_dynamodb(user_id)}, ConsistentRead=True) if "Item" in response: return SafeDict(self.utils.dynamodb_to_python( response["Item"])) else: return SafeDict() except ResourceNotExistsError: raise Exception( f"DynamoDb table {self.table_name} do not exist or in the process" "of being created. Failed to get attributes from DynamoDb table." ) except Exception as e: raise Exception( f"Failed to retrieve attributes from DynamoDb table." f"Exception of type {type(e).__name__} occurred: {str(e)}")
def persistent_user_id(self) -> str: if not isinstance(self._persistent_user_id, str) or (self._persistent_user_id.replace(" ", "") == ""): if self.is_alexa_v1 is True: user_id = SafeDict(self.alexaHandlerInput.session.user).get("userId").to_str(default=None) elif self.is_dialogflow_v1 is True: user_id = self.dialogFlowHandlerInput.user_id elif self.is_bixby_v1 is True: user_id = self.bixbyHandlerInput.request.context.userId if not isinstance(user_id, str) or user_id.replace(" ", "") == "": from inoft_vocal_framework.utils.general import generate_uuid4 self._persistent_user_id = generate_uuid4() # We need to set the persistent_user_id before memorizing it, because the memorize function will access the # persistent_user_data, and if the user_id is not set, we will get stuck in an infinite recursion loop self.persistent_memorize("userId", user_id) print(f"user_id {self._persistent_user_id} has been memorized in the database.") else: self._persistent_user_id = user_id logging.debug(f"_persistent_user_id = {self._persistent_user_id}") return self._persistent_user_id
class LaunchRequestHandler: CLASS_TYPE = "RequestHandler" def __init__(self, node_dict: dict): self.node_safedict = SafeDict(node_dict) self.node_name = self.node_safedict.get("name").to_str() self.class_name = to_class_name(self.node_name) self.code = None self.state_handler_class = None def process(self, parent_core: Core): next_paths = self.node_safedict.get("next").to_list() if len(next_paths) > 0: self.state_handler_class = StateHandler(node_name=self.node_name) for path in next_paths: self.state_handler_class.next_paths.append( path) # all_nodes_classes_dict[next_paths[0]["name"]] def render( self, parent_core: Core): # dict, parent_all_nodes_classes_dict: dict): created_classes = list() next_state_handler_class = None if self.state_handler_class is not None: state_handler = StateHandler(node_name=self.node_name) state_handler.process(parent_core=parent_core) state_handler.render(parent_core=parent_core) created_classes.append(state_handler) next_state_handler_class = f"{self.class_name}StateHandler" self.code = TemplatesAccess().launch_request_handler_template.render( class_name=self.class_name, node_name=self.node_name, next_state_handler_class=next_state_handler_class, code_elements=parent_core.process_on_enter( self.node_safedict.get("onEnter").to_list())) created_classes.insert(0, self) # We always want for the request handler to be the first element in the classes. return created_classes
def simple_session_user_data(self) -> SafeDict: if self._simple_session_user_data is None: if self.is_alexa_v1 is True: self._simple_session_user_data = self.alexaHandlerInput.session_attributes elif self.is_dialogflow_v1 is True: self._simple_session_user_data = self.dialogFlowHandlerInput.simple_session_user_data elif self.is_bixby_v1 is True: print("simple_session_user_data is not implemented for the bixby platform.") if not isinstance(self._simple_session_user_data, SafeDict): self._simple_session_user_data = SafeDict() return self._simple_session_user_data
def __init__(self): self._queryText = str() self._action = str() self._parameters = SafeDict() self._allRequiredParamsPresent = bool() self._fulfillmentText = str() self._fulfillmentMessages = list() self._outputContexts = list() self._intent = Intent() self._intentDetectionConfidence = int() self._diagnosticInfo = dict() self._languageCode = str()
def process_paths(self, parent_core: Core, paths: list) -> list: processed_paths = list() for i, path in enumerate(paths): path = SafeDict(path) path_condition = path.get("condition").to_str(default=None) path_target_node_name = path.get("node").to_str(default=None) if path_condition is not None and path_target_node_name is not None: current_path_instance = StateHandler.Path( path_index=i, condition=path_condition, target_node_name=path_target_node_name) no_code_generated_for_path = current_path_instance.process( parent_core=parent_core) if no_code_generated_for_path is False: processed_paths.append(current_path_instance) else: print( f"\nWarning ! The node {self.node_name} had a condition {path_condition} that did not generated any code." ) if path_target_node_name == "": print( "It is likely because you did not define a target node for this condition." ) else: print( f"Yet you defined a target node. There is something fishy, you should look in botpress what is strange about the node {self.node_name}" ) if current_path_instance.condition_type == self.Path.CONDITION_TYPE_INTENT_NAME: if current_path_instance.condition_intent_name in self.counts_used_condition_intent_names.keys( ): self.counts_used_condition_intent_names[ current_path_instance.condition_intent_name] += 1 else: self.counts_used_condition_intent_names[ current_path_instance.condition_intent_name] = 1 return processed_paths
def get_smart_session_attributes(self, user_id: str, session_id: str, timeout_seconds: int) -> (SafeDict, bool): # If the value from get_field is of dict or list type, the SafeDict will be populated, otherwise it will be empty without errors. timeout_expired = True last_session_id = self.get_field(user_id=user_id, field_key="lastSessionId") if session_id == last_session_id: timeout_expired = False else: last_interaction_time = self.get_field( user_id=user_id, field_key="lastInteractionTime") if last_interaction_time is not None and time.time( ) <= last_interaction_time + timeout_seconds: timeout_expired = False if timeout_expired is False: return SafeDict( self.get_field( user_id=user_id, field_key=self.smart_session_attributes_key_name)), True else: return SafeDict(), False
def persistent_user_id(self) -> str: if not isinstance(self._persistent_user_id, str) or ( not (len(self._persistent_user_id.replace(" ", "")) > 0)): user_id: Optional[str] = None if self.is_alexa is True: user_id = SafeDict( self.alexaHandlerInput.session.user).get('userId').to_str( default=None) elif self.is_dialogflow is True: user_id = self.dialogFlowHandlerInput.get_user_id() elif self.is_bixby is True: user_id = self.bixbyHandlerInput.request.context.userId elif self.is_discord is True: user_id = self.discordHandlerInput.request.author.id if user_id is None or not isinstance( user_id, str) or not (len(user_id.replace(" ", "")) > 0): self._persistent_user_id = self.settings.user_data_plugin.register_new_user( ) else: self._persistent_user_id = user_id logging.debug(f"_persistent_user_id = {self._persistent_user_id}") return self._persistent_user_id
def process(self): for message_dict in self.input_messages_items: message_dict = SafeDict(message_dict) speech_items = list() # todo: make multilang (might require the premium version of botpress) main_speech_dict = message_dict.get("formData").to_dict() for key, value in main_speech_dict.items(): if "text" in key: if value is not None and value != "": speech_items.append(prettify_speech_text(value)) if "variations" in key: if isinstance(value, list): for speech_variation in value: if speech_variation is not None and speech_variation != "": speech_items.append( prettify_speech_text(value)) message_item = self.MessageItem( id_value=message_dict.get("id").to_str(), speech_items=speech_items) self.output_messages_dict[message_item.id] = message_item
def __init__(self, identifier: str, audio_item_dict: dict = None): self.identifier = identifier if audio_item_dict is not None: if isinstance(audio_item_dict, dict): audio_item_dict = SafeDict(audio_item_dict) if not isinstance(audio_item_dict, SafeDict): raise Exception( f"The audio_item_dict must be of type dict or SafeDict but was {type(audio_item_dict)}: {audio_item_dict}" ) self.mp3_file_url = audio_item_dict.get("url").to_str() self.title = audio_item_dict.get("title").to_str() self.subtitle = audio_item_dict.get("subtitle").to_str() self.offset_in_milliseconds = audio_item_dict.get( "offsetInMilliseconds").to_int() self.icon_image_url = audio_item_dict.get("iconImageUrl").to_str() self.background_image_url = audio_item_dict.get( "backgroundImageUrl").to_str()
def handle_any_platform(self, event: dict, context: dict): print(f"Event = {json_dumps(event)}\nContext = {context}") self.check_everything_implemented() event_safedict = SafeDict(classic_dict=event) # The 'rawPath' is for ApiGatewayV2, use the key 'resource' (without the comma) if using ApiGatewayV1 if event_safedict.get( "rawPath").to_str() == "/googleAssistantDialogflowV1": # A google-assistant or dialogflow request always pass trough an API gateway self.handler_input.is_dialogflow_v1 = True event = NestedObjectToDict.get_dict_from_json( event_safedict.get("body").to_str()) elif event_safedict.get("rawPath").to_str() == "/samsungBixbyV1": # A samsung bixby request always pass trough an API gateway self.handler_input.is_bixby_v1 = True from urllib import parse event = { "context": NestedObjectToDict.get_dict_from_json( stringed_json_dict=event_safedict.get("body").to_str()) ["$vivContext"], "parameters": dict( parse.parse_qsl( event_safedict.get("rawQueryString").to_str())) } elif "amzn1." in event_safedict.get("context").get("System").get( "application").get("applicationId").to_str(): # Alexa always go last, since it do not pass trough an api resource, its a less robust identification than the other platforms. self.handler_input.is_alexa_v1 = True else: from inoft_vocal_framework.messages import ERROR_PLATFORM_NOT_SUPPORTED raise Exception(ERROR_PLATFORM_NOT_SUPPORTED) self.handler_input.load_event(event=event) return self.process_request()
def api_gateway_v2_url(self, api_id: str): try: return SafeDict(self.api_gateway_client.get_api(ApiId=api_id)).get("ApiEndpoint").to_str(default=None) except Exception as e: return False
def get_lambda_function_arn(self, function_name: str): return SafeDict(self.lambda_client.get_function(FunctionName=function_name)).get("Configuration").get("FunctionArn").to_str()
class Core(CoreClients): def __init__(self): # , pool: ThreadPoolExecutor): super().__init__() self.settings = Settings() self.tags = {"framework": "InoftVocalFramework"} self._iam_role = None self._credentials_arn = None self._aws_account_id = None self._session_unix_time = None self._session_count_created_statement_ids = 0 self.role_name = "InoftVocalFrameworkLambdaExecution" self.http_methods = ['ANY'] self.default_description = "Created with the Inoft Vocal Framework" def get_lambda_function_arn(self, function_name: str): return SafeDict(self.lambda_client.get_function(FunctionName=function_name)).get("Configuration").get("FunctionArn").to_str() def api_gateway_v2_url(self, api_id: str): try: return SafeDict(self.api_gateway_client.get_api(ApiId=api_id)).get("ApiEndpoint").to_str(default=None) except Exception as e: return False def get_lambda_function_versions(self, function_name: str) -> list: try: response = self.lambda_client.list_versions_by_function(FunctionName=function_name) return response.get('Versions', list()) except Exception as e: click.echo(f"Lambda function {function_name} not found. Error : {e}") return list() def create_lambda_function(self, bucket=None, s3_key: str = None, local_zip: bytes = None, function_name: str = None, handler=None, description: str = "Inoft Vocal Framework Deployment", timeout: int = 30, memory_size: int = 512, publish: bool = True, runtime=None): """ Given a bucket and key (or a local path) of a valid Lambda-zip, a function name and a handler, register that Lambda function. """ kwargs = dict( FunctionName=function_name, Runtime=runtime, Role=self.credentials_arn, # "arn:aws:iam::631258222318:role/service-role/alexa_hackaton-cite-des-sciences_fakenews-challeng-role-ck3sxsyt", # self.credentials_arn, # todo: make dynamic and create automaticly role if missing Handler=handler, Description=description, Timeout=timeout, MemorySize=memory_size, Publish=publish, Layers=[ "arn:aws:lambda:eu-west-3:631258222318:layer:inoft-vocal-framework_0-38-5:1", ] ) if local_zip is not None: kwargs['Code'] = { 'ZipFile': local_zip } else: kwargs['Code'] = { 'S3Bucket': bucket, 'S3Key': s3_key } response = self.lambda_client.create_function(**kwargs) lambda_arn = response["FunctionArn"] version = response['Version'] click.echo(f"Created new lambda function {function_name} with arn of {lambda_arn}") return lambda_arn def update_lambda_function_code(self, lambda_arn: str, object_key_name: str, bucket_name: str): response = self.lambda_client.update_function_code( FunctionName=lambda_arn, S3Bucket=bucket_name, S3Key=object_key_name, Publish=True, ) def update_lambda_function_configuration(self, function_name: str, handler_function_path: str = None, lambda_layers_arns: list = None): kwargs = dict(FunctionName=function_name) if handler_function_path is not None: kwargs["Handler"] = handler_function_path if lambda_layers_arns is not None and len(lambda_layers_arns) > 0: kwargs["Layers"] = lambda_layers_arns response = self.lambda_client.update_function_configuration(**kwargs) def create_api_gateway(self, lambda_arn: str, lambda_name: str, description: str = None) -> str: # todo: fix bug if id of api gateway is present in file, but the api has been deleted, it will not try to recreate it api_name = lambda_name or lambda_arn.split(":")[-1] api_creation_response = SafeDict(self.api_gateway_client.create_api(Name=api_name, Description=description or self.default_description, Target=lambda_arn, ProtocolType="HTTP")) api_id = api_creation_response.get("ApiId").to_str() self.create_and_setup_api_routes(api_id=api_id, lambda_arn=lambda_arn) return api_id def create_and_setup_api_routes(self, api_id: str, lambda_arn: str): integration_creation_response = SafeDict(self.api_gateway_client.create_integration(ApiId=api_id, IntegrationType="AWS_PROXY", PayloadFormatVersion="2.0", IntegrationUri=lambda_arn, TimeoutInMillis=10000)) integration_id = integration_creation_response.get("IntegrationId").to_str(default=None) if integration_id is None: raise Exception(f"Error while creating the route integration of the api towards the lambda_function." f"The integration_id was not found in the integration creation response." f"Please delete the api and redo the deployment." f"If the issue persist, create an Issue topic on the github page of the framework.") route_names = ["amazonAlexaV1", "googleAssistantDialogflowV1", "samsungBixbyV1", "appleSiriV1"] route_names_to_settings_keys = {"amazonAlexaV1": "alexaApiEndpointUrlNotRecommendedToUse", "googleAssistantDialogflowV1": "googleAssistantApiEndointUrl", "samsungBixbyV1": "samsungBixbyApiEndointUrl", "appleSiriV1": "siriApiEndointUrl"} api_gateway_root_url = self.api_gateway_v2_url(api_id=api_id) for route_name in route_names: self.boto_session.get_credentials() response = self.api_gateway_client.create_route( ApiId=api_id, AuthorizationType="None", RouteKey=f"ANY /{route_name}", # A space is required between the HTTP method and the / Target=f"integrations/{integration_id}", ) self.add_lambda_permission_to_call_api_resource(lambda_arn=lambda_arn, api_id=api_id, route_key=route_name) api_route_url = f"{api_gateway_root_url}/{route_name}" click.echo(f"Api route {click.style(route_name, fg='green')} creation complete accessible on {api_route_url}") self.settings.settings.get_set("deployment", {}).get_set("endpoints", {}).put( route_names_to_settings_keys[route_name], api_route_url).reset_navigated_dict() # We reset the navigated dict after a final put def add_lambda_permission_to_call_api_resource(self, lambda_arn: str, api_id: str, route_key: str): response = self.lambda_client.add_permission( FunctionName=lambda_arn, StatementId=self.get_session_new_statement_id(), Action="lambda:InvokeFunction", Principal="apigateway.amazonaws.com", SourceArn=f"arn:aws:execute-api:{self.boto_session.region_name}:{self.aws_account_id}:{api_id}/*/*/{route_key}", ) @property def iam_role(self) -> SafeDict: if self._iam_role is None: try: self._iam_role = SafeDict(self.iam.get_role(RoleName=self.role_name)["Role"]) except botocore.exceptions.ClientError: # If a ClientError happened while getting the role, it means he do not exist. logging.debug(f"Creating {self.role_name} IAM Role..") attach_policy_obj = json.loads(self.attach_policy) assume_policy_obj = json.loads(self.assume_policy) self._iam_role = SafeDict(self.iam.create_role(RoleName=self.role_name, AssumeRolePolicyDocument=self.assume_policy)["Role"]) # create or update the role's policies if needed policy = self.iam_resource.RolePolicy(self.role_name, "inoft-vocal-permissions") try: if policy.policy_document != attach_policy_obj: logging.debug(f"Updating inoft-vocal-permissions policy on {self.role_name} IAM Role.") policy.put(PolicyDocument=self.attach_policy) except botocore.exceptions.ClientError: logging.debug(f"Creating inoft-vocal-permissions policy on {self.role_name} IAM Role.") policy.put(PolicyDocument=self.attach_policy) role_policy_dict = self._iam_role.get("AssumeRolePolicyDocument").to_dict() if role_policy_dict != assume_policy_obj: if (SafeDict(role_policy_dict["Statement"][0]).get("Principal").get("Service").to_any() != assume_policy_obj["Statement"][0]["Principal"]["Service"]): logging.debug(f"Updating assume role policy on {self.role_name} IAM Role.") self.iam_client.update_assume_role_policy(RoleName=self.role_name, PolicyDocument=self.assume_policy) return self._iam_role @property def credentials_arn(self): if self._credentials_arn is None: self._credentials_arn = self.iam_role.get("Arn").to_str() return self._credentials_arn @credentials_arn.setter def credentials_arn(self, credentials_arn) -> None: self._credentials_arn = credentials_arn @property def aws_account_id(self) -> str: if self._aws_account_id is None: self._aws_account_id = boto3.client("sts").get_caller_identity().get("Account") return self._aws_account_id def get_session_new_statement_id(self) -> str: # No restriction is set on the statement id. To created my type of ids, i take the same unix # time across the session, and each time we generated a new statement id, i add 1 to the unix time. # Dumb and simple, but it assure that i will never have the same id twice. if self._session_unix_time is None: self._session_unix_time = time.time() self._session_count_created_statement_ids += 1 # After turning the modified unix time into a string, we remove any point, that would have # been used to separate the decimals, because AWS cannot accept a point in a id string. return str(self._session_unix_time + self._session_count_created_statement_ids).replace(".", "") def create_s3_bucket_if_missing(self, bucket_name: str, region_name: str): try: self.s3_client.head_bucket(Bucket=bucket_name) except ClientError as e: click.echo(f"Trying to create a new S3 Bucket with name {click.style(text=bucket_name, fg='yellow', bold=True)}" f" in region {click.style(text=region_name, fg='yellow', bold=True)}") available_regions_for_s3 = self.boto_session.get_available_regions(service_name="s3") if region_name not in available_regions_for_s3: raise Exception(f"The region {region_name} was not available for s3. Here is the available regions : {available_regions_for_s3}") self.s3_client.create_bucket(Bucket=bucket_name, CreateBucketConfiguration={"LocationConstraint": region_name}) click.echo(f"Completed creation of the new bucket.") def upload_to_s3(self, filepath: str, object_key_name: str, bucket_name: str, region_name: str) -> bool: # If an error happen while uploading to S3, then the upload will not be # successful. We use that as our way to send a success response. try: self.create_s3_bucket_if_missing(bucket_name=bucket_name, region_name=region_name) self.s3_client.upload_file(Filename=filepath, Bucket=bucket_name, Key=object_key_name) return True except NoCredentialsError as e: click.echo(f"Almost there ! You just need to configure your AWS credentials." f"\nYou can follow the official documentation (you will need to install the awscli by running pip install awscli) " f"then go to https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html#configuration" f"\nOr you can follow a video made by Robinson Labourdette from Inoft, as a guide to configure your credentials.") if click.confirm("Press Y to access the video."): selected_language = click.prompt("Type the language in which you would like the video. The followings are available :", type=click.Choice(["English", "French"])) if selected_language == "English": click.echo("English here you go !") elif selected_language == "French": click.echo("Français la voila !") click.echo("Follow the instructions that is available in the video, then when you are all set up, redo the command you just tried") while True: if click.confirm("Press y to exit"): exit(201) break # A little break, just to make sure that if the exit do not work, we do not stay stuck in this loop. else: click.echo("Ok, then follow the boto documentation, and once you have configured your credentials, relaunch the cli command that you were trying to use" " (https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html#configuration)") except Exception as e: click.echo(f"Error while getting/creating/uploading to the S3 bucket : {e}") return False def remove_from_s3(self, file_name: str, bucket_name: str): try: self.s3_client.head_bucket(Bucket=bucket_name) except botocore.exceptions.ClientError as e: # If a client error is thrown, then check that it was a 404 error. # If it was a 404 error, then the bucket does not exist. error_code = int(e.response["Error"]["Code"]) if error_code == 404: return False try: self.s3_client.delete_object(Bucket=bucket_name, Key=file_name) return True except (botocore.exceptions.ParamValidationError, botocore.exceptions.ClientError): return False
import jinja2 from inoft_vocal_framework.bixby_core.templates.templates_access import TemplatesAccess from inoft_vocal_framework.safe_dict import SafeDict from inoft_vocal_framework.utils.general import load_json model_dict = SafeDict(load_json("F:/Inoft/skill_histoire_decryptage_1/inoft_vocal_framework/bixby_core/test_model.json")) intents = model_dict.get("intents").to_dict() class Core: def render(self): out = TemplatesAccess().endpoints_template.render(intents=intents) print(out) @staticmethod def write_to_file(text: str, filepath: str): with open(filepath, "w+") as file: file.write(text) Core().render()
def slots(self) -> SafeDict: if isinstance(self._slots, dict): self._slots = SafeDict(self._slots) return self._slots
def slots(self, slots: dict) -> None: if not isinstance(slots, dict): raise Exception(f"slots was type {type(slots)} which is not valid value for his parameter.") self._slots = SafeDict(slots)
def parameters(self, parameters: dict) -> None: if not isinstance(parameters, dict): raise Exception( f"parameters was type {type(parameters)} which is not valid value for his parameter." ) self._parameters = SafeDict(parameters)
def parameters(self) -> SafeDict: if isinstance(self._parameters, dict): self._parameters = SafeDict(self._parameters) return self._parameters
def get_last_used_audioplayer_handlers_group(self) -> SafeDict: return SafeDict( self._parent_handler_input.persistent_remember( 'lastUsedAudioPlayerHandlersGroupClass', specific_object_type=dict))
def __init__(self): self._name = str() self._confirmationStatus = str() self._slots = SafeDict()