512 lines
21 KiB
Bash
Executable File
512 lines
21 KiB
Bash
Executable File
#!/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} $*" >&2; }
|
|
ok() { echo -e "${GREEN}[OK]${NC} $*" >&2; }
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $*" >&2; }
|
|
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 or Download GyanDoot ───────────────────────────────────────────
|
|
# In the source repo (gyandoot-v2): builds from Cargo workspace
|
|
# In the release repo (gyandoot-release): uses prebuilt binary
|
|
ensure_gyandoot_binary() {
|
|
local root_dir
|
|
root_dir="$(cd "$(dirname "$0")" 2>/dev/null && pwd || echo "$PWD")"
|
|
cd "$root_dir"
|
|
|
|
# Check 1: Is there a Cargo workspace? → Build from source
|
|
local probe="$root_dir"
|
|
while [ "$probe" != "/" ]; do
|
|
if [ -f "$probe/Cargo.toml" ] && grep -q '\[workspace\]' "$probe/Cargo.toml" 2>/dev/null; then
|
|
info "Source code found — building GyanDoot from source..."
|
|
cd "$probe"
|
|
cargo build --release 2>&1 | tail -5
|
|
ok "Build complete"
|
|
echo "$probe/target/release/gyandoot"
|
|
return 0
|
|
fi
|
|
probe="$(dirname "$probe")"
|
|
done
|
|
|
|
# Check 2: Is there a prebuilt binary in the linux/ directory?
|
|
local os
|
|
os="$(uname -s)"
|
|
local arch
|
|
arch="$(uname -m)"
|
|
|
|
# Map platform names
|
|
local os_dir
|
|
case "$os" in
|
|
Darwin) os_dir="macos" ;;
|
|
Linux) os_dir="linux" ;;
|
|
CYGWIN*|MINGW*|MSYS*) os_dir="windows" ;;
|
|
*) err "Unsupported OS: $os" ;;
|
|
esac
|
|
|
|
local prebuilt="$root_dir/$os_dir/gyandoot"
|
|
if [ -f "$prebuilt" ]; then
|
|
info "Prebuilt binary found at $prebuilt"
|
|
echo "$prebuilt"
|
|
return 0
|
|
fi
|
|
|
|
# Check 3: Download from source repo (clone and build)
|
|
info "No prebuilt binary found for $os/$arch"
|
|
info "Cloning source repository to build from scratch..."
|
|
local clone_dir
|
|
clone_dir="$(mktemp -d 2>/dev/null || echo "/tmp/gyandoot-build-$$")"
|
|
|
|
if command -v git &>/dev/null; then
|
|
git clone --depth=1 https://git.gyannetra.in/gnpl_admin/gyandoot-v2.git "$clone_dir" 2>&1 | tail -5 >&2
|
|
cd "$clone_dir"
|
|
cargo build --release 2>&1 | tail -5 >&2
|
|
if [ -f "target/release/gyandoot" ]; then
|
|
ok "Built from source"
|
|
echo "$clone_dir/target/release/gyandoot"
|
|
return 0
|
|
fi
|
|
if [ -f "target/release/gyandoot.exe" ]; then
|
|
ok "Built from source"
|
|
echo "$clone_dir/target/release/gyandoot.exe"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
err "Could not find or build GyanDoot binary.
|
|
1. Clone the source repo: git clone https://git.gyannetra.in/gnpl_admin/gyandoot-v2.git
|
|
2. cd gyandoot-v2 && cargo build --release
|
|
3. Then run: ./target/release/gyandoot"
|
|
}
|
|
|
|
# ─── Install Binary ──────────────────────────────────────────────────────
|
|
install_binary() {
|
|
local binary_path="$1"
|
|
local bin_name
|
|
|
|
if [ -z "$binary_path" ]; then
|
|
err "No binary path provided to install_binary"
|
|
fi
|
|
|
|
if [ ! -f "$binary_path" ]; then
|
|
err "Binary not found at $binary_path"
|
|
fi
|
|
|
|
bin_name="$(basename "$binary_path")"
|
|
|
|
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 "$binary_path" "/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 "$binary_path" "$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 "$binary_path" "$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 or download binary ─────────────────────────────────────
|
|
info "Phase 3: Preparing GyanDoot binary..."
|
|
local gyandoot_binary
|
|
gyandoot_binary="$(ensure_gyandoot_binary)"
|
|
ok "Binary ready: $gyandoot_binary ($(du -sh "$gyandoot_binary" 2>/dev/null | cut -f1))"
|
|
|
|
# ── Install binary ────────────────────────────────────────────────
|
|
info "Phase 4: Installing binary..."
|
|
install_binary "$gyandoot_binary"
|
|
|
|
# ── Optional: system service ───────────────────────────────────────
|
|
info "Phase 5: Service setup..."
|
|
prompt_service_install
|
|
|
|
# ── Done ───────────────────────────────────────────────────────────
|
|
print_post_install
|
|
}
|
|
|
|
main "$@" |