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)
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()
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 ""
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
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
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 ""
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
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.")
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.")
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
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 ""
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