示例#1
0
    def handle_create_event(self, message):
        """
        Handler to create a new event in the calendar. It checked first
        if a title or date is given in the intent message. Then the user is
        asked for missing information as start time, duration or full-day event.
        If all information are present the event is created using the CalDav interface.
        :param message: the intent message
        :return: None
        """
        title, date = get_title_date_from_message(message)
        fullday = False

        while title is None:
            title = self.get_response("ask.for.title", {"action": "create"})
        self.log.info(f"set title of new event to: {title}")

        if date is None:
            date_response = self.get_response("ask.for.date")
            date, rest = extract_datetime(date_response)
        self.log.info(f"set date of new event to: {date}")

        title = self.remove_time_from_title(title)

        if date.time() == dt.time(0):
            time, rest = None, None
            pattern = re.compile(r"full\s*day")
            while time is None or time.time() == dt.time(0):
                rest = self.get_response("new.event.starttime",
                                         {"event": title})
                if rest is not None:
                    extracted = extract_datetime(rest)
                    if extracted is not None:
                        time, rest = extracted
                    if re.search(pattern, rest):
                        fullday = True
                        break

            if not fullday:
                date = datetime.combine(date.date(), time.time())

        duration = None
        while duration is None:
            if not fullday:
                duration_utterance = self.get_response(
                    "ask.duration.new.event")
                duration, rest = extract_duration(duration_utterance)
            else:
                duration_utterance = self.get_response("ask.fullday.duration")
                duration = extract_number(duration_utterance)

        self.log.info(
            f"New calendar event will be created. Title: {title}, Date: {str(date)}"
        )

        self.caldav_interface.create_new_event(title, date, duration, fullday)

        self.speak_dialog("successful.create.event", {
            "event": title,
            "date": nice_date(date)
        })
 def handle_rain_waves_wind_intent(self, message):
     utterance = message.data.get('utterance', "")
     match, confidence = match_one(utterance, self.play_list)
     try:
         track_duration = int(
             extract_duration(utterance)[0].total_seconds())
     except AttributeError:
         return None
     self.play_track(match, track_duration, utterance)
 def handle_white_noise_intent(self, message):
     utterance = message.data.get('utterance', "")
     try:
         track_duration = int(
             extract_duration(utterance)[0].total_seconds())
     except AttributeError:
         return None
     self.play_track(join(dirname(__file__), "whitenoise.mp3"),
                     track_duration, utterance)
    def _seek_relative(self, message, controller):
        direction = 1 if "Forward" in message.data else -1

        duration = extract_duration(message.utterance_remainder())[0]
        duration = duration.seconds if duration else self._default_duration
        duration *= direction

        current_time = controller.status.current_time
        controller.seek(current_time + duration)
        LOGGER.info("Seek {duration} on {device}".format(duration=duration,
                                                         device=controller))
    def _fetch_movie_details(self, movie):
        # Fetch extra movie data from dedicated webpage
        movie_page = get(movie.getchildren()[5].getchildren()[0].get('href'))
        movie_data = html.fromstring(movie_page.content)
        # TODO cache result - is it worth creating a movie class?
        duration_mins = movie.getchildren()[2].text[0:-1] + ' minutes'
        synopsis_element = movie_data.xpath(
            '//div[@id="main_content"]/div[@class="container"] \
            /div[@class="row"]/div[@class="span8"] \
            /div[@class="content"]/p')
        # Sometimes they put a span tag around the synopsis text...
        synopsis = synopsis_element[0].text if synopsis_element[0].text \
                   else synopsis_element[0].getchildren()[0].text
        # Remaining details in relatively consistent locations on right side.
        right_panel = movie_data.xpath(
            '//div[@id="main_content"]/div[@class="container"] \
            /div[@class="row"]/div[@class="span4"]')[0]

        def get_info(info_type):
            # Find element containing info as heading, then return next element
            heading = next((x for x in right_panel if x.text == info_type))
            info = heading.getnext().text if heading.getnext().text \
                   else heading.getnext().getchildren().text
            return info

        # Construct return object
        movie_details = {
            # First details from program page
            'title': movie.getchildren()[0].getchildren()[0].text,
            'length': nice_duration(extract_duration(duration_mins)[0]),
            'rating': movie.getchildren()[3].text,
            'screening_location': movie.getchildren()[4].text,
            # Remaining from movie_data
            'synopsis': synopsis,
            'director': get_info('Director'),
            'year': get_info('Year'),
            'country': get_info('Country of Origin'),
            'language': get_info('Language'),
        }
        return movie_details
