Ejemplo n.º 1
0
def remove_modules(modules: dict, modules_to_remove: List[str]) -> bool:
    '''
    Gathers list of modules currently installed in the ~/MagicMirror/modules
    directory, and removes each of the modules from the folder, if modules are
    currently installed. Otherwise, the user is shown an error message alerting
    them no modules are currently installed.

    Parameters:
        modules (dict): Dictionary of MagicMirror modules
        modules_to_remove (list): List of modules to remove

    Returns:
        bool: True upon success, False upon failure
    '''

    installed_modules: dict = get_installed_modules(modules)

    if not installed_modules:
        utils.error_msg("No modules are currently installed.")
        return False

    modules_dir: str = os.path.join(utils.MAGICMIRROR_ROOT, 'modules')
    original_dir: str = os.getcwd()

    if not os.path.exists(modules_dir):
        msg = "Failed to find MagicMirror root. Have you installed MagicMirror properly? "
        msg += "You may also set the env variable 'MMPM_MAGICMIRROR_ROOT' to the MagicMirror root directory."
        utils.error_msg(msg)
        return False

    os.chdir(modules_dir)
    successful_removals: List[str] = []
    curr_dir: str = os.getcwd()

    for module in modules_to_remove:
        dir_to_rm: str = os.path.join(curr_dir, module)

        try:
            shutil.rmtree(dir_to_rm)
            successful_removals.append(module)
        except OSError:
            utils.warning_msg(f"The directory for '{module}' does not exist.")

    if successful_removals:
        print(colors.B_GREEN +
              "The following modules were successfully deleted:" + colors.N)

        for removal in successful_removals:
            print(colors.RESET + f"{removal}")
    else:
        utils.error_msg("Unable to remove modules.")
        return False

    os.chdir(original_dir)
    return True
Ejemplo n.º 2
0
def load_modules(force_refresh: bool = False) -> dict:
    '''
    Reads in modules from the hidden 'snapshot_file'  and checks if the file is
    out of date. If so, the modules are gathered again from the MagicMirror 3rd
    Party Modules wiki.

    Parameters:
        force_refresh (bool): Boolean flag to force refresh of snapshot

    Returns:
        bool: False upon failure
        modules (dict): list of modules upon success
    '''

    modules: dict = {}

    if not utils.assert_snapshot_directory():
        utils.error_msg('Failed to create directory for MagicMirror snapshot')
        sys.exit(1)

    # if the snapshot has expired, or doesn't exist, get a new one
    if force_refresh:
        utils.plain_print(utils.green_plus() +
                          " Refreshing MagicMirror module snapshot ... ")
        modules = retrieve_modules()

        # save the new snapshot
        with open(utils.SNAPSHOT_FILE, "w") as snapshot:
            json.dump(modules, snapshot)

        print(utils.done())

    else:
        with open(utils.SNAPSHOT_FILE, "r") as snapshot_file:
            modules = json.load(snapshot_file)

    if os.path.exists(utils.MMPM_EXTERNAL_SOURCES_FILE) and os.stat(
            utils.MMPM_EXTERNAL_SOURCES_FILE).st_size:
        try:
            with open(utils.MMPM_EXTERNAL_SOURCES_FILE, "r") as f:
                modules[utils.EXTERNAL_MODULE_SOURCES] = json.load(f)[
                    utils.EXTERNAL_MODULE_SOURCES]
        except Exception:
            utils.warning_msg(
                f'Failed to load data from {utils.MMPM_EXTERNAL_SOURCES_FILE}.'
            )

    return modules
