Пример #1
0
def best_confidence(title, query):
    """Find best match for a title against a query.
    Some titles include ( Remastered 2016 ) and similar info. This method
    will test the raw title and a version that has been parsed to remove
    such information.
    Arguments:
        title: title name from spotify search
        query: query from user
    Returns:
        (float) best condidence
    """
    best = title.lower()
    best_stripped = re.sub(r'(\(.+\)|-.+)$', '', best).strip()
    return max(fuzzy_match(best, query),
               fuzzy_match(best_stripped, query))
    def get_timezone(self, locale):
        print("get_timezone")
        #print("5")
        try:
            #gère les noms de villes connues ex: "New York", "Paris", ect...
            return pytz.timezone(self.astral[locale].timezone)
        except:
            print("try_1 failed")
            pass
        try:
            # gère du code tel que "Nice/France"
            return pytz.timezone(locale)
        except:
            print("try_2 failed")
            pass
        timezones = self.translate_namedvalues("timezone.value")
        for timezone in timezones:
            if locale.lower() == timezone.lower():
                # suppose que la traduction est correcte
                return pytz.timezone(timezones[timezone].strip())
        target = locale.lower()
        best = None
        for name in pytz.all_timezones:
            normalized = name.lower().replace("_", " ").split("/")
            if len(normalized) == 1:
                pct = fuzzy_match(normalized[0], target)
            elif len(normalized) >= 2:
                pct = fuzzy_match(normalized[1], target)
                pct2 = fuzzy_match(normalized[-2] + " " + normalized[-1],
                                   target)
                pct3 = fuzzy_match(normalized[-1] + " " + normalized[-2],
                                   target)
                pct = max(pct, pct2, pct3)
            if not best or pct >= best[0]:
                best = (pct, name)
        if best and best[0] > 0.8:
            return pytz.timezone(best[1])
        if best and best[0] > 0.3:
            say = re.sub(r"([a-z])([A-Z])", r"\g<1> \g<2>", best[1])
            say = say.replace("_", " ")
            say = say.split("/")
            say.reverse()
            say = " ".join(say)
            if self.ask_yesno("vouliez.vous.dire", data={"zone_name":
                                                         say}) == "yes":
                return pytz.timezone(best[1])

        return None
Пример #3
0
    def query_playlist(self, playlist):
        """ Try to find a playlist.

            First searches the users playlists, then tries to find a public
            one.

            Arguments:
                playlist (str): Playlist to search for

            Returns: Tuple with confidence and data or NOTHING_FOUND
        """
        result, conf = self.get_best_playlist(playlist)
        if playlist and conf > 0.5:
            uri = self.playlists[result]
            return (conf, {'data': uri, 'name': playlist, 'type': 'playlist'})
        else:
            data = self.spotify.search(playlist, type='playlist')
            if data and data['playlists']['items']:
                best = data['playlists']['items'][0]
                confidence = fuzzy_match(best['name'].lower(), playlist)
                print(best)
                return (confidence, {
                    'data': best,
                    'name': best['name'],
                    'type': 'playlist'
                })

        return NOTHING_FOUND
Пример #4
0
    def ocp_hppodcraft_readings_playlist(self, phrase, media_type):
        score = self.get_base_score(phrase, media_type)

        if media_type == MediaType.PODCAST:
            return

        pl = [{
            "match_confidence": fuzzy_match(phrase, k) * 100,
            "media_type": MediaType.AUDIOBOOK,
            "uri": v["stream"],
            "title": k,
            "playback": PlaybackType.AUDIO,
            "image": self.default_image,
            "bg_image": self.default_bg,
            "skill_icon": self.skill_icon,
            "author": "HPPodcraft",
            "album": "HPPodcraft"
        } for k, v in self.readings.items()]
        pl = sorted(pl, key=lambda k: k["title"])
        return [{
            "match_confidence": score,
            "media_type": MediaType.AUDIOBOOK,
            "playlist": pl,
            "playback": PlaybackType.AUDIO,
            "skill_icon": self.skill_icon,
            "image": self.default_bg,
            "bg_image": self.default_bg,
            "title": "HPPodcraft (Audiobook Readings)",
            "author": "H. P. Lovecraft"
        }]
