Beispiel #1
0
 def respond_to_bot(self, audio_string):
     # don't send response to bot with audio_string containing "filler" p hrases.
     if not is_match(
             audio_string,
         ["I'm here...", "I'm listening...", "(in mute)", "listening..."]):
         audio_string = audio_string.replace(f"{self.assistant_name}:", "")
         self.bot.send_message(audio_string)
Beispiel #2
0
    def deactivate(self, voice_data=""):
        # commands to terminate virtual assistant
        if is_match(voice_data, self._get_commands("terminate")) or self.restart_request:
            if self.isSleeping() and voice_data:
                self.print(
                    f"{self.BLACK_GREEN}{self.master_name}:{self.GREEN} {voice_data}")

            # play end prompt sound effect
            self.speak("<end prompt>", end_prompt=True)
            self.sleep(False)

            if "restart" in voice_data or self.restart_request:
                self.restart()
                self.restart_request = False

            else:
                self.speak(choice(self._get_commands("terminate_response")))
                self.mute_assistant(f"stop {self.assistant_name}")
                self.print(f"\n{self.assistant_name} assistant DEACTIVATED.\n")
                # volume up the music player, if applicable
                self.skills.music_volume(70)

            time.sleep(2)
            # terminate and end the virtual assistant application
            sys.exit()
            exit()
Beispiel #3
0
    def control_system(self, voice_data):
        command = ""
        confirmation = "no"

        try:
            if "shutdown" in voice_data:
                # shudown command sequence for 15 seconds
                command = "shutdown /s /t 15"

            elif is_match(voice_data, ["restart", "reboot"]):
                # restart command sequence for 15 seconds
                command = "shutdown /r /t 15"

            if command:
                # confirmation = self.tts.listen_to_audio(f"\033[1;33;41m Are you sure to \"{'Restart' if '/r' in command else 'Shutdown'}\" your computer? (yes/no): ")

                # execute the shutdown/restart command if confirmed by user
                # if "yes" in confirmation.lower().strip():
                os.system(command)
                return f"Ok! {'Reboot' if '/r' in command else 'Shutdown'} sequence will commence in approximately 10 seconds..."
                # return f"{'Reboot' if '/r' in command else 'Shutdown'} is canceled."

        except Exception:
            self.Log("Shutdown/Restart System Skill Error.")

        return ""
