def get_trash_day_info(mycity_request): """ Generates response object for a trash day inquiry. :param mycity_request: MyCityRequestDataModel object :return: MyCityResponseDataModel object """ logger.debug('MyCityRequestDataModel received:' + mycity_request.get_logger_string()) mycity_response = MyCityResponseDataModel() # Determine if we have required address information. Request if we do not. if intent_constants.CURRENT_ADDRESS_KEY not in mycity_request.session_attributes: mycity_request, location_permissions = get_address_from_user_device( mycity_request) if not location_permissions: return request_device_address_permission_response() elif intent_constants.CURRENT_ADDRESS_KEY not in mycity_request.session_attributes: return request_user_address_response(mycity_request) current_address = \ mycity_request.session_attributes[intent_constants.CURRENT_ADDRESS_KEY] # grab relevant information from session address parsed_address, _ = usaddress.tag(current_address) # If we have more specific info then just the street # address, make sure we are in Boston if not is_address_in_city(current_address): mycity_response.output_speech = NOT_IN_BOSTON_SPEECH mycity_response.should_end_session = True mycity_response.card_title = CARD_TITLE return mycity_response if not address_utils.is_address_valid(parsed_address): mycity_response.output_speech = speech_constants.ADDRESS_NOT_UNDERSTOOD mycity_response.dialog_directive = "ElicitSlotTrash" mycity_response.reprompt_text = None mycity_response.session_attributes = mycity_request.session_attributes mycity_response.card_title = CARD_TITLE mycity_response.should_end_session = True return clear_address_from_mycity_object(mycity_response) # currently assumes that trash day is the same for all units at # the same street address address = " ".join([ parsed_address['AddressNumber'], parsed_address['StreetName'], parsed_address['StreetNamePostType'] ]) neighborhood = parsed_address["PlaceName"] \ if "PlaceName" in parsed_address \ and not parsed_address["PlaceName"].isdigit() \ else None if "Neighborhood" in mycity_request.intent_variables and \ "value" in mycity_request.intent_variables["Neighborhood"]: neighborhood = \ mycity_request.intent_variables["Neighborhood"]["value"] try: trash_days = get_trash_and_recycling_days(address, neighborhood) trash_days_speech = build_speech_from_list_of_days(trash_days) mycity_response.output_speech = speech_constants.PICK_UP_DAY.format( trash_days_speech) mycity_response.should_end_session = True except InvalidAddressError: address_string = address mycity_response.output_speech = speech_constants.ADDRESS_NOT_FOUND.format( address_string) mycity_response.dialog_directive = "ElicitSlotTrash" mycity_response.reprompt_text = None mycity_response.session_attributes = mycity_request.session_attributes mycity_response.card_title = CARD_TITLE mycity_response.should_end_session = True return clear_address_from_mycity_object(mycity_response) except BadAPIResponse: mycity_response.output_speech = speech_constants.BAD_API_RESPONSE mycity_response.should_end_session = True except MultipleAddressError as error: addresses = [ re.sub(r' \d{5}', '', address) for address in error.addresses ] address_list = ', '.join(addresses) mycity_response.output_speech = speech_constants.MULTIPLE_ADDRESS_ERROR.format( address_list) mycity_response.dialog_directive = "ElicitSlotNeighborhood" mycity_response.should_end_session = False # Setting reprompt_text to None signifies that we do not want to reprompt # the user. If the user does not respond or says something that is not # understood, the session will end. mycity_response.reprompt_text = None mycity_response.session_attributes = mycity_request.session_attributes mycity_response.card_title = CARD_TITLE return mycity_response
def get_trash_day_info(mycity_request): """ Generates response object for a trash day inquiry. :param mycity_request: MyCityRequestDataModel object :return: MyCityResponseDataModel object """ logger.debug('MyCityRequestDataModel received:' + mycity_request.get_logger_string()) mycity_response = MyCityResponseDataModel() if intent_constants.CURRENT_ADDRESS_KEY in mycity_request.session_attributes: current_address = \ mycity_request.session_attributes[intent_constants.CURRENT_ADDRESS_KEY] # grab relevant information from session address address_parser = StreetAddressParser() a = address_parser.parse(current_address) if not address_utils.is_address_valid(a): mycity_response.output_speech = speech_constants.ADDRESS_NOT_UNDERSTOOD mycity_response.dialog_directive = "ElicitSlotTrash" mycity_response.reprompt_text = None mycity_response.session_attributes = mycity_request.session_attributes mycity_response.card_title = CARD_TITLE mycity_response.should_end_session = True return clear_address_from_mycity_object(mycity_response) # currently assumes that trash day is the same for all units at # the same street address address = str(a['house']) + " " + str(a['street_full']) zip_code = str(a["other"]).zfill(5) if a["other"] and a["other"].isdigit() else None neighborhood = a["other"] if a["other"] and not a["other"].isdigit() else None zip_code_key = intent_constants.ZIP_CODE_KEY if zip_code is None and zip_code_key in \ mycity_request.session_attributes: zip_code = mycity_request.session_attributes[zip_code_key] if "Neighborhood" in mycity_request.intent_variables and \ "value" in mycity_request.intent_variables["Neighborhood"]: neighborhood = mycity_request.intent_variables["Neighborhood"]["value"] try: trash_days = get_trash_and_recycling_days(address, zip_code, neighborhood) trash_days_speech = build_speech_from_list_of_days(trash_days) mycity_response.output_speech = speech_constants.PICK_UP_DAY.format(trash_days_speech) mycity_response.should_end_session = True except InvalidAddressError: address_string = address if zip_code: address_string = address_string + " with zip code {}"\ .format(zip_code) mycity_response.output_speech = speech_constants.ADDRESS_NOT_FOUND.format(address_string) mycity_response.dialog_directive = "ElicitSlotTrash" mycity_response.reprompt_text = None mycity_response.session_attributes = mycity_request.session_attributes mycity_response.card_title = CARD_TITLE mycity_response.should_end_session = True return clear_address_from_mycity_object(mycity_response) except BadAPIResponse: mycity_response.output_speech = speech_constants.BAD_API_RESPONSE mycity_response.should_end_session = True except MultipleAddressError as error: addresses = [re.sub(r' \d{5}', '', address) for address in error.addresses] address_list = ', '.join(addresses) mycity_response.output_speech = speech_constants.MULTIPLE_ADDRESS_ERROR.format(address_list) mycity_response.dialog_directive = "ElicitSlotNeighborhood" mycity_response.should_end_session = False else: logger.error("Error: Called trash_day_intent with no address") mycity_response.output_speech = speech_constants.ADDRESS_NOT_UNDERSTOOD mycity_response.should_end_session = True # Setting reprompt_text to None signifies that we do not want to reprompt # the user. If the user does not respond or says something that is not # understood, the session will end. mycity_response.reprompt_text = None mycity_response.session_attributes = mycity_request.session_attributes mycity_response.card_title = CARD_TITLE return mycity_response
def test_missing_street_number_is_not_validated(self): address = StreetAddressParser().parse("Everdean St") self.assertFalse(address_utils.is_address_valid(address))
def test_missing_street_name_is_not_validated(self): address = StreetAddressParser().parse("46") self.assertFalse(address_utils.is_address_valid(address))
def test_valid_address_is_validated(self): address = StreetAddressParser().parse("46 Everdean St") self.assertTrue(address_utils.is_address_valid(address))
def get_voting_location(mycity_request: MyCityRequestDataModel) -> \ MyCityResponseDataModel: """ Generates response object for a polling location inquiry which includes a user's location to vote. :param mycity_request: MyCityRequestDataModel object :return: MyCityResponseDataModel object """ logger.debug('MyCityRequestDataModel received:' + mycity_request.get_logger_string()) mycity_response = MyCityResponseDataModel() mycity_response.card_title = CARD_TITLE # check for address for locating voting location if intent_constants.CURRENT_ADDRESS_KEY not in \ mycity_request.session_attributes: mycity_request, location_permissions = \ get_address_from_user_device(mycity_request) if not location_permissions: return request_device_address_permission_response() elif intent_constants.CURRENT_ADDRESS_KEY not in \ mycity_request.session_attributes: return request_user_address_response(mycity_request) current_address = \ mycity_request.session_attributes[intent_constants.CURRENT_ADDRESS_KEY] # If we have more specific info then just the street # address, make sure we are in Boston if not is_address_in_city(current_address): mycity_response.output_speech = NOT_IN_BOSTON_SPEECH mycity_response.should_end_session = True mycity_response.card_title = CARD_TITLE return mycity_response # grab relevant information from session address parsed_address, _ = usaddress.tag(current_address) if not is_address_valid(parsed_address): mycity_response.output_speech = ADDRESS_NOT_UNDERSTOOD mycity_response.dialog_directive = "ElicitSlotVotingIntent" mycity_response.reprompt_text = None mycity_response.session_attributes = mycity_request.session_attributes mycity_response.card_title = CARD_TITLE mycity_response.should_end_session = True return clear_address_from_mycity_object(mycity_response) zipcode = None if "Zipcode" in mycity_request.intent_variables and \ "value" in mycity_request.intent_variables["Zipcode"]: zipcode = \ mycity_request.intent_variables["Zipcode"]["value"].zfill(5) mycity_response.reprompt_text = None mycity_response.should_end_session = True try: top_candidate = gis_utils.geocode_address(current_address, zipcode) ward_precinct = vote_utils.get_ward_precinct_info(top_candidate) poll_location = vote_utils.get_polling_location(ward_precinct) output_speech = LOCATION_SPEECH. \ format(poll_location[LOCATION_NAME], poll_location[LOCATION_ADDRESS]) mycity_response.output_speech = output_speech except ParseError: mycity_response.output_speech = NO_WARD_OR_PRECINCT except BadAPIResponse: mycity_response.output_speech = BAD_API_RESPONSE except MultipleAddressError as error: address_list = ', '.join(error.addresses) mycity_response.output_speech = MULTIPLE_ADDRESS_ERROR mycity_response.dialog_directive = "ElicitSlotZipCode" mycity_response.should_end_session = False return mycity_response