Пример #5
0
    def search_bandcamp_tracks(self, phrase, media_type=MediaType.GENERIC):
        base_score = 0
        if self.voc_match(phrase, "bandcamp"):
            base_score = 15
        if media_type == MediaType.MUSIC:
            base_score += 5
        phrase = self.remove_voc(phrase, "bandcamp")

        try:
            for match in BandCamp.search_tracks(phrase):
                artist_name = match.artist.name
                track_score = fuzzy_match(match.title, phrase) * 100
                score = base_score + track_score
                yield {
                    "match_confidence": min(100, score),
                    "media_type": MediaType.MUSIC,
                    "uri": "bandcamp//" + match.url,
                    "playback": PlaybackType.AUDIO,
                    "image": match.image,
                    "bg_image": match.image,
                    "duration": match.duration * 1000,
                    "skill_icon": self.skill_icon,
                    "title": match.title + f" ({artist_name})",
                    "artist": artist_name,
                    "skill_id": self.skill_id
                }
        except:
            pass
Пример #6
0
 def handle_validator(self, message):
     self.log.info(self.recordfile)
     if not self.settings["usevalidator"]:
         return True
     msg = message.data.get('utterance')
     self.log.info("match " + str(msg))
     if msg is None:
         #self.remove_event('recognizer_loop:record_end')
         #self.remove_fallback(self.handle_validator)
         self.halt = None
         return True
     if self.voc_match(msg, "stop"):
         self.log.info('Stop')
         self.halt = True
         return True
     elif self.voc_match(msg, "break"):
         self.log.info("break")
         self.halt = "break"
         return True
     elif fuzzy_match(msg, self.new_name) > 0.8:
         self.log.info('skip File to no wakewords')
         self.halt = False
         return True
     else:
         self.halt = None
         return True
Пример #7
0
    def _fuzzy_match(self, word, phrase, threshold):
        """
            Search a phrase to another phrase using fuzzy_match. Matches on a
            per word basis, and will not match if word is a subword.
            Args:
                word (str): string to be searched on a phrase
                phrase (str): string to be matched against the word
                threshold (int): minimum fuzzy matching score to be considered
                                 a match
            Returns:
                (boolean): True if word is found in phrase. False if not.
        """
        matched = False
        score = 0
        phrase_split = phrase.split(' ')
        word_split_len = len(word.split(' '))

        for i in range(len(phrase_split) - word_split_len, -1, -1):
            phrase_comp = ' '.join(phrase_split[i:i + word_split_len])
            score_curr = fuzzy_match(phrase_comp, word.lower())

            if score_curr > score and score_curr >= threshold:
                score = score_curr
                matched = True

        return matched
Пример #8
0
 def query_genre(self, genre, bonus=0.0):
     LOG.debug("genre {}".format(genre))
     results = self.am.search(genre,
                              library_only=self.library_only,
                              tracks=True,
                              albums=False,
                              playlists=False,
                              artists=False,
                              stations=False)
     best_score = 0.0
     best_match = ""
     for res in results:
         if 'track' in res[0]:
             for hit in res[1]['hits']:
                 primaryGenre = hit['document']['primaryGenre']
                 score = fuzzy_match(genre.lower(), primaryGenre.lower())
                 if score > best_score:
                     best_match = primaryGenre
                     best_score = score
                 if (best_score + bonus) >= 1.0:
                     break
     if best_score > 0.0:
         conf = min(best_score + bonus, 1.0)
         return (conf, {
             'genre': best_match,
             'name': genre,
             'type': 'Genre'
         })
