def preference_speech(self, message=None) -> dict: """ Returns the speech dictionary that contains language and spoken response preferences Equivalent to self.user_config["speech"] for non-server use """ try: nick = get_message_user(message) if message else None if self.server: if not message or not nick: LOG.warning("No message given!") return self.user_config['speech'] if message.context.get("nick_profiles"): return message.context["nick_profiles"][nick]["speech"] else: LOG.error(f"Unable to get user settings! message={message.data}") else: return self.user_config['speech'] except Exception as x: LOG.error(x) return {'stt_language': 'en', 'stt_region': 'US', 'alt_languages': ['en'], 'tts_language': "en-us", 'tts_gender': 'female', 'neon_voice': 'Joanna', 'secondary_tts_language': '', 'secondary_tts_gender': '', 'secondary_neon_voice': '', 'speed_multiplier': 1.0, 'synonyms': {} }
def update_profile(self, new_preferences: dict, message: Message = None): """ Updates a user profile with the passed new_preferences :param new_preferences: dict of updated preference values. Should follow {section: {key: val}} format :param message: Message associated with request """ if self.server: nick = get_message_user(message) if message else None new_skills_prefs = new_preferences.pop("skills") old_skills_prefs = message.context["nick_profiles"][nick]["skills"] combined_skill_prefs = {**old_skills_prefs, **new_skills_prefs} combined_changes = {k: v for dic in new_preferences.values() for k, v in dic.items()} if new_skills_prefs: combined_changes["skill_settings"] = json.dumps(list(combined_skill_prefs.values())) new_preferences["skills"] = combined_skill_prefs LOG.debug(f"combined_skill_prefs={combined_skill_prefs}") combined_changes["username"] = nick self.socket_emit_to_server("update profile", ["skill", combined_changes, message.context["klat_data"]["request_id"]]) self.bus.emit(Message("neon.remove_cache_entry", {"nick": nick})) old_preferences = message.context["nick_profiles"][nick] message.context["nick_profiles"][nick] = {**old_preferences, **new_preferences} else: for section, settings in new_preferences: # section in user, brands, units, etc. for key, val in settings: self.user_config[section][key] = val self.user_config.write_changes()
def preference_location(self, message=None) -> dict: """ Get the JSON data structure holding location information. Equivalent to self.user_config["location"] for non-server use """ try: nick = get_message_user(message) if message else None if self.server: if not message or not nick: LOG.warning("No message given!") return self.user_config['location'] if message.context.get("nick_profiles"): return message.context["nick_profiles"][nick]["location"] else: LOG.error(f"Unable to get user settings! message={message.data}") else: return self.user_config['location'] except Exception as x: LOG.error(x) return {'lat': 47.4799078, 'lng': -122.2034496, 'city': 'Renton', 'state': 'Washington', 'country': 'USA', 'tz': 'America/Los_Angeles', 'utc': -8.0 }
def preference_user(self, message=None) -> dict: """ Returns the user dictionary with name, email Equivalent to self.user_config["user"] for non-server use """ try: nick = get_message_user(message) if message else None if self.server: if not message or not nick: LOG.warning("No message given!") return self.user_config['user'] if message.context.get("nick_profiles"): return message.context["nick_profiles"][nick]["user"] else: LOG.error(f"Unable to get user settings! message={message.data}") else: return self.user_config['user'] except Exception as x: LOG.error(x) return {'first_name': '', 'middle_name': '', 'last_name': '', 'preferred_name': '', 'full_name': '', 'dob': 'YYYY/MM/DD', 'age': '', 'email': '', 'username': '', 'password': '', 'picture': '', 'about': '', 'phone': '', 'email_verified': False, 'phone_verified': False }
def preference_skill(self, message=None) -> dict: """ Returns the skill settings configuration Equivalent to self.settings for non-server :param message: Message associated with request :return: dict of skill preferences """ nick = get_message_user(message) if message else None if self.server and nick: try: skill = self.skill_id LOG.info(f"Get server prefs for skill={skill}") user_overrides = message.context["nick_profiles"][nick][ "skills"].get(self.skill_id, dict()) LOG.debug(user_overrides) merged_settings = {**self.settings, **user_overrides} if user_overrides.keys() != merged_settings.keys(): LOG.info( f"New settings keys: user={nick}|skill={self.skill_id}|user={user_overrides}" ) self.update_skill_settings(merged_settings, message) return merged_settings except Exception as e: LOG.error(e) return self.settings
def preference_brands(self, message=None) -> dict: """ Returns a brands dictionary for the user Equivalent to self.user_config["speech"] for non-server use """ try: nick = get_message_user(message) if message else None if self.server: if not message or not nick: LOG.warning("No message given!") return self.user_config['brands'] if message.context.get("nick_profiles"): return message.context["nick_profiles"][nick]["brands"] else: LOG.error( f"Unable to get user settings! message={message.data}") else: return self.user_config['brands'] except Exception as x: LOG.error(x) return { 'ignored_brands': {}, 'favorite_brands': {}, 'specially_requested': {} }
def get_utterance_user(self, message: Optional[Message]) -> str: """ Gets the user associated with the given message. Returns default 'local' or 'server' if no user specified. Args: message: Message associated with request Returns: Username associated with the message or a default value of 'local' or 'server'. """ if self.server: default_user = "******" else: default_user = self.preference_user(message).get("username", "local") if not message: return default_user try: return get_message_user(message) or default_user except Exception as e: LOG.error(e) # TODO: Depreciate this and fix underlying error DM return default_user
def preference_unit(self, message=None) -> dict: """ Returns the units dictionary that contains time, date, measure formatting preferences Equivalent to self.user_config["units"] for non-server use """ try: nick = get_message_user(message) if message else None if self.server: if not message or not nick: LOG.warning("No message given!") return self.user_config['units'] if message.context.get("nick_profiles"): return message.context["nick_profiles"][nick]["units"] else: LOG.error( f"Unable to get user settings! message={message.data}") else: return self.user_config['units'] except Exception as x: LOG.error(x) return {'time': 12, 'date': 'MDY', 'measure': 'imperial'}
def speak(self, utterance, expect_response=False, wait=False, meta=None, message=None, private=False, speaker=None): """ Speak a sentence. Arguments: utterance (str): sentence mycroft should speak expect_response (bool): set to True if Mycroft should listen for a response immediately after speaking the utterance. message (Message): message associated with the input that this speak is associated with private (bool): flag to indicate this message contains data that is private to the requesting user speaker (dict): dict containing language or voice data to override user preference values wait (bool): set to True to block while the text is being spoken. meta: Information of what built the sentence. """ # registers the skill as being active meta = meta or {} meta['skill'] = self.name self.enclosure.register(self.name) if utterance: if not message: # Find the associated message LOG.debug('message is None.') message = dig_for_message() if not message: message = Message("speak") if not speaker: speaker = message.data.get("speaker", None) nick = get_message_user(message) if private and self.server: LOG.debug("Private Message") title = message.context["klat_data"]["title"] need_at_sign = True if title.startswith("!PRIVATE"): users = title.split(':')[1].split(',') for idx, val in enumerate(users): users[idx] = val.strip() if len(users) == 2 and "Neon" in users: need_at_sign = False elif len(users) == 1: need_at_sign = False elif nick.startswith("guest"): need_at_sign = False if need_at_sign: LOG.debug("Send message to private cid!") utterance = f"@{nick} {utterance}" data = {"utterance": utterance, "expect_response": expect_response, "meta": meta, "speaker": speaker} if message.context.get("cc_data", {}).get("emit_response"): msg_to_emit = message.reply("skills:execute.response", data) else: message.context.get("timing", {})["speech_start"] = time.time() msg_to_emit = message.reply("speak", data, message.context) LOG.debug(f"Skill speak! {data}") LOG.debug(msg_to_emit.msg_type) self.bus.emit(msg_to_emit) else: LOG.warning("Null utterance passed to speak") LOG.warning(f"{self.name} | message={message}") if wait: wait_while_speaking()