diff --git a/e-bin.sh b/e-bin.sh index 32b213e..bd45307 100644 --- a/e-bin.sh +++ b/e-bin.sh @@ -1,9 +1,4 @@ #!/bin/bash -# -# -# -####[ Variables ]####################################################################### - ## Colors for output YELLOW="$(printf '\033[0;33m')" @@ -14,143 +9,67 @@ RED="$(printf '\033[1;31m')" NC="$(printf '\033[0m')" # No color. readonly YELLOW GREEN BLUE CYAN RED NC -## Toastielab project details -readonly API_URL="https://toastielab.dev/api/v1/repos/EllieBotDevs/elliebot" - -## other constants. +## Other constants. readonly BOT_EXECUTABLE="EllieBot" -readonly BIN_DIR="elliebot-bin" -readonly BIN_DIR_OLD="elliebot-bin.old" -readonly CREDS_FILE="creds.yml" -readonly CREDS_EXAMPLE_FILE="creds_example.yml" -# Packages `ffmpeg` and `ffprobe` are highly recommended dependencies for `yt-dlp`. -# NOTE: Do not add `python`, `python3`, or `python-is-python3` to this list, as they are -# checked separately. -readonly REQUIRED_TOOLS=("jq" "yt-dlp") - - -####[ Functions ]####################################################################### - +readonly BIN_DIR="ellie" +readonly BACKUP_DIR="ellie_backups" +readonly CREDS_FILE="$BIN_DIR/data/creds.yml" +readonly CREDS_EXAMPLE_FILE="$BIN_DIR/data/creds_example.yml" #### -# Display the main menu. -display_menu() { - clear - echo "${BLUE}===== EllieBot Release Installer =====${NC}" - echo "1. Install" - echo "2. Run" - echo "3. Edit credentials" - echo "4. Exit" - echo -n "${CYAN}Enter your choice:${NC} " -} - -#### -# Identify the system architecture, and return a string that represents +# Identify the system architecture and OS, and return a string that represents it. # # RETURNS: -# - linux-x64: For x86_64. -# - linux-arm64: For aarch64 or arm64. -# - unsupported: For all other architectures. +# - linux-x64: For Linux x86_64. +# - linux-arm64: For Linux aarch64 or arm64. +# - osx-x64: For macOS x86_64. +# - osx-arm64: For macOS arm64. +# - unsupported: For all other architectures or operating systems. get_arch() { - case $(uname -m) in - x86_64) echo "linux-x64" ;; - aarch64|arm64) echo "linux-arm64" ;; - *) echo "unsupported" ;; + local os + os=$(uname -s) + local arch + arch=$(uname -m) + + case "$os" in + Linux) + case "$arch" in + x86_64) echo "linux-x64" ;; + aarch64 | arm64) echo "linux-arm64" ;; + *) echo "unsupported" ;; + esac + ;; + Darwin) + case "$arch" in + x86_64) echo "osx-x64" ;; + arm64) echo "osx-arm64" ;; + *) echo "unsupported" ;; + esac + ;; + *) + echo "unsupported" + ;; esac } -#### -# Perform a download operation using either 'wget' or 'curl'. -# -# NEW GLOBALS: -# - METHOD: The method used to download files ('wget' or 'curl'). -# -# PARAMETERS: -# - $1: url (Required) -# - The full URL to download the item from. -# - $2: output_file (Optional, Default: "") -# - The name of the file to save the item to. -# - IMPORTANT: If no output file is specified, the content at the URL will be -# output to stdout. -# - $3: error_message (Optional, Default: "ERROR: Failed to download the item") -# - The message to display if the download fails. -# - $4: is_silent (Optional, Default: false) -# - If true, the download will be silent. -# - Valid Options: -# - true -# - false -# -# RETURNS: -# - 0: On successful download. -# - 1: On failure to download the item. -dl() { - local url="$1" - local output_file="${2:-}" - local error_message="${3:-ERROR: Failed to download the item}" - local is_silent="${4:-false}" - local flags=() - - ## Sets a global constant to indicate whether 'wget' or 'curl' is should be used to - ## download files. Additionally, set any applicable flags that are to be used. - if [[ -z $METHOD ]]; then - if hash curl &>/dev/null; then - METHOD="curl" - # Set a silent flag if the user wants to download silently. - [[ $is_silent == true ]] && flags+=("-s") - # If an output file is specified, add the '-o' flag. - [[ -n $output_file ]] && flags+=("-L" "-o" "$output_file") - elif hash wget &>/dev/null; then - METHOD="wget" - # Set a silent flag if the user wants to download silently. - [[ $is_silent == true ]] && flags+=("-q") - - ## If an output file is specified, add the '-O' flag with the file name. - if [[ -n $output_file ]]; then - flags+=("-O" "$output_file") - ## If no output file is specified, add the '-O-' flag to output to stdout. - else - flags+=("-O-") - fi - else - echo "${RED}ERROR: Neither 'wget' nor 'curl' is installed${NC}" >&2 - echo "${CYAN}Please install one of them and try again${NC}" >&2 - return 1 +backup_bot() { + if [ -d $BIN_DIR/data/ ]; then + if [ ! -d $BACKUP_DIR/ ]; then + mkdir $BACKUP_DIR fi + + date_now=$(date +%s) + cp -r $BIN_DIR/data "$BACKUP_DIR/$date_now-data" + + echo "${BLUE}Your current data " fi - - ## Download the file. - "$METHOD" "${flags[@]}" "$url" || { - echo "${RED}$error_message${NC}" >&2 - return 1 - } - return 0 -} - -#### -# Download EllieBot's archive. -# -# PARAMETERS: -# - $1: url (Required) -# - The full URL to download the archive from. -# - $2: output (Required) -# - The name of the file to save the archive to. -# -# RETURNS: -# - 0: On successful download. -# - 1: On failure to download the archive. -download_archive() { - local url="$1" - local output="$2" - - dl "$url" "$output" "ERROR: Failed to download the archive" || return 1 - return 0 } # TODO: Still needs to move data from the old directory to the new one. #### # Downloads the latest release, extracts it, and sets up EllieBot's directory. If -# the directory already exists, it will be renamed to `elliebot-bin.old`. If -# `elliebot-bin.old` already exists, it will be deleted. +# the directory already exists, it will be renamed to `ellie.old`. If +# `ellie.old` already exists, it will be deleted. # # PARAMETERS: # - $1: version (Required) @@ -158,72 +77,66 @@ download_archive() { # # RETURNS: # - 1: On failure of some operation. -install_software() { +install_bot() { local version="$1" - local archive_dir_name - local archive_name="elliebot-v${version}.tar" - local arch; arch=$(get_arch) - local tar_url="${API_URL}/packages/generic/elliebot-build/${version}/${version}-${arch}-build.tar" + local arch + arch=$(get_arch) + local output="ellie-new" + local tar_url="https://toastielab.dev/EllieBotDevs/elliebot/releases/download/${version}/ellie-${arch}.tar.gz" - ## NOTE: We could move this outside of the function, such that when the script is - ## executed, the architecture is determined once, then exit the script if the - ## architecture is unsupported. - if [[ $arch == "unsupported" ]]; then - echo "${RED}ERROR: Unsupported architecture${NC}" >&2 - return 1 - fi + [[ $arch == "unsupported" ]] && { echo "${RED}ERROR: Unsupported architecture${NC}" >&2; return 1; } echo "${BLUE}Downloading '${version}' for '${arch}'...${NC}" - download_archive "$tar_url" "$archive_name" || return 1 - echo "${BLUE}Extracting...${NC}" - tar -xf "$archive_name" || { - echo "${RED}ERROR: Failed to extract the release${NC}" >&2 + [[ -d $output ]] && rm -r ./$output + mkdir ./$output + + if ! curl -L "$tar_url" | tar -xzf - -C ./$output --strip-components=1; then + echo "${RED}ERROR: Failed to download or extract the archive${NC}" >&2 + rm -r ./$output return 1 - } - - archive_dir_name=$(tar -tf "$archive_name" | head -1 | cut -f1 -d"/") - - ## If `elliebot-bin.old` already exists, delete it, so that we can rename the - ## current `elliebot-bin` to it. - if [[ -d $BIN_DIR_OLD ]]; then - echo "${BLUE}Removing '$BIN_DIR_OLD'...${NC}" - rm -rf "$BIN_DIR_OLD" fi - ## If the directory already exists, rename it to `elliebot-bin.old`. if [[ -d $BIN_DIR ]]; then - echo "${BLUE}Renaming '$BIN_DIR' to '$BIN_DIR_OLD'...${NC}" - mv "$BIN_DIR" "$BIN_DIR_OLD" - fi - - echo "${BLUE}Renaming '$archive_dir_name' to '$BIN_DIR'...${NC}" - if [[ -d $archive_dir_name ]]; then - mv "$archive_dir_name" "$BIN_DIR" + backup_bot + mv "$BIN_DIR" "${BIN_DIR}-old" else - echo "${RED}ERROR: Unarchived directory '$archive_dir_name' not found${NC}" >&2 - return 1 + echo "${BLUE}EllieBot not installed. Installing for the first time.${NC}" + fi + + mv ./$output $BIN_DIR + + if [[ -d "${BIN_DIR}-old" ]]; then + echo "${BLUE}Copying over data folder...${NC}" + [[ -d "${BIN_DIR}-old/data/" ]] && cp -rf "${BIN_DIR}-old/data/"* "$BIN_DIR/data/" fi - rm "$archive_name" chmod +x "${BIN_DIR}/${BOT_EXECUTABLE}" echo "${GREEN}Installation complete!${NC}" + + # Clean up any leftover folders + [[ -d $output ]] && rm -r ./$output + [[ -d "${BIN_DIR}-old" ]] && rm -r "${BIN_DIR}-old" } +# TODO: Somehow get the bot version, and +# paint available versions with color +# RED: older (downgrade), not recommended +# GREEN: newer (upgrade) +# BLUE: same (reinstall) + #### # Display a list of available versions, and prompt the user to select one to install. install_submenu() { local versions - # NOTE: This works because the `jq` command outputs a newline-separated list. - mapfile -t versions < <( - dl "${API_URL}/releases" "" "ERROR: Failed to get releases" \ - true | jq -r '.[].tag_name' | sort -V -r - ) + + # get versions from /refs/tags github endpoint + mapfile -t versions < <(curl -s https://toastielab.dev/api/v1/repos/EllieBotDevs/elliebot/git/refs/tags | grep -oP '"ref": "refs/tags/\K[^"]+') echo "${CYAN}Select version to install:${NC}" select version in "${versions[@]}"; do if [[ -n $version ]]; then - install_software "$version" + install_bot "$version" break else echo "${RED}ERROR: Invalid selection${NC}" @@ -232,25 +145,23 @@ install_submenu() { } #### -# Check if the 'token' in 'creds.yml' is set. +# Determines whether the 'token' field in the credentials file is set. # -# NOTE: This function is not foolproof, as it only checks if the 'token' is set to an -# empty string. It does not check if the token is valid. +# NOTE: +# This is not a comprehensive check for the validity of the token; it only verifies +# that the token field is not empty. # # RETURNS: -# - 0: If the 'token' is not set. -# - 1: If the 'token' is set. +# - 0: If the token is set. +# - 1: If the token is not set. is_token_set() { - if [[ ! -f $BIN_DIR/$CREDS_FILE ]]; then - return 0 - elif grep -Eq '^token: '\'\''' "$BIN_DIR/$CREDS_FILE"; then + if grep -Eq '^token: '\'\''' "$CREDS_FILE"; then return 1 else return 0 fi } - #### # Verify that the bot is installed, the token in the 'creds.yml' file is set, and then # run the bot. @@ -272,14 +183,17 @@ run_bot() { fi ## Create the creds file if it doesn't exist. - if [[ ! -f $BIN_DIR/$CREDS_FILE ]]; then - cp -f "$BIN_DIR/$CREDS_EXAMPLE_FILE" "$BIN_DIR/$CREDS_FILE" + if [[ ! -f $CREDS_FILE ]]; then + if [[ ! -f $CREDS_EXAMPLE_FILE ]]; then + echo "${RED}ERROR: 'creds_xample.yml'not found. Make sure the bot is installed${NC}" >&2 + return 1 + fi + cp -f "$CREDS_EXAMPLE_FILE" "$CREDS_FILE" fi - ## Ensure that the token is set. Do note that it won't say if the token is invalid. - if ! is_token_set; then - echo "${YELLOW}WARNING: 'token' is not set in '$CREDS_FILE'. Please add your" \ - "token and try again.${NC}" >&2 + ## Ensure that the token is set in the creds file or check if env var bot_token is set + if ! is_token_set && [[ -z "${bot_token}" ]]; then + echo "${RED}ERROR: Bot token not set. Please set it in the credentials file or as an environment variable.${NC}" >&2 return 1 fi @@ -289,114 +203,116 @@ run_bot() { popd >/dev/null || return 1 } -#### -# Verify that Python 3 is installed, and that the version is 3.9 or higher. -# -# RETURNS: -# - 0: If the verification passes. -# - 1: If the verification fails. -python_verification() { - local verification_passed=true +install_music_dependencies() { + curl -L -o e-musicreq.sh https://toastielab.dev/EllieBotDevs/ellie-bash-installer/raw/branch/v5/e-prereq.sh || { + echo "ERROR: Failed to download the music dependencies installer" + return 1 + } - ## Verify that Python 3 is installed. - if ! hash python3 &>/dev/null; then - echo "${YELLOW}WARNING: Python 3 is not installed${NC}" >&2 - verification_passed=false - fi - - ## Some systems, specifically Linux distributions like Ubuntu, don't have `python` - ## aliased to `python3`. This check is to ensure that `python` is available. - if ! hash python &>/dev/null; then - echo "${YELLOW}WARNING: The 'python' command is not available${NC}" >&2 - echo "${CYAN}You may need to install 'python-is-python3'${NC}" >&2 - verification_passed=false - fi - - ## Some systems still have python2 available and installed. We need to ensure that - ## the version of python is 3.9 or higher. - if ! python -c "import sys; assert sys.version_info >= (3, 9)" &>/dev/null; then - echo "${YELLOW}WARNING: Python 3.9 or higher is required${NC}" >&2 - verification_passed=false - fi - - [[ $verification_passed == false ]] && return 1 - return 0 -} - -#### -# Check if external tools that often need to be installed are available. If any are -# missing, print an error message and exit. -# -# EXITS: -# - 1: If any of the required tools are not installed. -verify_tools() { - local all_tools_installed=true - - for tool in "${REQUIRED_TOOLS[@]}"; do - if ! hash "$tool" &>/dev/null; then - all_tools_installed=false - echo "${YELLOW}WARNING: '$tool' is not installed${NC}" >&2 - fi - done - - python_verification - - if [[ $all_tools_installed == false ]]; then - echo "${CYAN}Please install the required tools and try again${NC}" >&2 - exit 1 - fi -} - -# TODO: Still needs to be edited/expanded upon. -edit_creds() { - local creds_file="${BIN_DIR}/creds.yml" - - if [[ ! -d $BIN_DIR ]]; then - echo "Please install the bot first." - return 1 - fi - - if [[ ! -f $creds_file ]]; then - cp $BIN_DIR/creds_example.yml $creds_file - fi - - local file="$1" - local editors=("nano" "micro" "code" "vim" "emacs" "gedit") - - if [ ! -f "$file" ]; then - echo "ERROR: File '$file' does not exist." >&2 + if [[ ! -f e-musicreq.sh ]]; then + echo "${RED}ERROR: Failed to download the music dependencies installer${NC}" >&2 return 1 fi - for editor in "${editors[@]}"; do - if command -v "$editor" >/dev/null 2>&1; then - "$editor" "$file" - return 0 - fi - done - - echo "ERROR: No known text editors (${editors[*]}) are available on this system." >&2 - return 1 + chmod +x e-musicreq.sh + ./e-musicreq.sh + rm e-musicreq.sh } +edit_creds() { + if [[ ! -f $CREDS_FILE ]]; then + cp $CREDS_EXAMPLE_FILE $CREDS_FILE + fi -####[ Main ]############################################################################ + # ask the user to input the token + echo "Please input your token: " + echo "" + read -r token + # check if the token is not empty + if [[ -z "$token" ]]; then + echo "ERROR: Invalid token." >&2 + return 1 + fi -verify_tools + # replace the token in the creds file + # by finding a line which starts with 'token: ' and replacing it + sed -i "s/token: .*/token: \"$token\"/" $CREDS_FILE +} + +migrate_from_v5() { + + # 0. Ensure that the bot is installed + if [[ ! -d $BIN_DIR ]]; then + echo "${RED}ERROR: EllieBot v6 not installed. Please install it first and then you'll be able to migrate.${NC}" + return 1 + fi + + # 1. Check if there is a elliebot/output folder + if [ ! -d "elliebot/output" ]; then + echo "${RED}ERROR: No v5 installation found.${NC}" + return 1 + fi + + # 2. Copy over the entirety of the data folder and overwrite + if [ -d "elliebot/output/data/" ]; then + # strings are no longer there, nor do we need them + rm -rf elliebot/output/data/strings + cp -rf elliebot/output/data/* ellie/data/ + + # move the data folder to avoid double migration + mv elliebot/output/data elliebot/output/data.old + fi + + # Done + echo "${GREEN}Migration successful! Your v6 bot is now in the 'ellie' folder.${NC}" + MIGRATED=1 +} + +#### +# Display the main menu options. +display_menu() { + clear + echo "${BLUE}===== EllieBot Release Installer =====${NC}" + echo "1. Install" + echo "2. Run" + echo "3. Add Token" + echo "4. Install music dependencies" + echo "5. Exit" + if [[ ! $MIGRATED -eq 1 && -d "elliebot/output/data" ]]; then + echo "6. Migrate v5 from-source version" + fi + echo -n "${CYAN}Enter your choice:${NC} " +} + +MIGRATED=1 +# check if there is a elliebot/output/data folder +if [ ! -d "elliebot/output/data" ]; then + MIGRATED=0 +fi while true; do display_menu read -r choice - case $choice in - 1) install_submenu ;; - 2) run_bot ;; - 3) edit_creds ;; - 4) echo "${GREEN}Exiting...${NC}"; exit 0 ;; - *) echo "${RED}ERROR: Invalid option${NC}" ;; + 1) install_submenu ;; + 2) run_bot ;; + 3) edit_creds ;; + 4) install_music_dependencies ;; + 5) + echo "${GREEN}Exiting...${NC}" + exit 0 + ;; + 6) + if [[ $MIGRATED -eq 1 || ! -d "elliebot/output/data" ]]; then + echo "${YELLOW}WARNING: Nothing to migrate. You must have a v5 elliebot/output folder!${NC}" >&2 + break + fi + migrate_from_v5 + ;; + *) echo "${RED}ERROR: Invalid option${NC}" ;; esac - echo "${CYAN}Press [Enter] to continue...${NC}" + echo "${CYAN}Press [Enter] to continue${NC}" read -r -done +done \ No newline at end of file diff --git a/e-install.sh b/e-install.sh new file mode 100644 index 0000000..66971f9 --- /dev/null +++ b/e-install.sh @@ -0,0 +1,13 @@ +#!/bin/sh +echo "" +echo "Welcome to EllieBot." +echo "Downloading the latest installer..." +root=$(pwd) + +rm "$root/e-bin.sh" 1>/dev/null 2>&1 +curl -L -o "$root/e-bin.sh" https://toastielab.dev/EllieBotDevs/ellie-bash-installer/raw/branch/v6/e-bin.sh + +bash e-bin.sh +cd "$root" +rm "$root/e-bin.sh" +exit 0 \ No newline at end of file diff --git a/e-prereq.sh b/e-prereq.sh index 1dd2b09..052b6f7 100644 --- a/e-prereq.sh +++ b/e-prereq.sh @@ -1,163 +1,253 @@ -#!/bin/bash -e -# Install dotnet -root=$(pwd) -echo "" +#!/bin/bash -function INSTALL_YTDLP { - wget https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -O ~/.local/bin/yt-dlp - chmod a+rx ~/.local/bin/yt-dlp +if [ "$EUID" -ne 0 ]; then + sudo_cmd="sudo " +fi + +declare -A -r APT_CMD=( + ["update"]="${sudo_cmd}apt update" + ["install"]="${sudo_cmd}apt install -y" +) + +declare -A -r DNF_CMD=( + ["update"]="${sudo_cmd}dnf update -y" + ["install"]="${sudo_cmd}dnf install -y" +) + +declare -A -r ZYPPER_CMD=( + ["update"]="${sudo_cmd}zypper refresh" + ["install"]="${sudo_cmd}zypper install -y" +) + +declare -A -r BREW_CMD=( + ["update"]="${sudo_cmd}brew update" + ["install"]="${sudo_cmd}brew install" +) + +declare -A -r PACMAN_CMD=( + ["update"]="${sudo_cmd}pacman -Sy" + ["install"]="${sudo_cmd}pacman -Sy --noconfirm" +) + +readonly YT_DLP_PATH="$HOME/.local/bin/yt-dlp" + +#### +# Identify the system's distribution, version, and architecture. +# +# NOTE: +# The 'os-release' file is used to determine the distribution and version. This file +# is present on almost every distributions running systemd. +# +# NEW GLOBALS: +# - DISTRO: The distribution name. +# - VER: The distribution version. +# - SVER: The distribution version without the minor version. +# - ARCH: The system architecture. +# - BITS: The system architecture in bits. +detect_sys_info() { + if [[ $(uname -s) == "Darwin" ]]; then + DISTRO="darwin" + VER=$(sw_vers -productVersion) + elif [[ -f /etc/os-release ]]; then + . /etc/os-release + DISTRO="$ID" + VER="$VERSION_ID" # Version: x.x.x... + SVER=${VER//.*/} # Version: x + else + DISTRO=$(uname -s) + VER=$(uname -r) + fi + + case $(uname -m) in + x86_64) BITS="64"; ARCH="x64" ;; + aarch64) BITS="64"; ARCH="arm64" ;; + armv*) BITS="32"; ARCH="arm32" ;; # Generic ARM 32-bit. + i*86) BITS="32"; ARCH="x86" ;; + *) BITS="?"; ARCH="$(uname -m)" ;; # Fallback to uname output. + esac } -wget -q -N https://toastielab.dev/EllieBotDevs/ellie-bash-installer/raw/branch/v5/detectOS.sh -declare DETECTED=($(bash detectOS.sh)) +#### +# Install 'yt-dlp' at '~/.local/bin/yt-dlp'. +# +# EXITS: +# - 1: Failed to download 'yt-dlp'. +install_yt_dlp() { -if [[ ${DETECTED[0]} = "" ]]; then exit 1; fi - -OS="${DETECTED[0]}" -VER="${DETECTED[1]}" -ARCH="${DETECTED[2]}" -SVER="${DETECTED[3]}" - -echo "This installer will download all of the required packages for EllieBot. It will use about 350MB of space. This might take awhile to download if you do not have a good internet connection.\n" -echo -e "Would you like to continue? \nYour OS: $OS \nOS Version: $VER \nArchitecture: $ARCH" - -while true; do - read -p "[y/n]: " yn - case $yn in - [Yy]* ) clear; echo Running EllieBot Auto-Installer; sleep 2; break;; - [Nn]* ) echo Quitting...; rm e-prereq.sh && exit;; - * ) echo "Couldn't get that please type [y] for Yes or [n] for No.";; - esac -done - -echo "" - -if [ "$OS" = "Ubuntu" ]; then - if [ "$VER" = "23.10" ]; then - echo -e "*Ubuntu 23.10 will reach End Of Life (EOL) on July 01, 2024. For more information, see the official Ubuntu EOL page. " + if command -v yt-dlp &>/dev/null; then + echo "${BLUE}Updating 'yt-dlp'...${NC}" + yt-dlp -U || { + echo "${RED}Failed to update 'yt-dlp'${NC}" >&2 + } + return fi - echo "Installing dotnet" - wget "https://packages.microsoft.com/config/ubuntu/$VER/packages-microsoft-prod.deb" -O packages-microsoft-prod.deb - sudo dpkg -i packages-microsoft-prod.deb - rm packages-microsoft-prod.deb - sudo apt-get update; - sudo apt-get install -y apt-transport-https && sudo apt-get update; - sudo apt-get install -y dotnet-sdk-8.0; + # get correct yt-dlp based on arch + local yt_dlp_url="https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux" + case $ARCH in + x64) yt_dlp_url="${yt_dlp_url}" ;; + arm64) yt_dlp_url="${yt_dlp_url}_aarch64" ;; + arm32) yt_dlp_url="${yt_dlp_url}_armv7l" ;; + *) echo "${RED}Unsupported architecture: $ARCH${NC}" >&2; return 1 ;; + esac - echo "Installing Git and Tmux..." - sudo apt-get install git tmux -y + [[ ! -d "$HOME/.local/bin" ]] && mkdir -p "$HOME/.local/bin" - echo "Installing music prerequisites..." - sudo apt-get install libopus0 opus-tools libopus-dev libsodium-dev python ffmpeg -y - echo "" - INSTALL_YTDLP + if [[ ! -f $YT_DLP_PATH ]]; then + echo "${BLUE}Installing 'yt-dlp'...${NC}" + curl -L "$yt_dlp_url" -o "$YT_DLP_PATH" || { + echo "${RED}Failed to download 'yt-dlp'${NC}" >&2 + return 1 + } + fi -elif [ "$OS" = "Debian" ]; then - if [[ "$SVER" == "9" ]]; then - echo "Support for Debian 9 has reached End of Life (EOL) as of August 9, 2022" - echo "Please upgrade to Debian 10 or newer" - rm e-prereq.sh + echo "${BLUE}Modifying permissions for 'yt-dlp'...${NC}" + chmod a+rx "$YT_DLP_PATH" +} + +#### +# Installs music prerequisites. +# +# PARAMETERS: +# - $1: cmd_array (Required) +# - The associative array containing the package manager commands. +# - $2: pkg_list (Required) +# - The array containing the list of packages to install. +install_music_prereqs() { + local -n cmd_array="$1" + local -n pkg_list="$2" + + echo -e "${YELLOW}About to run: ${cmd_array["update"]}${NC}" + read -p "${CYAN}Continue? [y/N]: ${NC}" -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + ${cmd_array["update"]} || { + echo "${RED}Failed to update${NC}" >&2 + exit 1 + } + else + echo "${RED}Update skipped${NC}" + fi + + + echo -e "${YELLOW}About to run: ${cmd_array["install"]} ${pkg_list[*]}${NC}" + read -p "${CYAN}Continue? [y/N]: ${NC}" -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + ${cmd_array["install"]} "${pkg_list[@]}" || { + echo "${RED}Failed to install music prerequisites${NC}" >&2 + exit 1 + } + else + echo "${RED}Installation cancelled${NC}" exit 1 fi - echo "Installing dotnet..." - wget https://packages.microsoft.com/config/debian/"$SVER"/packages-microsoft-prod.deb -O packages-microsoft-prod.deb - sudo dpkg -i packages-microsoft-prod.deb - rm packages-microsoft-prod.deb + install_yt_dlp - sudo apt-get update; \ - sudo apt-get install -y apt-transport-https && \ - sudo apt-get update && \ - sudo apt-get install -y dotnet-sdk-8.0 + echo -e "\n${GREEN}Finished installing music prerequisites${NC}" +} - echo "Installing Git and Tmux..." - sudo apt-get install git tmux -y +detect_sys_info - echo "Installing music prerequisites..." - sudo apt-get install libopus0 libopus-dev libsodium-dev ffmpeg -y - echo "" - INSTALL_YTDLP - -elif [ "$OS" = "Fedora" ]; then - sudo dnf -y install dotnet-sdk-8.0 - sudo dnf -y install git tmux - - sudo dnf -y install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm - sudo dnf -y install ffmpeg - sudo dnf -y install opus-tools opus libsodium - INSTALL_YTDLP - -elif [ "$OS" = "openSUSE Leap" ] || [ "$OS" = "openSUSE Tumbleweed" ]; then - echo -e "Installing dotnet..." - sudo zypper install -y libicu wget - sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc - wget https://packages.microsoft.com/config/opensuse/15/prod.repo - sudo mv prod.repo /etc/zypp/repos.d/microsoft-prod.repo - sudo chown root:root /etc/zypp/repos.d/microsoft-prod.repo - sudo zypper install -y dotnet-sdk-8.0 - - echo -e "\nInstalling git, tmux..." - sudo zypper install -y git tmux - - echo -e "\nInstalling music prerequisites..." - sudo zypper install -y ffmpeg libopus0 yt-dlp - -elif [ "$OS" = "LinuxMint" ]; then - echo "Installing Git and Tmux..." - sudo apt-get update; - sudo apt-get install -y git tmux - - echo "Installing dotnet..." - if [ "$SVER" = "19" ] || [ "$SVER" = "20" ]; then - wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb - elif [ "$SVER" = "21" ]; then - wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb - fi - - sudo dpkg -i packages-microsoft-prod.deb - rm packages-microsoft-prod.deb - sudo apt-get update && \ - sudo apt-get install -y dotnet-sdk-8.0 - - sudo apt-get install -y apt-transport-https && \ - sudo apt-get update; - - echo "Installing music prerequisites..." - sudo apt-get install -y libopus0 opus-tools libopus-dev libsodium-dev ffmpeg - INSTALL_YTDLP - -elif [ "$OS" = "AlmaLinux" ] || [ "$OS" = "Rocky Linux" ]; then - echo "Installing dotnet..." - sudo dnf install -y dotnet-sdk-8.0 - - echo "Installing Git and Tmux..." - sudo dnf install -y wget git opus tmux python3.11 - - echo "Installing music prerequisites..." - - if [ "$SVER" = "8" ]; then - sudo dnf -y install https://download.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm - sudo yum install yum-utils -y - sudo yum-config-manager --enable powertools - fi - - sudo dnf install -y --nogpgcheck https://mirrors.rpmfusion.org/free/el/rpmfusion-free-release-$(rpm -E %rhel).noarch.rpm - sudo dnf install -y ffmpeg - INSTALL_YTDLP - -elif [ "$OS" = "Darwin" ]; then - brew update - brew install wget git ffmpeg openssl opus opus-tools opusfile libffi libsodium tmux python yt-dlp - - brew install mono-libgdiplus +if [[ $BITS == "32" ]]; then + echo "${RED}Your system is 32-bit, which is unsupported${NC}" >&2 + exit 1 fi -echo -echo "EllieBot Prerequisites Installation completed..." -read -n 1 -s -p "Press any key to continue..." -sleep 2 +case "$DISTRO" in + ubuntu) + readonly pkgs=(ffmpeg curl) + case "$VER" in + 22.04|24.04) install_music_prereqs APT_CMD pkgs ;; + *) unsupported ;; + esac + ;; + debian) + readonly pkgs=(ffmpeg curl) + case "$SVER" in + 1[1-3]) install_music_prereqs APT_CMD pkgs ;; + *) unsupported ;; + esac + ;; + linuxmint) + readonly pkgs=(ffmpeg curl) + case "$SVER" in + 2[0-3]) install_music_prereqs APT_CMD pkgs ;; + *) unsupported ;; + esac + ;; + fedora) + readonly pkgs=(ffmpeg-free curl) + case "$SVER" in + 38|39|40|41|42|43) install_music_prereqs DNF_CMD pkgs ;; + *) unsupported ;; + esac + ;; + almalinux|rocky) + el_ver=$(rpm -E %rhel) -cd "$root" -rm "$root/e-prereq.sh" -exit 0 + # add rpm fusion repo + repo_cmd=( + "${sudo_cmd}dnf install -y epel-release" + "sudo dnf install --nogpgcheck https://mirrors.rpmfusion.org/free/el/rpmfusion-free-release-${el_ver}.noarch.rpm -y" + ) + + if (( el_ver == 8 )); then + repo_cmd+=("${sudo_cmd}dnf config-manager --set-enabled powertools") + elif (( el_ver == 9 )); then + repo_cmd+=("${sudo_cmd}dnf config-manager --set-enabled crb") + fi + + echo "${YELLOW}In order to install ffmpeg, you need to enable the RPM Fusion repository.${NC}" + echo "${YELLOW}The following commands will be run:${NC}" + for cmd in "${repo_cmd[@]}"; do + echo " ${YELLOW}-> $cmd${NC}" + done + + # ask the user whether it's ok to run this command + read -p "${CYAN}Do you want to continue with these commands? [y/N]: ${NC}" -n 1 -r + echo "" + if [[ $REPLY =~ ^[Yy]$ ]]; then + for cmd in "${repo_cmd[@]}"; do + echo "${BLUE}Running: $cmd${NC}" + $cmd || { + echo "${RED}Failed to run: $cmd${NC}" >&2 + exit 1 + } + done + else + echo "${RED}User opted to cancel the command execution.${NC}" >&2 + exit 1 + fi + + readonly pkgs=(ffmpeg curl) + install_music_prereqs DNF_CMD pkgs + ;; + opensuse-leap) + readonly pkgs=(ffmpeg curl) + case "$VER" in + 15.5|15.6|15.7) install_music_prereqs ZYPPER_CMD pkgs ;; + *) unsupported ;; + esac + ;; + opensuse-tumbleweed) + readonly pkgs=(ffmpeg curl) + install_music_prereqs ZYPPER_CMD pkgs ;; + arch|artix) + readonly pkgs=(ffmpeg pipewire-jack curl) + install_music_prereqs PACMAN_CMD pkgs + ;; + darwin) + if ! command -v brew &>/dev/null; then + echo "${RED}Homebrew is not installed. Please install Homebrew first.${NC}" >&2 + exit 1 + fi + readonly pkgs=(ffmpeg python curl) + install_music_prereqs BREW_CMD pkgs + ;; + *) + echo "${RED}Unsupported distribution: $DISTRO${NC}" >&2 + exit 1 + ;; +esac \ No newline at end of file