Beispiel #4
0
            def _weatherReport(data):
                report = ""
                try:
                    max_temp = ""
                    min_temp = ""
                    ave_temp = ""
                    conditions = []
                    current_hour = int(dt.now().strftime("%I"))
                    current_meridian_indicator = dt.now().strftime("%p")
                    time_frame = "morning" if ("AM" == current_meridian_indicator and current_hour <= 10) else ("afternoon" if (("AM" == current_meridian_indicator and current_hour > 10) or (
                        "PM" == current_meridian_indicator and current_hour == 12) or ("PM" == current_meridian_indicator and current_hour <= 2)) else "night")

                    data = data.replace('rain', 'raining').replace(
                        'few clouds', 'cloudy').replace("clear", "clear skies")

                    for item in data.split("\n"):
                        if "°C" in item:
                            temps = item.replace("between", "").replace(
                                "°C", "").split("and")

                            if len(temps) > 1:
                                min_temp = temps[0].strip()
                                max_temp = temps[1].strip()
                                ave_temp = str(
                                    (int(max_temp) + int(min_temp)) // 2)
                            else:
                                ave_temp = item.replace("°C", "").strip()

                        elif is_match(item, ["|"]):
                            for cond in item.split("|"):
                                if time_frame == "morning" and "early morning" in cond:
                                    if "(" in cond:
                                        conditions.append(
                                            cond[:cond.index("(")].strip())
                                elif time_frame == "afternoon" and "afternoon" in cond:
                                    if "(" in cond:
                                        conditions.append(
                                            cond[:cond.index("(")].strip())
                                elif "(" in cond:
                                    conditions.append(
                                        cond[:cond.index("(")].strip())
                                # conditions.append(cond.strip())

                            if max_temp and min_temp:
                                if len(conditions) > 2:
                                    report = f"{conditions[0]} and {ave_temp}°C. Expect mixed conditions starting {time_frame} and the rest of the day. Temperatures are heading down from {max_temp}°C to {min_temp}°C."
                                else:
                                    report = f"{conditions[0]} and {ave_temp}°C. Expect {' and '.join(conditions)} starting {time_frame} with mixed conditions for the rest of the day. Temperatures are heading down from {max_temp}°C to {min_temp}°C."
                            else:
                                conditions = ' and '.join(conditions)
                                report = f"{ave_temp}°C with mixed condition like {conditions}."
                        else:
                            conditions = item.strip()
                            report = f"{conditions} and {ave_temp}°C."

                except Exception:
                    pass
                    self.Log("Wolfram|Alpha Weather Report Error.")

                return report
Beispiel #5
0
        def _wake_assistant(listen_timeout=1, voice_data=""):
            if listen_timeout == 0:
                if not voice_data:
                    voice_data = self.listen_to_audio()

                if self.deactivate(voice_data):
                    return False

                wakeup_command = self._get_commands("wakeup")
                # wake command is invoked and the user ask question immediately.
                if len(voice_data.split(" ")) > 2 and is_match(voice_data, wakeup_command):
                    self.maximize_command_interface()
                    self.print(f"{self.BLACK_GREEN}{self.master_name}:{self.GREEN} {voice_data}")
                    self.sleep(False)
                    # play end speaking prompt sound effect
                    self.speak("<start prompt>", start_prompt=True)
                    self.print(f"{self.assistant_name}: (awaken)")
                    _formulate_responses(clean_voice_data(voice_data, self.assistant_name))
                    return True

                # wake commands is invoked and expected to ask for another command
                elif is_match(voice_data, wakeup_command):
                    self.maximize_command_interface()
                    self.print(
                        f"{self.BLACK_GREEN}{self.master_name}:{self.GREEN} {voice_data}")
                    self.print(f"{self.assistant_name}: (awaken)")
                    self.sleep(False)
                    # announce greeting from assistant
                    _awake_greetings()

                    # listen for commands
                    voice_data = self.listen_to_audio()

                    if voice_data:
                        # play end prompt sound effect before
                        self.speak("<end prompt>", end_prompt=True)
                        _formulate_responses(voice_data)
                    return True

            return False
Beispiel #6
0
    def control_wifi(self, voice_data):
        command = ""
        try:
            if is_match(voice_data, ["on", "open", "enable"]):
                # if "on" in voice_data or "open" in voice_data:
                command = "enabled"
            if is_match(voice_data, ["off", "close", "disable"]):
                # elif "off" in voice_data or "close" in voice_data:
                command = "disabled"

            if command:
                os.system(f"netsh interface set interface \"Wi-Fi\" {command}")

                if "disabled" in command:
                    # announce before going off-line
                    self.print(f"\033[1;33;41m {self.assistant_name} is Offline...")

                alternate_responses = self._get_commands("acknowledge response")
                return f"{choice(alternate_responses)} I {command} the Wi-Fi."

        except Exception:
            self.Log("Wi-Fi Skill Error.")

        return ""
Beispiel #7
0
    def mute_assistant(self, voice_data):
        mute_commands = self._get_commands("mute")

        # commands to interrupt virtual assistant
        if is_match(voice_data, mute_commands) or is_match_and_bare(voice_data, mute_commands, self.assistant_name):

            if "nevermind" in voice_data:
                self.speak("No problem. I won't")
            # minimize the command interface
            self.maximize_command_interface(False)
            # don't listen for commands temporarily
            self.print(f"{self.assistant_name}: (in mute)")

            # play end prompt sound effect
            self.speak("(mute/sleep prompt)", mute_prompt=True)

            self.sleep(True)
            # volume up the music player, if applicable
            self.skills.music_volume(70)
            return True

        return False
Beispiel #8
0
        def _formulate_responses(voice_data):
            response_message = ""
            ask_google = True
            ask_wikipedia = True
            ask_wolfram = True
            not_confirmation = True
            use_calc = True
            adjust_system_volume = False

            try:

                # respond to wake command(s) ("hey <assistant_name>")
                if _wake_assistant(voice_data=voice_data):
                    return

                if self.mute_assistant(voice_data):
                    return

                # respond to deactivation commands
                if self.deactivate(voice_data):
                    sys.exit()

                # night mode
                if is_match(voice_data, self._get_commands("night mode")):
                    self.night_mode()
                    return

                # day mode
                if is_match(voice_data, self._get_commands("day mode")):
                    self.day_mode()
                    return

                # commands for greeting
                greeting_commands = self._get_commands("greeting")
                if is_match(voice_data, greeting_commands):
                    meta_keyword = extract_metadata(
                        voice_data, greeting_commands)

                    # it's a greeting if no extracted metadata, or..
                    # metadata is assistant's name, or..
                    # metadata have matched with confirmation commands.
                    if (not meta_keyword) or (meta_keyword == f"{self.assistant_name}".lower()):
                        self.speak(choice(self._get_commands("greeting_responses")))
                        return

                # commands to ask for assistant's name
                if is_match(voice_data, self._get_commands("ask_assistant_name")):
                    self.speak(
                        f"{choice(self._get_commands('ask_assistant_name_response'))}.")
                    return

                # commands to change wallpaper
                if is_match(voice_data, self._get_commands("wallpaper")):
                    wallpaper_response = self.skills.wallpaper()

                    if wallpaper_response:
                        self.speak(wallpaper_response)
                        return

                """
                    Remove the assistant's name in voice_data
                    from this point forward of code block
                    to avoid misleading data.
                """
                voice_data = clean_voice_data(voice_data, self.assistant_name)

                # respond to calling assistant's name
                if voice_data == "":
                    _awake_greetings(start_prompt=False)
                    return

                # today's breafing
                if is_match(voice_data, ["happening today", "what did I miss"]):
                    _happening_today()
                    return True

                # commands for playing music
                music_commands = self._get_commands("play_music")
                music_control_commands = self._get_commands("control_music")
                if is_match(voice_data, music_commands + music_control_commands):

                    if is_match(voice_data, music_control_commands) and not is_match(voice_data, music_commands):
                        setting_response = self.skills.music_setting(voice_data)
                        if setting_response:
                            self.speak(setting_response)
                            self.sleep(True)
                            return True

                    music_keyword = extract_metadata(voice_data, music_commands)
                    music_response = self.skills.play_music(music_keyword)

                    if music_response:
                        response_message += music_response
                        ask_google = False
                        ask_wikipedia = False
                        ask_wolfram = False
                        not_confirmation = False
                        use_calc = False
                        if "I couldn't find" not in music_response:
                            # mute and sleep assistant when playing music
                            self.sleep(True)

                # commands for controlling screen brightness, wi-fi and to shutdown/restart system
                if is_match(voice_data, (self._get_commands("brightness") + self._get_commands("wifi") + self._get_commands("system_shutdown_restart"))):
                    system_responses = ""
                    if "brightness" in voice_data:
                        system_responses = self.skills.screen_brightness(voice_data)
                    elif "wi-fi" in voice_data:
                        system_responses = self.skills.control_wifi(voice_data)
                    elif ("shutdown" in voice_data) or ("restart" in voice_data) or ("reboot" in voice_data):
                        # if we got response from shutdown command, initiate deactivation
                        restart_msg = self.skills.control_system(voice_data)

                        if restart_msg:
                            self.speak(restart_msg)
                            if "Ok!" in restart_msg:
                                # terminate virtual assistant
                                self.deactivate(self._get_commands("terminate")[0])
                        # return immediately, don't process for other commands any further
                        return

                    if system_responses:
                        response_message += system_responses
                        use_calc = False

                # commands for controlling system volume
                system_volume_commands = self._get_commands("system volume")
                if is_match(voice_data, system_volume_commands):
                    volume_meta = extract_metadata(voice_data, system_volume_commands)

                    vol_value = [value.replace("%", "") for value in volume_meta.split(" ") if value.replace("%", "").isdigit()]
                    if len(vol_value):
                        vol_value = vol_value[0]
                    else:
                        vol_value = ""

                    vol = ""
                    if vol_value and is_match(voice_data, ["increase", "turn up", "up"]):
                        vol = f"-{vol_value}"
                    elif vol_value and is_match(voice_data, ["decrease", "turn down", "down"]):
                        vol = f"+{vol_value}"
                    elif is_match(voice_data, ["increase", "turn up", "up"]):
                        vol = "-1"
                    elif is_match(voice_data, ["decrease", "turn down", "down"]):
                        vol = "+1"
                    elif vol_value:
                        vol = vol_value

                    self.skills.system_volume(vol)
                    response_message += choice(self._get_commands("acknowledge response"))
                    adjust_system_volume = True
                    ask_google = False
                    ask_wikipedia = False
                    ask_wolfram = False
                    not_confirmation = False
                    use_calc = False

                # commands for creating a new project automation
                create_project_commands = self._get_commands("create_project")
                if is_match(voice_data, create_project_commands):
                    new_proj_metadata = extract_metadata(
                        voice_data, create_project_commands)

                    if new_proj_metadata:
                        lang = "python"
                        proj_name = "NewProjectFolder"

                        lang_idx = new_proj_metadata.find("in")
                        if lang_idx >= 0 and len(new_proj_metadata.split()) > 1:
                            lang = new_proj_metadata[(lang_idx + 2):]

                        alternate_responses = self._get_commands("acknowledge response")
                        self.speak(f"{choice(alternate_responses)} Just a momement.")

                        create_proj_response = self.skills.initiate_new_project(
                            lang=lang, proj_name=proj_name)
                        self.speak(f"Initiating new {lang} project.")
                        self.speak(create_proj_response)
                        return

                # commands to ask time
                if is_match(voice_data, self._get_commands("time")):
                    response_time = self.skills.ask_time(voice_data)

                    if response_time:
                        response_message += response_time
                        ask_google = False
                        ask_wikipedia = False
                        ask_wolfram = False
                        not_confirmation = False
                        use_calc = False

                # commands for simple math calculations
                if use_calc and is_match(voice_data, self._get_commands("math_calculation")):
                    calc_response = self.skills.calculator(voice_data)

                    if calc_response:
                        response_message += calc_response
                        ask_google = False
                        ask_wikipedia = False
                        ask_wolfram = False
                        not_confirmation = False
                        use_calc = False

                # commands to open apps
                if is_match(voice_data, self._get_commands("open_apps")):
                    open_app_response = self.skills.open_application(voice_data)

                    if open_app_response:
                        response_message += open_app_response
                        ask_google = False
                        ask_wikipedia = False
                        ask_wolfram = False
                        not_confirmation = False
                        use_calc = False

                # commands to find local files and document
                find_file_commands = self._get_commands("find_file")
                if is_match(voice_data, find_file_commands):
                    file_keyword = extract_metadata(
                        voice_data, find_file_commands)
                    find_file_response = self.skills.find_file(file_keyword)

                    if find_file_response:
                        response_message += find_file_response
                        # we found response from find_file, don't search on google or wiki
                        ask_google = False
                        ask_wikipedia = False
                        ask_wolfram = False
                        not_confirmation = False
                        use_calc = False

                preposition_words = self._get_commands("prepositions")
                # commands for news briefing
                news_commands = self._get_commands("news") + [f"news {news_preposition}" for news_preposition in preposition_words]
                if is_match(voice_data, news_commands):
                    news_found = False

                    self.speak("I'm on it...")
                    self.print("\n Fetching information from news channels...\n")

                    # get news information from sources
                    self.news.fetch_news()

                    # get meta data to use for news headline search
                    news_meta_data = extract_metadata(voice_data, (news_commands + preposition_words))
                    about = f" on \"{news_meta_data}\"" if news_meta_data else ""

                    # breaking news report
                    if is_match(voice_data, ["breaking news"]):
                        # if news.check_breaking_news() and self.can_listen:
                        news_response = _breaking_news_report(on_demand=True)
                        if len(news_response) <= 0:
                            self.speak("Sorry, no Breaking News available (at the moment).")
                            return True
                        else:
                            self.speak(news_response)
                            news_found = True

                    # latest news
                    elif self.news.check_latest_news():

                        # top 3 latest news report
                        if is_match(voice_data, ["news briefing", "flash briefing", "news report", "top news", "top stories", "happening today"]):
                            news_briefing = self.news.cast_latest_news(
                                news_meta_data)
                            number_of_results = len(news_briefing)

                            if number_of_results > 0:
                                if number_of_results > 2:
                                    number_of_results = 3

                                news_found = True
                                self.speak(f"Here are your latest news briefing{about}.")
                                for i in range(0, number_of_results):
                                    # let's get the redirected url (if possible) from link we have
                                    redirect_url = requests.get(news_briefing[i]["source url"])
                                    # open the source article in webbrowser.
                                    open_news_url_thread = Thread(target=execute_map, args=("open browser", [redirect_url.url],))
                                    open_news_url_thread.setDaemon(True)
                                    open_news_url_thread.start()
                                    # send the link to bot
                                    self.respond_to_bot(redirect_url.url)
                                    self.speak(f"{news_briefing[i]['report']}")

                        # top 1 latest news report
                        elif is_match(voice_data, ["latest", "most", "recent", "flash news", "news flash"]):
                            news_deets = self.news.cast_latest_news(news_meta_data)
                            if len(news_deets) > 0:
                                news_found = True
                                # get the first index (latest) on the list of news
                                top_news = news_deets[0]
                                self.speak(f"Here's the latest news{about}.")
                                # let's get the redirected url (if possible) from link we have
                                redirect_url = requests.get(top_news["source url"])
                                # open the source article in webbrowser.
                                open_news_url_thread = Thread(target=execute_map, args=("open browser", [redirect_url.url],))
                                open_news_url_thread.setDaemon(True)
                                open_news_url_thread.start()
                                # send the link to bot
                                self.respond_to_bot(redirect_url.url)
                                self.speak(f"{top_news['report']}")

                        # random news report for today
                        else:
                            latest_news = self.news.cast_latest_news(news_meta_data)
                            if len(latest_news) > 0:
                                if news_meta_data:
                                    self.speak(f"Here's what I found{about}.")

                                news_found = True
                                # choose random news from list of latest news today
                                random_news_today = choice(latest_news)
                                # let's get the redirected url (if possible) from link we have
                                redirect_url = requests.get(random_news_today["source url"])
                                # open the source article in webbrowser.
                                open_news_url_thread = Thread(target=execute_map, args=("open browser", [redirect_url.url],))
                                open_news_url_thread.setDaemon(True)
                                open_news_url_thread.start()
                                # send the link to bot
                                self.respond_to_bot(redirect_url.url)
                                self.speak(f"{random_news_today['report']}")

                        if news_found:
                            self.speak("More details of this news in the source article. It should be in your web browser now.")

                    if news_meta_data and not news_found:
                        self.speak(f"I couldn't find \"{news_meta_data}\" on your News Feed. Sorry about that.")

                    return True

                # commands for youtube
                youtube_commands = self._get_commands("youtube")
                if is_match(voice_data, youtube_commands):
                    # extract youtube keyword to search
                    youtube_keyword = extract_metadata(
                        voice_data, youtube_commands)
                    # search the keyword in youtube website
                    youtube_response = self.skills.youtube(youtube_keyword)

                    # we got response from youtube, now append it to list of response_message
                    if youtube_response:
                        response_message += youtube_response
                        # don't search into google we found answer from youtube
                        ask_wolfram = False
                        ask_wikipedia = False
                        ask_google = False
                        not_confirmation = False

                # commands to use google maps
                google_maps_commands = self._get_commands("google_maps")
                if ask_google and is_match(voice_data, google_maps_commands):
                    # extract the location name
                    location = extract_metadata(
                        voice_data, google_maps_commands)

                    if location:
                        response_message += self.skills.google_maps(location)
                        # don't search on google we found answers from maps
                        ask_wolfram = False
                        ask_wikipedia = False
                        ask_google = False
                        not_confirmation = False

                # commands for confirmation
                confirmation_commands = self._get_commands("confirmation")

                # try wolfram for answers
                if ask_wolfram and not any(word for word in voice_data.split() if word in confirmation_commands):
                    # using commands from google to extract useful meta data for wolfram search
                    wolfram_response = self.skills.wolfram_search(voice_data)
                    # fun holiday information from timeanddate.com
                    title, message, did_you_know = self.skills.fun_holiday()
                    if wolfram_response and message and "today is" in wolfram_response:
                        wolfram_response += f"\n\nAccording to TimeAndDate.com, {message}\n{did_you_know}"

                    if wolfram_response:
                        response_message += wolfram_response
                        ask_wikipedia = False
                        ask_google = False
                        not_confirmation = False

                # commands for wikipedia, exception is "weather" commands
                wiki_commands = self._get_commands("wikipedia")
                if ask_wikipedia and is_match(voice_data, wiki_commands):
                    # extract the keyword
                    wiki_keyword = extract_metadata(voice_data, wiki_commands)
                    # get aswers from wikipedia
                    wiki_result = self.skills.wikipedia_search(
                        wiki_keyword=wiki_keyword, voice_data=voice_data)

                    keyword_list = wiki_keyword.lower().split(" ")
                    # if answer from wikipedia contains more than 2 words
                    if len(keyword_list) > 2:
                        match_count = 0

                        for word in keyword_list:
                            # and matched with context of question, return wikipedia answer
                            if word in wiki_result.lower():
                                match_count += 1
                        if match_count < 4:
                            # else, return nothing
                            wiki_result = ""

                    if wiki_result:
                        response_message += wiki_result
                        # don't search into google we found answer from wikipedia
                        ask_google = False
                        not_confirmation = False

                # commands to search on google
                google_commands = self._get_commands("google")
                if ask_google and is_match(voice_data, google_commands):
                    # remove these commands on keyword to search on google
                    google_keyword = extract_metadata(
                        voice_data, google_commands)

                    # search on google if we have a keyword
                    if google_keyword:
                        response_message += self.skills.google(google_keyword)
                        not_confirmation = False

                if not_confirmation and is_match(voice_data, confirmation_commands):
                    confimation_keyword = extract_metadata(
                        voice_data, confirmation_commands).strip()

                    # it's' a confirmation if no extracted metadata or..
                    # metadata have matched with confirmation commands.
                    if not confimation_keyword or is_match(confimation_keyword, confirmation_commands):
                        self.speak(choice(self._get_commands("confirmation_responses")))
                        # mute and sleep assistant when playing music
                        self.sleep(True)
                        # return immediately, it is a confirmation command,
                        # we don't need further contextual answers
                        return

                # we did not found any response
                if not response_message:
                    # set the unknown response
                    response_message = choice(self._get_commands("unknown_responses"))

                # anounce all the respons(es).
                self.speak(response_message)

                # mute/sleep assistant if volume is adjusted
                if adjust_system_volume:
                    self.sleep(True)

                return True

            except Exception:
                self.Log("Error forumulating response.")
                self.respond_to_bot("Error forumulating response.")
Beispiel #9
0
    def play_music(self, voice_data):
        songWasFound = False
        option = '"play all"'
        shuffle = "True"
        mode = "compact"
        title = "none"
        artist = "none"
        genre = "none"
        response = ""

        try:
            import sys
            sys.path.append(self.UTILS_DIR)
            from musicplayer import MusicPlayer
            mp = MusicPlayer()

            # change the directory to location of batch file to execute
            os.chdir(self.UTILS_DIR)

            music_word_found = True if is_match(
                voice_data, ["music", "songs"]) else False
            meta_data = voice_data.lower().replace("&", "and").replace(
                "music", "").replace("songs", "").strip()

            if meta_data == "":
                # mode = "compact"
                alternate_responses = self._get_commands("acknowledge response")
                response = f"{choice(alternate_responses)} Playing all songs{', shuffled' if shuffle == 'True' else '...'}"
                songWasFound = True

            elif meta_data and "by" in meta_data.split(" ") and meta_data.find("by") > 0 and len(meta_data.split()) >= 3:
                option = '"play by"'

                by_idx = meta_data.find("by")
                title = meta_data[:(by_idx - 1)].strip().capitalize()
                artist = meta_data[(by_idx + 3):].strip().capitalize()

                if mp.search_song_by(title, artist, title):
                    songWasFound = True
                    artist = f'"{artist}"'
                    genre = title

                    alternate_responses = self._get_commands("acknowledge response")
                    response = f"{choice(alternate_responses)} Playing \"{title}\" by {artist}..."
                else:
                    response = f"I couldn't find \"{title}\" in your music."

            elif meta_data:
                option = '"play by"'
                title = f'"{meta_data}"'
                artist = f'"{meta_data}"'
                genre = f'"{meta_data}"'

                mp.title = meta_data
                mp.artist = meta_data
                mp.genre = meta_data

                if mp.search_song_by(meta_data, meta_data, meta_data):
                    songWasFound = True
                    alternate_responses = self._get_commands("acknowledge response")
                    response = f"{choice(alternate_responses)} Now playing \"{meta_data.capitalize()}\" {'music...' if music_word_found else '...'}"
                else:
                    response = f"I couldn't find \"{meta_data.capitalize()}\" in your music."

            if songWasFound:
                mp.player_status("close")
                # batch file to play some music in new window
                os.system(
                    f'start cmd /k "play_some_music.bat {option} {shuffle} {mode} {title} {artist} {genre}"')

            # get back to virtual assistant directory
            os.chdir(self.ASSISTANT_DIR)

            return response

        except Exception:
            self.Log("Play Music Skill Error.")
Beispiel #10
0
    def open_application(self, voice_data):
        confirmation = ""
        app_names = []
        app_commands = []
        urls = []

        def modified_app_names():
            clean_app_names = voice_data
            special_app_names = ["vs code", "sublime text", "wi-fi manager", "wifi manager", "wi-fi monitoring", "ms code", "ms vc", "microsoft excel", "spread sheet", "ms excel", "microsoft word", "ms word", "microsoft powerpoint", "ms powerpoint", "task scheduler",
                                 "visual studio code", "pse ticker", "command console", "command prompt", "control panel", "task manager", "resource monitor", "resource manager", "device manager", "windows services", "remove programs", "add remove"]
            for name in special_app_names:
                if name in voice_data:
                    # make one word app name by using hyphen
                    clean_app_names = clean_app_names.replace(
                        name, name.replace(" ", "-"))

            # return unique list of words/app names
            return {word for word in clean_app_names.split(" ")}

        try:
            for app in modified_app_names():
                if is_match(app, ["explorer", "folder"]):
                    app_commands.append(
                        "start explorer C:\\Users\\Dave\\DEVENV\\Python")
                    app_names.append("Windows Explorer")

                elif is_match(app, ["control-panel"]):
                    app_commands.append("start control")
                    app_names.append("Control Panel")

                elif is_match(app, ["device-manager", "device"]):
                    app_commands.append("start devmgmt.msc")
                    app_names.append("Device Manager")

                elif is_match(app, ["windows-services", "services"]):
                    app_commands.append("start services.msc")
                    app_names.append("Windows Services")

                elif is_match(app, ["add-remove-program", "remove-programs", "add-remove", "unistall"]):
                    app_commands.append("start control appwiz.cpl")
                    app_names.append("Programs and Features")

                elif is_match(app, ["resource-manager", "resource-monitor"]):
                    app_commands.append("start resmon")
                    app_names.append("Resource Manager")

                elif is_match(app, ["task-manager"]):
                    app_commands.append("start Taskmgr")
                    app_names.append("Task Manager")

                elif is_match(app, ["task-scheduler", "scheduler"]):
                    app_commands.append("start taskschd.msc")
                    app_names.append("Task Scheduler")

                elif is_match(app, ["notepad", "textpad", "notes"]):
                    app_commands.append("start notepad")
                    app_names.append("Notepad")

                elif is_match(app, ["calculator"]):
                    app_commands.append("start calc")
                    app_names.append("Calculator")

                elif is_match(app, ["command-console", "command-prompt", "terminal", "command"]):
                    app_commands.append("start cmd")
                    app_names.append("Command Console")

                elif is_match(app, ["microsoft-excel", "ms-excel", "excel", "spread-sheet"]):
                    app_commands.append("start excel")
                    app_names.append("Microsoft Excel")

                elif is_match(app, ["microsoft-word", "ms-word", "word"]):
                    app_commands.append("start winword")
                    app_names.append("Microsoft Word")

                elif is_match(app, ["microsoft-powerpoint", "ms-powerpoint", "powerpoint"]):
                    app_commands.append("start winword")
                    app_names.append("Microsoft Powerpoint")

                elif is_match(app, ["spotify"]):
                    app_commands.append(
                        "C:\\Users\\Dave\\AppData\\Roaming\\Spotify\\Spotify.exe")
                    app_names.append("Spotify")

                elif is_match(app, ["vscode", "vs-code", "ms-code", "ms-vc", "visual-studio-code"]):
                    app_commands.append("start code -n")
                    app_names.append("Visual Studio Code")

                elif is_match(app, ["sublime", "sublime-text"]):
                    app_commands.append("start sublime_text -n")
                    app_names.append("Sublime Text 3")

                elif is_match(app, ["newsfeed", "news"]):
                    app_names.append("Newsfeed Ticker")
                    # change directory to NewsTicker library
                    os.chdir(self.NEWS_DIR)
                    # execute batch file that will open Newsfeed on a newo console window
                    os.system('start cmd /k \"start News Ticker.bat\"')
                    # get back to virtual assistant directory after command execution
                    os.chdir(self.ASSISTANT_DIR)

                elif is_match(app, ["wi-fi-monitoring", "wi-fi-manager", "wifi-manager"]):
                    app_names.append("Wi-Fi Manager")
                    # change directory to Wi-Fi manager library
                    os.chdir(self.UTILS_DIR)
                    # execute batch file that will open Wi-Fi manager on a newo console window
                    os.system('start cmd /k \"wifi manager.bat\"')
                    # get back to virtual assistant directory after command execution
                    os.chdir(self.ASSISTANT_DIR)

                elif is_match(app, ["pse-ticker", "pse"]):
                    app_names.append("Philippine Stock Exchange Ticker")
                    # change directory to PSE library resides
                    os.chdir(self.PSE_DIR)
                    # open PSE ticker in new window
                    os.system('start cmd /k \"start_PSE.bat\"')
                    # get back to virtual assistant directory after command execution
                    os.chdir(self.ASSISTANT_DIR)

                elif is_match(app, ["youtube", "google", "netflix", "github", "facebook", "twitter", "instagram", "wikipedia"]):
                    if app == "youtube":
                        app_names.append("Youtube")
                        urls.append("https://www.youtube.com/")
                    elif app == "google":
                        app_names.append("Google")
                        urls.append("https://www.google.com/")
                    elif app == "netflix":
                        app_names.append("Netflix")
                        urls.append("https://www.netflix.com/ph/")
                    elif app == "github":
                        urls.append("https://www.github.com")
                        app_names.append("Github")
                    elif app == "facebook":
                        urls.append("https://www.facebook.com")
                        app_names.append("Facebook")
                    elif app == "twitter":
                        urls.append("https://www.twitter.com")
                        app_names.append("Twitter")
                    elif app == "instagram":
                        urls.append("https://www.instagram.com")
                        app_names.append("Instagram")
                    elif app == "wikipedia":
                        urls.append("https://www.wikipedia.org")
                        app_names.append("Wikipedia")

            # launch local applications using python's os.system class
            if len(app_commands) > 0:
                open_app_thread = Thread(
                    target=execute_map, args=("open system", app_commands,))
                open_app_thread.setDaemon(True)
                open_app_thread.start()

            # open the webapp in web browser
            if len(urls) > 0:
                open_browser_thread = Thread(
                    target=execute_map, args=("open browser", urls,))
                open_browser_thread.setDaemon(True)
                open_browser_thread.start()
                # send the links to bot
                with task.ThreadPoolExecutor() as exec:
                    exec.map(self.tts.respond_to_bot, urls)

            if len(app_names) > 0:
                alternate_responses = self._get_commands("acknowledge response")
                confirmation = f"Ok! opening {' and '.join(app_names)}..."
                alternate_responses.append(confirmation)
                confirmation = choice(alternate_responses)

        except Exception:
            self.Log("Open Application Skill Error.", logging.DEBUG)

        return confirmation
Beispiel #11
0
    def calculator(self, voice_data):
        operator = ""
        number1 = 0
        percentage = 0
        answer = None
        equation = ""

        try:
            # evaluate if there are square root or cube root questions, replace with single word
            evaluated_voice_data = voice_data.replace(",", "").replace("power of", "power#of").replace(
                "square root", "square#root").replace("cube root", "cube#root").split(" ")

            for word in evaluated_voice_data:
                if is_match(word, ["+", "plus", "add"]):
                    operator = " + " if not word.replace("+",
                                                         "").isdigit() else word
                    equation += operator
                elif is_match(word, ["-", "minus", "subtract"]):
                    operator = " - " if not word.replace("-",
                                                         "").isdigit() else word
                    equation += operator
                elif is_match(word, ["x", "times", "multiply", "multiplied"]):
                    operator = " * "
                    equation += operator
                elif is_match(word, ["/", "divide", "divided"]):
                    operator = " / "
                    equation += operator
                elif is_match(word, ["^", "power#of"]):
                    operator = " ^ "
                    equation += operator
                elif is_match(word, ["square#root"]):
                    equation += "x2"
                elif is_match(word, ["cube#root"]):
                    equation += "x3"
                elif is_match(word, ["percent", "%"]):
                    operator = "%"
                    if not word.isdigit() and "%" in word:
                        equation += f"{word} of "
                        percentage = w2n.word_to_num(word.replace("%", ""))
                    else:
                        equation += "% of "
                        percentage = number1
                    number1 = 0
                elif is_match(word, ["dot", "point", "."]):
                    equation += word

                # try to convert words to numbers
                elif word.isdigit() or is_match(word, ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "zero"]):
                    # build the equation
                    equation += str(w2n.word_to_num(word)).replace(" ", "")

                    # store number value for special equations (percentage, square root, cube root)
                    if percentage or ("x2" in equation) or ("x3" in equation):
                        number1 = word

            if percentage and int(number1) > 0:
                equation = f"{percentage}*.01*{number1}"
                # evaluate percentage equation
                answer = float(eval(equation))
                # create a readable equation
                equation = f"{percentage}% of {number1}"

            # no percentage computation was made,
            # just return equivalent value of percent
            if (answer is None) and percentage:
                return f"{percentage}% is {percentage * .01}"

            if "x2" in equation:
                equation = f"{number1}**(1./2.)"
            elif "x3" in equation:
                equation = f"{number1}**(1./3.)"
            elif "^" in equation:
                # can't evaluate
                return ""

            if (answer is None) and equation:
                try:
                    # evaluate the equation made
                    answer = eval(equation.replace(",", ""))
                except ZeroDivisionError:
                    return choice(["The answer is somwhere between infinity, negative infinity, and undefined.", "The answer is undefined."])
                except Exception:
                    self.Log(
                        "Calculator Skill Exception (handled).", logging.INFO)
                    return ""

            if answer is not None:
                with_decimal_point = float('{:.02f}'.format(answer))

                # check answer for decimal places,
                # convert to whole number if decimal point value is ".00"
                positive_float = int(
                    (str(with_decimal_point).split('.'))[1]) > 0

                format_answer = with_decimal_point if positive_float else int(
                    answer)

                # bring back the readable format of square root and cube root
                equation = equation.replace(f"{number1}**(1./2.)", f"square root of {number1}").replace(
                    f"{number1}**(1./3.)", f"cube root of {number1}")

                equation = [equation, "The answer"]

                return f"{choice(equation)} is {'approximately ' if positive_float else ''}{format_answer}"
            else:
                return ""

        except Exception:
            self.Log("Calculator Skill Error.")
            return ""