Ejemplo n.º 3
0
def check_for_mmpm_enhancements(assume_yes=False, gui=False) -> bool:
    '''
    Scrapes the main file of MMPM off the github repo, and compares the current
    version, versus the one available in the master branch. If there is a newer
    version, the user is prompted for an upgrade.

    Parameters:
        None

    Returns:
        bool: True on success, False on failure
    '''

    try:
        log.logger.info(
            f'Checking for MMPM enhancements. Current version: {mmpm.__version__}'
        )

        MMPM_FILE = urlopen(utils.MMPM_FILE_URL)
        contents: str = str(MMPM_FILE.read())

        version_line: List[str] = re.findall(r"__version__ = \d+\.\d+",
                                             contents)
        version_list: List[str] = re.findall(r"\d+\.\d+", version_line[0])
        version_number: float = float(version_list[0])

        if version_number and mmpm.__version__ < version_number:
            log.logger.info(f'Found newer version of MMPM: {version_number}')
            valid_response = False

            if gui:
                print(f'Currently installed version: {mmpm.__version__}')
                print(f'Available version: {version_number}\n')
                message = f"A newer version of MMPM is available ({version_number}). Please upgrade via terminal using 'mmpm -e'"
                utils.separator(message)
                print(message)
                utils.separator(message)
                return True

            print(utils.done())

            while not valid_response:
                print(f'\nCurrently installed version: {mmpm.__version__}')
                print(f'Available version: {version_number}\n')

                response = "yes" if assume_yes else input(
                    colors.B_GREEN +
                    "A newer version of MMPM is available\n\n" + colors.RESET +
                    "Would you like to upgrade now?" + colors.B_WHITE +
                    " [yes/y | no/n]: " + colors.RESET)

                if response in ("yes", "y"):
                    valid_response = True
                    original_dir = os.getcwd()

                    message = "Upgrading MMPM"

                    utils.separator(message)
                    print(colors.B_CYAN + message + colors.RESET)
                    utils.separator(message)

                    log.logger.info(
                        f'User chose to update MMPM with {original_dir} as the starting directory'
                    )

                    os.chdir(os.path.join('/', 'tmp'))
                    os.system('rm -rf /tmp/mmpm')

                    try:
                        return_code, _, stderr = utils.clone(
                            'mmpm', utils.MMPM_REPO_URL)
                    except OSError:
                        utils.error_msg('Failed to clone MMPM repo')
                        sys.exit(1)

                    if return_code:
                        utils.error_msg(stderr)
                        sys.exit(1)

                    os.chdir('/tmp/mmpm')

                    # if the user needs to be prompted for their password, this can't be a subprocess
                    os.system('make reinstall')

                    os.chdir(original_dir)
                    log.logger.info(
                        f'Changing back to original working directory: {original_dir}'
                    )

                elif response in ("no", "n"):
                    valid_response = True
                else:
                    utils.warning_msg("Respond with yes/no or y/n.")
        else:
            print(utils.done())
            print(
                "\nNo enhancements available for MMPM. You have the latest version."
            )
            log.logger.info('No newer version of MMPM available')
            return False
        return True
    except HTTPError:
        return False
Ejemplo n.º 4
0
def install_magicmirror(gui=False) -> bool:
    '''
    Installs MagicMirror. First checks if a MagicMirror installation can be
    found, and if one is found, prompts user to update the MagicMirror.
    Otherwise, searches for current version of NodeJS on the system. If one is
    found, the MagicMirror is then installed. If an old version of NodeJS is
    found, a newer version is installed before installing MagicMirror.

    Parameters:
        None

    Returns:
        bool: True upon succcess, False upon failure
    '''

    original_dir: str = os.getcwd()

    try:
        if not os.path.exists(utils.MAGICMIRROR_ROOT):
            print(colors.B_CYAN + "MagicMirror directory not found. " +
                  colors.RESET + "Installing MagicMirror..." + colors.RESET)
            os.system(
                'bash -c "$(curl -sL https://raw.githubusercontent.com/MichMich/MagicMirror/master/installers/raspberry.sh)"'
            )

        else:
            if not gui:
                message = colors.B_CYAN + "MagicMirror directory found. " + colors.RESET + "Would you like to check for updates? [yes/no | y/n]: "

            valid_response = False

            while not valid_response:
                response: str = 'yes' if gui else input(message)

                if response in ("no", "n"):
                    print(colors.B_MAGENTA + "Aborting MagicMirror update")
                    break

                if response in ("yes", "y"):
                    os.chdir(utils.MAGICMIRROR_ROOT)

                    print(colors.B_CYAN + "Checking for updates..." +
                          colors.RESET)
                    return_code, stdout, stderr = utils.run_cmd(
                        ['git', 'fetch', '--dry-run'])

                    if return_code:
                        utils.error_msg(stderr)
                        break

                    if not stdout:
                        print("No updates available for MagicMirror.")
                        break

                    print(colors.B_CYAN + "Updates found for MagicMirror. " +
                          colors.RESET + "Requesting upgrades...")
                    error_code, _, stderr = utils.run_cmd(['git', 'pull'])

                    if error_code:
                        utils.error_msg(stderr)
                        return False

                    print(utils.done())
                    error_code, _, stderr = utils.npm_install()

                    if error_code:
                        utils.error_msg(stderr)
                        valid_response = True

                    print(utils.done())
                else:
                    utils.warning_msg("Respond with yes/no or y/n.")
    except Exception:
        return False

    os.chdir(original_dir)
    return True
