#!/bin/sh # RF-Swift Installer Script # Usage: curl -fsSL "https://get.rfswift.io/" | sh # or: wget -qO- "https://get.rfswift.io/" | sh set -e # Configuration GITHUB_REPO="PentHertz/RF-Swift" # Color codes for better readability RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' MAGENTA='\033[0;35m' CYAN='\033[0;36m' NC='\033[0m' # No Color # Function to output colored text color_echo() { local color=$1 local text=$2 case $color in "red") printf "${RED}%s${NC}\n" "${text}" ;; "green") printf "${GREEN}%s${NC}\n" "${text}" ;; "yellow") printf "${YELLOW}%s${NC}\n" "${text}" ;; "blue") printf "${BLUE}%s${NC}\n" "${text}" ;; "magenta") printf "${MAGENTA}%s${NC}\n" "${text}" ;; "cyan") printf "${CYAN}%s${NC}\n" "${text}" ;; *) printf "%s\n" "${text}" ;; esac } # Fun welcome message fun_welcome() { color_echo "cyan" "đ WELCOME TO THE RF-Swift Installer! đ" color_echo "yellow" "Prepare yourself for an epic journey in the world of radio frequencies! đĄ" } # Fun thank you message after installation thank_you_message() { color_echo "green" "đ You did it! RF-Swift is now ready for action! đ" color_echo "magenta" "Thank you for installing. You've just taken the first step towards RF mastery! đ§" } # Function to check if a command exists command_exists() { command -v "$1" >/dev/null 2>&1 } # Function to check if we have sudo privileges have_sudo_access() { if command_exists sudo; then sudo -v >/dev/null 2>&1 return $? fi return 1 } # Function to get the current user even when run with sudo get_real_user() { if [ -n "$SUDO_USER" ]; then echo "$SUDO_USER" else whoami fi } # Function to prompt user for yes/no with terminal redirection solution prompt_yes_no() { local prompt="$1" local default="$2" # Optional default (y/n) local response # Try to use /dev/tty for interactive input even in pipe scenarios if [ -t 0 ]; then # Standard terminal input is available tty_device="/dev/stdin" elif [ -e "/dev/tty" ]; then # We're in a pipe but /dev/tty might be available tty_device="/dev/tty" else # No interactive terminal available, use defaults if [ "$default" = "n" ]; then echo "${YELLOW}${prompt} (y/n): Defaulting to no (no terminal available)${NC}" return 1 else echo "${YELLOW}${prompt} (y/n): Defaulting to yes (no terminal available)${NC}" return 0 fi fi # Try to read from the terminal while true; do printf "${YELLOW}%s (y/n): ${NC}" "${prompt}" if read -r response < "$tty_device" 2>/dev/null; then case "$response" in [Yy]* ) return 0 ;; [Nn]* ) return 1 ;; * ) echo "Please answer yes (y) or no (n)." ;; esac else # Failed to read from terminal, use default if [ "$default" = "n" ]; then echo "${YELLOW}${prompt} (y/n): Defaulting to no (couldn't read from terminal)${NC}" return 1 else echo "${YELLOW}${prompt} (y/n): Defaulting to yes (couldn't read from terminal)${NC}" return 0 fi fi done } # Function to create an alias for RF-Swift in the user's shell configuration create_alias() { local bin_path="$1" color_echo "blue" "đ Setting up an alias for RF-Swift..." # Get the real user even when run with sudo REAL_USER=$(get_real_user) USER_HOME=$(eval echo ~${REAL_USER}) # Determine shell from the user's default shell USER_SHELL=$(getent passwd "${REAL_USER}" 2>/dev/null | cut -d: -f7 | xargs basename 2>/dev/null) if [ -z "${USER_SHELL}" ]; then USER_SHELL=$(basename "${SHELL}") fi SHELL_RC="" ALIAS_LINE="alias rfswift='${bin_path}/rfswift'" # Determine the correct shell configuration file case "${USER_SHELL}" in bash) # Check for .bash_profile first (macOS preference), then .bashrc (Linux preference) if [ -f "${USER_HOME}/.bash_profile" ]; then SHELL_RC="${USER_HOME}/.bash_profile" elif [ -f "${USER_HOME}/.bashrc" ]; then SHELL_RC="${USER_HOME}/.bashrc" else # Default to .bashrc if neither exists SHELL_RC="${USER_HOME}/.bashrc" fi ;; zsh) SHELL_RC="${USER_HOME}/.zshrc" ;; fish) SHELL_RC="${USER_HOME}/.config/fish/config.fish" ALIAS_LINE="alias rfswift '${bin_path}/rfswift'" # fish has different syntax ;; *) color_echo "yellow" "â ī¸ Unsupported shell ${USER_SHELL}. Please manually add an alias for rfswift." return 1 ;; esac # Create the configuration file if it doesn't exist if [ ! -f "${SHELL_RC}" ]; then if [ "${USER_SHELL}" = "fish" ]; then # For fish, ensure config directory exists mkdir -p "$(dirname "${SHELL_RC}")" fi touch "${SHELL_RC}" if [ $? -ne 0 ]; then color_echo "yellow" "â ī¸ Unable to create ${SHELL_RC}. Please manually add the alias." return 1 fi fi # Check if alias already exists if grep -q "alias rfswift" "${SHELL_RC}" 2>/dev/null; then color_echo "yellow" "An existing rfswift alias was found in ${SHELL_RC}" if prompt_yes_no "Do you want to replace the existing alias?" "y"; then # Remove the existing alias line(s) if [ "${USER_SHELL}" = "fish" ]; then sed -i.bak '/alias rfswift /d' "${SHELL_RC}" 2>/dev/null || sed -i '' '/alias rfswift /d' "${SHELL_RC}" 2>/dev/null else sed -i.bak '/alias rfswift=/d' "${SHELL_RC}" 2>/dev/null || sed -i '' '/alias rfswift=/d' "${SHELL_RC}" 2>/dev/null fi # Add the new alias if echo "${ALIAS_LINE}" >> "${SHELL_RC}"; then color_echo "green" "â Updated RF-Swift alias in ${SHELL_RC}" color_echo "yellow" "⥠To use the alias immediately, run: source ${SHELL_RC}" return 0 else color_echo "yellow" "â ī¸ Failed to update alias in ${SHELL_RC}. Please manually update the alias." color_echo "blue" "đĄ Run this command to add it manually: echo '${ALIAS_LINE}' >> ${SHELL_RC}" return 1 fi else color_echo "blue" "Keeping existing alias." return 0 fi fi # Add the alias if it doesn't exist if echo "${ALIAS_LINE}" >> "${SHELL_RC}"; then color_echo "green" "â Added RF-Swift alias to ${SHELL_RC}" color_echo "yellow" "⥠To use the alias immediately, run: source ${SHELL_RC}" return 0 else color_echo "yellow" "â ī¸ Failed to add alias to ${SHELL_RC}. Please manually add the alias." color_echo "blue" "đĄ Run this command to add it manually: echo '${ALIAS_LINE}' >> ${SHELL_RC}" return 1 fi } # Function to check if Docker is installed check_docker() { color_echo "blue" "đ Checking if Docker is installed..." if command_exists docker; then color_echo "green" "â Docker is already installed. You're all set for RF-Swift!" return 0 fi color_echo "yellow" "â ī¸ Docker is not installed on your system." color_echo "blue" "âšī¸ Docker is required for RF-Swift to work properly." # Provide advice on running Docker with reduced privileges color_echo "cyan" "đ Docker Security Advice:" color_echo "cyan" " - Consider using Docker Desktop which provides a user-friendly interface" color_echo "cyan" " - On Linux, add your user to the 'docker' group to avoid using sudo with each Docker command" color_echo "cyan" " - Use rootless Docker mode if you need enhanced security" color_echo "cyan" " - Always pull container images from trusted sources" # Ask if the user wants to install Docker if prompt_yes_no "Would you like to install Docker now?" "n"; then install_docker return $? else color_echo "yellow" "â ī¸ Docker installation skipped. You'll need to install Docker manually before using RF-Swift." return 1 fi } # Function to install Docker install_docker() { case "$(uname -s)" in Darwin*) if command_exists brew; then color_echo "blue" "đ Installing Docker via Homebrew..." brew install --cask docker color_echo "blue" "đ Launching Docker Desktop now... Hold tight!" open -a Docker color_echo "yellow" "âŗ Give it a moment, Docker is warming up!" i=1 while [ $i -le 30 ]; do if command_exists docker && docker info >/dev/null 2>&1; then color_echo "green" "â Docker is up and running!" return 0 fi sleep 2 i=$((i + 1)) done color_echo "yellow" "Docker is installed but still starting. Please open Docker manually if needed." else color_echo "red" "đ¨ Homebrew is not installed! Please install Homebrew first:" color_echo "yellow" '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"' color_echo "yellow" "Then, run the script again!" return 1 fi ;; Linux*) color_echo "blue" "đ§ Installing Docker on your Linux machine..." color_echo "yellow" "â ī¸ This will require sudo privileges to install Docker." if ! have_sudo_access; then color_echo "red" "đ¨ Unable to obtain sudo privileges. Docker installation requires sudo." return 1 fi color_echo "blue" "Using sudo to install Docker..." if command_exists curl; then curl -fsSL "https://get.docker.com/" | sudo sh elif command_exists wget; then wget -qO- "https://get.docker.com/" | sudo sh else color_echo "red" "đ¨ Missing curl/wget. Please install one of them." return 1 fi if command_exists sudo && command_exists groups; then if ! groups | grep -q docker; then color_echo "blue" "đ§ Adding you to the Docker group..." sudo usermod -aG docker "$(get_real_user)" color_echo "yellow" "⥠You may need to log out and log back in for this to take effect." fi fi if command_exists systemctl; then color_echo "blue" "đ Starting Docker service..." sudo systemctl start docker sudo systemctl enable docker fi color_echo "green" "đ Docker is now installed and running!" ;; *) color_echo "red" "đ¨ Unsupported OS detected: $(uname -s). Docker can't be installed automatically here." return 1 ;; esac } # Function to get the latest release information get_latest_release() { color_echo "blue" "đ Detecting the latest RF-Swift release..." # Default version as fallback DEFAULT_VERSION="0.6.3" VERSION="${DEFAULT_VERSION}" # Initialize with default # First try: Use GitHub API with a proper User-Agent to avoid rate limiting issues if command_exists curl; then # First method: direct API call with proper headers to avoid throttling LATEST_INFO=$(curl -s -H "User-Agent: RF-Swift-Installer" "https://api.github.com/repos/${GITHUB_REPO}/releases/latest") # Check if we got a proper response if echo "${LATEST_INFO}" | grep -q "tag_name"; then # Extract version, handle both with and without "v" prefix DETECTED_VERSION=$(echo "${LATEST_INFO}" | grep -o '"tag_name": *"[^"]*"' | sed 's/.*: *"v\{0,1\}\([^"]*\)".*/\1/') if [ -n "${DETECTED_VERSION}" ]; then VERSION="${DETECTED_VERSION}" color_echo "green" "â Successfully retrieved latest version using GitHub API" fi else color_echo "yellow" "GitHub API query didn't return expected results. Trying alternative method..." fi fi # Second try: Parse the releases page directly if API method failed if [ "${VERSION}" = "${DEFAULT_VERSION}" ] && command_exists curl; then color_echo "blue" "Trying direct HTML parsing method..." RELEASES_PAGE=$(curl -s -L -H "User-Agent: RF-Swift-Installer" "https://github.com/${GITHUB_REPO}/releases/latest") # Look for version in the page title and URL DETECTED_VERSION=$(echo "${RELEASES_PAGE}" | grep -o "${GITHUB_REPO}/releases/tag/v[0-9][0-9.]*" | head -1 | sed 's/.*tag\/v//') if [ -n "${DETECTED_VERSION}" ]; then VERSION="${DETECTED_VERSION}" color_echo "green" "â Retrieved version ${VERSION} by parsing GitHub releases page" else # One last attempt - look for version in the title DETECTED_VERSION=$(echo "${RELEASES_PAGE}" | grep -o '