#!/usr/bin/env bash # ═══════════════════════════════════════════════════════════════════════════ # GyanDoot v2.0 — Cross-Platform Universal Installer # ═══════════════════════════════════════════════════════════════════════════ # # Detects: macOS (arm64/x86_64), Linux (x86_64/aarch64/i686), # WSL (Windows Subsystem for Linux), Windows (Git Bash/MSYS2) # # Usage: # curl -fsSL https://git.gyannetra.in/gnpl_admin/gyandoot-release/raw/main/install.sh | bash # # Or locally: # ./install.sh # ═══════════════════════════════════════════════════════════════════════════ set -euo pipefail # ─── Colors ────────────────────────────────────────────────────────────── GREEN='\033[0;32m' BLUE='\033[0;34m' YELLOW='\033[1;33m' RED='\033[0;31m' CYAN='\033[0;36m' NC='\033[0m' info() { echo -e "${BLUE}[INFO]${NC} $*"; } ok() { echo -e "${GREEN}[OK]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } err() { echo -e "${RED}[ERR]${NC} $*" >&2; exit 1; } banner() { echo -e "${CYAN}" echo ' ______ __ _ _ _ ____ ___ ___ _____ ' echo ' / ___\ \ / // \ | \ | | _ \ / _ \ / _ \_ _|' echo '| | _ \ V // _ \ | \| | | | | | | | | | || | ' echo '| |_| | | |/ ___ \| |\ | |_| | |_| | |_| || | ' echo ' \____| |_/_/ \_\_| \_|____/ \___/ \___/ |_| ' echo -e "${NC}" echo -e "${GREEN} GyanDoot v2.0 — Knowledge Messenger${NC}" echo " Cross-Platform Universal Installer" echo "" } # ─── Platform Detection ────────────────────────────────────────────────── detect_architecture() { local arch arch="$(uname -m)" case "$arch" in x86_64|amd64) echo "x86_64" ;; aarch64|arm64) echo "aarch64" ;; i686|i386) echo "i686" ;; *) err "Unsupported architecture: $arch" ;; esac } detect_os() { local os os="$(uname -s)" case "$os" in Linux) echo "linux" ;; Darwin) echo "darwin" ;; CYGWIN*|MINGW*|MSYS*) echo "windows" ;; *) err "Unsupported OS: $os" ;; esac } detect_wsl() { if [ -f /proc/version ] && grep -qiE 'microsoft|wsl' /proc/version 2>/dev/null; then return 0 fi return 1 } get_shell_profile() { case "$SHELL" in */zsh) echo "$HOME/.zshrc" ;; */bash) echo "$HOME/.bashrc" ;; */fish) echo "$HOME/.config/fish/config.fish" ;; *) echo "$HOME/.profile" ;; esac } # ─── Dependency Installers ─────────────────────────────────────────────── install_rust_if_needed() { if ! command -v cargo &>/dev/null; then info "Rust toolchain not found. Installing..." if [ "$(uname -s)" = "Darwin" ] || [ "$(uname -s)" = "Linux" ]; then curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y source "$HOME/.cargo/env" elif [[ "$(uname -s)" =~ ^(CYGWIN|MINGW|MSYS) ]]; then # Windows: download rustup-init.exe powershell -Command "& {Invoke-WebRequest -Uri https://win.rustup.rs -OutFile '%TEMP%\rustup-init.exe'; Start-Process '%TEMP%\rustup-init.exe' -Wait -ArgumentList '-y'}" export PATH="$PATH:$HOME/.cargo/bin" else err "No Rust install method for this platform" fi ok "Rust installed ($(cargo --version))" else ok "Rust already installed ($(cargo --version))" fi } install_node_if_needed() { if ! command -v node &>/dev/null; then info "Node.js not found. Installing..." if command -v nvm &>/dev/null || [ -s "$HOME/.nvm/nvm.sh" ]; then [ -s "$HOME/.nvm/nvm.sh" ] && \. "$HOME/.nvm/nvm.sh" nvm install 22 2>/dev/null || nvm install node elif [ "$(uname -s)" = "Darwin" ]; then if command -v brew &>/dev/null; then brew install node else warn "Install Node.js manually: https://nodejs.org" fi elif [[ "$(uname -s)" =~ ^(CYGWIN|MINGW|MSYS) ]]; then warn "Install Node.js from: https://nodejs.org" else # Linux: use nvm curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash [ -s "$HOME/.nvm/nvm.sh" ] && \. "$HOME/.nvm/nvm.sh" nvm install 22 fi ok "Node.js installed ($(node --version))" else ok "Node.js already installed ($(node --version))" fi # Ensure npx is available if ! command -v npx &>/dev/null; then warn "npx not found. Installing corepack..." npm install -g npx 2>/dev/null || true fi } # ─── Linux System Dependencies ─────────────────────────────────────────── # Camoufox (Playwright-based) needs these on Linux/WSL CAMOUFOX_LINUX_DEPS=( libgtk-3-0 libnss3 libnspr4 libatk1.0-0t64 libatk-bridge2.0-0t64 libcups2t64 libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libpango-1.0-0 libcairo2 libasound2t64 libxcb-shm0 libx11-xcb1 libx11-6 libxcb1 libxext6 libxcursor1 libxi6 libfreetype6 libfontconfig1 libxshmfence1 libxrender1 libdbus-1-3 ) install_linux_deps() { if [ "$(uname -s)" != "Linux" ]; then return 0 fi if detect_wsl; then info "WSL detected. Installing Linux system dependencies..." fi local missing=() if command -v dpkg-query &>/dev/null; then for pkg in "${CAMOUFOX_LINUX_DEPS[@]}"; do if ! dpkg-query -W -f='${Status}' "$pkg" 2>/dev/null | grep -q "install ok installed"; then local alt_pkg="${pkg%t64}" if [ "$alt_pkg" != "$pkg" ] && dpkg-query -W -f='${Status}' "$alt_pkg" 2>/dev/null | grep -q "install ok installed"; then continue fi missing+=("$pkg") fi done else missing=("${CAMOUFOX_LINUX_DEPS[@]}") fi if [ ${#missing[@]} -eq 0 ]; then info "All Linux system dependencies already installed" return 0 fi info "Installing ${#missing[@]} missing Linux system dependencies..." if command -v apt-get &>/dev/null; then if command -v sudo &>/dev/null; then sudo apt-get update -qq 2>/dev/null || true sudo apt-get install -y -qq "${missing[@]}" 2>/dev/null || { warn "Some packages failed. Retrying with fix..." sudo apt-get --fix-broken install -y -qq 2>/dev/null || true local fallback=() for pkg in "${missing[@]}"; do local alt="${pkg%t64}" [ "$alt" != "$pkg" ] && fallback+=("$alt") done [ ${#fallback[@]} -gt 0 ] && sudo apt-get install -y -qq "${fallback[@]}" 2>/dev/null || true } else apt-get update -qq 2>/dev/null || true apt-get install -y -qq "${missing[@]}" 2>/dev/null || true fi ok "Linux system dependencies installed" elif command -v dnf &>/dev/null; then sudo dnf install -y nss nspr atk at-spi2-atk cups-libs \ libdrm libXcomposite libXdamage libXrandr mesa-libgbm \ pango alsa-lib libxkbcommon libxcb libX11-xcb libX11 \ libXext libXcursor libXfixes libXi gtk3 cairo-gobject 2>/dev/null || true ok "Linux system dependencies installed" elif command -v yum &>/dev/null; then sudo yum install -y nss nspr atk at-spi2-atk cups-libs \ libdrm libXcomposite libXdamage libXrandr mesa-libgbm \ pango alsa-lib libxkbcommon 2>/dev/null || true ok "Linux system dependencies installed" else warn "No supported package manager. Install deps manually." warn "Required: ${CAMOUFOX_LINUX_DEPS[*]}" fi } # ─── Camoufox Browser Installer ────────────────────────────────────────── install_camoufox_browser() { info "Installing Camoufox browser (anti-detection engine)..." install_linux_deps if ! command -v npx &>/dev/null && ! command -v npm &>/dev/null; then warn "Node.js not found. Skipping Camoufox install." warn "Install Node.js and re-run: npm install -g camoufox-browser@0.1.0" return 0 fi # Step 1: Install npm package info "Installing npm package (camoufox-browser@0.1.0)..." npm install -g camoufox-browser@0.1.0 2>&1 | tail -3 || { warn "npm install failed. Try manually: npm install -g camoufox-browser@0.1.0" return 0 } # Step 2: Download browser binary info "Downloading Camoufox browser binary (~311MB)..." npx --yes camoufox-js@0.11.0 fetch 2>&1 || { warn "Download failed. Try manually: npx --yes camoufox-js@0.11.0 fetch" return 0 } # Step 3: macOS — remove Gatekeeper quarantine if [ "$(uname -s)" = "Darwin" ]; then if command -v xattr &>/dev/null; then info "Removing macOS quarantine from Camoufox..." xattr -dr com.apple.quarantine ~/Library/Caches/camoufox 2>/dev/null || true fi fi # Step 4: Verify local cache_dir if [ "$(uname -s)" = "Darwin" ]; then cache_dir="$HOME/Library/Caches/camoufox" else cache_dir="$HOME/.cache/camoufox" fi if [ -f "$cache_dir/version.json" ]; then ok "Camoufox browser installed ($(du -sh "$cache_dir" 2>/dev/null | cut -f1))" else warn "Browser binary not found. Run manually: npx --yes camoufox-js@0.11.0 fetch" fi } # ─── Build GyanDoot ────────────────────────────────────────────────────── build_gyandoot() { local root_dir root_dir="$(cd "$(dirname "$0")" 2>/dev/null && pwd || echo "$PWD")" # Find workspace root (where Cargo.toml with [workspace] is) cd "$root_dir" while [ "$PWD" != "/" ]; do if [ -f "Cargo.toml" ] && grep -q '\[workspace\]' Cargo.toml 2>/dev/null; then info "Found workspace root at $PWD" break fi cd .. done if [ "$PWD" = "/" ]; then err "Could not find Cargo workspace. Make sure you're in the gyandoot-v2 directory." fi info "Building GyanDoot v2.0 (release mode)..." cargo build --release 2>&1 | tail -5 ok "Build complete ($(du -sh target/release/gyandoot* 2>/dev/null | cut -f1))" } # ─── Install Binary ────────────────────────────────────────────────────── install_binary() { local target_dir="$PWD/target/release" local bin_name="gyandoot" if [ -f "$target_dir/gyandoot.exe" ]; then bin_name="gyandoot.exe" fi if [ ! -f "$target_dir/$bin_name" ]; then err "Binary not found at $target_dir/$bin_name" fi local os os="$(uname -s)" local install_dir="" local installed_to="" case "$os" in Darwin|Linux) # Priority: ~/.cargo/bin/ → /usr/local/bin → ~/.local/bin/ if [ -d "$HOME/.cargo/bin" ] && echo "$PATH" | grep -q "$HOME/.cargo/bin"; then install_dir="$HOME/.cargo/bin" elif [ -d "/usr/local/bin" ]; then if [ -w "/usr/local/bin" ]; then install_dir="/usr/local/bin" else info "Need sudo to install to /usr/local/bin" sudo cp "$target_dir/$bin_name" "/usr/local/bin/$bin_name" sudo chmod +x "/usr/local/bin/$bin_name" install_dir="/usr/local/bin" fi elif [ -d "$HOME/.local/bin" ] && echo "$PATH" | grep -q "$HOME/.local/bin"; then install_dir="$HOME/.local/bin" else mkdir -p "$HOME/.cargo/bin" install_dir="$HOME/.cargo/bin" if ! echo "$PATH" | grep -q "$HOME/.cargo/bin"; then warn "Add ~/.cargo/bin to your PATH in $(get_shell_profile):" echo " export PATH=\"\$HOME/.cargo/bin:\$PATH\"" fi fi if [ -n "$install_dir" ]; then cp "$target_dir/$bin_name" "$install_dir/$bin_name" chmod +x "$install_dir/$bin_name" installed_to="$install_dir/$bin_name" fi ;; CYGWIN*|MINGW*|MSYS*) install_dir="/usr/local/bin" cp "$target_dir/$bin_name" "$install_dir/$bin_name" chmod +x "$install_dir/$bin_name" installed_to="$install_dir/$bin_name" ;; *) err "Unsupported OS: $os" ;; esac ok "Installed to $installed_to" # ── Verify PATH resolution ────────────────────────────────────────── local cmd_path cmd_path="$(command -v gyandoot 2>/dev/null || true)" if [ -z "$cmd_path" ]; then warn "'gyandoot' not found in PATH. Use: $installed_to" elif [ "$cmd_path" != "$installed_to" ]; then warn "OLD binary at '$cmd_path' takes priority over '$installed_to'." warn "Remove old: sudo rm $cmd_path || rm $cmd_path" warn "Then 'gyandoot run' will use the new version." else ok "'gyandoot' resolves to the newly installed binary." fi } # ─── Post-Install Summary ──────────────────────────────────────────────── print_post_install() { echo "" ok "GyanDoot v2.0 installed successfully!" echo "" echo "╔═══════════════════════════════════════════════════════════╗" echo "║ Quick Start ║" echo "╠═══════════════════════════════════════════════════════════╣" echo "║ gyandoot --help Show all commands ║" echo "║ gyandoot setup Interactive config wizard ║" echo "║ gyandoot run Start interactive agent ║" echo "╠═══════════════════════════════════════════════════════════╣" echo "║ Browser Tools (anti-detection): ║" echo "║ gyandoot browser health Check Camoufox status ║" echo "║ gyandoot browser search Search the web ║" echo "║ gyandoot browser browse Visit a website ║" echo "╠═══════════════════════════════════════════════════════════╣" echo "║ Service Management: ║" echo "║ gyandoot service install Auto-start on boot ║" echo "║ gyandoot service status Check service status ║" echo "╚═══════════════════════════════════════════════════════════╝" echo "" if [ "$(uname -s)" = "Darwin" ]; then echo " 🍎 macOS — Camoufox Gatekeeper (one-time):" echo " xattr -dr com.apple.quarantine ~/Library/Caches/camoufox" echo "" fi if detect_wsl; then echo " ⚠️ WSL detected — Node.js must be installed INSIDE WSL." echo " (The Windows-side Node.js is not accessible from WSL.)" echo "" fi } # ─── Service Installation Prompt ───────────────────────────────────────── prompt_service_install() { echo "────────────────────────────────────────────" echo " Optional: Auto-start GyanDoot on Boot?" echo "────────────────────────────────────────────" echo " GyanDoot can run as a system service and" echo " start automatically when your computer boots." echo "" echo " (You can also do this later: gyandoot service install)" echo "" read -r -p " Install system service? [y/N]: " response case "$response" in [yY]|[yY][eE][sS]) info "Installing GyanDoot system service..." gyandoot service install 2>&1 || warn "Service install failed (run later: gyandoot service install)" ;; *) info "Skipping service install" ;; esac } # ═══════════════════════════════════════════════════════════════════════════ # MAIN # ═══════════════════════════════════════════════════════════════════════════ main() { banner local os arch os=$(detect_os) arch=$(detect_architecture) info "Detected: $os / $arch" if detect_wsl; then info "WSL (Windows Subsystem for Linux) detected" fi # ── Install dependencies ─────────────────────────────────────────── info "Phase 1: Checking prerequisites..." install_rust_if_needed install_node_if_needed # ── Install Camoufox browser ─────────────────────────────────────── info "Phase 2: Installing Camoufox browser..." install_camoufox_browser # ── Build from source ────────────────────────────────────────────── info "Phase 3: Building GyanDoot..." build_gyandoot # ── Install binary ───────────────────────────────────────────────── info "Phase 4: Installing binary..." install_binary # ── Optional: system service ─────────────────────────────────────── info "Phase 5: Service setup..." prompt_service_install # ── Done ─────────────────────────────────────────────────────────── print_post_install } main "$@"