Пример #9
0
    def _get_timer(self, name):
        # Retrieve the next timer set to trigger

        # Referenced it by duration? "the 5 minute timer"
        secs = self._extract_duration(name)
        if secs:
            for timer in self.active_timers:
                if timer["duration"] == secs:
                    return timer

        # Referenced by index?  "The first", "number three"
        num = extractnumber(name)
        if num and num - 1 < self.timer_index:
            for timer in self.active_timers:
                if timer["index"] == num:
                    return timer

        # Referenced by name (fuzzy matched)?
        timer = None
        best = 0.5  # minimum threshold for a match
        for t in self.active_timers:
            score = fuzzy_match(name, t["name"])
            if score > best:
                best = score
                timer = t
        if timer:
            return timer

        return None
Пример #10
0
    def search_bandcamp_album(self, phrase, media_type=MediaType.GENERIC):
        base_score = 0
        if self.voc_match(phrase, "bandcamp"):
            base_score = 10
        if media_type == MediaType.MUSIC:
            base_score += 10
        phrase = self.remove_voc(phrase, "bandcamp")

        try:
            for album in BandCamp.search_albums(phrase):
                artist_name = album.artist.name
                album_score = fuzzy_match(album.title, phrase) * 100
                artist_score = fuzzy_match(artist_name, phrase) * 100
                score = artist_score * 0.3 + album_score * 0.7

                pl = [{
                    "match_confidence": min(100, score) - idx,
                    "media_type": MediaType.MUSIC,
                    "uri": "bandcamp//" + track.url,
                    "playback": PlaybackType.AUDIO,
                    "image": track.image or album.image,
                    "bg_image": album.image,
                    "skill_icon": self.skill_icon,
                    "title": track.title,
                    "duration": track.duration * 1000,
                    "skill_id": self.skill_id,
                    "album": album.title
                } for idx, track in enumerate(album.tracks)]

                if pl:
                    yield {
                        "match_confidence": score,
                        "media_type": MediaType.AUDIO,
                        "playback": PlaybackType.AUDIO,
                        "playlist": pl,  # return full playlist result
                        "image": album.image,
                        "bg_image": album.image,
                        "skill_icon": self.skill_icon,
                        "album": album.title,
                        "duration": sum(t["duration"] for t in pl),
                        "title": album.title + f" (Full Album)",
                        "skill_id": self.skill_id
                    }
        except:
            pass
Пример #11
0
 def get_best_public_playlist(self, playlist):
     data = self.spotify.search(playlist, type='playlist')
     if data and data['playlists']['items']:
         best = data['playlists']['items'][0]
         confidence = fuzzy_match(best['name'].lower(), playlist)
         if confidence > 0.7:
             return (confidence, {
                 'data': best,
                 'name': best['name'],
                 'type': 'playlist'
             })
     return NOTHING_FOUND
Пример #12
0
 def test_matches(self):
     self.assertTrue(fuzzy_match("you and me", "you and me") >= 1.0)
     self.assertTrue(fuzzy_match("you and me", "you") < 0.5)
     self.assertTrue(fuzzy_match("You", "you") > 0.5)
     self.assertTrue(fuzzy_match("you and me", "you") ==
                     fuzzy_match("you", "you and me"))
     self.assertTrue(fuzzy_match("you and me", "he or they") < 0.2)
Пример #13
0
    def _get_timezone_from_fuzzymatch(self, locale):
        """Fuzzymatch a location against the pytz timezones.

        The pytz timezones consists of
        Location/Name pairs.  For example:
            ["Africa/Abidjan", "Africa/Accra", ... "America/Denver", ...
             "America/New_York", ..., "America/North_Dakota/Center", ...
             "Cuba", ..., "EST", ..., "Egypt", ..., "Etc/GMT+3", ...
             "Etc/Zulu", ... "US/Eastern", ... "UTC", ..., "Zulu"]

        These are parsed and compared against the provided location.
        """
        target = locale.lower()
        best = None
        for name in pytz.all_timezones:
            # Separate at '/'
            normalized = name.lower().replace("_", " ").split("/")
            if len(normalized) == 1:
                pct = fuzzy_match(normalized[0], target)
            elif len(normalized) >= 2:
                # Check for locations like "Sydney"
                pct1 = fuzzy_match(normalized[1], target)
                # locations like "Sydney Australia" or "Center North Dakota"
                pct2 = fuzzy_match(normalized[-2] + " " + normalized[-1],
                                   target)
                pct3 = fuzzy_match(normalized[-1] + " " + normalized[-2],
                                   target)
                pct = max(pct1, pct2, pct3)
            if not best or pct >= best[0]:
                best = (pct, name)
        if best and best[0] > 0.8:
            # solid choice
            return pytz.timezone(best[1])
        elif best and best[0] > 0.3:
            say = speakable_timezone(best[1])
            if self.ask_yesno("did.you.mean.timezone", data={"zone_name":
                                                             say}) == "yes":
                return pytz.timezone(best[1])
        else:
            return None
