示例#1
0
 def query_song(self, song: str, bonus=0.0):
     """
         Try to find song
     :param self:
     :param song:
     :return:
     """
     by_word = ' {} '.format(self.translate('by'))
     if len(song.split(by_word)) > 1:
         song, artist = song.split(by_word)
         self.log.info("Using search by artist")
         confidence, data = self.query_artist(artist)
         if confidence > 0.6:
             songs = self.client.search('artist', data['data'])
             #songtitles = [t['title'].lower() for t in songs]
             key, confidence = match_one(song, songs)
             return confidence + 0.1, {'data': {'title': key, 'artist': data['data']}, 'name': key, 'type': 'track'}
         else:
             return NOTHING_FOUND
     else:
         song_search = song
     if self.songs and len(self.songs) > 0:
         key, confidence = match_one(song, self.songs)
         return confidence + bonus, {'data': self.client.search('title', key)[0], 'name': key, 'type': 'track'}
     else:
         return NOTHING_FOUND
示例#2
0
    def _get_country_geometry(query, region=None, min_score=0.7):
        best_score = 0
        best_match = None

        shapename = 'admin_0_countries'
        countries_shp = cartopy.io.shapereader.natural_earth(
            resolution='110m', category='cultural', name=shapename)

        for country in cartopy.io.shapereader.Reader(countries_shp).records():
            country_name = country.attributes['NAME'].lower()
            country_long_name = country.attributes['NAME_LONG'].lower()

            reg = country.attributes["REGION_WB"].lower()
            subregion = country.attributes["SUBREGION"].lower()
            continent = country.attributes["CONTINENT"].lower()

            match, score = match_one(query.lower(),
                                     [country_long_name, country_name])

            if region:
                _, score2 = match_one(region.lower(),
                                      [reg, subregion, continent])
                score = (score + score2) / 2

            if score > best_score:
                best_score = score
                best_match = country.geometry

        if best_score < min_score:
            best_match = None

        return best_match
示例#3
0
 def remove_by_name(self, name):
     """ removes the specified skill folder name """
     LOG.info("searching skill by name: " + name)
     folders = self.skills.keys()
     names = [self.skills[skill]["name"] for skill in folders]
     f_skill, f_score = match_one(name, folders)
     n_skill, n_score = match_one(name, names)
     installed = False
     if n_score > 0.5:
         for s in self.skills:
             if self.skills[s]["name"] == n_skill:
                 LOG.info("found skill by name")
                 skill = self.skills[s]
                 installed = skill["installed"]
                 self.skills[s]["installed"] = False
                 break
     elif f_score > 0.5:
         LOG.info("found skill by folder name")
         skill = self.skills[f_skill]
         installed = skill["installed"]
         self.skills[f_skill]["installed"] = False
     if not installed:
         LOG.warning("skill is not installed!")
         return False
     remove(skill["path"])
     LOG.info("skill removed")
     return True
示例#4
0
    def handle_change_module_intent(self, message):
        self.validate_voices()
        module, voice = self._message_to_engine(message)
        # ask user if engine not explicit
        if not module:
            self.speak_dialog("engine.select", wait=True)
            module = self.ask_selection(self.available_engines)

            # fuzzy match transcription in case STT wasnt perfect
            if module is not None and module not in self.available_engines:
                words = message.data["utterance"].split(" ")
                for w in words:
                    _voice, vscore = match_one(w, self.available_voices)
                    if vscore >= 0.8:
                        voice = _voice
                    _engine, escore = match_one(w, self.available_engines)
                    if escore >= 0.8:
                        module = _engine

        # pick default voice if None selected
        if module is not None and voice is None and module in self.voices:
            self.log.debug("Default voice for engine " + module)
            voice = self.voices[module][0]

        # check if abort is needed
        if module is not None and module not in self.available_engines:
            self.speak_dialog("engine.invalid", {"engine": module})
            self.speak_dialog("check.config")
            return
        if module is None:
            self.speak_dialog("noengine")
            return
        self.log.info("Selected TTS engine: " + str(module))
        self.log.info("Selected TTS voice: " + str(voice))
        self.change_voice(module, voice)