示例#6
0
    def _extract_duration(self, text):
        """ Extract duration in seconds
        Args:
            text (str): Full request, e.g. "set a 30 second timer"
        Returns:
            (int): Seconds requested, or None
            (str): Remainder of utterance
        """
        if not text:
            return None, None

        # Some STT engines return "30-second timer" not "30 second timer"
        # Deal with that before calling extract_duration().
        # TODO: Fix inside parsers
        utt = text.replace("-", " ")
        duration, str_remainder = extract_duration(utt, self.lang)
        if duration:
            # Remove "  and" left behind from "for 1 hour and 30 minutes"
            # prevents it being interpretted as a name "for  and"
            str_remainder = re.sub(r'\s\sand', '', str_remainder, flags=re.I)
            return duration.total_seconds(), str_remainder

        return None, text
示例#7
0
    def seek_intent(self, message):

        global time_actual

        init(self)
        power_on(self)  # TODO solve API delay in fast seeking

        if status_power == "ON":
            self.log.debug("DEBUG CHANNEL SEEK")

            if status_device(self) == "NOPLAY":
                self.log.info("KUKI IS NOT PLAYING ANY VIDEO")
                self.speak_dialog('shifting.no.play')
                sys.exit()  # TODO need refactor

            # check where actual video time is
            time_now = datetime.now().timestamp()  # actual time in UTC

            if time_actual == "":
                time_actual = time_now - 5  # set actual time right now minus 5 sec (one chunk protection)
                self.log.debug("USE UTC TIME")

            else:
                if time_actual / 1000 > time_now:
                    time_actual = time_now - 5
                    self.log.debug("BACK FROM FUTURE")

                else:
                    actual_time_position = datetime.fromtimestamp(time_actual)
                    self.log.debug("USE ACTUAL TIME POSITION")

            # check if duration of datetime is present
            duration = message.data.get('duration')
            date_or_time = message.data.get('datetime')

            if duration is not None:
                self.log.debug("DURATION FOUND")
                move = extract_duration(
                    message.data["utterance"])[1]  # seek direction
                duration = duration.replace(
                    "-",
                    " ")  # some STT engines return "5-minutes" not "5 minutes"
                time = extract_duration(duration)[
                    0]  # seek duration in seconds
                time_clean = int(time.seconds)  # duration like integer

                # words of seek direction. TODO need refactor to detect locales and read data from localized files, self.lang etc.
                self.move_word = {
                    'zpět': "zpět",
                    'nazpět': "zpět",
                    'zpátky': "zpět",
                    'dozadu': "zpět",
                    'vrátit': "zpět",
                    'dopředu': "dopředu",
                    'vpřed': "dopředu",
                    'back': "back",
                    'rewind': "back",
                    'forward': "forward",
                    'fast forward': "forward",
                    'ahead': "forward"
                }

                move_direction = self.move_word[move]  # select move from word

                if move_direction == "zpět" or "back":
                    self.log.debug("SEEK BACK")
                    time_position = time_actual - time_clean

                elif move_direction == "dopředu" or "forward":
                    self.log.debug("SEEK FORWARD")
                    time_position = time_actual + time_clean

                else:
                    self.log.error("ERROR IN SEEKING")
                    sys.exit()

            elif date_or_time is not None:
                self.log.info("DATETIME FOUND")

                when = message.data.get('utterance').lower()
                when = extract_datetime(when)[0]
                time_position = datetime.timestamp(when)
                move_direction = ''

            else:
                self.log.error("SEEK DATA NOT FOUND")
                sys.exit()

            #API POST
            self.api_headers = {'X-SessionKey': session}
            self.api_post = {
                'action': "seek",
                'position': time_position * 1000
            }  # Kuki platform needs milisecond

            self.api_remote = requests.post(url=API_REMOTE_URL +
                                            preferred_device_id,
                                            headers=self.api_headers,
                                            data=self.api_post)

            self.speak_dialog('shifting', data={'move': move_direction})
