Esempio n. 1
0
def update_hifumi():
    """
    Updates Hifumi via Git.
    Useful if something wents wrong or if a new version comes out.
    :return: Git call, then exit code.
    0 if went fine, 1 or exception if error ocurred.
    """
    if get_latest_release() == __version__:
        info("Hifumi is already the latest version."
             "No need to perform an update right now!")
    else:
        try:
            code = subprocess.call(("git", "pull", "--ff-only"))
        except subprocess.CalledProcessError:
            error("\nError: Git not found. It's either not installed or "
                  "not in the PATH environment variable. Please fix this!")
            return
        if not code:
            info("\nHifumi is now updated successfully!")
            sample_file = Path('./config/sample_settings.py')
            if sample_file.is_file():
                sample_file.unlink()
        else:
            error("\nUh oh! An error ocurred and "
                  "update is going to be aborted.\n"
                  "This error might be caused from "
                  "the environment edits you made. "
                  "Please fix this by going to the maintenance menu.")
Esempio n. 2
0
def run():
    """
    Main function of the program
    :return: An initialization request to the 
    program or an error if Python/pip is wrong.
    """
    os.chdir(str(Path(__file__).parent))
    if not logger_success:
        computer_meets_color()  # lol
        main()
    if not SYSTEM_OK:
        error("Sorry! This operation system is not compatible with "
              "Hifumi's environment and might not run at all. Hifumi "
              "is only supported for Windows, Mac, Linux and "
              "Raspberry Pi. Please install one of those OS and try "
              "again.")
        exit(1)
    elif not PYTHON_OK:
        error("Sorry! This Python version is not compatible. Hifumi needs "
              "Python 3.6 or higher. You have Python version {}.\n".format(
                  platform.python_version()) + " Install the required "
              "version and try again.\n")
        exit(1)
    elif not pip:
        error("Hey! Python is installed but you are missing the pip module."
              "\nPlease reinstall Python without "
              "unchecking any option during the setup >_<")
        exit(1)
    else:
        info("Initializating...")
        if IS_LINUX and not is_command():
            info(
                "We detected this launcher is not a bash command. Would you like "
                "to create a bash command to execute this launcher?")
            if user_pick_yes_no():
                bash_command()
        elif detect_errors():
            clear_screen()
            print("You got some warnings/errors. It's highly recommended "
                  "to fix them before you continue.\n")
            string_errors()
            pause()
            clear_screen()
        else:
            main()
Esempio n. 3
0
def edit_settings():
    """
    Opens settings.py file in the notepad if present.
    :return: The action or an exception if an error ocurred.
    """
    path = Path('./config/settings.yml')
    sample_path = Path('./config/sample_settings.yml')
    if path.is_file():
        __edit_settings(path)
    elif not path.is_file() and sample_path.is_file():
        info("It looks like it's your first time running Hifumi launcher.\n"
             "sample_settings.yml is going to be renamed to settings.yml.\n")
        pause()
        sample_path.rename(str(path))
        edit_settings()
    else:
        error("An error ocurred while opening the "
              "settings into editor. If the file does not exist, "
              "please reinstall Hifumi from zero.\n")
        pause()
Esempio n. 4
0
def stop_hifumi():
    """
    Stops Hifumi from running if started with PM2
    :return: Exit code, 0 if fine, else more than 0.
    """
    interpreter = sys.executable.split('/')[-1]
    if not interpreter:
        raise RuntimeError("Couldn't find Python interpreter")

    run_script = Path("./run.py")
    # Don't worry about shard mode, that's toggleable via settings.py
    if not run_script.is_file():
        error("Hifumi's main file to run is not available. "
              "Please reinstall Hifumi!")
        pause()
        main()
    code = subprocess.call(['pm2', 'stop', 'run.py'])
    if code is 0:
        info("Hifumi has been terminated successfully.")
    else:  # If error
        error("Hifumi is not registered into PM2. No need to use this now.")
    pause()
Esempio n. 5
0
def update_pip():
    """
    Updates pip, a.k.a the Python package manager.
    :return: Pip call, then exit code. 
    0 if everything is fine, 1 if error ocurred.
    """
    interpreter = sys.executable.split('/')[-1]

    if not interpreter:
        error("Python interpreter not found.")
        return

    args = [interpreter, "-m", "pip", "install", "--upgrade", "pip"]

    code = subprocess.call(args)

    if code == 0:
        info("\nPip updated successfully to the latest version!")
    else:
        error(
            "\nUh oh! An error ocurred and installation is going "
            "to be aborted.\nPlease fix the error above basing in the docs.\n")
