#!/usr/bin/env bash # # qlpycon installer # Usage: # pipe2bash: # curl -sSL https://6bit.ch/qlpycon/install.sh | bash # # local: # mkdir qlpycon # cd qlpycon # chmod u+x install.sh # ./install.sh # # or run directly from cloned repo: # git clone https://git.6bit.ch/xbl/qlpycon.git # cd qlpycon # chmod u+x install.sh # ./install.sh # set -e TAR_URL="https://6bit.ch/qlpycon.tar.gz" BIN_DIR="$HOME/.local/bin" BIN_PATH="$BIN_DIR/qlpycon" # === Colors ===> RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' MAGENTA='\033[0;35m' NC='\033[0m' info() { echo -e "${CYAN} o_o [INFO]${NC} $*"; } success() { echo -e "${GREEN} ^_^ [SUCCESS]${NC} $*"; } warn() { echo -e "${YELLOW} >_< [WARN]${NC} $*"; } die() { echo -e "${RED} x_x [ERROR]${NC} $*" >&2; exit 1; } # === Checks ===> check_dependencies() { info "Checking dependencies..." command -v python3 >/dev/null 2>&1 || die "python3 is required but not installed" # Check Python version >= 3.9 python3 -c " import sys if sys.version_info < (3, 9): print('Python 3.9+ required, found ' + sys.version) sys.exit(1) " || die "Python 3.9 or higher is required" command -v pip3 >/dev/null 2>&1 || \ python3 -m pip --version >/dev/null 2>&1 || \ die "pip is required but not installed" success "Dependencies OK" } # === Source detection ===> detect_source() { if [[ -f "./main.py" && -d "./lib" ]]; then echo "repo" else echo "download" fi } # === Download ===> download_and_extract() { info "Downloading to temp and extracting to $INSTALL_DIR..." mkdir -p "$INSTALL_DIR" TMP_TAR=$(mktemp) if command -v curl >/dev/null 2>&1; then curl -sSL "$TAR_URL" -o "$TMP_TAR" || die "Download failed" else wget -qO "$TMP_TAR" "$TAR_URL" || die "Download failed" fi if ! file "$TMP_TAR" | grep -q 'gzip'; then rm -f "$TMP_TAR" die "Download failed or URL returned invalid content" fi # Preserve existing config if updating if [[ -f "$INSTALL_DIR/qlpycon.conf" ]]; then warn "Existing qlpycon.conf found - keeping it" tar -xzf "$TMP_TAR" -C "$INSTALL_DIR" --exclude='qlpycon.conf' || die "Extraction failed" else tar -xzf "$TMP_TAR" -C "$INSTALL_DIR" || die "Extraction failed" fi rm -f "$TMP_TAR" success "Extracted to $INSTALL_DIR" } # === Venv ===> setup_venv() { info "Setting up Python virtual environment..." if [[ ! -d "$INSTALL_DIR/venv" ]] || [[ ! -f "$INSTALL_DIR/venv/bin/pip" ]]; then python3 -m venv "$INSTALL_DIR/venv" || die "Failed to create venv" else warn "venv already exists - skipping creation" fi info "Installing pip" "$INSTALL_DIR/venv/bin/pip" install --quiet --upgrade pip info "Installing pyzmq via pip" "$INSTALL_DIR/venv/bin/pip" install --quiet pyzmq success "Virtual environment ready" } # === Launcher ===> write_launcher() { info "Writing launcher to $BIN_PATH..." mkdir -p "$BIN_DIR" echo "BIN_PATH is: $BIN_PATH" cat > "$BIN_PATH" << EOF #!/usr/bin/env bash # qlpycon launcher — generated by install.sh QLPYCON_DIR="$INSTALL_DIR" if [[ ! -d "\$QLPYCON_DIR" ]]; then echo "Error: qlpycon directory not found: \$QLPYCON_DIR" echo "Re-run install.sh or cry :(" exit 1 fi cd "\$QLPYCON_DIR" source "\$QLPYCON_DIR/venv/bin/activate" exec python3 main.py "\$@" EOF chmod +x "$BIN_PATH" success "Launcher written to $BIN_PATH" } # === PATH check ===> check_path() { info "Checking \$PATH..." if [[ ":$PATH:" != *":$BIN_DIR:"* ]]; then warn "$BIN_DIR is not in your PATH." echo "" echo " Add this to your ~/.bashrc or ~/.zshrc:" echo " export PATH=\"\$HOME/.local/bin:\$PATH\"" echo "" else success "\$PATH is superfine" fi } # === Config ===> setup_config() { if [[ ! -f "$INSTALL_DIR/qlpycon.conf" ]]; then if [[ -f "$INSTALL_DIR/qlpycon.conf.example" ]]; then cp "$INSTALL_DIR/qlpycon.conf.example" "$INSTALL_DIR/qlpycon.conf" success "Created $INSTALL_DIR/qlpycon.conf from example" fi fi } # === Main ===> main() { print_banner() { cat <<'EOF' _/ _/_/_/ _/ _/_/_/ _/ _/ _/_/_/ _/_/ _/_/_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/_/_/ _/ _/_/_/ _/_/_/ _/_/_/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/_/ EOF } if command -v lolcat >/dev/null 2>&1 && [[ ${LOLCAT:-1} -eq 1 ]]; then { print_banner echo echo " qlpycon installer" } | lolcat - else echo -e "${MAGENTA}" print_banner echo -e "${NC}" echo -e "${CYAN} qlpycon installer${NC}" fi echo check_dependencies SOURCE=$(detect_source) if [[ "$SOURCE" == "repo" ]]; then INSTALL_DIR="$(pwd)" info "Running from cloned repo - using $INSTALL_DIR" else DEFAULT_DIR="$HOME/.local/share/qlpycon" read -p "Install directory [$DEFAULT_DIR]: " USER_DIR