Пример #1
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)}!")
Пример #2
0
def listen(timeout: Union[int, float], phrase_limit: Union[int, float], sound: bool = True,
           stdout: bool = True) -> Union[str, None]:
    """Function to activate listener, this function will be called by most upcoming functions to listen to user input.

    Args:
        timeout: Time in seconds for the overall listener to be active.
        phrase_limit: Time in seconds for the listener to actively listen to a sound.
        sound: Flag whether to play the listener indicator sound. Defaults to True unless set to False.
        stdout: Flag whether to print the listener status on screen.

    Returns:
        str:
         - Returns recognized statement from the microphone.
    """
    with Microphone() as source:
        try:
            playsound(sound=indicators.start, block=False) if sound else None
            sys.stdout.write("\rListener activated...") if stdout else None
            listened = recognizer.listen(source=source, timeout=timeout, phrase_time_limit=phrase_limit)
            playsound(sound=indicators.end, block=False) if sound else None
            support.flush_screen()
            recognized = recognizer.recognize_google(audio_data=listened)
            logger.info(recognized)
            return recognized
        except (UnknownValueError, RequestError, WaitTimeoutError):
            return
        except (ConnectionError, TimeoutError, requests.exceptions.RequestException, requests.exceptions.Timeout) as \
                error:
            logger.error(error)
Пример #3
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])
Пример #4
0
def save_audio(frames: list, sample_rate: int) -> NoReturn:
    """Converts audio frames into a recording to store it in a wav file.

    Args:
        frames: List of frames.
        sample_rate: Sample rate.
    """
    recordings_location = os.path.join(os.getcwd(), 'recordings')
    if not os.path.isdir(recordings_location):
        os.makedirs(recordings_location)
    filename = os.path.join(recordings_location, f"{datetime.now().strftime('%B_%d_%Y_%H%M')}.wav")
    logger.info(f"Saving {len(frames)} audio frames into {filename}")
    sys.stdout.write(f"\rSaving {len(frames)} audio frames into {filename}")
    recorded_audio = numpy.concatenate(frames, axis=0).astype(dtype=numpy.int16)
    soundfile.write(file=filename, data=recorded_audio, samplerate=sample_rate, subtype='PCM_16')
    support.flush_screen()
Пример #5
0
def initiator(phrase: str = None, should_return: bool = False) -> None:
    """When invoked by ``Activator``, checks for the right keyword to wake up and gets into action.

    Args:
        phrase: Takes the processed string from ``SentryMode`` as input.
        should_return: Flag to return the function if nothing is heard.
    """
    if not phrase and should_return:
        return
    support.flush_screen()
    if [
            word for word in phrase.lower().split() if word in [
                'morning', 'night', 'afternoon', 'after noon', 'evening',
                'goodnight'
            ]
    ]:
        shared.called['time_travel'] = True
        if (event := support.celebrate()) and 'night' not in phrase.lower():
            speaker.speak(text=f'Happy {event}!')
        if 'night' in phrase.split() or 'goodnight' in phrase.split():
            Thread(target=pc_sleep).start() if env.macos else None
        time_travel()
        shared.called['time_travel'] = False
Пример #6
0
def music(phrase: str = None) -> NoReturn:
    """Scans music directory in the user profile for ``.mp3`` files and plays using default player.

    Args:
        phrase: Takes the phrase spoken as an argument.
    """
    sys.stdout.write("\rScanning music files...")
    get_all_files = (os.path.join(
        root, f) for root, _, files in os.walk(os.path.join(env.home, "Music"))
                     for f in files)
    if music_files := [
            file for file in get_all_files
            if os.path.splitext(file)[1] == '.mp3'
    ]:
        chosen = random.choice(music_files)
        if phrase and 'speaker' in phrase:
            google_home(device=phrase, file=chosen)
        else:
            if env.macos:
                subprocess.call(["open", chosen])
            else:
                os.system(f'start wmplayer "{chosen}"')
            support.flush_screen()
            speaker.speak(text=f"Enjoy your music {env.title}!")
Пример #7
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)
Пример #8
0
            pass

    devices = []
    with ThreadPoolExecutor(max_workers=100) as executor:
        for info in executor.map(
                ip_scan, range(1, 101)
        ):  # scans host IDs 1 to 255 (eg: 192.168.1.1 to 192.168.1.255)
            devices.append(
                info
            )  # this includes all the NoneType values returned by unassigned host IDs
    devices = dict(
        [i for i in devices if i]
    )  # removes None values and converts list to dictionary of name and ip pair

    if not device or not file:
        support.flush_screen()
        speaker.speak(
            text=
            f"You have {len(devices)} devices in your IP range {env.title}! "
            f"{support.comma_separator(list(devices.keys()))}. You can choose one and ask me to play "
            f"some music on any of these.")
        return
    else:
        chosen = [
            value for key, value in devices.items()
            if key.lower() in device.lower()
        ]
        if not chosen:
            speaker.speak(
                text=
                f"I don't see any matching devices {env.title}!. Let me help you. "
Пример #9
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?')