Пример #14
0
 def test_matches(self):
     self.assertTrue(fuzzy_match("you and me", "you and me") >= 1.0)
     self.assertTrue(fuzzy_match("you and me", "you") < 0.5)
     self.assertTrue(fuzzy_match("You", "you") > 0.5)
     self.assertTrue(fuzzy_match("you and me", "you") ==
                     fuzzy_match("you", "you and me"))
     self.assertTrue(fuzzy_match("you and me", "he or they") < 0.2)
Пример #15
0
 def query_album(self, album, bonus):
     data = None
     by_word = ' {} '.format(self.translate('by'))
     if len(album.split(by_word)) > 1:
         album, artist = album.split(by_word)
         album = '*{}* artist:{}'.format(album, artist)
         bonus += 0.1
     data = self.spotify.search(album, type='album')
     if data and data['albums']['items']:
         best = data['albums']['items'][0]['name']
         confidence = min(fuzzy_match(best.lower(), album) + bonus, 1.0)
         return (confidence, {'data': data, 'name': None, 'type': 'album'})
     return None, None
Пример #16
0
    def search_bandcamp_artist(self, phrase, media_type=MediaType.GENERIC):
        base_score = 0
        if self.voc_match(phrase, "bandcamp"):
            base_score = 30
        if media_type == MediaType.MUSIC:
            base_score += 15
        phrase = self.remove_voc(phrase, "bandcamp")

        try:
            # artist top tracks
            for match in BandCamp.search_artists(phrase):
                artist_name = match.name
                artist_score = fuzzy_match(artist_name, phrase) * 100
                score = base_score + artist_score

                # all albums
                for idx, album in enumerate(match.albums):
                    pl = [{
                        "match_confidence": min(100, score) - idx2,
                        "media_type": MediaType.MUSIC,
                        "uri": "bandcamp//" + track.url,
                        "playback": PlaybackType.AUDIO,
                        "image": track.image or album.image or match.image,
                        "bg_image": album.image or match.image,
                        "skill_icon": self.skill_icon,
                        "duration": track.duration * 1000,
                        "title": track.title,
                        "artist": artist_name,
                        "skill_id": self.skill_id,
                        "album": album.title
                    } for idx2, track in enumerate(album.tracks)]

                    if pl:
                        yield {
                            "match_confidence": score - idx,
                            "media_type": MediaType.AUDIO,
                            "playback": PlaybackType.AUDIO,
                            "playlist": pl,  # return full playlist result
                            "image": album.image or match.image,
                            "bg_image": album.image or match.image,
                            "skill_icon": self.skill_icon,
                            "album": album.title,
                            "duration": sum(t["duration"] for t in pl),
                            "title":
                            album.title + f" ({artist_name}|Full Album)",
                            "skill_id": self.skill_id
                        }
        except Exception as e:
            pass
Пример #17
0
    def _fuzzy_match_word_from_phrase(self, word, phrase, threshold):
        matched = False
        score = 0
        phrase_split = phrase.split(' ')
        word_split_len = len(word.split(' '))

        for i in range(len(phrase_split) - word_split_len, -1, -1):
            phrase_comp = ' '.join(phrase_split[i:i + word_split_len])
            score_curr = fuzzy_match(phrase_comp, word.lower())

            if score_curr > score and score_curr >= threshold:
                score = score_curr
                matched = True

        return matched
