Exemplo n.º 1
0
def create_reminder(hour,
                    minute,
                    am_pm,
                    message,
                    to_about,
                    timer: str = None) -> NoReturn:
    """Creates the lock file necessary to set a reminder.

    Args:
        hour: Hour of reminder time.
        minute: Minute of reminder time.
        am_pm: AM/PM of reminder time.
        message: Message to be reminded for.
        to_about: remind to or remind about as said in phrase.
        timer: Number of minutes/hours to reminder.
    """
    if not os.path.isdir('reminder'):
        os.mkdir('reminder')
    pathlib.Path(
        os.path.join(
            "reminder",
            f"{hour}_{minute}_{am_pm}|{message.replace(' ', '_')}.lock")
    ).touch()
    if timer:
        logger.info(
            f"Reminder created for '{message}' at {hour}:{minute} {am_pm}")
        speaker.speak(
            text=f"{random.choice(conversation.acknowledgement)}! "
            f"I will remind you {to_about} {message}, after {timer}.")
    else:
        speaker.speak(
            text=f"{random.choice(conversation.acknowledgement)}! "
            f"I will remind you {to_about} {message}, at {hour}:{minute} {am_pm}."
        )
Exemplo n.º 2
0
def ip_info(phrase: str) -> None:
    """Gets IP address of the host machine.

    Args:
        phrase: Takes the spoken phrase an argument and tells the public IP if requested.
    """
    if "public" in phrase.lower():
        if not internet_checker():
            speaker.speak(
                text=f"You are not connected to the internet {env.title}!")
            return
        if ssid := get_ssid():
            ssid = f"for the connection {ssid} "
        else:
            ssid = ""
        output = None
        try:
            output = f"My public IP {ssid}is " \
                     f"{json.load(urllib.request.urlopen(url='https://ipinfo.io/json')).get('ip')}"
        except (urllib.error.HTTPError, urllib.error.URLError) as error:
            logger.error(error)
        try:
            output = output or f"My public IP {ssid}is " \
                               f"{json.loads(urllib.request.urlopen(url='http://ip.jsontest.com').read()).get('ip')}"
        except (urllib.error.HTTPError, urllib.error.URLError) as error:
            logger.error(error)
        if not output:
            output = f"I was unable to fetch the public IP {env.title}!"
Exemplo n.º 3
0
def reminder(phrase: str) -> None:
    """Passes hour, minute, am/pm and reminder message to Reminder class which initiates a thread for reminder.

    Args:
        phrase: Takes the voice recognized statement as argument and extracts the time and message from it.
    """
    message = re.search(' to (.*) at ', phrase) or re.search(' about (.*) at ', phrase) or \
        re.search(' to (.*) after ', phrase) or re.search(' about (.*) after ', phrase) or \
        re.search(' to (.*) in ', phrase) or re.search(' about (.*) in ', phrase) or \
        re.search(' to (.*)', phrase) or re.search(' about (.*)', phrase)
    if not message:
        speaker.speak(
            text=
            'Reminder format should be::Remind me to do something, at some time.'
        )
        return
    to_about = 'about' if 'about' in phrase else 'to'
    if 'minute' in phrase:
        if minutes := support.extract_nos(input_=phrase, method=int):
            min_ = 'minutes' if minutes > 1 else 'minute'
            hour, minute, am_pm = (
                datetime.now() +
                timedelta(minutes=minutes)).strftime("%I %M %p").split()
            create_reminder(hour=hour,
                            minute=minute,
                            am_pm=am_pm,
                            message=message.group(1).strip(),
                            timer=f"{minutes} {min_}",
                            to_about=to_about)
            return
Exemplo n.º 4
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])
Exemplo n.º 5
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
Exemplo n.º 6
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()
Exemplo n.º 7
0
def volume(phrase: str = None, level: int = None) -> None:
    """Controls volume from the numbers received. Defaults to 50%.

    See Also:
        SetVolume for Windows: https://rlatour.com/setvol/

    Args:
        phrase: Takes the phrase spoken as an argument.
        level: Level of volume to which the system has to set.
    """
    if not level:
        if 'mute' in phrase.lower():
            level = 0
        elif 'max' in phrase.lower() or 'full' in phrase.lower():
            level = 100
        else:
            level = support.extract_nos(input_=phrase, method=int)
            if level is None:
                level = env.volume
    support.flush_screen()
    if env.macos:
        os.system(f'osascript -e "set Volume {round((8 * level) / 100)}"')
    else:
        os.system(f'SetVol.exe {level}')
    support.flush_screen()
    if phrase:
        speaker.speak(text=f"{random.choice(conversation.acknowledgement)}!")
