#!/bin/sh # Bootstrap over HTTPS; subsequent `botme update` calls verify signed releases. # Keep this function wrapper so a truncated download cannot start installation. install_botme() { set -eu fail() { printf 'botme: %s\n' "$*" >&2; exit 1; } os=$(uname -s) arch=$(uname -m) if [ "$os" = Darwin ] && [ "$(sysctl -n hw.optional.arm64 2>/dev/null || true)" = 1 ]; then arch=arm64 fi case "$os/$arch" in Darwin/arm64|Darwin/aarch64) target=aarch64-apple-darwin ;; Linux/x86_64) target=x86_64-unknown-linux-musl ;; Linux/aarch64|Linux/arm64) target=aarch64-unknown-linux-musl ;; *) fail "No build is available for $os/$arch." ;; esac destination="$HOME/.local/bin" existing=$(command -v botme || true) case "$existing" in ""|"$destination/botme") ;; *) fail "botme already exists at $existing. Update or remove that installation first." ;; esac workdir=$(mktemp -d) staged="" trap 'rm -rf "$workdir"; [ -z "$staged" ] || rm -rf "$staged"' EXIT trap 'exit 130' INT trap 'exit 143' TERM cd "$workdir" fetch() { curl --proto '=https' --tlsv1.2 -fsSL --connect-timeout 15 --max-time 120 "$1" -o "$2"; } base=https://get.bot.me/cli fetch "$base/stable/latest.json" envelope.json # Read only the base64 record and numeric version from our release format. # Never evaluate manifest text as shell code; all download paths are fixed. record=$(sed -n 's/.*"record"[[:space:]]*:[[:space:]]*"\([A-Za-z0-9+/=]*\)".*/\1/p' envelope.json) [ -n "$record" ] || fail 'The release manifest has no record.' printf '%s' "$record" | base64 -d > record.json version=$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)".*/\1/p' record.json) case "$version" in ""|*[!0-9.]*) fail 'The release version is invalid.' ;; esac name="botme-$target.tar.gz" fetch "$base/v$version/SHA256SUMS" SHA256SUMS hash=$(awk -v name="$name" '$2 == name { print $1 }' SHA256SUMS) [ "${#hash}" = 64 ] || fail 'The release checksum is missing or invalid.' case "$hash" in *[!a-f0-9]*) fail 'The release checksum is invalid.' ;; esac printf 'Installing botme %s (%s)…\n' "$version" "$target" fetch "$base/v$version/$name" "$name" if [ "$os" = Darwin ]; then printf '%s %s\n' "$hash" "$name" | shasum -a 256 -c - else printf '%s %s\n' "$hash" "$name" | sha256sum -c - fi tar -xzf "$name" botme [ -f botme ] && [ ! -L botme ] || fail 'The archive does not contain a regular botme executable.' mkdir -p "$destination" staged=$(mktemp -d "$destination/.botme.XXXXXX") install -m 755 botme "$staged/botme" mv -f "$staged/botme" "$destination/botme" "$destination/botme" --version # Only configure the user's chosen shell; an opt-out supports managed setups. if [ "${BOTME_NO_MODIFY_PATH:-0}" != 1 ]; then # Preserve variables for expansion by the user's next shell. # shellcheck disable=SC2016 line='case ":$PATH:" in *":$HOME/.local/bin:"*) ;; *) export PATH="$HOME/.local/bin:$PATH" ;; esac' add_path() { mkdir -p "$(dirname "$1")" if ! grep -Fqx "$line" "$1" 2>/dev/null; then printf '\n# Bot.Me CLI\n%s\n' "$line" >> "$1" printf 'Added ~/.local/bin to PATH in %s\n' "$1" fi } case "${SHELL:-}" in */zsh|zsh) add_path "${ZDOTDIR:-$HOME}/.zshrc" ;; */bash|bash) add_path "$HOME/.bashrc" profile="$HOME/.profile" [ ! -f "$HOME/.bash_login" ] || profile="$HOME/.bash_login" [ ! -f "$HOME/.bash_profile" ] || profile="$HOME/.bash_profile" add_path "$profile" ;; */fish|fish) # shellcheck disable=SC2016 line='fish_add_path --path "$HOME/.local/bin"' add_path "${XDG_CONFIG_HOME:-$HOME/.config}/fish/conf.d/botme.fish" ;; *) printf 'Add %s to PATH in your shell configuration.\n' "$destination" ;; esac fi printf '\nInstalled to %s/botme\n' "$destination" case ":$PATH:" in *":$destination:"*) printf 'Run: botme --help\n' ;; *) printf 'Open a new terminal, or use: %s/botme --help\n' "$destination" ;; esac } install_botme