示例#5
0
    def _get_region_countries(self, query, min_score=0.7):
        countries = []
        region, score = match_one(query, self.regions)

        if score > min_score - 0.15:
            countries = self.search_country_by_region(region)
        if score < min_score:
            region, score = match_one(query, self.subregions)
            if score > min_score:
                countries = self.search_country_by_subregion(region)

        return [c["name"] for c in countries]
示例#6
0
 def match_name_to_folder(self, name):
     LOG.info("searching skill by name: " + name)
     folders = self.skills.keys()
     names = [self.skills[skill]["name"] for skill in folders]
     f_skill, f_score = match_one(name, folders)
     n_skill, n_score = match_one(name, names)
     if n_score > 0.6:
         for s in self.skills:
             if self.skills[s]["name"] == n_skill:
                 LOG.info("found skill by name")
                 return s
     elif f_score > 0.6:
         LOG.info("found skill by folder name")
         return f_skill
     return None
示例#7
0
    def get_best_playlist(self, playlist):
        """ Get best playlist matching the provided name

        Arguments:
            playlist (str): Playlist name

        Returns: (str) best match, confidence, asin
        """
        LOG.debug("playlist {}".format(playlist))
        results = self.am.search(playlist,
                                 library_only=self.library_only,
                                 tracks=False,
                                 albums=False,
                                 playlists=True,
                                 artists=False,
                                 stations=False)
        playlists = {}
        for res in results:
            # LOG.debug(res[0])
            if 'playlist' in res[0]:
                for hit in res[1]['hits']:
                    title = hit['document']['title'].lower()
                    asin = hit['document']['asin']
                    playlists[title] = {
                        'asin': asin,
                        'title': hit['document']['title']
                    }
        if playlists:
            key, confidence = match_one(playlist.lower(),
                                        list(playlists.keys()))
            LOG.debug("key {} confidence {}".format(key, confidence))
            if confidence > 0.7:
                return key, confidence, playlists[key]
        return None, 0, None
示例#8
0
 def dialog_match(self, saved_dialog, skill):
     for path in self.paths_gen(skill):
         for root, dirs, files in os.walk(path):
             for f in files:
                 ### for intent files
                 filename = os.path.join(root, f)
                 if self.lang in filename:  ## reduce selection to reduce load list size
                     if filename.endswith(".dialog"):
                         try:
                             match, confidence = match_one(
                                 self.saved_answer,
                                 self._lines_from_path(filename))
                             self.log.info("match " + str(match) +
                                           " confidence " + str(confidence))
                             if confidence > 0.8:
                                 saved_utt = self.get_response(
                                     "found.output", data={"match": match})
                                 if saved_utt is not None:
                                     match, saved_utt = self.var_found(
                                         saved_utt, match)
                                     self.ask_save_intent_dialog(
                                         saved_utt, filename, match, skill)
                                     self.acknowledge()
                                 else:
                                     self.speak_dialog("cancel")
                         except:
                             self.log.info("fail load match: " + filename)
