#!/usr/bin/env bash set -o pipefail # ============================================================ # HASTEBIN # ============================================================ UPLOAD_URL="https://pste.us/documents" BASE_URL="https://pste.us" # Catppuccin Mocha palette BLUE="\033[38;2;137;180;250m" CYAN="\033[38;2;137;220;235m" GREEN="\033[38;2;166;227;161m" MAUVE="\033[38;2;203;166;247m" PINK="\033[38;2;245;194;231m" RED="\033[38;2;243;139;168m" YELLOW="\033[38;2;249;226;175m" TEXT="\033[38;2;205;214;244m" SUBTEXT="\033[38;2;166;173;200m" DIM="\033[38;2;108;112;134m" RESET="\033[0m" TMP_RESPONSE="" TMP_PROGRESS="" # ------------------------------------------------------------ # Cleanup # ------------------------------------------------------------ cleanup() { [[ -n "$TMP_RESPONSE" && -f "$TMP_RESPONSE" ]] && rm -f "$TMP_RESPONSE" [[ -n "$TMP_PROGRESS" && -f "$TMP_PROGRESS" ]] && rm -f "$TMP_PROGRESS" } trap cleanup EXIT trap 'exit 130' INT TERM # ------------------------------------------------------------ # Error # ------------------------------------------------------------ die() { echo printf " ${RED}✗${RESET} ${TEXT}%s${RESET}\n" "$1" echo exit 1 } # ------------------------------------------------------------ # Dependencies # ------------------------------------------------------------ for cmd in curl jq gum fzf; do command -v "$cmd" &>/dev/null || die "Missing dependency: $cmd" done # ------------------------------------------------------------ # Arguments # ------------------------------------------------------------ FILE_PATH="${1:-}" case "$FILE_PATH" in -h|--help) cat <<'EOF' Usage: hastebin hastebin Upload a file to pste.us and copy the resulting URL. EOF exit 0 ;; esac # ------------------------------------------------------------ # Select file # ------------------------------------------------------------ if [[ -z "$FILE_PATH" ]]; then FILE_PATH=$( find . -maxdepth 1 -type f -printf '%f\n' | fzf \ --prompt=" 󰈔 " \ --border=rounded \ --border-label=" hastebin " \ --border-label-pos=2 \ --reverse \ --header=" ↑↓ navigate • enter select • esc cancel " \ --pointer="▸" \ --marker="◆" \ --color="bg+:#313244,bg:#11111b,spinner:#f5c2e7,hl:#f38ba8,fg:#cdd6f4,header:#7f849c,pointer:#a6e3a1,marker:#f5c2e7,fg+:#cdd6f4,prompt:#89b4fa,hl+:#f38a8a,border:#585b70" \ --preview='bat --style=numbers --color=always --line-range=:80 {}' \ --preview-window='right:55%:wrap' ) [[ -n "$FILE_PATH" ]] || exit 0 fi # ------------------------------------------------------------ # Validate # ------------------------------------------------------------ [[ -f "$FILE_PATH" ]] || die "File does not exist: $FILE_PATH" [[ -r "$FILE_PATH" ]] || die "File is not readable: $FILE_PATH" # ------------------------------------------------------------ # File info # ------------------------------------------------------------ FILE_NAME="$(basename "$FILE_PATH")" FILE_BYTES=$(stat -c%s "$FILE_PATH" 2>/dev/null || stat -f%z "$FILE_PATH" 2>/dev/null || echo 0) if command -v numfmt &>/dev/null; then FILE_SIZE=$(numfmt --to=iec --suffix=B "$FILE_BYTES") else FILE_SIZE=$(du -h "$FILE_PATH" | cut -f1) fi FILE_TYPE=$(file -b "$FILE_PATH" 2>/dev/null || echo "Unknown") FILE_TYPE="${FILE_TYPE%%,*}" # Keep the type short if (( ${#FILE_TYPE} > 35 )); then FILE_TYPE="${FILE_TYPE:0:32}..." fi # ------------------------------------------------------------ # Temporary files # ------------------------------------------------------------ TMP_RESPONSE=$(mktemp) TMP_PROGRESS=$(mktemp) # ------------------------------------------------------------ # Header # ------------------------------------------------------------ clear echo printf " ${MAUVE}◆${RESET} ${TEXT}Hastebin${RESET} ${DIM}·${RESET} ${SUBTEXT}secure little file sharing${RESET}\n" echo printf " ${DIM}────────────────────────────────────────────────────────${RESET}\n" printf " ${BLUE}󰈔${RESET} ${TEXT}%s${RESET}\n" "$FILE_NAME" printf " ${DIM}size${RESET} ${SUBTEXT}%s${RESET} ${DIM}type${RESET} ${SUBTEXT}%s${RESET}\n" \ "$FILE_SIZE" \ "$FILE_TYPE" printf " ${DIM}────────────────────────────────────────────────────────${RESET}\n" echo # ------------------------------------------------------------ # Upload indicator # ------------------------------------------------------------ printf " ${CYAN}󰑓${RESET} ${TEXT}Uploading${RESET} " # Small animated dots ( while true; do printf "${DIM}.${RESET}" sleep 0.25 printf "\b \b" printf "${DIM}..${RESET}" sleep 0.25 printf "\b\b \b\b" printf "${DIM}...${RESET}" sleep 0.25 printf "\b\b\b \b\b\b" done ) & SPINNER_PID=$! # ------------------------------------------------------------ # Upload # ------------------------------------------------------------ curl \ -fS \ --progress-bar \ -X POST \ -H "Content-Type: text/plain" \ --data-binary @"$FILE_PATH" \ "$UPLOAD_URL" \ >"$TMP_RESPONSE" \ 2>"$TMP_PROGRESS" & CURL_PID=$! wait "$CURL_PID" CURL_STATUS=$? kill "$SPINNER_PID" 2>/dev/null wait "$SPINNER_PID" 2>/dev/null printf "\r\033[2K" # ------------------------------------------------------------ # Upload failed # ------------------------------------------------------------ if [[ "$CURL_STATUS" -ne 0 ]]; then printf " ${RED}✗${RESET} ${TEXT}Upload failed.${RESET}\n" echo exit 1 fi # ------------------------------------------------------------ # Parse response # ------------------------------------------------------------ HASTE_KEY=$(jq -r '.key // empty' "$TMP_RESPONSE" 2>/dev/null) [[ -n "$HASTE_KEY" ]] || die "Server returned an invalid response." URL="$BASE_URL/$HASTE_KEY" # ------------------------------------------------------------ # Clipboard # ------------------------------------------------------------ COPIED=false if command -v wl-copy &>/dev/null; then printf '%s' "$URL" | wl-copy COPIED=true elif command -v xclip &>/dev/null; then printf '%s' "$URL" | xclip -selection clipboard COPIED=true elif command -v xsel &>/dev/null; then printf '%s' "$URL" | xsel --clipboard --input COPIED=true elif command -v pbcopy &>/dev/null; then printf '%s' "$URL" | pbcopy COPIED=true fi # ------------------------------------------------------------ # Generate QR # ------------------------------------------------------------ QR="" if command -v qrencode &>/dev/null; then QR=$( qrencode \ -t ANSIUTF8 \ -m 0 \ -l M \ "$URL" ) fi # ------------------------------------------------------------ # Result # ------------------------------------------------------------ echo printf " ${GREEN}╭─${RESET} ${GREEN}✓${RESET} ${TEXT}Uploaded${RESET} ${GREEN}──────────────────────────────────────╮${RESET}\n" printf " ${GREEN}│${RESET} ${GREEN}│${RESET}\n" printf " ${GREEN}│${RESET} ${DIM}FILE${RESET} ${TEXT}%s${RESET}\n" "$FILE_NAME" printf " ${GREEN}│${RESET} ${DIM}SIZE${RESET} ${TEXT}%s${RESET}\n" "$FILE_SIZE" printf " ${GREEN}│${RESET} ${DIM}TYPE${RESET} ${TEXT}%s${RESET}\n" "$FILE_TYPE" printf " ${GREEN}│${RESET} ${GREEN}│${RESET}\n" printf " ${GREEN}│${RESET} ${DIM}URL${RESET} ${GREEN}│${RESET}\n" printf " ${GREEN}│${RESET} ${BLUE}%s${RESET}\n" "$URL" printf " ${GREEN}│${RESET} ${GREEN}│${RESET}\n" # ------------------------------------------------------------ # QR # ------------------------------------------------------------ if [[ -n "$QR" ]]; then printf " ${GREEN}│${RESET} ${DIM}SCAN${RESET} ${GREEN}│${RESET}\n" while IFS= read -r line; do printf " ${GREEN}│${RESET} %s\n" "$line" done <<< "$QR" printf " ${GREEN}│${RESET} ${GREEN}│${RESET}\n" fi # ------------------------------------------------------------ # Clipboard status # ------------------------------------------------------------ if [[ "$COPIED" == true ]]; then printf " ${GREEN}│${RESET} ${GREEN}󰆏${RESET} ${SUBTEXT}Copied to clipboard${RESET} ${GREEN}│${RESET}\n" else printf " ${GREEN}│${RESET} ${YELLOW}󰆏${RESET} ${SUBTEXT}Clipboard unavailable${RESET} ${GREEN}│${RESET}\n" fi printf " ${GREEN}│${RESET} ${GREEN}│${RESET}\n" printf " ${GREEN}╰────────────────────────────────────────────────────────╯${RESET}\n" echo # ------------------------------------------------------------ # Done # ------------------------------------------------------------ if [[ "$COPIED" == true ]]; then printf " ${GREEN}◆${RESET} ${SUBTEXT}Ready — URL is in your clipboard.${RESET}\n" else printf " ${YELLOW}◆${RESET} ${SUBTEXT}Ready — copy the URL above.${RESET}\n" fi echo