Beispiel #12
0
    def wolfram_search(self, voice_data):
        response = ""
        meta_data = ""
        parts_of_speech = self._get_commands("parts of speech")

        try:
            client = wolframalpha.Client(self.WOLFRAM_APP_ID)

            def _resolveListOrDict(value):
                if isinstance(value, list):
                    return value[0]["plaintext"]
                else:
                    return value["plaintext"]

            def _removeBrackets(value):
                if value:
                    return value.replace("|", "").strip().split("(")[0].replace("  ", " ")
                else:
                    return ""

            def _weatherReport(data):
                report = ""
                try:
                    max_temp = ""
                    min_temp = ""
                    ave_temp = ""
                    conditions = []
                    current_hour = int(dt.now().strftime("%I"))
                    current_meridian_indicator = dt.now().strftime("%p")
                    time_frame = "morning" if ("AM" == current_meridian_indicator and current_hour <= 10) else ("afternoon" if (("AM" == current_meridian_indicator and current_hour > 10) or (
                        "PM" == current_meridian_indicator and current_hour == 12) or ("PM" == current_meridian_indicator and current_hour <= 2)) else "night")

                    data = data.replace('rain', 'raining').replace(
                        'few clouds', 'cloudy').replace("clear", "clear skies")

                    for item in data.split("\n"):
                        if "°C" in item:
                            temps = item.replace("between", "").replace(
                                "°C", "").split("and")

                            if len(temps) > 1:
                                min_temp = temps[0].strip()
                                max_temp = temps[1].strip()
                                ave_temp = str(
                                    (int(max_temp) + int(min_temp)) // 2)
                            else:
                                ave_temp = item.replace("°C", "").strip()

                        elif is_match(item, ["|"]):
                            for cond in item.split("|"):
                                if time_frame == "morning" and "early morning" in cond:
                                    if "(" in cond:
                                        conditions.append(
                                            cond[:cond.index("(")].strip())
                                elif time_frame == "afternoon" and "afternoon" in cond:
                                    if "(" in cond:
                                        conditions.append(
                                            cond[:cond.index("(")].strip())
                                elif "(" in cond:
                                    conditions.append(
                                        cond[:cond.index("(")].strip())
                                # conditions.append(cond.strip())

                            if max_temp and min_temp:
                                if len(conditions) > 2:
                                    report = f"{conditions[0]} and {ave_temp}°C. Expect mixed conditions starting {time_frame} and the rest of the day. Temperatures are heading down from {max_temp}°C to {min_temp}°C."
                                else:
                                    report = f"{conditions[0]} and {ave_temp}°C. Expect {' and '.join(conditions)} starting {time_frame} with mixed conditions for the rest of the day. Temperatures are heading down from {max_temp}°C to {min_temp}°C."
                            else:
                                conditions = ' and '.join(conditions)
                                report = f"{ave_temp}°C with mixed condition like {conditions}."
                        else:
                            conditions = item.strip()
                            report = f"{conditions} and {ave_temp}°C."

                except Exception:
                    pass
                    self.Log("Wolfram|Alpha Weather Report Error.")

                return report

            weather_commands = self._get_commands("weather")
            report_type = "weather forecast"
            current_location = "Malolos, Bulacan"
            is_weather_report = False

            if is_match(voice_data, weather_commands):
                meta_data = extract_metadata(
                    voice_data, (["in", "on", "for", "this"] + weather_commands)).replace("forecast", "")

                if is_match(voice_data, ["rain", "precipitation"]):
                    report_type = "rain forecast"
                elif is_match(voice_data, ["temperature"]):
                    report_type = "temperature"

                # let's build the query for weather, temperature or precipitation forecast.
                # this will be our parameter input in Wolfram API
                if is_match(voice_data, ["in", "on", "for", "this"]):
                    if meta_data:
                        voice_data = f"{report_type} for {meta_data}"
                    else:
                        voice_data = f"{report_type} for {current_location}"
                else:
                    meta_data = extract_metadata(voice_data, weather_commands)
                    voice_data = f"{report_type} for {current_location} {meta_data}"
                is_weather_report = True

            # send query to Wolfram Alpha
            wolframAlpha = client.query(voice_data)

            # check if we have a successful result
            if wolframAlpha["@success"] == True:
                # may contain extracted question or query meta data
                pod0 = wolframAlpha["pod"][0]

                # may contain the answer
                pod1 = wolframAlpha["pod"][1]

                # extracting wolfram question interpretation from pod0
                question = _resolveListOrDict(pod0["subpod"])

                # removing unnecessary parenthesis
                question = _removeBrackets(question).strip()

                # checking if pod1 has primary=true or title=result|definition
                if (("definition" in pod1["@title"].lower()) or ("result" in pod1["@title"].lower()) or (pod1.get("@primary", "false") == True)):

                    # extract result from pod1
                    wolfram_response = _resolveListOrDict(pod1["subpod"])

                    # if no answers found return a blank response
                    if (wolfram_response is None) or is_match(wolfram_response, ["(data not available)", "(no data available)", "(unknown)"]):
                        return ""

                    # create a weather report
                    if is_weather_report:
                        # rain forecast (precipitation)
                        if "precipitation" in question:
                            precipitation_forecast = ""

                            if "rain" in wolfram_response:
                                precipitation_forecast = choice(
                                    [f"The forecast calls for {wolfram_response} for{question}", f"Yes, I think we'll see some {wolfram_response} for {question}"])
                            else:
                                precipitation_forecast = choice(
                                    [f"It doesn't look like it's going to {wolfram_response} for{question}", f"I don't believe it will {wolfram_response} for {question}"]).replace("no precipitation", "rain")
                            return precipitation_forecast.replace("precipitation forecast", "").replace("rain\n", "rain on ")

                        # weather and temperature forecast
                        report_heading = "Here's the " + question.replace("temperature", "temperature for").replace(
                            "weather forecast", "weather forecast for").replace("\n", ", ")
                        report_prefix = "It's currently"

                        if report_type == "weather forecast":
                            wolfram_response = _weatherReport(wolfram_response)

                        if is_match(meta_data, self._get_commands("time and day")):
                            report_prefix = f"{meta_data.capitalize()} will be"

                        return f"{report_heading}. \n\n{report_prefix} {wolfram_response}"

                    # remove "according to" phrase in wolfram response
                    if is_match(wolfram_response, ["(according to"]):
                        wolfram_response = wolfram_response.split(
                            "(according to")[0]

                    if is_match(wolfram_response, ["I was created by"]):
                        wolfram_response = f"I was created by {self.master_name}."

                    wolfram_meta = wolfram_response.split("|")

                    # replace "Q:" and "A:" prefixes and replace new space instead
                    if is_match(wolfram_response, ["Q: ", "A: "]) or is_match(question, ["tell me a joke."]):
                        response = wolfram_response.replace(
                            "Q: ", "").replace("A: ", "\n\n")

                    # we found an array of information, let's disect if necessary
                    elif wolfram_response.count("|") > 2:
                        if is_match(wolfram_response, parts_of_speech):
                            # responding to definition of terms, and using the first answer in the list as definition
                            response = f"\"{question}\" \n. ({wolfram_meta[1]}) . \nIt means... {wolfram_meta[-1].strip().capitalize()}."
                        else:
                            # respond by showing list of information
                            for deet in wolfram_response.split(" | "):
                                response += f"{deet}.\n"

                            return f"Here's some information..\n{response}"

                    # we found an array of information, let's disect if necessary
                    elif wolfram_response.count("\n") > 3:
                        # respond by showing list of information
                        for deet in wolfram_response.split(" | "):
                            response += f"{deet}.\n"

                        return f"Here's some information..\n{response}"

                    # we found at least 1 set of defition, disect further if necessary
                    elif is_match(wolfram_response, ["|"]):
                        # extract the 12 hour time value
                        if is_match(voice_data, ["time"]):

                            # check for 12 hour time value
                            if len(wolfram_response.split(":")[0]) == 2:
                                hour = wolfram_response[:5]
                                ampm = wolfram_response[9:11]
                                response = f"{hour} {ampm}"
                            else:
                                hour = wolfram_response[:4]
                                ampm = wolfram_response[8:10]
                                response = f"{hour} {ampm}"

                        # responding to "do you know my name?"
                        elif is_match(wolfram_response, ["my name is"]):
                            # replace "Wolfram|Aplha" to assistant's name.
                            response = wolfram_response[:(wolfram_response.lower().find(
                                "my name is") + 11)] + self.assistant_name + ". Are you " + self.master_name + "?"

                        else:
                            # responding to definition of terms
                            if is_match(wolfram_response, parts_of_speech):
                                response = f"\"{question}\" \n. ({wolfram_meta[0]}) . \nIt means... {wolfram_meta[-1].strip().capitalize()}."
                            else:
                                response = wolfram_response

                    # single string response
                    else:
                        if is_match(voice_data, ["how do you spell", "spell", "spelling", "spells"]):

                            question = question.replace(
                                "spellings", "").strip()
                            if len(wolfram_response) > len(question):
                                # there are one or more word spelling, we need to figure out which one is in question.
                                word_found = False
                                for word in wolfram_response.split(" "):
                                    if word.lower() in voice_data.lower().split(" "):
                                        question = word
                                        wolfram_response = word
                                        word_found = True
                                        break

                                # if we don't find the word to spell in wolfram response, then it must be the "question"
                                if not word_found:
                                    wolfram_response = question

                            # let's split the letters of response to simulate spelling the word(s).
                            response = f'{question}\n\n . {" . ".join(list(wolfram_response.capitalize()))}'
                        else:
                            if "happy birthday to you." in question.lower():
                                response = wolfram_response.replace(
                                    "<fill in name of birthday person>", self.master_name)
                            elif wolfram_response.isdigit():
                                numeric_response = wolfram_response
                                if "date" not in question.lower():
                                    numeric_response = "{:,}".format(
                                        int(wolfram_response))

                                # response = f"{question} is {numeric_response}"
                                response = numeric_response
                            else:
                                response = wolfram_response

                    parts_of_speech.append("Here's some information.")
                    # don't include the evaluated question in result if it has "?", "here's some information" or more than 5 words in it
                    if len(voice_data.split(" ")) > 5 or is_match(voice_data, ["how do you spell", "spell", "spelling", "spells"]) or is_match(question, ["?", "tell me a joke.", "thank you.", "happy birthday to you."]) or is_match(response, parts_of_speech):
                        return response
                    else:
                        if question:
                            return f"{question} is {response}."
                        else:
                            return f"{question} {response}."

        except Exception:
            pass
            self.Log("Wolfram|Alpha Search Skill Error.")

        # if no answers found return a blank response
        return response