Пример #18
0
    def _get_frequency(self, utterance):
        """determine weekly or daily freqeuncy

        Arguments:
            utterance (str): utterance for Message object

        Returns:
            (int): 604800 for weekly or 86400 for daily
        """
        threshold = 0.85
        weekly_frequency = 604800
        daily_frequency = 86400

        days_list = self.translate_list('days')
        for day in days_list:
            for word in utterance.split():
                if fuzzy_match(word, day) > threshold:
                    return weekly_frequency

        daily_list = self.translate_list('everyday')
        for synonym in daily_list:
            for word in utterance.split():
                if fuzzy_match(word, synonym) > threshold:
                    return daily_frequency
Пример #19
0
 def handle_play_song_padatious_intent(self, message):
     # handle a more generic play command and extract name with padatious
     title = message.data.get("music")
     # fuzzy match with playlists
     best_score = 0
     best_name = ""
     for name in self.named_urls:
         score = fuzzy_match(title, name)
         if score > best_score:
             best_score = score
             best_name = name
     if best_score > 0.7:
         # we have a named list that matches
         urls = self.named_urls[best_name]
         self.bandcamp_play(urls=urls)
     self.bandcamp_play(title)
Пример #20
0
    def CPS_match_query_phrase(self, phrase):
        self.log.debug("phrase {}".format(phrase))
        # Not ready to play
        if not self.mediaplayer:
            return None

        data = None
        best_index = -1
        best_confidence = 0.0

        if 'podcast' in phrase.lower():
            bonus = 0.1
        else:
            bonus = 0

        podcast_names = [self.settings["nameone"], self.settings["nametwo"], self.settings["namethree"]]
        podcast_urls = [self.settings["feedone"], self.settings["feedtwo"], self.settings["feedthree"]]

        # fuzzy matching
        for index, name in enumerate(podcast_names):
            confidence = min(fuzzy_match(name.lower(), phrase.lower()) + bonus,
                             1.0)
            if confidence > best_confidence:
                best_index = index
                best_confidence = confidence
            self.log.debug("index {}, name {}, confidence {}".format(index, name, confidence))

        # check for exact match
        data = self.chosen_podcast(phrase, podcast_names, podcast_urls)

        if data:
            confidence = CPSMatchLevel.EXACT
        elif best_index >= 0:
            data = podcast_urls[best_index]
            if best_confidence > 0.9:
                confidence = CPSMatchLevel.EXACT
            elif best_confidence > 0.6:
                confidence = CPSMatchLevel.TITLE
            elif best_confidence > 0.1:
                confidence = CPSMatchLevel.CATEGORY
            else:
                confidence = CPSMatchLevel.GENERIC

        self.log.info("phrase: {} confidence: {} data: {}".format(phrase,
                                                                  confidence,
                                                                  data))
        return phrase, confidence, data
Пример #21
0
    def query_artist(self, artist, bonus=0.0):
        """Try to find an artist.

        Arguments:
            artist (str): Artist to search for
            bonus (float): Any bonus to apply to the confidence

        Returns: Tuple with confidence and data or NOTHING_FOUND
        """
        bonus += 0.1
        data = self.spotify.search(artist, type='artist')
        if data and data['artists']['items']:
            best = data['artists']['items'][0]['name']
            confidence = fuzzy_match(best, artist.lower()) + bonus
            confidence = min(confidence, 1.0)
            return (confidence, {'data': data, 'name': None, 'type': 'artist'})
        else:
            return NOTHING_FOUND
Пример #22
0
    def specific_query(self, phrase, bonus):
        """ Check if the phrase can be matched against a specific spotify
            request.

            This includes asking for playlists, albums, artists or songs.

            Arguments:
                phrase (str): Text to match against
                bonus (float): Any existing match bonus

            Returns: Tuple with confidence and data or NOTHING_FOUND
        """
        # Check if playlist
        match = re.match(self.translate_regex('playlist'), phrase)
        if match:
            return self.query_playlist(match.groupdict()['playlist'])

        # Check album
        match = re.match(self.translate_regex('album'), phrase)
        if match:
            bonus += 0.1
            album = match.groupdict()['album']
            return self.query_album(album, bonus)

        # Check artist
        match = re.match(self.translate_regex('artist'), phrase)
        if match:
            bonus += 0.1
            artist = match.groupdict()['artist']
            data = self.spotify.search(artist, type='artist')
            if data and data['artists']['items']:
                best = data['artists']['items'][0]['name']
                confidence = min(
                    fuzzy_match(best, artist.lower()) + bonus, 1.0)
                return (confidence, {
                    'data': data,
                    'name': None,
                    'type': 'artist'
                })
        match = re.match(self.translate_regex('song'), phrase)
        if match:
            song = match.groupdict()['track']
            return self.query_song(song, bonus)
        return NOTHING_FOUND