示例#9
0
    def query_album(self, album, bonus):
        """Try to find an album.

        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_search = album
        else:
            album_search = album
        albums = self.client.list('album')
        if len(albums) > 0:
            #albumlist = [a['album'].lower() for a in albums]
            key, confidence = match_one(album.lower(), self.albums)
            #album returns album name as data
            self.log.info("MPD Album: " + album + " matched to " + key + " with conf " + str(confidence))
            #not the best tactic
            data = {'data': self.client.search('album', key)[0], 'name': key, 'type': 'album'}
            return confidence, data
        else:
            return NOTHING_FOUND
示例#10
0
 def work_on_intent(self, filename, skill, location):
     #self.log.info('find intent file: '+filename)
     if self.lang in filename:
         fobj = open(filename)
         self.log.info('open intent file: '+filename)
         for line in fobj:
             match, confidence = match_one(self.saved_utt, [line])
             self.log.info('found intent: '+line.rstrip()+' '+str(confidence))
             if confidence > 0.5:
                 match, normal = self.normalise_question(match)
                 self.log.info('match '+str(confidence)+' found and normal '+normal)
                 if self.ask_yesno("do.you.mean", data={"match": normal}) is "yes":
                     fobj.close()
                     keywords = os.path.basename(filename).replace('.intent', '')
                     self.log.info('keywords: '+keywords)
                     question = self.saved_utt
                     question_path = self.file_system.path+"/skills/"+str(skill)+"/"+"vocab"+"/"+self.lang
                     self.log.info('bevor check: '+match)
                     question = self.check_question(question, match)
                     self.log.info('after check: '+match)
                     self.log.info('output question: '+match)
                     if self.ask_yesno("save.answer", data={"question": question, "skill": skill}) is "yes":
                         self.save_intent(question_path, question, keywords)
                     return
                 break
         fobj.close()
示例#11
0
 def intent_match(self, saved_utt, skill):
     vocs = []
     best_match = [0.5]
     for path in self.paths_gen(skill):
         self.log.info("search on path "+path)
         for root, dirs, files in os.walk(path):
             for f in files:
                 ### for intent files
                 filename = os.path.join(root, f)
                 if filename.endswith(".intent"):
                     i = filename.replace(".intent", "")
                     #for l in self.read_intent_lines(i, filename):
                     #self.log.info("test2"+str(self._lines_from_path(filename)))
                     try:
                         match, confidence = match_one(saved_utt, self._lines_from_path(filename))
                         self.log.info("match "+str(match)+ " confidence "+ str(confidence))
                         if confidence > best_match[0]:
                             self.log.info("better match "+str(match)+ " confidence "+ str(confidence))
                             best_match = [confidence, saved_utt, filename, match, skill]
                             self.log.info("save"+str(best_match))
                     except:
                             self.log.info("fail load intent: "+filename)
     else:
         self.log.info(str(best_match[0])+" and")
         if len(best_match) > 1:   
             match, saved_utt = self.var_found(best_match[1], best_match[3])
             self.ask_save_intent_dialog(best_match[1], best_match[2], best_match[3], best_match[4])
             self.acknowledge()
             match = self.filter_sentence(match)
             self.bus.emit(Message('recognizer_loop:utterance',
                               {"utterances": [match],
                                "lang": self.lang,
                                "session": skill.name}))
         else:
             self.speak_dialog("no.old.inquiry")
示例#12
0
    def parse_substance(self, text):
        data = {}
        # correct drug name slang
        sub = self.caterpillar.fix_substance_names(text)
        if not sub:
            LOG.warn("probable bad substance name")
        else:
            text = sub

        # match drug to info
        best, score = match_one(text, self.substances)
        LOG.debug(str(score) + " " + best)
        if best in self.chemicals.keys():
            data = self.chemicals[best]
        elif best in self.plants.keys():
            data = self.plants[best]
        elif best in self.animals.keys():
            data = self.animals[best]
        elif best in self.herbs.keys():
            data = self.herbs[best]
        elif best in self.pharms.keys():
            data = self.pharms[best]

        if data is None or score < 0.5:
            return False
        self.set_context("url", data["url"])
        self.set_context("substance", data["name"])
        LOG.info(str(data))
        return data
示例#13
0
    def handle_apprise(self, message):
        if not self.tags:
            self.speak_dialog('setup.error')
            return
        all_keyword = self.translate("AllKeyword")
        tags = self.tags
        tags[all_keyword.lower()] = all_keyword
        self.log.debug("tags %s" % tags)
        tag = message.data.get("tag")
        text = message.data.get("text")
        self.log.debug("tag: %s - text: %s" % (tag, text))

        success = False
        best_tag, score = match_one(tag.lower(), tags)
        self.log.debug("%s - %s" % (best_tag, score))
        if score > 0.9:
            if best_tag == all_keyword:
                success = self.apobj.notify(text, title=text)
            else:
                success = self.apobj.notify(text, title=text, tag=best_tag)
            self.log.debug("result %s" % success)
        if success:
            self.speak_dialog('send.success', {'tag': best_tag})
        else:
            self.speak_dialog('send.error', {'tag': best_tag})
示例#14
0
    def query_artist(self, artist, bonus=0.0):
        results = self.am.search(artist,
                                 library_only=self.library_only,
                                 tracks=False,
                                 albums=False,
                                 playlists=False,
                                 artists=True,
                                 stations=False)

        artists = {}
        for res in results:
            if 'artists' in res[0]:
                for hit in res[1]['hits']:
                    name = hit['document']['name'].lower()
                    asin = hit['document']['asin']
                    artists[name] = {
                        'asin': asin,
                        'name': hit['document']['name']
                    }
        if artists:
            key, confidence = match_one(artist.lower(), list(artists.keys()))
            if confidence > 0.7:
                confidence = min(confidence + bonus, 1.0)
                return (confidence, {
                    'asin': artists[key]['asin'],
                    'name': key,
                    'artist': artists[key]['name'],
                    'type': 'Artist'
                })
        return None, None
示例#15
0
 def paths_gen(self, skill=None):
     if skill is None:
         skill = self.get_response("what.skill")
     if skill is None:
         self.speak_dialog("cancel")
         return
     else:
         if type(skill) is str:
             skill = self.get_skill(skill)
     paths = []
     for folder in self.lang_paths:
         try:
             match, d = match_one(skill.name.replace("mycroft-", "").replace("skill", ""), os.listdir(folder))
             paths.append(folder+"/"+match)
         except:
             self.log.info("skip folder"+folder)
             pass
     else:
         try:
             paths.append(skill.path)
         except:
             self.log.info("no skill path")
             pass
     self.log.info("test "+str(paths))
     return paths                
 def skill_search(self, utter):
     """Redo with fuzzy mathcing"""
     skill, confidence = match_one(utter, self.examples_dict)
     if confidence > 0.5:
         return skill
     else:
         return None
示例#17
0
 def handle_tell_me_about(self, message):
     self.log.info(message.data.get('topic'))
     topic, conf = match_one(message.data.get('topic'), self.topics)
     point = [p for p in self.science_trail_points if p['name'] == topic]
     point = point[0]
     self.speak(point['snippet'])
     response = self.get_response(point['question'], num_retries=1)
     self.log.info('Submitting response for review')
示例#18
0
 def name_info(self, name):
     """ shows information about the skill matching <name> """
     LOG.info("searching skill by name: " + name)
     folders = self.skills.keys()
     names = [self.skills[skill]["name"] for skill in folders]
     f_skill, f_score = match_one(name, folders)
     n_skill, n_score = match_one(name, names)
     if n_score > 0.5:
         for s in self.skills:
             if self.skills[s]["name"] == n_skill:
                 LOG.info("skill found by name!")
                 return self.skills[s]
     elif f_score > 0.5:
         LOG.info("skill found by folder name!")
         return self.skills[f_skill]
     LOG.warning("skill not found")
     return {}
示例#19
0
    def generic_query(self, phrase, bonus):
                """Check for a generic query, not asking for any special feature.
                This will try to parse the entire phrase in the following order
                - As a user playlist
                - As an album
                - As a track
                maybe cut out the direct responses
                Arguments:
                    phrase (str): Text to match against
                    bonus (float): Any existing match bonus
                Returns: Tuple with confidence and data or NOTHING_FOUND
                """
                self.log.info('Handling "{}" as a generic query...'.format(phrase))
                results = []

                #check for playlist
                self.log.info('Checking playlists')
                conf, playlistdata = self.query_playlist(phrase)
                #decision
                if conf and conf > DIRECT_RESPONSE_CONFIDENCE:
                    return conf, playlistdata
                elif conf and conf > MATCH_CONFIDENCE:
                    results.append((conf, playlistdata))

                #Check for Artist
                self.log.info('Checking artists')

                conf, data = self.query_artist(phrase)
                if conf and conf > DIRECT_RESPONSE_CONFIDENCE:
                    return conf, data
                elif conf and conf > MATCH_CONFIDENCE:
                    results.append((conf, data))
                #Check for Track
                self.log.info('Checking tracks')
                if len(self.songs) > 0:
                    key, conf = match_one(phrase.lower(), self.songs)
                    #key = titles.index(key)
                    self.log.info("Matched with " + key + " at " + str(conf))
                    track_data = self.client.search('title', key)
                    data = {'data':track_data[0], 'name': key, 'type': 'track'}
                if conf and conf > DIRECT_RESPONSE_CONFIDENCE:
                    return conf, data
                elif conf and conf > MATCH_CONFIDENCE:
                    results.append((conf, data))

                #Check for album
                self.log.info("Checking albums")
                conf, data = self.query_album(phrase, bonus)
                if conf and conf > DIRECT_RESPONSE_CONFIDENCE:
                    return conf, data
                elif conf and conf > MATCH_CONFIDENCE:
                    results.append((conf, data))
                if len(results) == 0:
                    return NOTHING_FOUND
                else:
                    #return highest confidence value
                    results.reverse()
                    return sorted(results, key=lambda x: x[0])[-1]
示例#20
0
    def ask_selection(self,
                      options,
                      dialog='',
                      data=None,
                      min_conf=0.65,
                      numeric=False):
        """Read options, ask dialog question and wait for an answer.

        This automatically deals with fuzzy matching and selection by number
        e.g.
            "first option"
            "last option"
            "second option"
            "option number four"

        Arguments:
              options (list): list of options to present user
              dialog (str): a dialog id or string to read AFTER all options
              data (dict): Data used to render the dialog
              min_conf (float): minimum confidence for fuzzy match, if not
                                reached return None
              numeric (bool): speak options as a numeric menu
        Returns:
              string: list element selected by user, or None
        """
        assert isinstance(options, list)

        if not len(options):
            return None
        elif len(options) == 1:
            return options[0]

        if numeric:
            for idx, opt in enumerate(options):
                opt_str = "{number}, {option_text}".format(
                    number=pronounce_number(idx + 1, self.lang),
                    option_text=opt)

                self.speak(opt_str, wait=True)
        else:
            opt_str = join_list(options, "or", lang=self.lang) + "?"
            self.speak(opt_str, wait=True)

        resp = self.get_response(dialog=dialog, data=data)

        if resp:
            match, score = match_one(resp, options)
            if score < min_conf:
                if self.voc_match(resp, 'last'):
                    resp = options[-1]
                else:
                    num = extract_number(resp, self.lang, ordinals=True)
                    resp = None
                    if num and num < len(options):
                        resp = options[num - 1]
            else:
                resp = match
        return resp
示例#21
0
 def handle_news_intent(self, message):
     # clean a bit the utterance
     remainder = message.utterance_remainder()
     # fuzzy match available feeds
     feed, score = match_one(remainder, self.feeds.keys())
     # if score is low fallback to default
     if score <= 0.5:
         feed = self.default_feed
     self.play_news(feed)
示例#22
0
 def handle_probe_distance(self, message):
     if self.probe_cache is None:
         self.probe_cache = probe_distances()["spaceprobe_distances"]
     probe = match_one(message.data["probe"].strip().replace(" ", "-"),
                       list(
                           self.probe_cache.keys()))
     distance = float(self.probe_cache[probe].lower())
     self.speak_dialog("probe.distance",
                       {"distance": distance, "probe": probe})
 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)
示例#24
0
 def score_likelihood(self, word_dict):
     resources = word_dict["resources"]
     # get from json
     scores = []
     for resource in resources:
         # returns each intent scored by how similar they are to utterance
         # resource next to them to identify scores
         scores += [[resource, list(match_one(self.words, resources[resource]))]]
     return scores
示例#25
0
    def handle_pick_recipe(self, message):
        os.popen("skills/Energy-Monitor/./GUI.sh ")
        self.speak_dialog('pick.recipes')
        wait_while_speaking()

        title = message.data.get('title')
        score = match_one(title, self.play_list)
        print(score)
        if score[1] > 0.5:
            self.speak('your recipe is ')
            filepath = (score[0])
            file1 = open("recipe.dat", "w")
            file1.write(filepath)
            file1.close()
            recipe = open(filepath, "r")
            recipe = recipe.read()

            TMP = os.popen(
                "$HOME/mycroft-core/skills/all-recipes-skill/bash/" +
                self.lang + "/./FILE " + filepath).read()
            IMAGE = ("/opt/mycroft/skills/all-recipes-skill/recipes/pics/" +
                     TMP)
            IMAGE = IMAGE.strip()
            print(IMAGE)

            ########## FRACTION COINVERSION ############
            Recipe_CONV = os.popen(
                "$HOME/mycroft-core/skills/all-recipes-skill/bash/" +
                self.lang + "/./FRAC " + filepath).read()
            file0 = open("recipe.conv", "w")
            file0.write(Recipe_CONV)
            file0.close()
            file1 = open("recipe2.dat", "w")
            file1.write('recipe.conv')
            file1.close()
            filepath = open("recipe2.dat", "r")
            path = filepath.read()
            #############################################

            self.gui.show_image(IMAGE)
            time.sleep(3)
            self.is_reading = True
            with open(path) as fp:
                for cnt, line in enumerate(fp):
                    if self.is_reading is False:
                        break
                    self.speak("{}".format(line), wait=True)
                    self.gui['title'] = "FAVORITES"
                    self.gui['reclist'] = " "
                    self.gui['summary'] = recipe
                    self.gui.show_page("recipe.qml", override_idle=600)

        else:
            #find  return None
            self.speak('Sorry I could not find that recipe in my library')
示例#26
0
 def handle_pick_white_noise(self, message):
     self.speak_dialog('pick.white-noise')
     wait_while_speaking()
     title = message.data.get('title')
     score = match_one(title, self.play_list)
     print(score)
     if score[1] > 0.5:
         self.process = play_mp3(score[0])
     else:
         return None
         self.speak('Sorry I could not find that white noise in my library')
示例#27
0
    def query_genre(self, genre: str, bonus = 0.0):
        """

        :param genre:
        :param bonus:
        :return:
        """
        key, confidence = match_one(genre, self.genre)
        if confidence > 0.7:
            return confidence, {'data': {'genre': key}, 'name':key, 'type': 'genre'}
        else:
            return NOTHING_FOUND
    def setDirection(self, str):

        # build list of directions and destinations as strings
        dirList = [' '.join(x) for x in self.currentDirections]

        # select one destinaiton
        dirKey, dirConfidence = match_one(str, dirList)

        # set direction id to index of selected destination
        self.currentDirection = dirList.index(dirKey)

        return (self.currentDirections[self.currentDirection])
示例#29
0
    def get_best_playlist(self, playlist):
        """ Get best playlist matching the provided name

        Arguments:
            playlist (str): Playlist name

        Returns: (str) best match
        """
        key, confidence = match_one(playlist, self.playlists.keys())
        if confidence > 0.5:
            return key
        else:
            return None
    def setStop(self, stopName):

        # build dictionay of stops if necessary
        self.getStops()

        # find closest match on route
        theStop = key, confidence = match_one(stopName, list(self.busStops))
        self.stopId = self.busStops.get(key)

        # record stop name
        self.stopName = theStop[0]

        return (self.stopName)
示例#31
0
 def test_match_one(self):
     # test list of choices
     choices = ['frank', 'kate', 'harry', 'henry']
     self.assertEqual(match_one('frank', choices)[0], 'frank')
     self.assertEqual(match_one('fran', choices)[0], 'frank')
     self.assertEqual(match_one('enry', choices)[0], 'henry')
     self.assertEqual(match_one('katt', choices)[0], 'kate')
     # test dictionary of choices
     choices = {'frank': 1, 'kate': 2, 'harry': 3, 'henry': 4}
     self.assertEqual(match_one('frank', choices)[0], 1)
     self.assertEqual(match_one('enry', choices)[0], 4)