From 5003f9df8fb33f4ff5deacb71b6a2bec603710cc Mon Sep 17 00:00:00 2001 From: Daniel McKnight Date: Tue, 9 Jul 2024 18:21:54 -0700 Subject: [PATCH 1/7] Refactor `translate` to `resources.render_dialog` --- __init__.py | 124 ++++++++++++++++++++++++++++------------------------ 1 file changed, 68 insertions(+), 56 deletions(-) diff --git a/__init__.py b/__init__.py index 0765f04..dc02a11 100644 --- a/__init__.py +++ b/__init__.py @@ -116,12 +116,12 @@ def _handle_location_ipgeo_update(self, message): if not all(user_coords) or user_coords == default_coords: LOG.info(f'Updating default user config from ip geolocation') new_loc = { - 'lat': str(updated_location['coordinate']['latitude']), - 'lon': str(updated_location['coordinate']['longitude']), - 'city': updated_location['city']['name'], - 'state': updated_location['city']['state']['name'], - 'country': updated_location['city']['state']['country']['name'], - } + 'lat': str(updated_location['coordinate']['latitude']), + 'lon': str(updated_location['coordinate']['longitude']), + 'city': updated_location['city']['name'], + 'state': updated_location['city']['state']['name'], + 'country': updated_location['city']['state']['country']['name'], + } name, offset = self._get_timezone_from_location(new_loc) new_loc['lng'] = new_loc.pop('lon') new_loc['tz'] = name @@ -184,7 +184,7 @@ def handle_unit_change(self, message: Message): updated_prefs = {"units": {"measure": new_unit}} self.update_profile(updated_prefs, message) self.speak_dialog("units_changed", - {"unit": self.translate(f"word_{new_unit}")}, + {"unit": self.resources.render_dialog(f"word_{new_unit}")}, private=True) self._emit_weather_update(message) @@ -219,7 +219,7 @@ def handle_date_format_change(self, message: Message): """ new_setting = "YMD" if message.data.get("ymd") else \ "MDY" if message.data.get("mdy") else \ - "DMY" if message.data.get("dmy") else None + "DMY" if message.data.get("dmy") else None if not new_setting: raise RuntimeError("Missing required date format vocab") @@ -271,15 +271,15 @@ def handle_transcription_retention(self, message: Message): current_setting = get_user_prefs(message)["privacy"][kind] if current_setting == allow: self.speak_dialog("transcription_already_set", - {"transcription": self.translate(transcription), - "enabled": self.translate(enabled)}, + {"transcription": self.resources.render_dialog(transcription), + "enabled": self.resources.render_dialog(enabled)}, private=True) else: updated_prefs = {"privacy": {kind: allow}} self.update_profile(updated_prefs, message) self.speak_dialog("transcription_changed", - {"transcription": self.translate(transcription), - "enabled": self.translate(enabled)}, + {"transcription": self.resources.render_dialog(transcription), + "enabled": self.resources.render_dialog(enabled)}, private=True) @intent_handler(IntentBuilder("SpeakSpeed").require("speak_to_me") @@ -310,11 +310,11 @@ def handle_speech_speed(self, message: Message): if speed == current_speed == self.MAX_SPEECH_SPEED: self.speak_dialog("speech_speed_limit", - {"limit": self.translate("word_faster")}, + {"limit": self.resources.render_dialog("word_faster")}, private=True) elif speed == current_speed == self.MIN_SPEECH_SPEED: self.speak_dialog("speech_speed_limit", - {"limit": self.translate("word_slower")}, + {"limit": self.resources.render_dialog("word_slower")}, private=True) elif speed == 1.0: self.speak_dialog("speech_speed_normal", private=True) @@ -350,13 +350,13 @@ def handle_change_location_timezone(self, message: Message): do_timezone = True do_location = self.ask_yesno( "also_change_location_tz", - {"type": self.translate("word_location"), + {"type": self.resources.render_dialog("word_location"), "new": requested_place}) == "yes" elif message.data.get("location"): do_location = True do_timezone = self.ask_yesno( "also_change_location_tz", - {"type": self.translate("word_timezone"), + {"type": self.resources.render_dialog("word_timezone"), "new": requested_place}) == "yes" else: do_location = False @@ -366,7 +366,7 @@ def handle_change_location_timezone(self, message: Message): self.update_profile({"location": {"tz": tz_name, "utc": utc_offset}}) self.speak_dialog("change_location_tz", - {"type": self.translate("word_timezone"), + {"type": self.resources.render_dialog("word_timezone"), "location": f"UTC {utc_offset}"}, private=True) if do_location: @@ -378,7 +378,7 @@ def handle_change_location_timezone(self, message: Message): 'lat': float(resolved_place['lat']), 'lng': float(resolved_place['lon'])}}) self.speak_dialog("change_location_tz", - {"type": self.translate("word_location"), + {"type": self.resources.render_dialog("word_location"), "location": resolved_place['address']['city']}, private=True) self._emit_weather_update(message) @@ -401,14 +401,14 @@ def handle_change_dialog_mode(self, message: Message): if new_limit_dialog == current_limit_dialog: self.speak_dialog("dialog_mode_already_set", - {"response": self.translate(new_dialog)}, + {"response": self.resources.render_dialog(new_dialog)}, private=True) return self.update_profile( {"response_mode": {"limit_dialog": new_limit_dialog}}) self.speak_dialog("dialog_mode_changed", - {"response": self.translate(new_dialog)}, + {"response": self.resources.render_dialog(new_dialog)}, private=True) @intent_handler(IntentBuilder("SayMyName").require("tell_me_my") @@ -433,7 +433,7 @@ def handle_say_my_name(self, message: Message): # TODO: Use get_response to ask for the user's name self.speak_dialog( "name_not_known", - {"name_position": self.translate("word_name")}, + {"name_position": self.resources.render_dialog("word_name")}, private=True) return if self.voc_match(utterance, "first_name"): @@ -466,11 +466,11 @@ def handle_say_my_name(self, message: Message): else: # TODO: Use get_response to ask for the user's name self.speak_dialog("name_not_known", - {"name_position": self.translate(request)}, + {"name_position": self.resources.render_dialog(request)}, private=True) else: self.speak_dialog("name_is", - {"name_position": self.translate(request), + {"name_position": self.resources.render_dialog(request), "name": name}, private=True) @intent_handler(IntentBuilder("SayMyEmail").require("tell_me_my") @@ -590,7 +590,7 @@ def handle_set_my_email(self, message: Message): extracted = message.data.get("rx_setting") LOG.debug(extracted) email_addr: str = extracted.split()[0] + \ - message.data.get("utterance").rsplit(extracted.split()[0])[1] + message.data.get("utterance").rsplit(extracted.split()[0])[1] dot = read_vocab_file(self.find_resource("dot.voc", 'vocab'))[0][0] at = read_vocab_file(self.find_resource("at.voc", 'vocab'))[0][0] email_words = email_addr.split() @@ -603,7 +603,7 @@ def handle_set_my_email(self, message: Message): if not validate_email(email_addr): self.speak_dialog("email_set_error", private=True) - email_addr = self.get_gui_input(self.translate("word_email_title"), + email_addr = self.get_gui_input(self.resources.render_dialog("word_email_title"), "test@neon.ai") if not email_addr or not validate_email(email_addr): LOG.warning(f"Invalid email_addr entered: {email_addr}") @@ -636,7 +636,7 @@ def handle_set_my_email(self, message: Message): private=True) else: self.speak_dialog("email_not_confirmed", private=True) - email_addr = self.get_gui_input(self.translate("word_email_title"), + email_addr = self.get_gui_input(self.resources.render_dialog("word_email_title"), "test@neon.ai") if email_addr: self.update_profile({"user": {"email": email_addr}}) @@ -715,9 +715,9 @@ def handle_set_my_name(self, message: Message): if (request and len(name.split()) > 3) or len(name.split()) > 4: LOG.warning(f"'{name}' does not look like a {request} name.") confirmed = self.ask_yesno("name_confirm_change", - {"position": self.translate( + {"position": self.resources.render_dialog( f"word_{request or 'name'}"), - "name": name}) + "name": name}) if not confirmed: self.speak_dialog("name_not_confirmed", private=True) @@ -725,7 +725,7 @@ def handle_set_my_name(self, message: Message): if name == user_profile[request]: self.speak_dialog( "name_not_changed", - {"position": self.translate(f"word_{request}"), + {"position": self.resources.render_dialog(f"word_{request}"), "name": name}, private=True) elif confirmed: name_parts = (name if request == n else user_profile.get(n) @@ -737,7 +737,7 @@ def handle_set_my_name(self, message: Message): message) self.speak_dialog( "name_set_part", - {"position": self.translate(f"word_{request}"), + {"position": self.resources.render_dialog(f"word_{request}"), "name": name}, private=True) else: preferred_name = user_profile["preferred_name"] or name @@ -750,7 +750,8 @@ def handle_set_my_name(self, message: Message): if all((user_profile[n] == updated_user_profile.get(n) for n in ("first_name", "middle_name", "last_name"))): self.speak_dialog("name_not_changed", - {"position": self.translate(f"word_name"), + {"position": self.resources.render_dialog( + f"word_name"), "name": name}) else: self.update_profile({"user": updated_user_profile}, message) @@ -773,20 +774,21 @@ def handle_say_my_language_settings(self, message: Message): primary_lang = pronounce_lang(language_settings["tts_language"]) second_lang = pronounce_lang( language_settings["secondary_tts_language"]) - self.speak_dialog("language_setting", - {"primary": self.translate("word_primary"), - "language": primary_lang, - "gender": self.translate( - f'word_{language_settings["tts_gender"]}')}, - private=True) + self.speak_dialog( + "language_setting", + {"primary": self.resources.render_dialog("word_primary"), + "language": primary_lang, + "gender": self.resources.render_dialog( + f'word_{language_settings["tts_gender"]}')}, + private=True) if second_lang and (second_lang != primary_lang or language_settings["tts_gender"] != language_settings["secondary_tts_gender"]): self.speak_dialog( "language_setting", - {"primary": self.translate("word_secondary"), + {"primary": self.resources.render_dialog("word_secondary"), "language": second_lang, - "gender": self.translate( + "gender": self.resources.render_dialog( f'word_{language_settings["secondary_tts_gender"]}')}, private=True) @@ -800,9 +802,9 @@ def handle_set_stt_language(self, message: Message): :param message: Message associated with request """ requested_lang = message.data.get('rx_language') or \ - message.data.get('request_language') + message.data.get('request_language') lang = self._parse_languages(message.data.get("utterance"))[0] or \ - requested_lang.split()[-1] + requested_lang.split()[-1] try: code, spoken_lang = self._get_lang_code_and_name(lang) except UnsupportedLanguageError as e: @@ -816,10 +818,11 @@ def handle_set_stt_language(self, message: Message): LOG.warning(f"{code} not found in: {self.stt_languages}") self.speak_dialog("language_not_supported", {"lang": spoken_lang, - "io": self.translate('word_understand')}, + "io": self.resources.render_dialog( + 'word_understand')}, private=True) return - dialog_data = {"io": self.translate("word_stt"), + dialog_data = {"io": self.resources.render_dialog("word_stt"), "lang": spoken_lang} if code == get_user_prefs(message)["speech"]["stt_language"]: self.speak_dialog("language_not_changed", dialog_data, @@ -844,7 +847,7 @@ def handle_set_tts_language(self, message: Message): :param message: Message associated with request """ language = message.data.get("rx_language") or \ - message.data.get("request_language") + message.data.get("request_language") primary, secondary = \ self._parse_languages(message.data.get("utterance")) LOG.info(f"primary={primary} | secondary={secondary} | " @@ -861,16 +864,18 @@ def handle_set_tts_language(self, message: Message): f" {self.tts_languages}") self.speak_dialog("language_not_supported", {"lang": primary_spoken, - "io": self.translate('word_speak')}, + "io": self.resources.render_dialog( + 'word_speak')}, private=True) return gender = self._get_gender(primary) or \ - user_settings["speech"]["tts_gender"] + user_settings["speech"]["tts_gender"] self.update_profile({"speech": {"tts_gender": gender, "tts_language": primary_code}}, message) self.speak_dialog("language_set", - {"io": self.translate("word_primary"), + {"io": self.resources.render_dialog( + "word_primary"), "lang": primary_spoken}, private=True) except UnsupportedLanguageError: LOG.warning(f"No language for primary request: {primary}") @@ -887,17 +892,19 @@ def handle_set_tts_language(self, message: Message): f" {self.tts_languages}") self.speak_dialog("language_not_supported", {"lang": secondary_spoken, - "io": self.translate('word_speak')}, + "io": self.resources.render_dialog( + 'word_speak')}, private=True) return gender = self._get_gender(secondary) or \ - user_settings["speech"]["secondary_tts_gender"] + user_settings["speech"]["secondary_tts_gender"] self.update_profile( {"speech": {"secondary_tts_gender": gender, "secondary_tts_language": secondary_code}}, message) self.speak_dialog("language_set", - {"io": self.translate("word_secondary"), + {"io": self.resources.render_dialog( + "word_secondary"), "lang": secondary_spoken}, private=True) except UnsupportedLanguageError: LOG.warning(f"No language for secondary request: {secondary}") @@ -915,16 +922,18 @@ def handle_set_tts_language(self, message: Message): LOG.warning(f"{code} not found in: {self.tts_languages}") self.speak_dialog("language_not_supported", {"lang": spoken, - "io": self.translate('word_speak')}, + "io": self.resources.render_dialog( + 'word_speak')}, private=True) return gender = self._get_gender(language) or \ - user_settings["speech"]["tts_gender"] + user_settings["speech"]["tts_gender"] self.update_profile({"speech": {"tts_gender": gender, "tts_language": code}}, message) self.speak_dialog("language_set", - {"io": self.translate("word_primary"), + {"io": self.resources.render_dialog( + "word_primary"), "lang": spoken}, private=True) except UnsupportedLanguageError: LOG.warning(f"No language for secondary request: {language}") @@ -995,6 +1004,7 @@ def _parse_languages(self, utterance: str) -> \ :param utterance: raw utterance spoken by the user :returns: spoken primary, secondary languages requested """ + def _get_rx_patterns(rx_file: str, utt: str): with open(rx_file) as f: for pat in f.read().splitlines(): @@ -1004,6 +1014,7 @@ def _get_rx_patterns(rx_file: str, utt: str): res = re.search(pat, utt) if res: return res + utterance = f"{utterance}\n" primary_tts = self.find_resource('primary_tts.rx', 'regex') secondary_tts = self.find_resource('secondary_tts.rx', 'regex') @@ -1019,7 +1030,7 @@ def _get_rx_patterns(rx_file: str, utt: str): if secondary_tts: try: secondary = _get_rx_patterns(secondary_tts, - utterance).group("rx_secondary")\ + utterance).group("rx_secondary") \ .strip() except (IndexError, AttributeError): secondary = None @@ -1075,8 +1086,9 @@ def _spoken_email(self, email_addr: str): """ Get a pronounceable email address string """ - return email_addr.replace('.', f' {self.translate("word_dot")} ')\ - .replace('@', f' {self.translate("word_at")} ') + return email_addr.replace( + '.', f' {self.resources.render_dialog("word_dot")} ') \ + .replace('@', f' {self.resources.render_dialog("word_at")} ') @staticmethod def _get_name_parts(name: str, user_profile: dict) -> dict: From b7bfc3d3fe097ec11df132ba21b599f154da9671 Mon Sep 17 00:00:00 2001 From: Daniel McKnight Date: Tue, 9 Jul 2024 18:28:41 -0700 Subject: [PATCH 2/7] Replace deprecated references Troubleshoot test failure --- __init__.py | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/__init__.py b/__init__.py index dc02a11..62f43f1 100644 --- a/__init__.py +++ b/__init__.py @@ -37,7 +37,7 @@ from ovos_bus_client import Message from neon_utils.location_utils import get_timezone from neon_utils.skills.neon_skill import NeonSkill -from neon_utils.user_utils import get_user_prefs +from neon_utils.user_utils import get_user_prefs, update_user_profile from neon_utils.language_utils import get_supported_languages from neon_utils.parse_utils import validate_email from lingua_franca.parse import extract_langcode, get_full_lang_code @@ -182,7 +182,7 @@ def handle_unit_change(self, message: Message): private=True) else: updated_prefs = {"units": {"measure": new_unit}} - self.update_profile(updated_prefs, message) + update_user_profile(updated_prefs, message) self.speak_dialog("units_changed", {"unit": self.resources.render_dialog(f"word_{new_unit}")}, private=True) @@ -206,7 +206,7 @@ def handle_time_format_change(self, message: Message): {"scale": str(new_setting)}, private=True) else: updated_prefs = {"units": {"time": new_setting}} - self.update_profile(updated_prefs, message) + update_user_profile(updated_prefs, message) self.speak_dialog("time_format_changed", {"scale": str(new_setting)}, private=True) @@ -230,7 +230,7 @@ def handle_date_format_change(self, message: Message): private=True) else: updated_prefs = {"units": {"date": new_setting}} - self.update_profile(updated_prefs, message) + update_user_profile(updated_prefs, message) self.speak_dialog("date_format_changed", {"format": message.data.get(new_setting.lower())}, private=True) @@ -244,7 +244,7 @@ def handle_speak_hesitation(self, message: Message): :param message: Message associated with request """ enabled = True if message.data.get("permit") else False - self.update_profile({"response_mode": {"hesitation": enabled}}) + update_user_profile({"response_mode": {"hesitation": enabled}}) if enabled: self.speak_dialog("hesitation_enabled", private=True) else: @@ -276,7 +276,7 @@ def handle_transcription_retention(self, message: Message): private=True) else: updated_prefs = {"privacy": {kind: allow}} - self.update_profile(updated_prefs, message) + update_user_profile(updated_prefs, message) self.speak_dialog("transcription_changed", {"transcription": self.resources.render_dialog(transcription), "enabled": self.resources.render_dialog(enabled)}, @@ -306,7 +306,7 @@ def handle_speech_speed(self, message: Message): speed = self.MAX_SPEECH_SPEED speed = round(speed, 1) - self.update_profile({"speech": {"speed_multiplier": speed}}) + update_user_profile({"speech": {"speed_multiplier": speed}}) if speed == current_speed == self.MAX_SPEECH_SPEED: self.speak_dialog("speech_speed_limit", @@ -363,7 +363,8 @@ def handle_change_location_timezone(self, message: Message): do_timezone = False if do_timezone: - self.update_profile({"location": {"tz": tz_name, + LOG.info(f"Update timezone: {tz_name}|{utc_offset}") + update_user_profile({"location": {"tz": tz_name, "utc": utc_offset}}) self.speak_dialog("change_location_tz", {"type": self.resources.render_dialog("word_timezone"), @@ -371,7 +372,7 @@ def handle_change_location_timezone(self, message: Message): private=True) if do_location: LOG.info(f"Update location: {resolved_place}") - self.update_profile({'location': { + update_user_profile({'location': { 'city': resolved_place['address']['city'], 'state': resolved_place['address'].get('state'), 'country': resolved_place['address']['country'], @@ -405,7 +406,7 @@ def handle_change_dialog_mode(self, message: Message): private=True) return - self.update_profile( + update_user_profile( {"response_mode": {"limit_dialog": new_limit_dialog}}) self.speak_dialog("dialog_mode_changed", {"response": self.resources.render_dialog(new_dialog)}, @@ -570,7 +571,7 @@ def handle_set_my_birthday(self, message: Message): # speakable_birthday = nice_date(birth_date, now=anchor_date) speakable_birthday = birth_date.strftime("%B %-d") - self.update_profile({"user": {"dob": formatted_birthday}}, message) + update_user_profile({"user": {"dob": formatted_birthday}}, message) self.speak_dialog("birthday_confirmed", {"birthday": speakable_birthday}, private=True) @@ -619,7 +620,7 @@ def handle_set_my_email(self, message: Message): if self.ask_yesno("email_overwrite", {"old": self._spoken_email(current_email), "new": self._spoken_email(email_addr)}) == "yes": - self.update_profile({"user": {"email": email_addr}}) + update_user_profile({"user": {"email": email_addr}}) self.speak_dialog("email_set", {"email": self._spoken_email(email_addr)}, private=True) @@ -630,7 +631,7 @@ def handle_set_my_email(self, message: Message): return if self.ask_yesno("email_confirmation", {"email": self._spoken_email(email_addr)}) == "yes": - self.update_profile({"user": {"email": email_addr}}) + update_user_profile({"user": {"email": email_addr}}) self.speak_dialog("email_set", {"email": self._spoken_email(email_addr)}, private=True) @@ -639,7 +640,7 @@ def handle_set_my_email(self, message: Message): email_addr = self.get_gui_input(self.resources.render_dialog("word_email_title"), "test@neon.ai") if email_addr: - self.update_profile({"user": {"email": email_addr}}) + update_user_profile({"user": {"email": email_addr}}) self.speak_dialog("email_set", {"email": self._spoken_email(email_addr)}, private=True) @@ -732,7 +733,7 @@ def handle_set_my_name(self, message: Message): for n in ("first_name", "middle_name", "last_name")) full_name = " ".join((n for n in name_parts if n)) - self.update_profile({"user": {request: name, + update_user_profile({"user": {request: name, "full_name": full_name}}, message) self.speak_dialog( @@ -754,7 +755,7 @@ def handle_set_my_name(self, message: Message): f"word_name"), "name": name}) else: - self.update_profile({"user": updated_user_profile}, message) + update_user_profile({"user": updated_user_profile}, message) self.speak_dialog("name_set_full", {"nick": preferred_name, "name": name_parts["full_name"]}, @@ -831,7 +832,7 @@ def handle_set_stt_language(self, message: Message): if self.ask_yesno("language_change_confirmation", dialog_data) == "yes": - self.update_profile({"speech": {"stt_language": code}}) + update_user_profile({"speech": {"stt_language": code}}) self.speak_dialog("language_set", dialog_data, private=True) else: @@ -870,7 +871,7 @@ def handle_set_tts_language(self, message: Message): return gender = self._get_gender(primary) or \ user_settings["speech"]["tts_gender"] - self.update_profile({"speech": {"tts_gender": gender, + update_user_profile({"speech": {"tts_gender": gender, "tts_language": primary_code}}, message) self.speak_dialog("language_set", @@ -898,7 +899,7 @@ def handle_set_tts_language(self, message: Message): return gender = self._get_gender(secondary) or \ user_settings["speech"]["secondary_tts_gender"] - self.update_profile( + update_user_profile( {"speech": {"secondary_tts_gender": gender, "secondary_tts_language": secondary_code}}, message) @@ -928,7 +929,7 @@ def handle_set_tts_language(self, message: Message): return gender = self._get_gender(language) or \ user_settings["speech"]["tts_gender"] - self.update_profile({"speech": {"tts_gender": gender, + update_user_profile({"speech": {"tts_gender": gender, "tts_language": code}}, message) self.speak_dialog("language_set", @@ -985,7 +986,7 @@ def handle_no_secondary_language(self, message: Message): Handle a user request to only hear responses in one language :param message: Message associated with request """ - self.update_profile({"speech": {"secondary_tts_language": "", + update_user_profile({"speech": {"secondary_tts_language": "", "secondary_neon_voice": ""}}, message) self.speak_dialog("only_one_language", private=True) From fc1fa98a8a20538d84409271f67ef33e21e0d59b Mon Sep 17 00:00:00 2001 From: Daniel McKnight Date: Tue, 9 Jul 2024 18:40:43 -0700 Subject: [PATCH 3/7] Pass messagebus to `update_user_profile` calls --- __init__.py | 50 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/__init__.py b/__init__.py index 62f43f1..1367d2a 100644 --- a/__init__.py +++ b/__init__.py @@ -182,7 +182,7 @@ def handle_unit_change(self, message: Message): private=True) else: updated_prefs = {"units": {"measure": new_unit}} - update_user_profile(updated_prefs, message) + update_user_profile(updated_prefs, message, self.bus) self.speak_dialog("units_changed", {"unit": self.resources.render_dialog(f"word_{new_unit}")}, private=True) @@ -206,7 +206,7 @@ def handle_time_format_change(self, message: Message): {"scale": str(new_setting)}, private=True) else: updated_prefs = {"units": {"time": new_setting}} - update_user_profile(updated_prefs, message) + update_user_profile(updated_prefs, message, self.bus) self.speak_dialog("time_format_changed", {"scale": str(new_setting)}, private=True) @@ -230,7 +230,7 @@ def handle_date_format_change(self, message: Message): private=True) else: updated_prefs = {"units": {"date": new_setting}} - update_user_profile(updated_prefs, message) + update_user_profile(updated_prefs, message, self.bus) self.speak_dialog("date_format_changed", {"format": message.data.get(new_setting.lower())}, private=True) @@ -244,7 +244,8 @@ def handle_speak_hesitation(self, message: Message): :param message: Message associated with request """ enabled = True if message.data.get("permit") else False - update_user_profile({"response_mode": {"hesitation": enabled}}) + update_user_profile({"response_mode": {"hesitation": enabled}}, + message, self.bus) if enabled: self.speak_dialog("hesitation_enabled", private=True) else: @@ -276,7 +277,7 @@ def handle_transcription_retention(self, message: Message): private=True) else: updated_prefs = {"privacy": {kind: allow}} - update_user_profile(updated_prefs, message) + update_user_profile(updated_prefs, message, self.bus) self.speak_dialog("transcription_changed", {"transcription": self.resources.render_dialog(transcription), "enabled": self.resources.render_dialog(enabled)}, @@ -306,7 +307,8 @@ def handle_speech_speed(self, message: Message): speed = self.MAX_SPEECH_SPEED speed = round(speed, 1) - update_user_profile({"speech": {"speed_multiplier": speed}}) + update_user_profile({"speech": {"speed_multiplier": speed}}, + message, self.bus) if speed == current_speed == self.MAX_SPEECH_SPEED: self.speak_dialog("speech_speed_limit", @@ -365,7 +367,8 @@ def handle_change_location_timezone(self, message: Message): if do_timezone: LOG.info(f"Update timezone: {tz_name}|{utc_offset}") update_user_profile({"location": {"tz": tz_name, - "utc": utc_offset}}) + "utc": utc_offset}}, + message, self.bus) self.speak_dialog("change_location_tz", {"type": self.resources.render_dialog("word_timezone"), "location": f"UTC {utc_offset}"}, @@ -377,7 +380,7 @@ def handle_change_location_timezone(self, message: Message): 'state': resolved_place['address'].get('state'), 'country': resolved_place['address']['country'], 'lat': float(resolved_place['lat']), - 'lng': float(resolved_place['lon'])}}) + 'lng': float(resolved_place['lon'])}}, message, self.bus) self.speak_dialog("change_location_tz", {"type": self.resources.render_dialog("word_location"), "location": resolved_place['address']['city']}, @@ -407,7 +410,8 @@ def handle_change_dialog_mode(self, message: Message): return update_user_profile( - {"response_mode": {"limit_dialog": new_limit_dialog}}) + {"response_mode": {"limit_dialog": new_limit_dialog}}, + message, self.bus) self.speak_dialog("dialog_mode_changed", {"response": self.resources.render_dialog(new_dialog)}, private=True) @@ -571,7 +575,8 @@ def handle_set_my_birthday(self, message: Message): # speakable_birthday = nice_date(birth_date, now=anchor_date) speakable_birthday = birth_date.strftime("%B %-d") - update_user_profile({"user": {"dob": formatted_birthday}}, message) + update_user_profile({"user": {"dob": formatted_birthday}}, + message, self.bus) self.speak_dialog("birthday_confirmed", {"birthday": speakable_birthday}, private=True) @@ -620,7 +625,8 @@ def handle_set_my_email(self, message: Message): if self.ask_yesno("email_overwrite", {"old": self._spoken_email(current_email), "new": self._spoken_email(email_addr)}) == "yes": - update_user_profile({"user": {"email": email_addr}}) + update_user_profile({"user": {"email": email_addr}}, + message, self.bus) self.speak_dialog("email_set", {"email": self._spoken_email(email_addr)}, private=True) @@ -631,7 +637,8 @@ def handle_set_my_email(self, message: Message): return if self.ask_yesno("email_confirmation", {"email": self._spoken_email(email_addr)}) == "yes": - update_user_profile({"user": {"email": email_addr}}) + update_user_profile({"user": {"email": email_addr}}, + message, self.bus) self.speak_dialog("email_set", {"email": self._spoken_email(email_addr)}, private=True) @@ -640,7 +647,8 @@ def handle_set_my_email(self, message: Message): email_addr = self.get_gui_input(self.resources.render_dialog("word_email_title"), "test@neon.ai") if email_addr: - update_user_profile({"user": {"email": email_addr}}) + update_user_profile({"user": {"email": email_addr}}, + message, self.bus) self.speak_dialog("email_set", {"email": self._spoken_email(email_addr)}, private=True) @@ -735,7 +743,7 @@ def handle_set_my_name(self, message: Message): full_name = " ".join((n for n in name_parts if n)) update_user_profile({"user": {request: name, "full_name": full_name}}, - message) + message, self.bus) self.speak_dialog( "name_set_part", {"position": self.resources.render_dialog(f"word_{request}"), @@ -755,7 +763,8 @@ def handle_set_my_name(self, message: Message): f"word_name"), "name": name}) else: - update_user_profile({"user": updated_user_profile}, message) + update_user_profile({"user": updated_user_profile}, + message, self.bus) self.speak_dialog("name_set_full", {"nick": preferred_name, "name": name_parts["full_name"]}, @@ -832,7 +841,8 @@ def handle_set_stt_language(self, message: Message): if self.ask_yesno("language_change_confirmation", dialog_data) == "yes": - update_user_profile({"speech": {"stt_language": code}}) + update_user_profile({"speech": {"stt_language": code}}, + message, self.bus) self.speak_dialog("language_set", dialog_data, private=True) else: @@ -873,7 +883,7 @@ def handle_set_tts_language(self, message: Message): user_settings["speech"]["tts_gender"] update_user_profile({"speech": {"tts_gender": gender, "tts_language": primary_code}}, - message) + message, self.bus) self.speak_dialog("language_set", {"io": self.resources.render_dialog( "word_primary"), @@ -902,7 +912,7 @@ def handle_set_tts_language(self, message: Message): update_user_profile( {"speech": {"secondary_tts_gender": gender, "secondary_tts_language": secondary_code}}, - message) + message, self.bus) self.speak_dialog("language_set", {"io": self.resources.render_dialog( "word_secondary"), @@ -931,7 +941,7 @@ def handle_set_tts_language(self, message: Message): user_settings["speech"]["tts_gender"] update_user_profile({"speech": {"tts_gender": gender, "tts_language": code}}, - message) + message, self.bus) self.speak_dialog("language_set", {"io": self.resources.render_dialog( "word_primary"), @@ -988,7 +998,7 @@ def handle_no_secondary_language(self, message: Message): """ update_user_profile({"speech": {"secondary_tts_language": "", "secondary_neon_voice": ""}}, - message) + message, self.bus) self.speak_dialog("only_one_language", private=True) def _emit_weather_update(self, message: Message): From bd740e431d1bd3e9124c61324fe81bfbb3cd9e2e Mon Sep 17 00:00:00 2001 From: Daniel McKnight Date: Tue, 9 Jul 2024 18:48:33 -0700 Subject: [PATCH 4/7] Add fallback to `county` if resolved location has no `city` --- __init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/__init__.py b/__init__.py index 1367d2a..c80dc2b 100644 --- a/__init__.py +++ b/__init__.py @@ -1161,8 +1161,8 @@ def _get_location_from_spoken_location(location: str, LOG.warning(f"Could not locate: {location}") return None if not place['address'].get("city"): - place["address"]["city"] = place["address"].get("town") or \ - place["address"].get("village") + LOG.warning(f"No city specified in {place['address']}") + place['address']['city'] = place['address'].get('county') except AttributeError: LOG.warning(f"Could not locate: {location}") return None From bf9de7204d1e6c496fcc0547188c4e2a845bca96 Mon Sep 17 00:00:00 2001 From: Daniel McKnight Date: Tue, 9 Jul 2024 18:51:17 -0700 Subject: [PATCH 5/7] Update test case to account for map change --- test/test_skill.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_skill.py b/test/test_skill.py index d145941..04ac89d 100644 --- a/test/test_skill.py +++ b/test/test_skill.py @@ -438,7 +438,7 @@ def _init_test_message(voc, location): "also_change_location_tz", {"type": "timezone", "new": "honolulu"}) self.skill.speak_dialog.assert_has_calls(( call("change_location_tz", - {"type": "location", "location": "Honolulu"}, private=True), + {"type": "location", "location": "Honolulu County"}, private=True), call("change_location_tz", {"type": "timezone", "location": "UTC -10.0"}, private=True)), True) From aeeb48996001eb9b6eddffec634b15ca5a8dc2f4 Mon Sep 17 00:00:00 2001 From: Daniel McKnight Date: Tue, 9 Jul 2024 18:55:35 -0700 Subject: [PATCH 6/7] Update test case to account for map change --- test/test_skill.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/test_skill.py b/test/test_skill.py index 04ac89d..5013d03 100644 --- a/test/test_skill.py +++ b/test/test_skill.py @@ -432,13 +432,14 @@ def _init_test_message(voc, location): # Change location and tz _init_test_message("location", "honolulu") + new_city = "Honolulu County" # TODO: This is semi-variable as the map API changes sleep(1) self.skill.handle_change_location_timezone(test_message) self.skill.ask_yesno.assert_called_once_with( "also_change_location_tz", {"type": "timezone", "new": "honolulu"}) self.skill.speak_dialog.assert_has_calls(( call("change_location_tz", - {"type": "location", "location": "Honolulu County"}, private=True), + {"type": "location", "location": new_city}, private=True), call("change_location_tz", {"type": "timezone", "location": "UTC -10.0"}, private=True)), True) @@ -448,7 +449,7 @@ def _init_test_message(voc, location): for setting in unchanged: self.assertEqual(profile["location"][setting], test_profile["location"][setting]) - self.assertEqual(profile["location"]["city"], "Honolulu") + self.assertEqual(profile["location"]["city"], new_city) self.assertEqual(profile["location"]["state"], "Hawaii") self.assertAlmostEqual(profile["location"]["lat"], 21.2890997, 0) self.assertAlmostEqual(profile["location"]["lng"], -157.717299, 0) From c4bffb3e27f62c1b0b1758fdcc80ca2bc2a80c29 Mon Sep 17 00:00:00 2001 From: Daniel McKnight Date: Tue, 9 Jul 2024 19:02:14 -0700 Subject: [PATCH 7/7] Update location handling --- __init__.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/__init__.py b/__init__.py index c80dc2b..a6a79df 100644 --- a/__init__.py +++ b/__init__.py @@ -761,7 +761,7 @@ def handle_set_my_name(self, message: Message): self.speak_dialog("name_not_changed", {"position": self.resources.render_dialog( f"word_name"), - "name": name}) + "name": name}) else: update_user_profile({"user": updated_user_profile}, message, self.bus) @@ -887,7 +887,7 @@ def handle_set_tts_language(self, message: Message): self.speak_dialog("language_set", {"io": self.resources.render_dialog( "word_primary"), - "lang": primary_spoken}, private=True) + "lang": primary_spoken}, private=True) except UnsupportedLanguageError: LOG.warning(f"No language for primary request: {primary}") self.speak_dialog("language_not_recognized", {"lang": primary}, @@ -916,7 +916,7 @@ def handle_set_tts_language(self, message: Message): self.speak_dialog("language_set", {"io": self.resources.render_dialog( "word_secondary"), - "lang": secondary_spoken}, private=True) + "lang": secondary_spoken}, private=True) except UnsupportedLanguageError: LOG.warning(f"No language for secondary request: {secondary}") self.speak_dialog("language_not_recognized", @@ -945,7 +945,7 @@ def handle_set_tts_language(self, message: Message): self.speak_dialog("language_set", {"io": self.resources.render_dialog( "word_primary"), - "lang": spoken}, private=True) + "lang": spoken}, private=True) except UnsupportedLanguageError: LOG.warning(f"No language for secondary request: {language}") self.speak_dialog("language_not_recognized", @@ -1161,8 +1161,12 @@ def _get_location_from_spoken_location(location: str, LOG.warning(f"Could not locate: {location}") return None if not place['address'].get("city"): + # TODO: Delegate this to `get_full_location` LOG.warning(f"No city specified in {place['address']}") - place['address']['city'] = place['address'].get('county') + place['address']['city'] = place["address"].get("town") or \ + place["address"].get("village") or \ + place["address"].get("hamlet") or \ + place['address'].get('county') except AttributeError: LOG.warning(f"Could not locate: {location}") return None