Пример #23
0
    def _get_timer(self, name, stage=None):
        # Retrieve the timer referenced by name
        # Go through a hierarchy of methods until a match is found

        # Referenced by name and optionally by stage
        # Note that a preset timer might have multiple stages, so it only a name
        #  is provided, multiple timers may be returned.
        timers = []
        for timer in self.active_timers:
            if stage:
                if timer["name"] == name and timer["stage"] == stage:
                    return [timer]
            if timer["name"] == name:
                timers.append(timer)
        # return any timers that were identified.
        if len(timers) > 0:
            return timers

        # Referenced it by duration? "the 5 minute timer"
        secs = self._extract_duration(name)
        if secs:
            for timer in self.active_timers:
                if timer["duration"] == secs:
                    return [timer]

        # Referenced by index?  "The first", "number three"
        num = extractnumber(name)
        if num and num - 1 < self.timer_index:
            for timer in self.active_timers:
                if timer["index"] == num:
                    return [timer]

        # Referenced by name (fuzzy matched)?
        timer = None
        best = 0.5  # minimum threshold for a match
        for t in self.active_timers:
            score = fuzzy_match(name, t["name"])
            if score > best:
                best = score
                timer = t
        if timer:
            return [timer]

        return None
Пример #24
0
 def handle_play_song_padatious_intent(self, message):
     # handle a more generic play command and extract name with padatious
     title = message.data.get("music")
     # fuzzy match with playlists
     best_score = 0
     best_name = ""
     for name in self.named_urls:
         score = fuzzy_match(title, name)
         if score > best_score:
             best_score = score
             best_name = name
     if best_score > 0.6:
         # we have a named list that matches
         urls = self.named_urls[best_name]
         random.shuffle(urls)
         # TODO use dialog
         self.speak(best_name)
         self.youtube_play(videos=urls)
     else:
         self.youtube_play(title)
Пример #25
0
    def specific_query(self, phrase, bonus):
        # Check if playlist
        match = re.match(self.translate('playlist_regex'), phrase)
        if match:
            bonus += 0.1
            playlist, conf = self.get_best_playlist(
                match.groupdict()['playlist'])
            confidence = min(conf + bonus, 1.0)
            if not playlist:
                return
            uri = self.playlists[playlist]
            return (conf, {'data': uri, 'name': playlist, 'type': 'playlist'})
        # Check album
        match = re.match(self.translate('album_regex'), phrase)
        if match:
            bonus += 0.1
            album = match.groupdict()['album']
            return self.query_album(album, bonus)

        # Check artist
        match = re.match(self.translate('artist_regex'), phrase)
        if match:
            bonus += 0.1
            artist = match.groupdict()['artist']
            data = self.spotify.search(artist, type='artist')
            if data and data['artists']['items']:
                best = data['artists']['items'][0]['name']
                confidence = min(
                    fuzzy_match(best, artist.lower()) + bonus, 1.0)
                return (confidence, {
                    'data': data,
                    'name': None,
                    'type': 'artist'
                })
        match = re.match(self.translate('song_regex'), phrase)
        if match:
            data = self.spotify.search(match.groupdict()['track'],
                                       type='track')
            if data:
                return (1.0, {'data': data, 'name': None, 'type': 'track'})
        return None, None