Ejemplo n.º 5
0
def install_modules(modules: dict, modules_to_install: List[str]) -> bool:
    '''
    Compares list of 'modules_to_install' to modules found within the
    'modules', clones the repository within the ~/MagicMirror/modules
    directory, and runs 'npm install' for each newly installed module.

    Parameters:
        modules (dict): Dictionary of MagicMirror modules
        modules_to_install (List[str]): List of modules to install

    Returns:
        bool: True upon success, False upon failure
    '''

    modules_dir: str = os.path.join(utils.MAGICMIRROR_ROOT, 'modules')

    if not os.path.exists(modules_dir):
        msg = "Failed to find MagicMirror root. Have you installed MagicMirror properly? "
        msg += "You may also set the env variable 'MMPM_MAGICMIRROR_ROOT' to the MagicMirror root directory."
        utils.error_msg(msg)
        return False

    log.logger.info(f'User selected modules to install: {modules_to_install}')
    log.logger.info(
        f'Changing into MagicMirror modules directory {modules_dir}')

    os.chdir(modules_dir)

    successful_installs: List[str] = []
    existing_modules: List[str] = []
    failed_installs: List[str] = []

    for module_to_install in modules_to_install:
        install_next: bool = False

        for _, category in modules.items():
            for module in category:
                if module[utils.TITLE] == module_to_install:
                    log.logger.info(
                        f'Matched {module[utils.TITLE]} to installation candidate'
                    )
                    title = module[utils.TITLE]
                    target = os.path.join(os.getcwd(), title)
                    repo = module[utils.REPOSITORY]

                    try:
                        os.mkdir(target)
                    except OSError:
                        log.logger.info(
                            f'Found {title} already in {os.getcwd()}. Skipping.'
                        )
                        utils.warning_msg(
                            f"The module {title} is already installed. To remove the module, run 'mmpm -r {title}'"
                        )
                        existing_modules.append(title)
                        install_next = True
                        continue

                    os.chdir(target)

                    message = f"Installing {title} @ {target}"
                    utils.separator(message)

                    print(colors.RESET + "Installing " + colors.B_CYAN +
                          f"{title}" + colors.B_YELLOW + " @ " + colors.RESET +
                          f"{target}")

                    utils.separator(message)
                    error_code, _, stderr = utils.clone(title, repo, target)

                    if error_code:
                        utils.warning_msg("\n" + stderr)
                        failed_installs.append(title)
                        install_next = True
                        continue

                    print(utils.done())
                    error: str = utils.handle_installation_process()

                    if error:
                        utils.error_msg(error)
                        failed_installs.append(title)

                    else:
                        successful_installs.append(title)

                    os.chdir(modules_dir)
                    install_next = True
                    break

            if install_next:
                break

    for module in failed_installs:
        failed_install_path = os.path.join(modules_dir, module)
        message = f"Failed to install {title}, removing the directory: '{failed_install_path}'"
        log.logger.info(message)
        utils.error_msg(message)
        utils.run_cmd(['rm', '-rf', failed_install_path], progress=False)

    for module in modules_to_install:
        if module not in successful_installs and module not in existing_modules and module not in failed_installs:
            utils.warning_msg(
                f"Unable to match '{module}' with installation candidate. Is the casing correct?"
            )

    if successful_installs:
        print(
            f"The installed modules may need additional configuring within '{utils.MAGICMIRROR_CONFIG_FILE}'"
        )
        return True

    return False