Esempio n. 6
0
def install_reqs():
    """
    Installs the required requirements for the environment.
    :return: Pip call, then exit code. 
    0 if everything is fine, 1 if error ocurred.
    """
    remove_reqs_readonly()
    interpreter = sys.executable.split('/')[-1]

    if not interpreter:
        error("Python interpreter not found.")
        return

    txt = REQS_TXT

    args = [
        interpreter, "-m", "pip", "install", "--upgrade", "--target",
        str(REQS_DIR), "-r", txt
    ]

    if IS_MAC:
        args.remove("--target")
        args.remove(str(REQS_DIR))

    code = subprocess.call(args)

    if code == 0:
        info("\nPython requirements installed successfully! "
             "Now installing PM2...")
        pm2_str = subprocess.call(['npm', 'install', 'pm2', '-g'])

        if pm2_str == 0:
            info("\nPM2 installed successfully!")
        else:
            error("\nUh oh! An error ocurred and installation is going to be "
                  "aborted.\nPlease fix the error above basing in the docs.\n")
    else:
        error("\nUh oh! An error ocurred and installation is going to "
              "be aborted.\nPlease fix the error above basing in the docs.\n")
Esempio n. 7
0
def run_hifumi(autorestart):
    """
    Start Hifumi, autorestart is toggleable.
    :return: Exit code, 0 if fine, else more than 0.
    """
    interpreter = sys.executable.split('/')[-1]
    if not interpreter:
        raise RuntimeError("Couldn't find Python interpreter")

    if not verify_requirements():
        error("You don't have the requirements that are needed to "
              "start the bot. Please install them first and try again.")
        pause()
        main()

    run_script = Path('./run.py')
    # Don't worry about shard mode, that's toggleable via settings.py
    if not run_script.is_file():
        error("Hifumi's main file to run is not available. "
              "Please reinstall Hifumi!")
        pause()
        main()
    try:
        if autorestart:
            cmd = ("pm2", "start", "run.py", "--name=Hifumi",
                   "--interpreter=" + interpreter)
            code = subprocess.call(cmd)
        else:
            cmd = (interpreter, "run.py")
            info("Hifumi is now started as single session! "
                 "To shutdown the bot, press CTRL+Z anytime.")
            code = subprocess.call(cmd)
    except KeyboardInterrupt:  # Triggered!
        code = 0
    if not autorestart and code is 0:  # If no error
        info("Hifumi has been terminated recently. Exit code: %d" % code)
    elif not autorestart and code is not 0:  # If error
        error("Hifumi has been terminated recently. Exit code: %d" % code)
    elif autorestart and code is not 0:
        clear_screen()
        info("Hifumi is already started! Restarting instead...")
        cmd = ("pm2", "restart", "run.py")
        subprocess.call(cmd)
    elif autorestart and code is 0:
        info("Hifumi has been started successfully!")
    else:  # If error
        error("Hifumi has been terminated recently. Exit code: %d" % code)
    pause()
Esempio n. 8
0
def reset_hifumi(reqs=False, data=False, cogs=False, git_reset=False):
    """
    Resets Hifumi or any of its properties (enabled to True boolean).
    If all of the parameters are enabled, Hifumi will get a 'factory reset'.
    :param reqs: Choose to reset the local packages.
    :param data: Choose to reset the data folder.
    :param cogs: Choose to reset the cogs (command modules).
    :param git_reset: Choose to replace all the 
    environment with the latest commit.
    :return: For reqs, data, cogs. Folder removing and result or exception
    (FileNotFoundError or another). 
    If git_reset an exit code. 0 if went fine, 1 if otherwise.
    """
    if reqs:
        try:
            shutil.rmtree(str(REQS_DIR), onerror=remove_readonly)
            info("Installed local packages wiped successfully!")
        except FileNotFoundError:
            pass
        except Exception as e:
            error("Uh oh! An error ocurred: {}".format(e))
    if data:
        try:
            shutil.rmtree("data", onerror=remove_readonly)
            info("'data' folder has been wiped.")
        except FileNotFoundError:
            pass
        except Exception as e:
            error("Uh oh! An error ocurred: {}".format(e))

    if cogs:
        try:
            shutil.rmtree("cogs", onerror=remove_readonly)
            info("'cogs' folder has been wiped.")
        except FileNotFoundError:
            pass
        except Exception as e:
            error("An error occurred when trying to remove the 'cogs' folder: "
                  "{}".format(e))

    if git_reset:
        code = subprocess.call(("git", "reset", "--hard"))
        if code == 0:
            info("Hifumi repaired successfully! to the last local commit. "
                 "If the bot is started, please restart it to make effect.")
        else:
            error("The repair has failed.")