Exemplo n.º 8
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.")
Exemplo n.º 9
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
Exemplo n.º 10
0
def alpha(text: str) -> bool:
    """Uses wolfram alpha API to fetch results for uncategorized phrases heard.

    Args:
        text: Takes the voice recognized statement as argument.

    Notes:
        Handles broad ``Exception`` clause raised when Full Results API did not find an input parameter while parsing.

    Returns:
        bool:
        Boolean True if wolfram alpha API is unable to fetch consumable results.

    References:
        `Error 1000 <https://products.wolframalpha.com/show-steps-api/documentation/#:~:text=(Error%201000)>`__
    """
    if not env.wolfram_api_key:
        return False
    alpha_client = wolframalpha.Client(app_id=env.wolfram_api_key)
    try:
        res = alpha_client.query(text)
    except Exception:  # noqa
        return False
    if res['@success'] == 'false':
        return False
    else:
        try:
            response = next(res.results).text.splitlines()[0]
            response = re.sub(r'(([0-9]+) \|)', '', response).replace(' |', ':').strip()
            if response == '(no data available)':
                return False
            speaker.speak(text=response)
            return True
        except (StopIteration, AttributeError):
            return False
Exemplo n.º 11
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)
Exemplo n.º 12
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()
Exemplo n.º 13
0
def restart_control(phrase: str = None, quiet: bool = False) -> NoReturn:
    """Controls the restart functions based on the user request.

    Args:
        phrase: Takes the phrase spoken as an argument.
        quiet: Take a boolean flag to restart without warning.
    """
    if phrase and ('pc' in phrase.lower() or 'computer' in phrase.lower()
                   or 'machine' in phrase.lower()):
        logger.info(
            f'JARVIS::Restart for {shared.hosted_device.get("device")} has been requested.'
        )
        restart()
    else:
        caller = sys._getframe(1).f_code.co_name  # noqa
        logger.info(f'Called by {caller}')
        if quiet:  # restarted due internal errors
            logger.info(f"Restarting {caller}")
        elif shared.called_by_offline:  # restarted via automator
            logger.info("Restarting all background processes!")
            caller = "OFFLINE"
        else:
            speaker.speak(
                text=
                "I didn't quite get that. Did you mean restart your computer?")
            return
        with db.connection:
            cursor = db.connection.cursor()
            cursor.execute("INSERT INTO restart (flag, caller) VALUES (?,?);",
                           (True, caller))
            cursor.connection.commit()
Exemplo n.º 14
0
def delete_todo() -> None:
    """Drops the table ``tasks`` from the database."""
    with tdb.connection:
        cursor = tdb.connection.cursor()
        cursor.execute('DROP TABLE IF EXISTS tasks')
        cursor.connection.commit()
    speaker.speak(
        text=f"I've dropped the table: tasks from the database {env.title}.")
Exemplo n.º 15
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}")
Exemplo n.º 16
0
def time_travel() -> None:
    """Triggered only from ``initiator()`` to give a quick update on the user's daily routine."""
    part_day = support.part_of_day()
    speaker.speak(text=f"Good {part_day} {env.name}!")
    if part_day == 'Night':
        if event := support.celebrate():
            speaker.speak(text=f'Happy {event}!')
        return
Exemplo n.º 17
0
def flip_a_coin() -> NoReturn:
    """Says ``heads`` or ``tails`` from a random choice."""
    playsound(sound=indicators.coin,
              block=True) if not shared.called_by_offline else None
    speaker.speak(
        text=
        f"""{random.choice(['You got', 'It landed on', "It's"])} {random.choice(['heads', 'tails'])} {env.title}"""
    )
Exemplo n.º 18
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
Exemplo n.º 19
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
Exemplo n.º 20
0
def initialize() -> None:
    """Awakens from sleep mode. ``greet_check`` is to ensure greeting is given only for the first function call."""
    if shared.greeting:
        speaker.speak(text="What can I do for you?")
    else:
        speaker.speak(text=f'Good {support.part_of_day()}.')
        shared.greeting = True
    renew()