示例#8
0
 def validate_duration(string):
     """Check that extract_duration returns a valid duration."""
     res = extract_duration(string, self.lang)
     return res and res[0]
示例#9
0
 def test_extract_duration_en(self):
     self.assertEqual(extract_duration("10 seconds"),
                      (timedelta(seconds=10.0), ""))
     self.assertEqual(extract_duration("5 minutes"),
                      (timedelta(minutes=5), ""))
     self.assertEqual(extract_duration("2 hours"), (timedelta(hours=2), ""))
     self.assertEqual(extract_duration("3 days"), (timedelta(days=3), ""))
     self.assertEqual(extract_duration("25 weeks"),
                      (timedelta(weeks=25), ""))
     self.assertEqual(extract_duration("seven hours"),
                      (timedelta(hours=7), ""))
     self.assertEqual(extract_duration("7.5 seconds"),
                      (timedelta(seconds=7.5), ""))
     self.assertEqual(
         extract_duration("eight and a half days thirty"
                          " nine seconds"),
         (timedelta(days=8.5, seconds=39), ""))
     self.assertEqual(extract_duration("Set a timer for 30 minutes"),
                      (timedelta(minutes=30), "set a timer for"))
     self.assertEqual(
         extract_duration("Four and a half minutes until"
                          " sunset"),
         (timedelta(minutes=4.5), "until sunset"))
     self.assertEqual(extract_duration("Nineteen minutes past the hour"),
                      (timedelta(minutes=19), "past the hour"))
     self.assertEqual(
         extract_duration("wake me up in three weeks, four"
                          " hundred ninety seven days, and"
                          " three hundred 91.6 seconds"),
         (timedelta(weeks=3, days=497,
                    seconds=391.6), "wake me up in , , and"))
     self.assertEqual(
         extract_duration("The movie is one hour, fifty seven"
                          " and a half minutes long"),
         (timedelta(hours=1, minutes=57.5), "the movie is ,  long"))
     self.assertEqual(extract_duration(""), None)
示例#10
0
    def handle_loop_whitenoise(self, message):
        print("inside loop handler")
        wait_while_speaking()
        print(message.data.get('sound'))
        self.stopped = False
        now = datetime.now()
        if message.data.get('sound') is not None:
            print("inside not None")
            title = message.data.get('sound')
            score = match_one(title, self.play_list)
            print(score)
            if score[1] > 0.5:
                self.process = play_wav(score[0])
                fname = score[0]
                with contextlib.closing(wave.open(fname, 'r')) as f:
                    frames = f.getnframes()
                    rate = f.getframerate()
                    duration = frames / float(rate)
                    self.audio_length = duration
                    print(duration)
                    self.songTimer = {
                        "file": fname,
                        "expires": now + timedelta(seconds=self.audio_length)
                    }
                    self.check_replay(None)
            else:
                return None
                self.speak('Sorry I could not find that sound in my library')
        else:
            print("inside None")
            sound_file = list(self.play_list.values())
            sound_file = random.choice(sound_file)
            print(sound_file)
            #if os.path.isfile(sound_file):
            wait_while_speaking()
            self.process = play_wav(sound_file)
            fname = sound_file
            with contextlib.closing(wave.open(fname, 'r')) as f:
                frames = f.getnframes()
                rate = f.getframerate()
                duration = frames / float(rate)
                self.audio_length = duration
                print(duration)
                self.songTimer = {
                    "file": fname,
                    "expires": now + timedelta(seconds=self.audio_length)
                }
                self.check_replay(None)

        #Extract Time and Duration of Audio Play
        utt = normalize(message.data.get('utterance', "").lower())
        extract = extract_duration(utt)
        print(extract)
        if extract:
            total_duration = extract[0]
            self.endtime = extract[0]
            utt = extract[1]
        utc = pytz.UTC
        print("Current Duration:")
        secs = self.endtime.total_seconds()

        time_expires = now + timedelta(seconds=secs)
        self.timer = {"duration": secs, "expires": time_expires}
        self.update_time(None)
