Added e-bin.sh
This commit is contained in:
parent
ce3d30c033
commit
0209679e97
1 changed files with 402 additions and 0 deletions
402
e-bin.sh
Normal file
402
e-bin.sh
Normal file
|
@ -0,0 +1,402 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
#
|
||||
#
|
||||
####[ Variables ]#######################################################################
|
||||
|
||||
|
||||
## Colors for output
|
||||
YELLOW="$(printf '\033[0;33m')"
|
||||
GREEN="$(printf '\033[0;32m')"
|
||||
BLUE="$(printf '\033[0;34m')"
|
||||
CYAN="$(printf '\033[0;36m')"
|
||||
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"
|
||||
|
||||
## 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 ]#######################################################################
|
||||
|
||||
|
||||
####
|
||||
# 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
|
||||
#
|
||||
# RETURNS:
|
||||
# - linux-x64: For x86_64.
|
||||
# - linux-arm64: For aarch64 or arm64.
|
||||
# - unsupported: For all other architectures.
|
||||
get_arch() {
|
||||
case $(uname -m) in
|
||||
x86_64) echo "linux-x64" ;;
|
||||
aarch64|arm64) echo "linux-arm64" ;;
|
||||
*) 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
|
||||
fi
|
||||
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.
|
||||
#
|
||||
# PARAMETERS:
|
||||
# - $1: version (Required)
|
||||
# - The release version to download.
|
||||
#
|
||||
# RETURNS:
|
||||
# - 1: On failure of some operation.
|
||||
install_software() {
|
||||
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/EllieBotDevs/generic/EllieBot-build/${version}/${version}-${arch}-build.tar"
|
||||
|
||||
## 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
|
||||
|
||||
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
|
||||
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"
|
||||
else
|
||||
echo "${RED}ERROR: Unarchived directory '$archive_dir_name' not found${NC}" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
rm "$archive_name"
|
||||
chmod +x "${BIN_DIR}/${BOT_EXECUTABLE}"
|
||||
echo "${GREEN}Installation complete!${NC}"
|
||||
}
|
||||
|
||||
####
|
||||
# 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
|
||||
)
|
||||
|
||||
echo "${CYAN}Select version to install:${NC}"
|
||||
select version in "${versions[@]}"; do
|
||||
if [[ -n $version ]]; then
|
||||
install_software "$version"
|
||||
break
|
||||
else
|
||||
echo "${RED}ERROR: Invalid selection${NC}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
####
|
||||
# Check if the 'token' in 'creds.yml' 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.
|
||||
#
|
||||
# RETURNS:
|
||||
# - 0: If the 'token' is not set.
|
||||
# - 1: If the 'token' is set.
|
||||
is_token_set() {
|
||||
if [[ ! -f $BIN_DIR/$CREDS_FILE ]]; then
|
||||
return 0
|
||||
elif grep -Eq '^token: '\'\''' "$BIN_DIR/$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.
|
||||
#
|
||||
# RETURNS:
|
||||
# - 1: If the bot is not installed, the executable is not found, or the token is not
|
||||
# set.
|
||||
run_bot() {
|
||||
## Ensure that the bot is installed.
|
||||
if [[ ! -d $BIN_DIR ]]; then
|
||||
echo "${RED}ERROR: EllieBot not installed. Please install it first.${NC}" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
## Ensures that the executable exists.
|
||||
if [[ ! -f $BIN_DIR/$BOT_EXECUTABLE ]]; then
|
||||
echo "${RED}ERROR: EllieBot executable not found${NC}" >&2
|
||||
return 1
|
||||
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"
|
||||
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
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "${BLUE}Attempting to run EllieBot...${NC}"
|
||||
pushd "$BIN_DIR" >/dev/null || return 1
|
||||
./$BOT_EXECUTABLE
|
||||
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
|
||||
|
||||
## 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
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
####[ Main ]############################################################################
|
||||
|
||||
|
||||
verify_tools
|
||||
|
||||
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}" ;;
|
||||
esac
|
||||
|
||||
echo "${CYAN}Press [Enter] to continue...${NC}"
|
||||
read -r
|
||||
done
|
Loading…
Add table
Reference in a new issue