def test_save_attributes_to_existing_table(self): mock_table = mock.Mock() mock_table.put_item.return_value = True self.dynamodb_resource.Table.return_value = mock_table self.partition_keygen.return_value = "test_partition_key" test_dynamodb_adapter = DynamoDbAdapter( table_name="test_table", partition_keygen=self.partition_keygen, dynamodb_resource=self.dynamodb_resource) try: test_dynamodb_adapter.save_attributes( request_envelope=self.request_envelope, attributes=self.attributes) except: # Should not reach here raise Exception("Save attributes failed on existing table") self.dynamodb_resource.Table.assert_called_once_with("test_table"), ( "Existing table name passed incorrectly to dynamodb get table " "call") self.partition_keygen.assert_called_once_with(self.request_envelope), ( "Partition Keygen provided incorrect input parameters during " "save attributes call") mock_table.put_item.assert_called_once_with( Item={ "id": "test_partition_key", "attributes": self.attributes } ), ("Partition keygen provided incorrect partition key in item for " "save attributes call")
def test_get_attributes_from_existing_table(self): mock_table = mock.Mock() mock_table.get_item.return_value = { "Item": { "attributes": self.attributes } } self.dynamodb_resource.Table.return_value = mock_table self.partition_keygen.return_value = "test_partition_key" test_dynamodb_adapter = DynamoDbAdapter( table_name="test_table", partition_keygen=self.partition_keygen, dynamodb_resource=self.dynamodb_resource) assert test_dynamodb_adapter.get_attributes( request_envelope=self.request_envelope) == self.attributes, ( "Get attributes from dynamodb table retrieves wrong values") self.dynamodb_resource.Table.assert_called_once_with("test_table"), ( "Existing table name passed incorrectly to dynamodb get " "table call") self.partition_keygen.assert_called_once_with(self.request_envelope), ( "Partition Keygen provided incorrect input parameters during get " "attributes call") mock_table.get_item.assert_called_once_with( Key={"id": "test_partition_key"}, ConsistentRead=True ), ("Partition keygen provided incorrect key for get attributes call")
def test_get_attributes_from_existing_table_custom_key_name_attribute_name( self): mock_table = mock.Mock() mock_table.get_item.return_value = { "Item": { "custom_attr": self.attributes } } self.dynamodb_resource.Table.return_value = mock_table self.partition_keygen.return_value = "test_partition_key" test_dynamodb_adapter = DynamoDbAdapter( table_name="test_table", partition_keygen=self.partition_keygen, dynamodb_resource=self.dynamodb_resource, partition_key_name="custom_key", attribute_name="custom_attr") assert test_dynamodb_adapter.get_attributes( request_envelope=self.request_envelope ) == self.attributes, ( "Get attributes from dynamodb table retrieves wrong values when " "custom partition key name and " "custom attribute name passed") self.dynamodb_resource.Table.assert_called_once_with("test_table"), ( "Existing table name passed incorrectly to dynamodb get table " "call") self.partition_keygen.assert_called_once_with(self.request_envelope), ( "Partition Keygen provided incorrect input parameters during get " "item call") mock_table.get_item.assert_called_once_with( Key={"custom_key": "test_partition_key"} ), ("Partition keygen provided incorrect key for get attributes call")
def test_save_attributes_to_existing_table_put_item_fails(self): mock_table = mock.Mock() mock_table.put_item.side_effect = ValueError("test exception") self.dynamodb_resource.Table.return_value = mock_table self.partition_keygen.return_value = "test_partition_key" test_dynamodb_adapter = DynamoDbAdapter( table_name="test_table", partition_keygen=self.partition_keygen, dynamodb_resource=self.dynamodb_resource) with self.assertRaises(PersistenceException) as exc: test_dynamodb_adapter.save_attributes( request_envelope=self.request_envelope, attributes=self.attributes) assert ( "Failed to save attributes to DynamoDb table. " "Exception of type ValueError occurred: test " "exception" ) in str(exc.exception), ( "Save attributes didn't raise Persistence Exception when put item " "failed on dynamodb resource") mock_table.put_item.assert_called_once_with( Item={ "id": "test_partition_key", "attributes": self.attributes }), ("DynamoDb Put item called with incorrect parameters")
class BaseRequestInterceptor(AbstractRequestInterceptor): def __init__(self): super().__init__() table_name = "" # TODO add request analysis dynamodb table name self.dynamodb = boto3.resource('dynamodb', region_name="eu-west-1", aws_access_key_id="", aws_secret_access_key="") # TODO add aws keys self.dynamo_client = DynamoDbAdapter( table_name, partition_key_name="request_id", partition_keygen=request_id_partition_keygen, create_table=False, dynamodb_resource=self.dynamodb ) def save_request(self, handler_input, payload): self.dynamo_client.save_attributes( request_envelope=handler_input.request_envelope, attributes=payload) return True def process(self, handler_input, request_handler=None): try: if hasattr(handler_input.request_envelope.request, 'intent'): slots = request_handler.get_slot_values(handler_input.request_envelope.request.intent.slots) analytics_payload = { "request_id": handler_input.request_envelope.request.request_id, "user_id": handler_input.request_envelope.session.user.user_id, "device_id": handler_input.request_envelope.context.system.device.device_id, "datetime": str(time.time()), "display": handler_input.request_envelope.context.display, "locale": handler_input.request_envelope.request.locale, 'request': handler_input.request_envelope.request.object_type, 'intent': handler_input.request_envelope.request.intent.name, } for slot in slots: analytics_resolved_key = "slot_{}_resolved_id".format(slot) analytics_synonym_key = "slot_{}_synonym".format(slot) analytics_is_valid_key = "slot_{}_is_validated".format(slot) analytics_payload.update({ analytics_resolved_key: slots[slot]["resolved"]["id"] if isinstance(slots[slot]["resolved"], dict) and 'id' in slots[slot]["resolved"] else slots[slot]["resolved"], analytics_synonym_key: slots[slot]["synonym"], analytics_is_valid_key: slots[slot]["is_validated"] }) self.save_request(handler_input, analytics_payload) except Exception as e: logger.error(str(e).replace("\n", "\r")) if DEBUG: raise e else: pass # In production we can skip saving analytics if it fails
def __init__(self): super().__init__() table_name = "" # TODO add request analysis dynamodb table name self.dynamodb = boto3.resource('dynamodb', region_name="eu-west-1", aws_access_key_id="", aws_secret_access_key="") # TODO add aws keys self.dynamo_client = DynamoDbAdapter( table_name, partition_key_name="request_id", partition_keygen=request_id_partition_keygen, create_table=False, dynamodb_resource=self.dynamodb )
def test_get_attributes_from_existing_table_get_item_returns_no_item(self): mock_table = mock.Mock() mock_table.get_item.return_value = {"attributes": self.attributes} self.dynamodb_resource.Table.return_value = mock_table self.partition_keygen.return_value = "test_partition_key" test_dynamodb_adapter = DynamoDbAdapter( table_name="test_table", partition_keygen=self.partition_keygen, dynamodb_resource=self.dynamodb_resource) assert test_dynamodb_adapter.get_attributes( request_envelope=self.request_envelope) == {}, ( "Get attributes returns incorrect response when no item is " "present in dynamodb table for provided key")
def test_delete_attributes_fails_with_no_existing_table(self): self.dynamodb_resource.Table.side_effect = ResourceNotExistsError( "test", "test", "test") self.dynamodb_resource.create_table.return_value = "test" test_dynamodb_adapter = DynamoDbAdapter( table_name="test_table", partition_keygen=self.partition_keygen, dynamodb_resource=self.dynamodb_resource) with self.assertRaises(PersistenceException) as exc: test_dynamodb_adapter.delete_attributes( request_envelope=self.request_envelope) assert "DynamoDb table test_table doesn't exist" in str( exc.exception), ( "Delete attributes didn't raise Persistence Exception when no " "existing table and create table set as false") self.dynamodb_resource.create_table.assert_not_called(), ( "Create table called on dynamodb resource when create_table flag " "is set as False")
def __init__(self): super().__init__() self.slot_values = {} # Initializing an empty dict, to read slots later for slot_key in self.SLOTS: self.slot_values[slot_key] = { "synonym": None, "resolved": None, "is_validated": False, } self.dynamodb = boto3.resource('dynamodb', region_name="eu-west-1", aws_access_key_id="", aws_secret_access_key="") # TODO add here AWS keys # Default partition keygen uses user_id in request_envelope as ID table_name = None # TODO user attributes table name self.dynamo_client = DynamoDbAdapter(table_name=table_name, partition_key_name="user_id", partition_keygen=user_id_partition_keygen, # default create_table=False, # default dynamodb_resource=self.dynamodb)
def test_delete_attributes_to_existing_table_delete_item_fails(self): mock_table = mock.Mock() mock_table.delete_item.side_effect = ValueError("test exception") self.dynamodb_resource.Table.return_value = mock_table self.partition_keygen.return_value = "test_partition_key" test_dynamodb_adapter = DynamoDbAdapter( table_name="test_table", partition_keygen=self.partition_keygen, dynamodb_resource=self.dynamodb_resource) with self.assertRaises(PersistenceException) as exc: test_dynamodb_adapter.delete_attributes( request_envelope=self.request_envelope) assert ("test exception") in str(exc.exception), ( "Delete attributes didn't raise Persistence Exception when delete item " "failed on dynamodb resource") mock_table.delete_item.assert_called_once_with( Key={"id": "test_partition_key"}), ( "DynamoDb Delete item called with incorrect parameters")
def test_create_table_doesnt_raise_exception_if_flag_set_existing_table( self): self.dynamodb_resource.create_table.side_effect = \ ResourceInUseException("Invalid call to create table") DynamoDbAdapter(table_name="test_table", partition_keygen=self.partition_keygen, dynamodb_resource=self.dynamodb_resource, create_table=True) self.dynamodb_resource.create_table.assert_called_once(), ( "Create table called when create_table flag is set " "during Adapter initialization and resource already exists")
def test_get_attributes_from_existing_table_get_item_fails(self): mock_table = mock.Mock() mock_table.get_item.side_effect = Exception("test exception") self.dynamodb_resource.Table.return_value = mock_table self.partition_keygen.return_value = "test_partition_key" test_dynamodb_adapter = DynamoDbAdapter( table_name="test_table", partition_keygen=self.partition_keygen, dynamodb_resource=self.dynamodb_resource) with self.assertRaises(PersistenceException) as exc: test_dynamodb_adapter.get_attributes( request_envelope=self.request_envelope) assert "Failed to retrieve attributes from DynamoDb table" in str( exc.exception ), ("Get attributes didn't raise Persistence Exception when get item " "failed on dynamodb resource") mock_table.get_item.assert_called_once_with( Key={"id": "test_partition_key"} ), ("Partition keygen provided incorrect key for get attributes call")
def test_existence_check_not_done_if_flag_not_set(self): self.dynamodb_resource.Table.side_effect = Exception( "Invalid call to get table") self.dynamodb_resource.create_table.side_effect = Exception( "Invalid call to create table") DynamoDbAdapter(table_name="test_table", partition_keygen=self.partition_keygen, dynamodb_resource=self.dynamodb_resource, create_table=False) self.dynamodb_resource.create_table.assert_not_called(), ( "Create table called when create_table flag is not set, during " "Adapter initialization")
def test_catch_get_table_exception_if_flag_set(self): self.dynamodb_resource.create_table.side_effect = ValueError( "Invalid call to create table") with self.assertRaises(PersistenceException) as exc: DynamoDbAdapter(table_name="test_table", partition_keygen=self.partition_keygen, dynamodb_resource=self.dynamodb_resource, create_table=True) assert ("Create table if not exists request failed: Exception of type " "ValueError occurred: " "Invalid call to create table") in str(exc.exception), ( "create table if not exists didn't raise exception when " "create_table flag is set and create table " "resource raises exception")
def setup_skill_builder(service: OpenDataService) -> CustomSkillBuilder: """Helper method to create the custom skill builder instance.""" logger.info({ "operation": "Setting up Custom Skill Builder with Dynamo DB persistence adapter", "dynamo_db_table_name": DYNAMO_DB_TABLE_NAME, }) dynamo_db_adapter = DynamoDbAdapter( table_name=DYNAMO_DB_TABLE_NAME, partition_key_name="id", attribute_name="attributes", create_table=True, dynamodb_resource=resource("dynamodb"), ) skill_builder = CustomSkillBuilder(persistence_adapter=dynamo_db_adapter) logger.info("Adding skill request handlers...") skill_builder.add_request_handler(LaunchRequestHandler()) skill_builder.add_request_handler(SaveTripPreferencesHandler()) skill_builder.add_request_handler(GetArrivalTimesNoPrefsIntentHandler()) skill_builder.add_request_handler(GetArrivalTimesIntentHandler(service)) skill_builder.add_request_handler(StartedInProgressFavoriteStopHandler()) skill_builder.add_request_handler(CompletedFavoriteStopHandler()) skill_builder.add_request_handler(StartedInProgressFavoriteLineHandler()) skill_builder.add_request_handler(CompletedFavoriteLineHandler(service)) skill_builder.add_request_handler(YesIntentHandler()) skill_builder.add_request_handler(NoIntentHandler()) skill_builder.add_request_handler(HelpIntentHandler()) skill_builder.add_request_handler(CancelOrStopIntentHandler()) skill_builder.add_request_handler(RepeatHandler()) skill_builder.add_request_handler(FallBackHandler()) skill_builder.add_request_handler(SessionEndedRequestHandler()) skill_builder.add_request_handler(IntentReflectorHandler()) logger.info("Adding skill exception handlers...") skill_builder.add_exception_handler(OpenDataAPIExceptionHandler()) skill_builder.add_exception_handler(GenericExceptionHandler()) logger.info("Adding skill request interceptors...") skill_builder.add_global_request_interceptor(LocalizationInterceptor()) skill_builder.add_global_request_interceptor(RequestLoggerInterceptor()) logger.info("Adding skill response interceptors...") skill_builder.add_global_response_interceptor(ResponseLoggerInterceptor()) tracer.put_annotation("SKILL_SETUP", "SUCCESS") tracer.put_metadata(key="environment", value=ENVIRONMENT.upper()) return skill_builder
def skill_configuration(self): # type: () -> SkillConfiguration """Create the skill configuration object using the registered components. """ skill_config = super(StandardSkillBuilder, self).skill_configuration skill_config.api_client = DefaultApiClient() if self.table_name is not None: kwargs = {"table_name": self.table_name} # type: Dict[str, Any] if self.auto_create_table: kwargs["create_table"] = self.auto_create_table if self.partition_keygen: kwargs["partition_keygen"] = self.partition_keygen if self.dynamodb_client: kwargs["dynamodb_resource"] = self.dynamodb_client skill_config.persistence_adapter = DynamoDbAdapter(**kwargs) return skill_config
import logging import json import random import os import boto3 # RSS feed URL of the podcast rss_url = "https://anchor.fm/s/172e72c0/podcast/rss" # Defining the database region, table name and dynamodb persistence adapter ddb_region = os.environ.get('DYNAMODB_PERSISTENCE_REGION') ddb_table_name = os.environ.get('DYNAMODB_PERSISTENCE_TABLE_NAME') ddb_resource = boto3.resource('dynamodb', region_name=ddb_region) dynamodb_adapter = DynamoDbAdapter(table_name=ddb_table_name, create_table=False, dynamodb_resource=ddb_resource) # Initializing the logger and setting the level to "INFO" # Read more about it here https://www.loggly.com/ultimate-guide/python-logging-basics/ logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) # Intent Handlers # Check if device supports audio playlack class CheckAudioInterfaceHandler(AbstractRequestHandler): def can_handle(self, handler_input): if handler_input.request_envelope.context.system.device: return handler_input.request_envelope.context.system.device.supported_interfaces.audio_player is None
from ask_sdk_model.services.monetization import (EntitledState, PurchasableState, InSkillProductsResponse, Error, InSkillProduct) from ask_sdk_model.interfaces.monetization.v1 import PurchaseResult from ask_sdk_model.interfaces.connections import SendRequestDirective from alexa import data from boto3.dynamodb.conditions import Key from ask_sdk_dynamodb.adapter import DynamoDbAdapter, user_id_partition_keygen logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) adapter = DynamoDbAdapter(table_name="my_home_santa_session", partition_key_name="id", attribute_name="attributes", create_table=True, partition_keygen=user_id_partition_keygen, dynamodb_resource=boto3.resource("dynamodb")) ''' Launch ''' class LaunchRequestHandler(AbstractRequestHandler): """Handler for Skill Launch.""" def can_handle(self, handler_input): # type: (HandlerInput) -> bool return ask_utils.is_request_type("LaunchRequest")(handler_input) def handle(self, handler_input): # type: (HandlerInput) -> Response
from config import settings from handlers import game_play_handlers, global_handlers, start_handlers, roll_call_handlers ENV = os.environ.get('ENV') adapter_config = { "table_name": settings.STORAGE['session_table'], "create_table": ENV == 'DEV', } if ENV == 'DEV': localhost = 'http://localhost:8000' adapter_config["dynamodb_resource"] = boto3.resource("dynamodb", endpoint_url=localhost) else: adapter_config["dynamodb_resource"] = boto3.resource("dynamodb") sb = CustomSkillBuilder(persistence_adapter=DynamoDbAdapter(**adapter_config)) sb.skill_id = settings.APP_ID sb.add_request_handler(game_play_handlers.AnswerHandler()) sb.add_request_handler(game_play_handlers.DontKnowNextHandler()) sb.add_request_handler(game_play_handlers.GameEventHandler()) sb.add_request_handler(game_play_handlers.PlayGameHandler()) sb.add_request_handler(game_play_handlers.EndGameHandler()) sb.add_request_handler(game_play_handlers.YesHandler()) sb.add_request_handler(roll_call_handlers.YesHandler()) sb.add_request_handler(roll_call_handlers.NoHandler()) sb.add_request_handler(roll_call_handlers.GameEventHandler()) sb.add_request_handler(start_handlers.PlayerCountHandler()) sb.add_request_handler(start_handlers.YesHandler()) sb.add_request_handler(start_handlers.NoHandler()) sb.add_request_handler(start_handlers.LaunchPlayGameHandler())
) # Save the details from assumed role into vars newsession_id = stsresponse["Credentials"]["AccessKeyId"] newsession_key = stsresponse["Credentials"]["SecretAccessKey"] newsession_token = stsresponse["Credentials"]["SessionToken"] ddb2 = boto3.resource( 'dynamodb', region_name='sa-east-1', aws_access_key_id=newsession_id, aws_secret_access_key=newsession_key, aws_session_token=newsession_token ) db = DynamoDbAdapter(table_name="dynamo_revolucao",partition_key_name="id",partition_keygen=user_id_partition_keygen,dynamodb_resource=ddb2) class LaunchRequestHandler(AbstractRequestHandler): """Handler for Skill Launch.""" def can_handle(self, handler_input): # type: (HandlerInput) -> bool return ask_utils.is_request_type("LaunchRequest")(handler_input) def handle(self, handler_input, ): # type: (HandlerInput) -> Response speak_output = "" try:# checar se usuario existe request_envelope = handler_input.request_envelope user = db.get_attributes(request_envelope=request_envelope)
class BaseRequestHandler(AbstractRequestHandler): """ This is the Base request handler the other handlers will inherit from. It contains basic functions such as the saving and access data from and to DynamoDB, using the DynamoDB persistence adaptor. This data can be both user data and analytics data """ SLOTS = [] # Filled in every handler def __init__(self): super().__init__() self.slot_values = {} # Initializing an empty dict, to read slots later for slot_key in self.SLOTS: self.slot_values[slot_key] = { "synonym": None, "resolved": None, "is_validated": False, } self.dynamodb = boto3.resource('dynamodb', region_name="eu-west-1", aws_access_key_id="", aws_secret_access_key="") # TODO add here AWS keys # Default partition keygen uses user_id in request_envelope as ID table_name = None # TODO user attributes table name self.dynamo_client = DynamoDbAdapter(table_name=table_name, partition_key_name="user_id", partition_keygen=user_id_partition_keygen, # default create_table=False, # default dynamodb_resource=self.dynamodb) @abstractmethod def can_handle(self, handler_input): """ Base method, not implemented here """ raise NotImplementedError def handle(self, handler_input): """ Super handler, called by every intent that wants to save request data """ BaseRequestInterceptor().process(handler_input=handler_input, request_handler=self) def get_attributes(self, handler_input): """ Gets user attributes from DynamoDB """ user_attr = self.dynamo_client.get_attributes(request_envelope=handler_input.request_envelope) if len(user_attr) == 0: # If the user didn't exist, we create a default set of attributes with the key 'first_use' to signal it default_attr = self.set_default_attributes(handler_input) default_attr['first_use'] = True return default_attr return user_attr def set_default_attributes(self, handler_input): """ Sets default user attributes to DynamoDB """ attr = { 'custom_attr': 'TODO', } self.dynamo_client.save_attributes(request_envelope=handler_input.request_envelope, attributes=attr) return attr def set_attributes(self, handler_input, attr): """ Overwrite user attributes to DynamoDB """ user_attr = self.dynamo_client.get_attributes(request_envelope=handler_input.request_envelope) for changed_attr in attr: user_attr[changed_attr] = attr[changed_attr] self.dynamo_client.save_attributes(request_envelope=handler_input.request_envelope, attributes=user_attr) # --------- Other methods def get_slot_values(self, filled_slots): """ Return slot values with additional info, to understand if the slots were filled """ if DEBUG: logger.info("Filled slots: {}".format(filled_slots).replace("\n", "\r")) if filled_slots is None: return {} for key, slot_item in six.iteritems(filled_slots): name = slot_item.name try: status_code = slot_item.resolutions.resolutions_per_authority[0].status.code if status_code == StatusCode.ER_SUCCESS_MATCH: self.slot_values[name] = { "synonym": slot_item.value, "resolved": slot_item.resolutions.resolutions_per_authority[0].values[0].value.__dict__, "is_validated": True, } elif status_code == StatusCode.ER_SUCCESS_NO_MATCH: self.slot_values[name] = { "synonym": slot_item.value, "resolved": slot_item.value, "is_validated": False, } else: pass except (AttributeError, ValueError, KeyError, IndexError, TypeError) as e: # for BUILT-IN intents, there are no resolutions, but the value is specified if slot_item.value is not None and slot_item.value != 'NONE': self.slot_values[name] = { "synonym": slot_item.value, "resolved": slot_item.value, "is_validated": True, } else: if DEBUG: logger.info("SLOT {} UNRESOLVED".format(name)) self.slot_values[name] = { "synonym": slot_item.value, "resolved": slot_item.value, "is_validated": False, } return self.slot_values
from ask_sdk_core.utils import is_intent_name, is_request_type from ask_sdk_model import Response from ask_sdk_core.attributes_manager import AttributesManager, AbstractPersistenceAdapter from ask_sdk_core.handler_input import HandlerInput from ask_sdk_core.exceptions import PersistenceException import msg_data #Implementiert den Logger zum loggen von Fehlermeldungen, Informationen uvm. logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) #Instanz des SkillBuilders. sb = SkillBuilder() #Die Instanzen der verschiedenen DynamoDbAdapter, die unterschiedliche Daten aus der Datenbank holen und aktualisieren können. name_adapter = DynamoDbAdapter(table_name="vpn_name", partition_key_name="userId") aufgaben_adapter = DynamoDbAdapter(table_name="aufgaben_bearbeitet", partition_key_name="userId") fragen_adapter = DynamoDbAdapter(table_name="antworten_index", partition_key_name="userId") status_adapter = DynamoDbAdapter(table_name="versuchsleiter_status", partition_key_name="userId") #Ein Wahrheitswert, der angibt, ob der Nutzer Hilfe benötigt. looking_for_help = False #Ein Hilfswert, der angibt, ob der Nutzer direkt zur Befragung/zu den Aufgaben weitergeleitet wird oder erst die Einführungsnachricht zu hören bekommt. #Hilfswert für den NoIntentHandler is_no_intent = True #Wird vor dem Start des Skills ausgeführt und sopeichert den in der Einführung angegeben Namen der VPN und den Skillstatus in den Session Attributen. class LaunchRequestInterceptor(AbstractRequestInterceptor): def process(self, handler_input): attrs = handler_input.attributes_manager.session_attributes try:
import logging from ask_sdk_core.handler_input import HandlerInput from ask_sdk_core.dispatch_components import AbstractRequestHandler, AbstractExceptionHandler, AbstractRequestInterceptor, AbstractResponseInterceptor from ask_sdk_core.utils import is_request_type, is_intent_name from ask_sdk_core.skill_builder import SkillBuilder from ask_sdk_model import Response from ask_sdk_core.attributes_manager import AbstractPersistenceAdapter from ask_sdk_dynamodb.adapter import DynamoDbAdapter import msg_data adapter = DynamoDbAdapter("vpn_name", partition_key_name="userId") sb = SkillBuilder() logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) user_name_slot = "name" class LaunchRequestHandler(AbstractRequestHandler): def can_handle(self, handler_input): return is_request_type("LaunchRequest")(handler_input) def handle(self, handler_input): speech = "Willkommen. Ich führe dich heute durch die Studie. Bitte gib mir deinen Namen, damit wir weitermachen können." question = "Bitte sage etwas wie mein Name ist Max Mustermann." handler_input.response_builder.speak(speech).ask(question) return handler_input.response_builder.response class FallbackIntentHandler(AbstractRequestHandler):