Ctrl K
ComunidadGuías…

install.sh

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/bin/sh
# unarr — cross-platform installer (Linux / macOS)
# Usage: curl -fsSL https://unarr.app/install.sh | sh
#    or: curl -fsSL https://raw.githubusercontent.com/Unarr-app/unarr-cli/main/install.sh | sh
#
# Options (env vars):
#   INSTALL_DIR=/usr/local/bin  — where to place the binary (default: /usr/local/bin or ~/.local/bin)
#   VERSION=0.5.0               — specific version (default: latest)
#   METHOD=binary|docker        — force install method (default: auto-detect)
set -e

REPO="Unarr-app/unarr-cli"
BINARY="unarr"

# ---- Colors (only if terminal) ----
if [ -t 1 ]; then
    BOLD="\033[1m"
    GREEN="\033[32m"
    YELLOW="\033[33m"
    RED="\033[31m"
    CYAN="\033[36m"
    RESET="\033[0m"
else
    BOLD="" GREEN="" YELLOW="" RED="" CYAN="" RESET=""
fi

info()  { printf "${CYAN}→${RESET} %s\n" "$1"; }
ok()    { printf "${GREEN}✓${RESET} %s\n" "$1"; }
warn()  { printf "${YELLOW}!${RESET} %s\n" "$1"; }
error() { printf "${RED}✗${RESET} %s\n" "$1" >&2; exit 1; }

# ---- Detect OS ----
detect_os() {
    OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
    case "$OS" in
        linux*)  OS="linux" ;;
        darwin*) OS="darwin" ;;
        mingw*|msys*|cygwin*) OS="windows" ;;
        *)       error "Unsupported OS: $OS. Use install.ps1 for Windows." ;;
    esac
}

# ---- Detect architecture ----
detect_arch() {
    ARCH="$(uname -m)"
    case "$ARCH" in
        x86_64|amd64)   ARCH="amd64" ;;
        aarch64|arm64)  ARCH="arm64" ;;
        *)              error "Unsupported architecture: $ARCH" ;;
    esac
}

# ---- Detect if we can write to /usr/local/bin ----
detect_install_dir() {
    if [ -n "$INSTALL_DIR" ]; then
        return
    fi

    if [ -w "/usr/local/bin" ]; then
        INSTALL_DIR="/usr/local/bin"
    elif [ -d "$HOME/.local/bin" ]; then
        INSTALL_DIR="$HOME/.local/bin"
    else
        mkdir -p "$HOME/.local/bin"
        INSTALL_DIR="$HOME/.local/bin"
    fi
}

# ---- Check if command exists ----
has() {
    command -v "$1" >/dev/null 2>&1
}

# ---- HTTP download (curl or wget) ----
download() {
    url="$1"
    output="$2"
    if has curl; then
        curl -fsSL -o "$output" "$url"
    elif has wget; then
        wget -qO "$output" "$url"
    else
        error "Neither curl nor wget found. Install one and retry."
    fi
}

# ---- Fetch text (for API) ----
fetch() {
    url="$1"
    if has curl; then
        curl -fsSL "$url"
    elif has wget; then
        wget -qO- "$url"
    fi
}

# ---- Get latest version from GitHub ----
get_latest_version() {
    if [ -n "$VERSION" ]; then
        return
    fi

    info "Checking latest version..."

    # Try GitHub API first
    response=$(fetch "https://api.github.com/repos/$REPO/releases/latest" 2>/dev/null || true)

    if [ -n "$response" ]; then
        # Parse tag_name from JSON (works without jq)
        VERSION=$(echo "$response" | grep '"tag_name"' | head -1 | sed 's/.*"tag_name"[[:space:]]*:[[:space:]]*"v\{0,1\}\([^"]*\)".*/\1/')
    fi

    if [ -z "$VERSION" ]; then
        # Fallback: follow redirect from /releases/latest
        if has curl; then
            VERSION=$(curl -fsSI "https://github.com/$REPO/releases/latest" 2>/dev/null | grep -i '^location:' | sed 's|.*/v\{0,1\}||' | tr -d '\r\n')
        fi
    fi

    if [ -z "$VERSION" ]; then
        error "Could not determine latest version. Set VERSION=x.y.z and retry."
    fi
}

# ---- Install via binary ----
install_binary() {
    get_latest_version

    # Strip leading 'v' if present
    VERSION="${VERSION#v}"

    archive="${BINARY}_${VERSION}_${OS}_${ARCH}.tar.gz"
    url="https://github.com/$REPO/releases/download/v${VERSION}/${archive}"

    info "Downloading $BINARY v$VERSION for $OS/$ARCH..."

    tmpdir=$(mktemp -d)

    download "$url" "$tmpdir/$archive"

    info "Extracting..."
    tar -xzf "$tmpdir/$archive" -C "$tmpdir"

    # Find binary (may be at root or in a subdir)
    bin_path=$(find "$tmpdir" -name "$BINARY" -type f | head -1)
    if [ -z "$bin_path" ]; then
        rm -rf "$tmpdir"
        error "Binary not found in archive"
    fi

    chmod +x "$bin_path"

    # Install
    if [ -w "$INSTALL_DIR" ]; then
        mv "$bin_path" "$INSTALL_DIR/$BINARY"
    else
        info "Requires sudo to install to $INSTALL_DIR"
        sudo mv "$bin_path" "$INSTALL_DIR/$BINARY"
    fi

    rm -rf "$tmpdir"

    ok "Installed $BINARY v$VERSION to $INSTALL_DIR/$BINARY"

    # Check PATH
    case ":$PATH:" in
        *":$INSTALL_DIR:"*) ;;
        *)
            warn "$INSTALL_DIR is not in your PATH."
            printf "    Add it with: ${BOLD}export PATH=\"%s:\$PATH\"${RESET}\n" "$INSTALL_DIR"
            ;;
    esac
}

