Пример #1
0
 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()
Пример #2
0
    def send_email(self, title, body, message=None, email_addr=None, attachments=None):
        """
        Send an email to the registered user's email.
        Email address priority: email_addr, user prefs from message, fallback to DeviceApi for Mycroft method

        Arguments:
            title (str): Title of email
            body  (str): HTML body of email. This supports
                         simple HTML like bold and italics
            email_addr (str): Optional email address to use
            attachments (dict): Optional dict of file names to Base64 encoded files
            message (Message): Optional message to get email from
        """
        if not email_addr and message:
            email_addr = self.preference_user(message).get("email")

        if email_addr:
            LOG.info("Send email via Neon Server")
            try:
                LOG.debug(f"body={body}")
                self.bus.emit(Message("neon.send_email", {"title": title, "email": email_addr, "body": body,
                                                          "attachments": attachments}))
            except Exception as e:
                LOG.error(e)
        else:
            super().send_email(title, body)
    def check_state(self):
        """Check if an event should be triggered."""
        with self.event_lock:
            # Check all events
            pending_messages = []
            for event in self.events:
                current_time = time.time()
                e = self.events[event]
                # Get scheduled times that has passed
                passed = [(t, r, d) for (t, r, d) in e if t <= current_time]
                # and remaining times that we're still waiting for
                remaining = [(t, r, d) for t, r, d in e if t > current_time]
                # Trigger registered methods
                for sched_time, repeat, data in passed:
                    pending_messages.append(Message(event, data))
                    # if this is a repeated event add a new trigger time
                    if repeat:
                        next_time = repeat_time(sched_time, repeat)
                        remaining.append((next_time, repeat, data))
                # update list of events
                self.events[event] = remaining

        # Remove events have are now completed
        self.clear_empty()

        # Finally, emit the queued up events that triggered
        for msg in pending_messages:
            self.bus.emit(msg)
Пример #4
0
    def make_active(self, duration_minutes=5):
        """Bump skill to active_skill list in intent_service.

        This enables converse method to be called even without skill being
        used in last 5 minutes.
        :param duration_minutes: duration in minutes for skill to remain active (-1 for infinite)
        """
        self.bus.emit(Message("active_skill_request",
                              {"skill_id": self.skill_id,
                               "timeout": duration_minutes}))
Пример #5
0
    def report_metric(self, name, data):
        """Report a skill metric to the Mycroft servers.

        Arguments:
            name (str): Name of metric. Must use only letters and hyphens
            data (dict): JSON dictionary to report. Must be valid JSON
        """
        combinded = deepcopy(data)
        combinded["name"] = name
        self.bus.emit(Message("neon.metric", combinded))
Пример #6
0
    def request_check_timeout(self, time_wait, intent_to_check):
        LOG.info("request received")
        LOG.info(time_wait)
        LOG.info(len(intent_to_check))
        try:
            if isinstance(intent_to_check, str):
                intent_to_check = [intent_to_check]

            for intent in intent_to_check:
                data = {'time_out': time_wait,
                        'intent_to_check': f"{self.skill_id}:{intent}"}
                LOG.debug(f"DM: Set Timeout: {data}")
                self.bus.emit(Message("set_timeout", data))
        except Exception as x:
            LOG.error(x)
Пример #7
0
 def mobile_skill_intent(self, action: str, arguments: dict, message: Message):
     """
     Handle a mobile skill intent response
     :param action: Name of action or event for mobile device to handle
     :param arguments: dict of key/value arguments to pass with action
     :param message: Message associated with request
     """
     fmt_args = ""
     for key, value in arguments:
         fmt_args += f"&{key}={value}"
     if self.server:
         emit_data = [action, fmt_args, message.context["klat_data"]["request_id"]]
         self.bus.emit(Message("css.emit", {"event": "mobile skill intent", "data": emit_data}))
     else:
         LOG.warning("Mobile intents are not supported on this device yet.")
Пример #8
0
 def on_message(self, _, message):
     parsed_message = Message.deserialize(message)
     self.emitter.emit('message', message)
     self.emitter.emit(parsed_message.msg_type, parsed_message)
Пример #9
0
    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()
Пример #10
0
 def socket_emit_to_server(self, event: str, data: list):
     LOG.debug(f"Emit event={event}, data={data}")
     self.bus.emit(Message("css.emit", {"event": event, "data": data}))