示例#11
0
    def handle_add_event_intent(self, message):
        utt = message.data['utterance']
        time_delta, remaining_utt = extract_duration(
            utt)  # get time duration from utterance
        start_time, remaining_utt = extract_datetime(
            remaining_utt)  # get time from utterance
        owner = message.data.get('Owner')  # get calendar owner
        utt = normalize(utt).replace("'s",
                                     "")  # normalize and drop 's in utterance
        parsed_utt = asjson(
            self.PEGParser.parse(utt))  # parse utterance for owner
        owner = parsed_utt.get('calendar_owner')
        if owner is None:  # if parser failed to get owner, prompt user
            owner = self.get_response('ask.calendar.owner')

        self.log.info('using owner: {}'.format(owner))

        try:  # get the calendar belonging to owner
            calName = self.nameToCalendar[owner]  # throw error if none found
        except KeyError:
            self.speak_dialog('no.calendar.found.error', {'name': owner})
            return

        if start_time is None:  # if start time not found
            start_time, _ = extract_datetime(
                self.get_response('ask.start.time'))  # ask the user

        if time_delta is None:  # if duration not found
            time_delta, _ = extract_duration(
                self.get_response('ask.duration'))  # ask the user

        if time_delta is None or start_time is None:  # if duration of start time STILL unkonwn
            self.speak(
                'sorry. i was not able to understand. please start over.'
            )  # fail
            return

        end_time = start_time + time_delta  # calculate end time

        eventName = self.get_response(
            'ask.event.name').title()  # ask for event name

        confirmation = self.ask_yesno(
            'confirm.event',  # confirm details
            {
                'event_name': eventName,
                'confirmation_text': self.confirmEventDetails(
                    start_time, end_time),
                'owner': self.calendarToName[calName]
            })
        if confirmation == 'no':
            self.speak_dialog('confirmation.failed')

        elif confirmation == 'yes':
            url, user, password = self.getConfigs()  # get  configs
            if url is None:  # if getConfigs returned None, it failed and
                pass  # already spoke to user
            else:
                calendar = self.getCalendar(
                    calName, url, user,
                    password)  # get calendar and create the event
                self.makeEvent(calendar,
                               start_time,
                               end_time,
                               eventName,
                               owner=self.calendarToName[calName])
        else:
            self.speak('sorry i did not understand.')
示例#12
0
 def test_extract_duration_en(self):
     self.assertEqual(extract_duration("10 seconds"),
                      (timedelta(seconds=10.0), ""))
     self.assertEqual(extract_duration("5 minutes"),
                      (timedelta(minutes=5), ""))
     self.assertEqual(extract_duration("2 hours"),
                      (timedelta(hours=2), ""))
     self.assertEqual(extract_duration("3 days"),
                      (timedelta(days=3), ""))
     self.assertEqual(extract_duration("25 weeks"),
                      (timedelta(weeks=25), ""))
     self.assertEqual(extract_duration("seven hours"),
                      (timedelta(hours=7), ""))
     self.assertEqual(extract_duration("7.5 seconds"),
                      (timedelta(seconds=7.5), ""))
     self.assertEqual(extract_duration("eight and a half days thirty"
                      " nine seconds"),
                      (timedelta(days=8.5, seconds=39), ""))
     self.assertEqual(extract_duration("Set a timer for 30 minutes"),
                      (timedelta(minutes=30), "set a timer for"))
     self.assertEqual(extract_duration("Four and a half minutes until"
                      " sunset"),
                      (timedelta(minutes=4.5), "until sunset"))
     self.assertEqual(extract_duration("Nineteen minutes past the hour"),
                      (timedelta(minutes=19), "past the hour"))
     self.assertEqual(extract_duration("wake me up in three weeks, four"
                                       " hundred ninety seven days, and"
                                       " three hundred 91.6 seconds"),
                      (timedelta(weeks=3, days=497, seconds=391.6),
                          "wake me up in , , and"))
     self.assertEqual(extract_duration("The movie is one hour, fifty seven"
                                       " and a half minutes long"),
                      (timedelta(hours=1, minutes=57.5),
                          "the movie is ,  long"))