def kill_alarm(phrase: str) -> None: """Removes lock file to stop the alarm which rings only when the certain lock file is present. Args: phrase: Takes the voice recognized statement as argument and extracts time from it. """ word = 'timer' if 'timer' in phrase else 'alarm' alarm_state = support.lock_files(alarm_files=True) if not alarm_state: speaker.speak(text=f"You have no {word}s set {env.title}!") elif len(alarm_state) == 1: hour, minute, am_pm = alarm_state[0][0:2], alarm_state[0][3:5], alarm_state[0][6:8] os.remove(f"alarm/{alarm_state[0]}") speaker.speak(text=f"Your {word} at {hour}:{minute} {am_pm} has been silenced {env.title}!") else: speaker.speak(text=f"Your {word}s are at {', and '.join(alarm_state).replace('.lock', '')}. " f"Please let me know which {word} you want to remove.", run=True) if not (converted := listener.listen(timeout=3, phrase_limit=4)): return alarm_time = converted.split()[0] am_pm = converted.split()[-1] if ":" in converted: hour = int(alarm_time.split(":")[0]) minute = int(alarm_time.split(":")[-1]) else: hour = int(alarm_time.split()[0]) minute = 0 hour, minute = f"{hour:02}", f"{minute:02}" am_pm = str(am_pm).replace('a.m.', 'AM').replace('p.m.', 'PM') if os.path.exists(f'alarm/{hour}_{minute}_{am_pm}.lock'): os.remove(f"alarm/{hour}_{minute}_{am_pm}.lock") speaker.speak(text=f"Your {word} at {hour}:{minute} {am_pm} has been silenced {env.title}!") else: speaker.speak(text=f"I wasn't able to find your {word} at {hour}:{minute} {am_pm}. Try again.")
def wikipedia_() -> None: """Gets any information from wikipedia using its API.""" speaker.speak(text="Please tell the keyword.", run=True) if keyword := listener.listen(timeout=3, phrase_limit=5): if any(word in keyword.lower() for word in keywords.exit_): return else: sys.stdout.write( f"\rGetting your info from Wikipedia API for {keyword}") try: result = wikipedia.summary(keyword) except wikipedia.DisambiguationError as error: sys.stdout.write(f"\r{error}") speaker.speak( text= f"Your keyword has multiple results {env.title}. {' '.join(error.options)}" "Please pick one and try again.") if shared.called_by_offline: return speaker.speak(run=True) if not (keyword1 := listener.listen(timeout=3, phrase_limit=5)): return result = wikipedia.summary(keyword1) except wikipedia.PageError: speaker.speak( text= f"I'm sorry {env.title}! I didn't get a response for the phrase: {keyword}." ) return
def locate_places(phrase: str = None) -> None: """Gets location details of a place. Args: phrase: Takes the phrase spoken as an argument. """ place = support.get_capitalized(phrase=phrase) if phrase else None # if no words found starting with an upper case letter, fetches word after the keyword 'is' eg: where is Chicago if not place: keyword = "is" before_keyword, keyword, after_keyword = phrase.partition(keyword) place = after_keyword.replace(" in", "").strip() if not place: if shared.called_by_offline: speaker.speak(text=f"I need a location to get you the details {env.title}!") return speaker.speak(text="Tell me the name of a place!", run=True) if not (converted := listener.listen(timeout=3, phrase_limit=4)) or "exit" in converted or "quit" in converted \ or "Xzibit" in converted: return place = support.get_capitalized(phrase=converted) if not place: keyword = "is" before_keyword, keyword, after_keyword = converted.partition(keyword) place = after_keyword.replace(" in", "").strip()
def renew() -> None: """Keeps listening and sends the response to ``conditions()`` function. Notes: - This function runs only for a minute. - split_phrase(converted) is a condition so that, loop breaks when if sleep in ``conditions()`` returns True. """ speaker.speak(run=True) waiter = 0 while waiter < 12: waiter += 1 if waiter == 1: converted = listener.listen(timeout=3, phrase_limit=5) else: converted = listener.listen(timeout=3, phrase_limit=5, sound=False) if not converted: continue remove = ['buddy', 'jarvis', 'hey', 'hello'] converted = ' '.join( [i for i in converted.split() if i.lower() not in remove]) if converted: if split_phrase( phrase=converted ): # should_return flag is not passed which will default to False break # split_phrase() returns a boolean flag from conditions. conditions return True only for sleep elif any(word in converted.lower() for word in remove): continue speaker.speak(run=True)
def start(self) -> NoReturn: """Runs ``audio_stream`` in a forever loop and calls ``initiator`` when the phrase ``Jarvis`` is heard.""" try: while True: sys.stdout.write("\rSentry Mode") if not self.audio_stream: self.open_stream() pcm = struct.unpack_from("h" * self.detector.frame_length, self.audio_stream.read(num_frames=self.detector.frame_length, exception_on_overflow=False)) self.recorded_frames.append(pcm) if self.detector.process(pcm=pcm) >= 0: playsound(sound=indicators.acknowledgement, block=False) self.close_stream() if phrase := listener.listen(timeout=env.timeout, phrase_limit=env.phrase_limit, sound=False): initiator(phrase=phrase, should_return=True) speaker.speak(run=True) if flag := support.check_restart(): logger.info(f"Restart condition is set to {flag[0]} by {flag[1]}") if flag[1] == "OFFLINE": stop_processes() for _handler in logger.handlers: if isinstance(_handler, logging.FileHandler): logger.removeHandler(hdlr=_handler) handler = custom_handler() logger.info(f"Switching to {handler.baseFilename}") logger.addHandler(hdlr=handler) shared.processes = start_processes() else: stop_processes(func_name=flag[1]) shared.processes[flag[1]] = start_processes(flag[1]) if flag := support.check_stop(): logger.info(f"Stopper condition is set to {flag[0]} by {flag[1]}") self.stop() terminator()
def sentry_mode() -> NoReturn: """Listens forever and invokes ``initiator()`` when recognized. Stops when ``restart`` table has an entry. See Also: - Gets invoked only when run from Mac-OS older than 10.14. - A regular listener is used to convert audio to text. - The text is then condition matched for wake-up words. - Additional wake words can be passed in a list as an env var ``LEGACY_KEYWORDS``. """ try: while True: sys.stdout.write("\rSentry Mode") if wake_word := listener.listen(timeout=10, phrase_limit=2.5, sound=False, stdout=False): support.flush_screen() if any(word in wake_word.lower() for word in env.legacy_keywords): playsound(sound=indicators.acknowledgement, block=False) if phrase := listener.listen(timeout=env.timeout, phrase_limit=env.phrase_limit, sound=False): initiator(phrase=phrase, should_return=True) speaker.speak(run=True) if flag := support.check_restart(): logger.info(f"Restart condition is set to {flag[0]} by {flag[1]}") if flag[1] == "OFFLINE": stop_processes() for _handler in logger.handlers: if isinstance(_handler, logging.FileHandler): logger.removeHandler(hdlr=_handler) handler = custom_handler() logger.info(f"Switching to {handler.baseFilename}") logger.addHandler(hdlr=handler) shared.processes = start_processes() else: stop_processes(func_name=flag[1]) shared.processes[flag[1]] = start_processes(flag[1])
def repeat() -> NoReturn: """Repeats whatever is heard.""" speaker.speak(text="Please tell me what to repeat.", run=True) if keyword := listener.listen(timeout=3, phrase_limit=10): if 'exit' in keyword or 'quit' in keyword or 'Xzibit' in keyword: pass else: speaker.speak(text=f"I heard {keyword}")
def add_todo() -> None: """Adds new items to the to-do list.""" speaker.speak(text=f"What's your plan {env.title}?", run=True) if not (item := listener.listen(timeout=3, phrase_limit=5) ) or 'exit' in item or 'quit' in item or 'Xzibit' in item: speaker.speak( text=f'Your to-do list has been left intact {env.title}.') return
def delete_todo_items() -> None: """Deletes items from an existing to-do list.""" speaker.speak(text=f"Which one should I remove {env.title}?", run=True) if not (item := listener.listen(timeout=3, phrase_limit=5) ) or 'exit' in item or 'quit' in item or 'Xzibit' in item: speaker.speak( text=f'Your to-do list has been left intact {env.title}.') return
def google_search(phrase: str = None) -> None: """Opens up a Google search for the phrase received. If nothing was received, gets phrase from user. Args: phrase: Takes the phrase spoken as an argument. """ phrase = phrase.split('for')[-1] if 'for' in phrase else None if not phrase: speaker.speak(text="Please tell me the search phrase.", run=True) if (converted := listener.listen(timeout=3, phrase_limit=5)) or 'exit' in converted or 'quit' in converted or \ 'xzibit' in converted or 'cancel' in converted: return else: phrase = converted.lower()
def shutdown(proceed: bool = False) -> None: """Gets confirmation and turns off the machine. Args: proceed: Boolean value whether to get confirmation. Raises: StopSignal: To stop Jarvis' PID. """ if not proceed: speaker.speak( text= f"{random.choice(conversation.confirmation)} turn off the machine?", run=True) converted = listener.listen(timeout=3, phrase_limit=3) else: converted = 'yes' if converted and any(word in converted.lower() for word in keywords.ok): stop_terminals() if env.macos: subprocess.call( ['osascript', '-e', 'tell app "System Events" to shut down']) else: os.system("shutdown /s /t 1") raise StopSignal else: speaker.speak(text=f"Machine state is left intact {env.title}!") return
def restart(ask: bool = True) -> None: """Restart triggers ``restart.py`` which in turn starts Jarvis after 5 seconds. Warnings: - | Restarts the machine without approval when ``uptime`` is more than 2 days as the confirmation is requested | in `system_vitals <https://thevickypedia.github.io/Jarvis/#executors.system.system_vitals>`__. - This is done ONLY when the system vitals are read, and the uptime is more than 2 days. Args: ask: Boolean flag to get confirmation from user. Raises: StopSignal: To stop Jarvis' PID. """ if ask: speaker.speak( text=f"{random.choice(conversation.confirmation)} restart your " f"{shared.hosted_device.get('device')}?", run=True) converted = listener.listen(timeout=3, phrase_limit=3) else: converted = 'yes' if any(word in converted.lower() for word in keywords.ok): stop_terminals() if env.macos: subprocess.call( ['osascript', '-e', 'tell app "System Events" to restart']) else: os.system("shutdown /r /t 1") raise StopSignal else: speaker.speak(text=f"Machine state is left intact {env.title}!") return
def apps(phrase: str) -> None: """Launches the requested application and if Jarvis is unable to find the app, asks for the app name from the user. Args: phrase: Takes the phrase spoken as an argument. """ keyword = phrase.split()[-1] if phrase else None ignore = ['app', 'application'] if not keyword or keyword in ignore: if shared.called_by_offline: speaker.speak(text=f'I need an app name to open {env.title}!') return speaker.speak(text=f"Which app shall I open {env.title}?", run=True) if keyword := listener.listen(timeout=3, phrase_limit=4): if 'exit' in keyword or 'quit' in keyword or 'Xzibit' in keyword: return else: speaker.speak(text="I didn't quite get that. Try again.") return
def github_controller(target: list) -> None: """Clones the GitHub repository matched with existing repository in conditions function. Asks confirmation if the results are more than 1 but less than 3 else asks to be more specific. Args: target: Takes repository name as argument which has to be cloned. """ if len(target) == 1: os.system(f"cd {env.home} && git clone -q {target[0]}") cloned = target[0].split('/')[-1].replace('.git', '') speaker.speak( text=f"I've cloned {cloned} on your home directory {env.title}!") return elif len(target) <= 3: newest = [new.split('/')[-1] for new in target] sys.stdout.write(f"\r{', '.join(newest)}") speaker.speak( text= f"I found {len(target)} results. On your screen {env.title}! Which one shall I clone?", run=True) if not (converted := listener.listen(timeout=3, phrase_limit=5)): if any(word in converted.lower() for word in keywords.exit_): return if 'first' in converted.lower(): item = 1 elif 'second' in converted.lower(): item = 2 elif 'third' in converted.lower(): item = 3 else: item = None speaker.speak( text= f"Only first second or third can be accepted {env.title}! Try again!" ) github_controller(target) os.system(f"cd {env.home} && git clone -q {target[item]}") cloned = target[item].split('/')[-1].replace('.git', '') speaker.speak( text=f"I've cloned {cloned} on your home directory {env.title}!" )
def voice_changer(phrase: str = None) -> None: """Speaks to the user with available voices and prompts the user to choose one. Args: phrase: Initiates changing voices with the model name. If none, defaults to ``Daniel`` """ if not phrase: voice_default() return voices: Union[list, object] = speaker.audio_driver.getProperty( "voices") # gets the list of voices available choices_to_say = [ "My voice module has been reconfigured. Would you like me to retain this?", "Here's an example of one of my other voices. Would you like me to use this one?", "How about this one?" ] for ind, voice in enumerate(voices): speaker.audio_driver.setProperty("voice", voices[ind].id) speaker.speak(text=f"I am {voice.name} {env.title}!") sys.stdout.write( f"\rVoice module has been re-configured to {ind}::{voice.name}") if ind < len(choices_to_say): speaker.speak(text=choices_to_say[ind]) else: speaker.speak(text=random.choice(choices_to_say)) speaker.speak(run=True) if not (keyword := listener.listen(timeout=3, phrase_limit=3)): voice_default() speaker.speak( text= f"Sorry {env.title}! I had trouble understanding. I'm back to my default voice." ) return elif "exit" in keyword or "quit" in keyword or "Xzibit" in keyword: voice_default() speaker.speak( text= f"Reverting the changes to default voice module {env.title}!") return
def distance_controller(origin: str = None, destination: str = None) -> None: """Calculates distance between two locations. Args: origin: Takes the starting place name as an optional argument. destination: Takes the destination place name as optional argument. Notes: - If ``origin`` is None, Jarvis takes the current location as ``origin``. - If ``destination`` is None, Jarvis will ask for a destination from the user. """ if not destination: speaker.speak(text="Destination please?") if shared.called_by_offline: return speaker.speak(run=True) if destination := listener.listen(timeout=3, phrase_limit=4): if len(destination.split()) > 2: speaker.speak(text=f"I asked for a destination {env.title}, not a sentence. Try again.") distance_controller() if "exit" in destination or "quit" in destination or "Xzibit" in destination: return
def directions(phrase: str = None, no_repeat: bool = False) -> None: """Opens Google Maps for a route between starting and destination. Uses reverse geocoding to calculate latitude and longitude for both start and destination. Args: phrase: Takes the phrase spoken as an argument. no_repeat: A placeholder flag switched during ``recursion`` so that, ``Jarvis`` doesn't repeat himself. """ place = support.get_capitalized(phrase=phrase) place = place.replace("I ", "").strip() if place else None if not place: speaker.speak(text="You might want to give a location.", run=True) if converted := listener.listen(timeout=3, phrase_limit=4): place = support.get_capitalized(phrase=converted) place = place.replace("I ", "").strip() if not place: if no_repeat: return speaker.speak(text=f"I can't take you to anywhere without a location {env.title}!") directions(phrase=None, no_repeat=True) if "exit" in place or "quit" in place or "Xzibit" in place: return
def meaning(phrase: str) -> None: """Gets meaning for a word skimmed from the user statement. Args: phrase: Takes the phrase spoken as an argument. """ keyword = phrase.split()[-1] if phrase else None if not keyword or keyword == 'word': speaker.speak(text="Please tell a keyword.", run=True) response = listener.listen(timeout=3, phrase_limit=3) if not response or any(word in response.lower() for word in keywords.exit_): return meaning(phrase=response) else: if definition := dictionary.meaning(term=keyword): n = 0 vowel = ['A', 'E', 'I', 'O', 'U'] for key, value in definition.items(): insert = 'an' if key[0] in vowel else 'a' repeated = 'also' if n != 0 else '' n += 1 mean = ', '.join(value[0:2]) speaker.speak( text= f'{keyword} is {repeated} {insert} {key}, which means {mean}.' ) if shared.called_by_offline: return speaker.speak(text=f'Do you wanna know how {keyword} is spelled?', run=True) response = listener.listen(timeout=3, phrase_limit=3) if any(word in response.lower() for word in keywords.ok): for letter in list(keyword.lower()): speaker.speak(text=letter) speaker.speak(run=True) else:
def notes() -> None: """Listens to the user and saves it as a text file.""" if (converted := listener.listen(timeout=5, phrase_limit=10)) or 'exit' in converted or 'quit' in converted or \ 'Xzibit' in converted: return
def system_vitals() -> None: """Reads system vitals on macOS. See Also: - Jarvis will suggest a reboot if the system uptime is more than 2 days. - If confirmed, invokes `restart <https://thevickypedia.github.io/Jarvis/#jarvis.restart>`__ function. """ output = "" if env.macos: if not env.root_password: speaker.speak( text= f"You haven't provided a root password for me to read system vitals {env.title}! " "Add the root password as an environment variable for me to read." ) return logger.info('Fetching system vitals') cpu_temp, gpu_temp, fan_speed, output = None, None, None, "" # Tested on 10.13, 10.14, 11.6 and 12.3 versions if not shared.hosted_device or not shared.hosted_device.get( 'os_version'): logger.warning( "hosted_device information was not loaded during startup. Reloading now." ) shared.hosted_device = hosted_device_info() if packaging.version.parse(shared.hosted_device.get( 'os_version')) > packaging.version.parse('10.14'): critical_info = [ each.strip() for each in (os.popen( f'echo {env.root_password} | sudo -S powermetrics --samplers smc -i1 -n1' )).read().split('\n') if each != '' ] support.flush_screen() for info in critical_info: if 'CPU die temperature' in info: cpu_temp = info.strip('CPU die temperature: ').replace( ' C', '').strip() if 'GPU die temperature' in info: gpu_temp = info.strip('GPU die temperature: ').replace( ' C', '').strip() if 'Fan' in info: fan_speed = info.strip('Fan: ').replace(' rpm', '').strip() else: fan_speed = subprocess.check_output( f'echo {env.root_password} | sudo -S spindump 1 1 -file /tmp/spindump.txt > /dev/null 2>&1;grep ' f'"Fan speed" /tmp/spindump.txt;sudo rm /tmp/spindump.txt', shell=True).decode('utf-8') if cpu_temp: cpu = f'Your current average CPU temperature is ' \ f'{support.format_nos(input_=temperature.c2f(arg=support.extract_nos(input_=cpu_temp)))}' \ f'\N{DEGREE SIGN}F. ' output += cpu speaker.speak(text=cpu) if gpu_temp: gpu = f'GPU temperature is {support.format_nos(temperature.c2f(support.extract_nos(gpu_temp)))}' \ f'\N{DEGREE SIGN}F. ' output += gpu speaker.speak(text=gpu) if fan_speed: fan = f'Current fan speed is {support.format_nos(support.extract_nos(fan_speed))} RPM. ' output += fan speaker.speak(text=fan) restart_time = datetime.fromtimestamp(psutil.boot_time()) second = (datetime.now() - restart_time).total_seconds() restart_time = datetime.strftime(restart_time, "%A, %B %d, at %I:%M %p") restart_duration = support.time_converter(seconds=second) output += f'Restarted on: {restart_time} - {restart_duration} ago from now.' if shared.called_by_offline: speaker.speak(text=output) return sys.stdout.write(f'\r{output}') speaker.speak( text= f"Your {shared.hosted_device.get('device')} was last booted on {restart_time}. " f"Current boot time is: {restart_duration}.") if second >= 259_200: # 3 days if boot_extreme := re.search('(.*) days', restart_duration): warn = int(boot_extreme.group().replace(' days', '').strip()) speaker.speak( text= f"{env.title}! your {shared.hosted_device.get('device')} has been running for more " f"than {warn} days. You must consider a reboot for better performance. Would you like " f"me to restart it for you {env.title}?", run=True) response = listener.listen(timeout=3, phrase_limit=3) if any(word in response.lower() for word in keywords.ok): logger.info( f'JARVIS::Restarting {shared.hosted_device.get("device")}') restart(ask=False)
if shared.called['report'] or shared.called['time_travel']: speaker.speak(run=True) def add_todo() -> None: """Adds new items to the to-do list.""" speaker.speak(text=f"What's your plan {env.title}?", run=True) if not (item := listener.listen(timeout=3, phrase_limit=5) ) or 'exit' in item or 'quit' in item or 'Xzibit' in item: speaker.speak( text=f'Your to-do list has been left intact {env.title}.') return speaker.speak( text=f"I heard {item}. Which category you want me to add it to?", run=True) if not (category := listener.listen(timeout=3, phrase_limit=3)): category = 'Unknown' if 'exit' in category or 'quit' in category or 'Xzibit' in category: speaker.speak( text=f'Your to-do list has been left intact {env.title}.') return with tdb.connection: cursor = tdb.connection.cursor() downloaded = cursor.execute( "SELECT category, item FROM tasks").fetchall() if downloaded: for c, i in downloaded: # browses through all categories and items if i == item and c == category: # checks if already present and updates items in case of repeated category speaker.speak( text= f"Looks like you already have the item: {item} added in, {category} category"
if not (target_device := device_selector(phrase=phrase)): support.no_env_vars() return if shared.called_by_offline: locate_device(target_device=target_device) return sys.stdout.write(f"\rLocating your {target_device}") target_device.play_sound() before_keyword, keyword, after_keyword = str(target_device).partition(":") # partitions the hostname info if before_keyword == "Accessory": after_keyword = after_keyword.replace(f"{env.name}’s", "").replace(f"{env.name}'s", "").strip() speaker.speak(text=f"I've located your {after_keyword} {env.title}!") else: speaker.speak(text=f"Your {before_keyword} should be ringing now {env.title}!") speaker.speak(text="Would you like to get the location details?", run=True) if not (phrase_location := listener.listen(timeout=3, phrase_limit=3)): return elif not any(word in phrase_location.lower() for word in keywords.ok): return locate_device(target_device=target_device) if env.icloud_recovery: speaker.speak(text="I can also enable lost mode. Would you like to do it?", run=True) phrase_lost = listener.listen(timeout=3, phrase_limit=3) if any(word in phrase_lost.lower() for word in keywords.ok): target_device.lost_device(number=env.icloud_recovery, text="Return my phone immediately.") speaker.speak(text="I've enabled lost mode on your phone.") else: speaker.speak(text=f"No action taken {env.title}!")
def google_maps(query: str) -> bool: """Uses google's places api to get places nearby or any particular destination. This function is triggered when the words in user's statement doesn't match with any predefined functions. Args: query: Takes the voice recognized statement as argument. Returns: bool: Boolean True if Google's maps API is unable to fetch consumable results. """ if not env.maps_api: return False maps_url = "https://maps.googleapis.com/maps/api/place/textsearch/json?" response = requests.get(maps_url + 'query=' + query + '&key=' + env.maps_api) collection = response.json()['results'] required = [] for element in range(len(collection)): try: required.append({ "Name": collection[element]['name'], "Rating": collection[element]['rating'], "Location": collection[element]['geometry']['location'], "Address": re.search('(.*)Rd|(.*)Ave|(.*)St |(.*)St,|(.*)Blvd|(.*)Ct', collection[element]['formatted_address']).group().replace(',', '') }) except (AttributeError, KeyError): pass if required: required = sorted(required, key=lambda sort: sort['Rating'], reverse=True) else: return False try: with open(fileio.location) as file: current_location = yaml.load(stream=file, Loader=yaml.FullLoader) except yaml.YAMLError as error: logger.error(error) return False results = len(required) speaker.speak(text=f"I found {results} results {env.title}!") if results != 1 else None start = current_location['latitude'], current_location['longitude'] n = 0 for item in required: item['Address'] = item['Address'].replace(' N ', ' North ').replace(' S ', ' South ').replace(' E ', ' East ') \ .replace(' W ', ' West ').replace(' Rd', ' Road').replace(' St', ' Street').replace(' Ave', ' Avenue') \ .replace(' Blvd', ' Boulevard').replace(' Ct', ' Court') latitude, longitude = item['Location']['lat'], item['Location']['lng'] end = f"{latitude},{longitude}" far = round(geodesic(start, end).miles) miles = f'{far} miles' if far > 1 else f'{far} mile' n += 1 if results == 1: option = 'only option I found is' next_val = f"Do you want to head there {env.title}?" elif n <= 2: option = f'{inflect.engine().ordinal(n)} option is' next_val = f"Do you want to head there {env.title}?" elif n <= 5: option = 'next option would be' next_val = "Would you like to try that?" else: option = 'other' next_val = 'How about that?' speaker.speak(text=f"The {option}, {item['Name']}, with {item['Rating']} rating, " f"on{''.join([j for j in item['Address'] if not j.isdigit()])}, which is approximately " f"{miles} away. {next_val}", run=True) sys.stdout.write(f"\r{item['Name']} -- {item['Rating']} -- " f"{''.join([j for j in item['Address'] if not j.isdigit()])}") if converted := listener.listen(timeout=3, phrase_limit=3): if 'exit' in converted or 'quit' in converted or 'Xzibit' in converted: break elif any(word in converted.lower() for word in keywords.ok): maps_url = f'https://www.google.com/maps/dir/{start}/{end}/' webbrowser.open(url=maps_url) speaker.speak(text=f"Directions on your screen {env.title}!") return True elif results == 1: return True elif n == results: speaker.speak(text=f"I've run out of options {env.title}!") return True else: continue else: return True
minute=minute, am_pm=am_pm, message=message.group(1).strip(), timer=f"{hours} {hour_}", to_about=to_about) return if not (extracted_time := support.extract_time(input_=phrase)): if shared.called_by_offline: speaker.speak( text= 'Reminder format should be::Remind me to do something, at some time.' ) return speaker.speak(text=f"When do you want to be reminded {env.title}?", run=True) if not (phrase := listener.listen(timeout=3, phrase_limit=4)): return if not (extracted_time := support.extract_time(input_=phrase)): return message = message.group(1).strip() extracted_time = extracted_time[0] am_pm = extracted_time.split()[-1] am_pm = str(am_pm).replace('a.m.', 'AM').replace('p.m.', 'PM') remind_time = extracted_time.split()[0] if ":" in extracted_time: hour = int(remind_time.split(":")[0]) minute = int(remind_time.split(":")[-1]) else: hour = int(remind_time.split()[0]) minute = 0 # makes sure hour and minutes are two digits
def guard_enable() -> None: """Security Mode will enable camera and microphone in the background. Notes: - If any speech is recognized or a face is detected, there will another thread triggered to send notifications. - Notifications will be triggered only after 5 minutes of previous notification. """ logger.info('Enabled Security Mode') speaker.speak(text=f"Enabled security mode {env.title}! I will look out for potential threats and keep you posted. " f"Have a nice {support.part_of_day()}, and enjoy yourself {env.title}!", run=True) cam_source, cam = None, None for i in range(0, 3): cam = cv2.VideoCapture(i) # tries thrice to choose the camera for which Jarvis has access if cam is None or not cam.isOpened() or cam.read() == (False, None): pass else: cam_source = i # source for security cam is chosen cam.release() break if cam_source is None: cam_error = 'Guarding mode disabled as I was unable to access any of the cameras.' logger.error(cam_error) communicator.notify(user=env.gmail_user, password=env.gmail_pass, number=env.phone_number, body=cam_error, subject="IMPORTANT::Guardian mode faced an exception.") return scale_factor = 1.1 # Parameter specifying how much the image size is reduced at each image scale. min_neighbors = 5 # Parameter specifying how many neighbors each candidate rectangle should have, to retain it. notified, date_extn, converted = None, None, None while True: # Listens for any recognizable speech and saves it to a notes file sys.stdout.write("\rSECURITY MODE") if not (converted := listener.listen(timeout=3, phrase_limit=10, sound=False)): continue if converted and any(word.lower() in converted.lower() for word in keywords.guard_disable): speaker.speak(text=f'Welcome back {env.title}! Good {support.part_of_day()}.') if os.path.exists(f'threat/{date_extn}.jpg'): speaker.speak(text=f"We had a potential threat {env.title}! Please check your email to confirm.") speaker.speak(run=True) logger.info('Disabled security mode') sys.stdout.write('\rDisabled Security Mode') break elif converted: logger.info(f'Conversation::{converted}') if cam_source is not None: # Capture images and keeps storing it to a folder validation_video = cv2.VideoCapture(cam_source) cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml") ignore, image = validation_video.read() scale = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) faces = cascade.detectMultiScale(scale, scale_factor, min_neighbors) date_extn = f"{datetime.now().strftime('%B_%d_%Y_%I_%M_%S_%p')}" try: if faces: pass except ValueError: # log level set to critical because this is a known exception when try check 'if faces' cv2.imwrite(f'threat/{date_extn}.jpg', image) logger.info(f'Image of detected face stored as {date_extn}.jpg') if not os.path.exists(f'threat/{date_extn}.jpg'): date_extn = None # if no notification was sent yet or if a phrase or face is detected notification thread will be triggered if (not notified or float(time.time() - notified) > 300) and (converted or date_extn): notified = time.time() Thread(target=threat_notify, kwargs=({"converted": converted, "phone_number": env.phone_number, "gmail_user": env.gmail_user, "gmail_pass": env.gmail_pass, "recipient": env.recipient or env.alt_gmail_user or env.gmail_user, "date_extn": date_extn})).start()
f"\rGetting your info from Wikipedia API for {keyword}") try: result = wikipedia.summary(keyword) except wikipedia.DisambiguationError as error: sys.stdout.write(f"\r{error}") speaker.speak( text= f"Your keyword has multiple results {env.title}. {' '.join(error.options)}" "Please pick one and try again.") if shared.called_by_offline: return speaker.speak(run=True) if not (keyword1 := listener.listen(timeout=3, phrase_limit=5)): return result = wikipedia.summary(keyword1) except wikipedia.PageError: speaker.speak( text= f"I'm sorry {env.title}! I didn't get a response for the phrase: {keyword}." ) return # stops with two sentences before reading whole passage formatted = ". ".join(result.split(". ")[0:2]) + "." speaker.speak( text=f"{formatted}. Do you want me to continue {env.title}?", run=True) if response := listener.listen(timeout=3, phrase_limit=3): if any(word in response.lower() for word in keywords.ok): speaker.speak(text=". ".join(result.split(". ")[3:]))
hour = int(alarm_time.split()[0]) minute = 0 # makes sure hour and minutes are two digits hour, minute = f"{hour:02}", f"{minute:02}" am_pm = str(am_pm).replace('a.m.', 'AM').replace('p.m.', 'PM') if int(hour) <= 12 and int(minute) <= 59: create_alarm(phrase=phrase, hour=hour, minute=minute, am_pm=am_pm) else: speaker.speak(text=f"An alarm at {hour}:{minute} {am_pm}? Are you an alien? " f"I don't think a time like that exists on Earth.") else: speaker.speak(text=f"Please tell me a time {env.title}!") if shared.called_by_offline: return speaker.speak(run=True) if converted := listener.listen(timeout=3, phrase_limit=4): if 'exit' in converted or 'quit' in converted or 'Xzibit' in converted: return else: set_alarm(converted) def kill_alarm(phrase: str) -> None: """Removes lock file to stop the alarm which rings only when the certain lock file is present. Args: phrase: Takes the voice recognized statement as argument and extracts time from it. """ word = 'timer' if 'timer' in phrase else 'alarm' alarm_state = support.lock_files(alarm_files=True) if not alarm_state:
def face_detection() -> None: """Initiates face recognition script and looks for images stored in named directories within ``train`` directory.""" support.flush_screen() train_dir = 'train' os.mkdir(train_dir) if not os.path.isdir(train_dir) else None speaker.speak( text= 'Initializing facial recognition. Please smile at the camera for me.', run=True) sys.stdout.write('\rLooking for faces to recognize.') try: result = Face().face_recognition() except CameraError: support.flush_screen() logger.error('Unable to access the camera.') speaker.speak( text= "I was unable to access the camera. Facial recognition can work only when cameras are " "present and accessible.") return if not result: sys.stdout.write('\rLooking for faces to detect.') speaker.speak( text="No faces were recognized. Switching on to face detection.", run=True) result = Face().face_detection() if not result: sys.stdout.write('\rNo faces were recognized nor detected.') speaker.speak( text= 'No faces were recognized. nor detected. Please check if your camera is working, ' 'and look at the camera when you retry.') return sys.stdout.write( '\rNew face has been detected. Like to give it a name?') speaker.speak( text='I was able to detect a face, but was unable to recognize it.' ) Image.open('cv2_open.jpg').show() speaker.speak( text= "I've taken a photo of you. Preview on your screen. Would you like to give it a name, " "so that I can add it to my database of known list? If you're ready, please tell me a name, " "or simply say exit.", run=True) phrase = listener.listen(timeout=3, phrase_limit=5) if not phrase or 'exit' in phrase or 'quit' in phrase or 'Xzibit' in phrase: os.remove('cv2_open.jpg') speaker.speak(text="I've deleted the image.", run=True) else: phrase = phrase.replace(' ', '_') # creates a named directory if it is not found already if not os.path.exists(f'{train_dir}/{phrase}'): os.makedirs(f'{train_dir}/{phrase}') c_time = datetime.now().strftime("%I_%M_%p") img_name = f"{phrase}_{c_time}.jpg" # adds current time to image name to avoid overwrite os.rename('cv2_open.jpg', img_name) # renames the files shutil.move(src=img_name, dst=f'{train_dir}/{phrase}' ) # move files into named directory within train_dir speaker.speak( text= f"Image has been saved as {img_name}. I will be able to recognize {phrase} in future." ) else: speaker.speak(text=f'Hi {result}! How can I be of service to you?')
cursor = db.connection.cursor() meeting_status = cursor.execute( "SELECT info, date FROM ics").fetchone() if meeting_status and meeting_status[0].startswith('You') and \ meeting_status[1] == datetime.now().strftime('%Y_%m_%d'): speaker.speak(text=meeting_status[0]) with db.connection: cursor = db.connection.cursor() event_status = cursor.execute( f"SELECT info FROM {env.event_app}").fetchone() if event_status and event_status[0].startswith('You'): speaker.speak(text=event_status[0]) todo() read_gmail() speaker.speak(text='Would you like to hear the latest news?', run=True) phrase = listen(timeout=3, phrase_limit=3) if any(word in phrase.lower() for word in keywords.ok): news() def sprint_name() -> NoReturn: """Generates a random sprint name.""" response = requests.get(url="https://sprint-name-gen.herokuapp.com/") if not response.ok: speaker.speak( text= "I wasn't able to get a sprint name sir! Why not name it, Jarvis failed?" ) return soup = BeautifulSoup(response.content, 'html.parser') name = soup.find('span', {'class': 'sprint-name'}).text