Esempio n. 9
0
def maintenance_menu():
    """
    Prints the options from the maintenance menu.
    :return: The maintenance menu.
    """
    clear_screen()
    if not IS_WINDOWS or not IS_MAC:
        warning("Before you continue, please verify this launcher and "
                "the bot are NOT installed in root folder, in '/' or "
                "any other important folder from the system to prevent "
                "that those ones get severely damaged. Proceed?")
        if user_pick_yes_no():
            autoclean()
            clear_screen()
            pass
        else:
            main()
    else:
        warning("Before you continue, please verify this launcher and "
                "the bot are NOT installed in a system important folder "
                "or an instance ran by the system, this to prevent "
                "that those ones get severely damaged. Proceed?")
        if user_pick_yes_no():
            autoclean()
            clear_screen()
            pass
        else:
            main()
    while True:
        print("Maintenance:\n")
        print("1. Repair environment (this won't include data)")
        print("2. Wipe 'data' folder")
        print("3. Wipe 'lib' folder (pip packages and libraries)")
        print("4. Clean Python cache (experimental)")
        print("5. Factory reset (please be careful)")
        print("\n0. Go back")
        choice = user_choice()
        if choice == "1":
            warning("Any code modification you have made will be lost. Data/"
                    "non-default cogs will be left intact. Are you sure?")
            if user_pick_yes_no():
                reset_hifumi(git_reset=True)
                pause()
        elif choice == "2":
            warning("Are you sure? This will wipe the 'data' folder, which "
                    "contains all your settings and cogs' data.\nThe 'cogs' "
                    "folder, however, will be left intact.")
            if user_pick_yes_no():
                reset_hifumi(data=True)
                pause()
        elif choice == "3":
            reset_hifumi(reqs=True)
            pause()
        elif choice == "4":
            warning("Are you sure?")
            if user_pick_yes_no():
                autoclean()
                info("Python cache should be cleaned now.")
                pause()
        elif choice == "5":
            warning("Are you sure? This will wipe ALL the installation "
                    "data.\nYou'll lose all your settings, cogs and any "
                    "modification you have made.\nThere is no going back, "
                    "so please be careful and choose wisely.")
            if user_pick_yes_no():
                reset_hifumi(reqs=True, data=True, cogs=True, git_reset=True)
                pause()
        elif choice == "0":
            break
        clear_screen()
Esempio n. 10
0
def download_ffmpeg(bitness):
    """
    Downloads FFMPEG from the official page. 
    It's a required tool for music commands.
    :param bitness: Can be 32bit or 64bit in string. 
    This is choosen for the download version.
    :return: FFMPEG download and a message 
    with instructions for the first time use.
    """
    clear_screen()
    repo = "https://github.com/hifumibot/hifumibot"
    verified = []

    if bitness == "32bit":
        info("Please download 'ffmpeg 32bit static' from the page that "
             "is about to open.\nOnce done, open the 'bin' folder located "
             "inside the zip.\nThere should be 3 files: ffmpeg.exe, "
             "ffplay.exe, ffprobe.exe.\nPut all three of them into the "
             "bot's main folder.")
        time.sleep(5)
        webbrowser.open(FFMPEG_BUILDS_URL)
        return

    for file in FFMPEG_FILES:
        file = Path(file)
        if file.is_file():
            warning("{} already present. Verifying integrity... "
                    "".format(file.name),
                    end="")
            _hash = calculate_md5(file.name)
            if _hash == FFMPEG_FILES[file.name]:
                verified.append(file.name)
                info("Done!")
                continue
            else:
                warning("Hash mismatch. Redownloading.")
        info("Downloading {}... Please wait.".format(file.name))
        with urllib.request.urlopen(repo + file.name) as data:
            with file.open(mode='wb') as f:
                f.write(data.read())
        info("FFMPEG downloaded! Please follow the instructions! "
             "Open the 'bin' folder located inside the zip.\nThere should "
             "be 3 files: ffmpeg.exe, ffplay.exe, ffprobe.exe.\nPut all "
             "three of them into the bot's main folder.")

    for file, _hash in FFMPEG_FILES.items():
        if file in verified:
            continue
        info("Verifying {}... ".format(file), end="")
        if not calculate_md5(file) != _hash:
            info("Passed.")
        else:
            warning("Hash mismatch. Please redownload.")

    info("\nAll files have been downloaded.")