Пример #26
0
    def query_album(self, album, bonus):
        """ Try to find an album.

            Searches Spotify by album and artist if available.

            Arguments:
                album (str): Album to search for
                bonus (float): Any bonus to apply to the confidence

            Returns: Tuple with confidence and data or NOTHING_FOUND
        """
        data = None
        by_word = ' {} '.format(self.translate('by'))
        if len(album.split(by_word)) > 1:
            album, artist = album.split(by_word)
            album = '*{}* artist:{}'.format(album, artist)
            bonus += 0.1
        data = self.spotify.search(album, type='album')
        if data and data['albums']['items']:
            best = data['albums']['items'][0]['name']
            confidence = min(fuzzy_match(best.lower(), album) + bonus, 1.0)
            return (confidence, {'data': data, 'name': None, 'type': 'album'})
        return NOTHING_FOUND
Пример #27
0
    def query_artist(self, artist, bonus=0.0):
        """Try to find an artist.

        Arguments:
            artist (str): Artist to search for
            bonus (float): Any bonus to apply to the confidence

        Returns: Tuple with confidence and data or NOTHING_FOUND
        """
        bonus += 0.1
        data = self.yt.search(artist, 'artists')
        if data:
            from pprint import pprint
            pprint(data[0])
            best = data[0]['artist']
            confidence = fuzzy_match(best, artist.lower()) + bonus
            confidence = min(confidence, 1.0)
            return (confidence, {
                'browseId': data[0]['browseId'],
                'name': None,
                'type': 'artist'
            })
        else:
            return NOTHING_FOUND
Пример #28
0
    def ocp_hppodcraft_playlist(self, phrase, media_type):
        score = self.get_base_score(phrase, media_type)
        if self.voc_match(phrase, "lovecraft"):
            score += 10
        if media_type == MediaType.PODCAST or \
                self.voc_match(phrase, "podcast"):
            score += 10
        elif media_type == MediaType.AUDIOBOOK:
            return
        else:
            score -= 15

        pl = [{
            "match_confidence": fuzzy_match(phrase, k) * 100,
            "media_type": MediaType.PODCAST,
            "uri": v["stream"],
            "title": k,
            "playback": PlaybackType.AUDIO,
            "image": self.default_image,
            "bg_image": self.default_bg,
            "skill_icon": self.skill_icon,
            "author": "HPPodcraft",
            "album": "HPPodcraft"
        } for k, v in self.episodes.items()]

        return [{
            "match_confidence": score,
            "media_type": MediaType.PODCAST,
            "playlist": pl,
            "playback": PlaybackType.AUDIO,
            "skill_icon": self.skill_icon,
            "image": self.default_bg,
            "bg_image": self.default_bg,
            "title": "HPPodcraft (Podcast)",
            "author": "H. P. Lovecraft"
        }]
Пример #29
0
    def handle_play_music_intent(self, message):
        """
        Handle playing of an Album or a Single Track, with an Artist specified
        Phrases like:
            Play the album Syro by Aphex Twin
            Play Tundra by Squarepusher (single track)
        """
        # album keyword lets us determine that the user has definitely asked for an album
        album_keyword = message.data.get('AlbumKeyword')
        # target can be a single track or an album
        target = message.data.get('MusicTarget')
        artist = message.data.get('Artist')

        search_results = self.search(target)

        if album_keyword:
            # user gave tan Album keyword so we can skip all other search results
            available_targets = search_results.get('album', [])
        else:
            available_targets = search_results.get(
                'song', []) + search_results.get('album', [])

        # make sure the targets returned from the search have the correct artist
        matching_targets = []

        for found_target in available_targets:
            if 'artist' not in found_target:
                # videos may show up in search results but will have no artist
                continue
            # use fuzzy matching on the artist name and only accept those that match the
            if fuzzy_match(
                    found_target.get('artist').lower().strip(),
                    artist.lower().strip()) > 0.8:
                matching_targets.append(found_target)

        # if no targets have a nearly matching artist we report the failure to the user
        if not matching_targets:
            self.speak_dialog('no.targets', {
                'target': target,
                'artist': artist
            })
            return

        # otherwise we 'match_one' target based on the target name.
        # build a dict matching target name to target id (needed for playing0
        final_targets = dict()

        for matching_target in matching_targets:
            if 'name' in matching_target:
                # name only exists in an album
                final_targets[matching_target['name']] = {
                    'id': matching_target['id'],
                    'type': 'album',
                    'artist': matching_target['artist']
                }
            else:
                # we only chose albums and songs from the search results so can safely assume we have a song
                # songs are identified by 'title'
                final_targets[matching_target['title']] = {
                    'id': matching_target['id'],
                    'type': 'song',
                    'artist': matching_target['artist']
                }

        chosen_target = dict(match_one(target, final_targets)[0])
        chose_target_name = next(
            t for t in final_targets
            if final_targets[t]['id'] == chosen_target['id'])

        self.speak_dialog('target', {
            'target': chose_target_name,
            'artist': chosen_target['artist']
        })

        if chosen_target['type'] == 'song':
            songs = [
                next(t for t in matching_targets
                     if t['id'] == chosen_target['id'])
            ]
        else:
            songs = self.get_album_tracks(chosen_target['id'])

        self.play_songs(songs)