Exemplo n.º 21
0
def pc_sleep() -> NoReturn:
    """Locks the host device using osascript and reduces brightness to bare minimum."""
    Thread(target=decrease_brightness).start()
    # os.system("""osascript -e 'tell app "System Events" to sleep'""")  # requires restarting Jarvis manually
    os.system(
        """osascript -e 'tell application "System Events" to keystroke "q" using {control down, command down}'"""
    )
    if not (shared.called['report'] or shared.called['time_travel']):
        speaker.speak(text=random.choice(conversation.acknowledgement))
Exemplo n.º 22
0
def speed_test() -> None:
    """Initiates speed test and says the ping rate, download and upload speed.

    References:
        Number of threads per core: https://psutil.readthedocs.io/en/latest/#psutil.cpu_count
    """
    if not (st := internet_checker()):
        speaker.speak(
            text=f"You're not connected to the internet {env.title}!")
        return
Exemplo n.º 23
0
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
    speaker.speak(text=name)
Exemplo n.º 24
0
def location() -> NoReturn:
    """Gets the user's current location."""
    try:
        with open(fileio.location) as file:
            current_location = yaml.load(stream=file, Loader=yaml.FullLoader)
    except yaml.YAMLError as error:
        logger.error(error)
        speaker.speak(text=f"I'm sorry {env.title}! I wasn't able to get the location details. Please check the logs.")
        return
    speaker.speak(text=f"I'm at {current_location.get('address', {}).get('road', '')} - "
                       f"{current_location.get('address', {}).get('city', '')} "
                       f"{current_location.get('address', {}).get('state', '')} - "
                       f"in {current_location.get('address', {}).get('country', '')}")
Exemplo n.º 25
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
Exemplo n.º 26
0
def news(news_source: str = 'fox') -> None:
    """Says news around the user's location.

    Args:
        news_source: Source from where the news has to be fetched. Defaults to ``fox``.
    """
    if not env.news_api:
        logger.warning("News apikey not found.")
        support.no_env_vars()
        return

    sys.stdout.write(f'\rGetting news from {news_source} news.')
    news_client = NewsApiClient(api_key=env.news_api)
    try:
        all_articles = news_client.get_top_headlines(
            sources=f'{news_source}-news')
    except newsapi_exception.NewsAPIException:
        speaker.speak(
            text=f"I wasn't able to get the news {env.title}! "
            "I think the News API broke, you may try after sometime.")
        return

    speaker.speak(text="News around you!")
    speaker.speak(text=' '.join(
        [article['title'] for article in all_articles['articles']]))
    if shared.called_by_offline:
        return

    if shared.called['report'] or shared.called['time_travel']:
        speaker.speak(run=True)
Exemplo n.º 27
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()
Exemplo n.º 28
0
    def avail_check(function_to_call: Callable) -> NoReturn:
        """Speaks an error message if any of the lights aren't reachable.

        Args:
            function_to_call: Takes the function/method that has to be called as an argument.
        """
        status = ThreadPool(processes=1).apply_async(func=thread_worker,
                                                     args=[function_to_call])
        speaker.speak(run=True)
        if failed := status.get(timeout=5):
            plural_ = "lights aren't available right now!" if failed > 1 else "light isn't available right now!"
            speaker.speak(
                text=
                f"I'm sorry sir! {support.number_to_words(input_=failed, capitalize=True)} {plural_}"
            )
Exemplo n.º 29
0
def robinhood() -> None:
    """Gets investment details from robinhood API."""
    if not all([env.robinhood_user, env.robinhood_pass, env.robinhood_qr]):
        logger.warning("Robinhood username, password or QR code not found.")
        support.no_env_vars()
        return

    sys.stdout.write("\rGetting your investment details.")
    rh = Robinhood()
    rh.login(username=env.robinhood_user,
             password=env.robinhood_pass,
             qr_code=env.robinhood_qr)
    raw_result = rh.positions()
    result = raw_result["results"]
    stock_value = watcher(rh, result)
    speaker.speak(text=stock_value)
Exemplo n.º 30
0
def sleep_control(phrase: str) -> bool:
    """Controls whether to stop listening or to put the host device on sleep.

    Args:
        phrase: Takes the phrase spoken as an argument.
    """
    phrase = phrase.lower()
    if 'pc' in phrase or 'computer' in phrase or 'imac' in phrase or \
            'screen' in phrase:
        pc_sleep() if env.macos else support.missing_windows_features()
    else:
        speaker.speak(
            text=f"Activating sentry mode, enjoy yourself {env.title}!")
        if shared.greeting:
            shared.greeting = False
    return True