# ---- Install via Docker ----
install_docker() {
    if ! has docker; then
        error "Docker not found. Install Docker first: https://docs.docker.com/get-docker/"
    fi

    info "Pulling unarr/cli:latest..."
    docker pull unarr/cli:latest 2>/dev/null || {
        info "Image not on Docker Hub yet, building from source..."
        tmpdir=$(mktemp -d)

        if has git; then
            git clone --depth 1 "https://github.com/$REPO.git" "$tmpdir/unarr"
            docker build -t unarr/cli:latest "$tmpdir/unarr"
            rm -rf "$tmpdir"
        else
            rm -rf "$tmpdir"
            error "git not found. Install git or pull the image manually."
        fi
    }

    ok "Docker image ready: unarr/cli:latest"

    printf "\n${BOLD}Quick start:${RESET}\n"
    cat <<'DOCKER_USAGE'

  # 1. Create config directory
  mkdir -p ~/.config/unarr

  # 2. Run setup (interactive)
  docker run -it --rm \
    -v ~/.config/unarr:/config \
    unarr/cli init

  # 3. Start daemon
  docker run -d --name unarr \
    --restart unless-stopped \
    --network host \
    --read-only \
    --memory 512m \
    -v ~/.config/unarr:/config \
    -v ~/Media:/downloads \
    unarr/cli

  # Or use the provided docker-compose.yml:
  # curl -fsSL https://raw.githubusercontent.com/Unarr-app/unarr-cli/main/docker-compose.yml > docker-compose.yml
  # docker compose up -d

DOCKER_USAGE
}

# ---- Uninstall ----
uninstall() {
    info "Uninstalling $BINARY..."

    # Remove binary
    for dir in /usr/local/bin "$HOME/.local/bin" /usr/bin; do
        if [ -f "$dir/$BINARY" ]; then
            if [ -w "$dir" ]; then
                rm -f "$dir/$BINARY"
            else
                sudo rm -f "$dir/$BINARY"
            fi
            ok "Removed $dir/$BINARY"
        fi
    done

    # Remove Docker
    if has docker; then
        docker rm -f unarr 2>/dev/null && ok "Removed Docker container 'unarr'"
        docker rmi unarr/cli:latest 2>/dev/null && ok "Removed Docker image"
    fi

    ok "Uninstalled. Config remains at ~/.config/unarr/ (delete manually if desired)."
    exit 0
}

# ---- Interactive menu ----
interactive_menu() {
    printf "\n"
    printf "  ${BOLD}unarr Installer${RESET}\n"
    printf "  ────────────────────────\n"
    printf "\n"
    printf "  Detected: ${CYAN}$OS/$ARCH${RESET}\n"
    printf "\n"
    printf "  Install method:\n"
    printf "\n"
    printf "    ${BOLD}1)${RESET} Binary — standalone executable, no dependencies\n"
    printf "    ${BOLD}2)${RESET} Docker — sandboxed, isolated filesystem access ${GREEN}(recommended)${RESET}\n"

    if [ "$OS" = "darwin" ] || has brew; then
        printf "    ${BOLD}3)${RESET} Homebrew — brew install unarr-app/tap/unarr\n"
    fi

    printf "    ${BOLD}u)${RESET} Uninstall\n"
    printf "\n"
    printf "  Choice [1/2"
    if [ "$OS" = "darwin" ] || has brew; then printf "/3"; fi
    printf "]: "

    read -r choice

    case "$choice" in
        1)      METHOD="binary" ;;
        2)      METHOD="docker" ;;
        3)
            if [ "$OS" = "darwin" ] || has brew; then
                METHOD="brew"
            else
                error "Invalid choice"
            fi
            ;;
        u|U)    uninstall ;;
        *)      error "Invalid choice: $choice" ;;
    esac
}

# ---- Main ----
main() {
    detect_os
    detect_arch
    detect_install_dir

    # Non-interactive if METHOD is set
    if [ -z "$METHOD" ]; then
        # If piped (non-interactive), default to binary
        if [ ! -t 0 ]; then
            METHOD="binary"
        else
            interactive_menu
        fi
    fi

    printf "\n"

    case "$METHOD" in
        binary)
            install_binary
            printf "\n  Run ${BOLD}unarr init${RESET} to get started.\n\n"
            ;;
        docker)
            install_docker
            ;;
        brew)
            if ! has brew; then
                error "Homebrew not found. Install it first: https://brew.sh"
            fi
            info "Installing via Homebrew..."
            brew install unarr-app/tap/unarr
            ok "Installed via Homebrew"
            printf "\n  Run ${BOLD}unarr init${RESET} to get started.\n\n"
            ;;
        *)
            error "Unknown method: $METHOD"
            ;;
    esac
}

main "$@"