Пример #30
0
    def handle_delete(self, message):
        # LOG.info(message.data)
        time = message.data.get('time') or ""
        ampm = message.data.get('ampm') or ""
        daytype = message.data.get('daytype') or ""

        name = self.get_alarm_name(time, ampm, daytype)
        # LOG.info(name)

        best_match = (None, float("-1"))
        for alarm in self.settings.get('alarms'):
            prob = fuzzy_match(name, alarm[1])
            if prob > 0.5 and prob > best_match[1]:
                best_match = (alarm[1], prob)

        best_match_repeat = (None, float("-1"))
        for alarm in self.settings.get('repeat_alarms'):
            prob = fuzzy_match(name, alarm[1])
            if prob > 0.5 and prob > best_match_repeat[1]:
                best_match_repeat = (alarm[1], prob)

        def _delete_one_time(name):
            self.delete_alarm(name)
            self.speak_dialog('delete.alarm', data={'name': name})

        def _delete_repeat(name):
            # all repeat alarms has 'repeat'
            # appended to name in the event scheduler
            self.delete_repeat(name + 'repeat')
            self.speak_dialog('delete.alarm.recurring', data={'name': name})

        diff = abs(best_match[1] - best_match_repeat[1])
        # if similar by 10% then ask for one to delete
        if 0.0 <= diff <= 0.1 and best_match[0] and best_match_repeat[0]:
            self.speak_dialog('delete.multimatch')
            self.speak_dialog('delete.match', data={'alarms': best_match[0]})
            self.speak_dialog('delete.match.repeat',
                              data={'alarms': best_match_repeat[0]})
            response = self.get_response('delete.multimatch.response')
            one_time = self.translate_list('one.time')
            recurring = self.translate_list('recurring')
            best_option = (None, float('-inf'), None)

            for option in one_time:
                prob = fuzzy_match(option, response)
                if prob > 0.5 and prob > best_option[1]:
                    best_option = (option, prob, "one time")

            for option in recurring:
                prob = fuzzy_match(option, response)
                if prob > 0.5 and prob > best_option[1]:
                    best_option = (option, prob, "recurring")

            if best_option[2] == "recurring":
                name = best_match_repeat[0]
                _delete_repeat(name)
            elif best_option[2] == "one time":
                name = best_match[0]
                _delete_one_time(name)
            else:
                self.speak_dialog('delete.no.options')
        elif best_match[1] > best_match_repeat[1] and best_match[0]:
            # delete best match
            name = best_match[0]
            _delete_one_time(name)
        elif best_match_repeat[1] > best_match[1] and best_match_repeat[0]:
            # delete best match repeat
            name = best_match_repeat[0]
            _delete_repeat(name)
        else:
            self.speak_dialog('delete.no.match')
Пример #31
0
 def match_feed_name(phrase, feed_name):
     return (fuzzy_match(phrase, feed_name) > 0.7 or fuzzy_match(
         phrase, feed_name + self.translate("News")) > 0.7)