示例#1
0
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.")
示例#2
0
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
示例#3
0
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()
示例#4
0
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)
示例#5
0
 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()
示例#6
0
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])
示例#7
0
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}")
示例#8
0
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
示例#9
0
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
示例#10
0
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()
示例#11
0
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
示例#12
0
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
示例#13
0
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
示例#14
0
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}!"
            )
示例#15
0
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
示例#16
0
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
示例#17
0
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
示例#18
0
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:
示例#19
0
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
示例#20
0
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)
示例#21
0
    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"
示例#22
0
    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}!")

示例#23
0
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
示例#24
0
                         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
示例#25
0
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()
示例#26
0
                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:]))
示例#27
0
            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:
示例#28
0
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?')
示例#29
0
        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