[Add] Initial commit.

This commit is contained in:
Ritchie Cunningham 2025-04-22 17:58:11 +01:00
parent b1192f2013
commit af1f264789
2 changed files with 412 additions and 2 deletions

111
README.md
View File

@ -1,3 +1,110 @@
# imgbb-uploader # ImgBB Upload Script (`imgbb`)
Small script to upload an image from clipboard or file to imgbb.com. URL is then inserted directly into clipboard ready to be pasted to IRC or.. wherever. [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) A simple Bash script to quickly upload images from the system clipboard (X11) or a specified file directly to [ImgBB](https://imgbb.com/) using their v1 API. It retrieves the direct image URL, prints it to STDOUT, and copies it to the X11 clipboard.
Ideal for quickly sharing screenshots or images in environments like IRC without needing to manually use the website interface.
**Author:** Ritchie Cunningham <ritchie@ritchiecunningham.co.uk>
**Version:** 1.0 (as of 22/04/2025)
## Features
* Upload images directly from the clipboard (PNG or JPEG).
* Upload images directly from a file path.
* Set an optional auto-deletion expiration time (e.g., `5m`, `2h`, `7d`, `0` for none).
* Specify a custom filename for the uploaded image on ImgBB.
* Optionally output and copy the URL in Markdown format.
* Copies the resulting URL to the X11 clipboard.
* Provides desktop notifications for progress and success/failure (optional).
## Dependencies
Make sure you have the following command-line tools installed:
* **curl:** Used for making the HTTP API request.
```bash
sudo apt install curl # Debian.
```
* **jq:** Used for parsing the JSON API response.
```bash
sudo apt install jq # Debian.
```
* **xclip:** Used for accessing the X11 clipboard. **This script will not work on Wayland sessions.**
```bash
sudo apt install xclip # Debian.
```
* **notify-send (Optional):** Used for desktop notifications. The script works without it but won't show popups.
```bash
sudo apt install notify-send # Debian (often in libnotify-bin).
```
## Installation
1. **Clone the repository:**
```bash
git clone git@git.ritchiecunningham.co.uk:Rtch/imgbb-uploader.git
cd imgbb-uploader
```
2. **Make the script executable:**
```bash
chmod +x imgbb
```
3. **Place in your PATH (Recommended):** Create a symbolic link to the script from a directory in your `$PATH` for easy execution (e.g., `~/.local/bin`, ensure this is in your `$PATH`).
```bash
mkdir -p ~/.local/bin
ln -s "$(pwd)/imgbb" ~/.local/bin/imgbb
```
Now you can just run `imgbb` from your terminal.
## Configuration
This script requires a **free API key** from ImgBB:
1. Go to [https://api.imgbb.com/](https://api.imgbb.com/) and register or log in to get your key.
2. Store the key in `.config/imgbb/uploader/api_key`.
* **File** Create the directory and file, then paste *only* your API key inside:
```bash
mkdir -p ~/.config/imgbb_uploader
nano ~/.config/imgbb_uploader/api_key
# Paste your key, save the file.
# Set permissions so only you can read it:
chmod 600 ~/.config/imgbb_uploader/api_key
```
## Usage
**Options:**
* `[filepath]` : Optional path to an image file to upload. If omitted, uses the clipboard content.
* `-e, --expire DURATION`: Set auto-deletion timeout. DURATION is a number followed by `s`(econds), `m`(inutes), `h`(ours), or `d`(ays) (e.g., `5m`, `2h`, `7d`, `300s`). Range: 60s-180d. Use `0`, `none`, or `never` for no expiration (overrides the default). Default expiration is 2 hours (7200s) if this option is not used.
* `-n, --name NAME`: Set a custom filename for the uploaded image on ImgBB.
* `--markdown`: Output and copy the URL in Markdown image format: `![](URL)`
* `-h, --help`: Show the help message and exit.
**Examples:**
```bash
# Upload image from clipboard, expire in 2 hours (default)
imgbb
# Upload specific image file, expire in 2 hours
imgbb screenshot.png
# Upload from clipboard, expire in 10 minutes
imgbb -e 10m
# Upload from clipboard, never expire
imgbb -e 0
# Upload file, give it a name on ImgBB, get Markdown output/copy
imgbb -n "Cool Diagram" --markdown diagram.jpg
# Show help
imgbb -h
# Notes
Currently relies on xclip and therefore only works reliably under X11 sessions. Wayland support would require adding logic to use wl-clipboard.
# License
This project is licensed under the GPL License. See the LICENSE file for details. (Action: You need to add a file named LICENSE to your repository containing the text of the GPL, likely GPLv3).

303
imgbb Executable file
View File

@ -0,0 +1,303 @@
#!/bin/bash
# -----------------------------------------------------------------------------
# Script Name: imgbb
# Description: Uploads an image from the system clipboard or a specified file
# to ImgBB (imgbb.com) using their V1 API. Retrieves the direct
# image URL, prints it to stdout, and copies it to the X11 clipboard.
# Author: Ritchie Cunningham <ritchie@ritchiecunningham.co.uk>
# License: GPL License
# Version: 3.0
# Date: 22/04/2025
# -----------------------------------------------------------------------------
# Usage Examples:
#
# Examples:
# imgbb # Upload clipboard, expire 2h.
# imgbb my_image.png # Upload file, expire 2h (or whatever you declare expire_seconds to).
# imgbb -e 10m # Upload clipboard, expire 10m.
# imgbb -e 0 # Upload clipboard, never expire.
# imgbb -n "Diagram" --markdown img.jpg.
# imgbb -h # See help for more information.
# -----------------------------------------------------------------------------
# Dependencies:
# - bash (v4+ required for =~, (( )), BASH_REMATCH)
# - curl: (e.g., sudo apt install curl)
# - jq: (e.g., sudo apt install jq)
# - xclip: (X11 clipboard access) (e.g., sudo apt install xclip)
# - notify-send: (Optional, for desktop notifications) (e.g., sudo apt install notify-send)
# - Coreutils: (mktemp, basename, rm, cat, echo, etc. - usually standard)
# -----------------------------------------------------------------------------
# Configuration:
# Requires an ImgBB API key (v1). Get one free: https://api.imgbb.com/
# Store the key:
# - File: ~/.config/imgbb_uploader/api_key (chmod 600 recommended)
# (Create directory: mkdir -p ~/.config/imgbb_uploader)
# -----------------------------------------------------------------------------
# Notes:
# - Uses 'xclip', works on X11 sessions only. Wayland requires 'wl-clipboard'.
# -----------------------------------------------------------------------------
# === Default Configuration & Argument Parsing. ===
API_KEY_FILE="$HOME/.config/imgbb_uploader/api_key"
filepath=""
expire_seconds="7200" # 2h - Set to "" for no expiry. or use flag -e 0, never or none.
custom_name=""
markdown_mode="false"
print_usage() {
echo "Usage: $(basename "$0") [options] [filepath]"
echo "Uploads image from clipboard (default) or filepath to ImgBB."
echo ""
echo "Options:"
echo " [filepath] Optional path to an image file to upload."
echo " -e, --expire DURATION Set auto-deletion timeout. DURATION is a number"
echo " followed by s(econds), m(inutes), h(ours), or d(ays)."
echo " Default unit is minutes if unspecified."
echo " '0', 'none', 'never' to override default expiry."
echo " -n, --name NAME Set a custom filename for the uploaded image."
echo " --markdown Output/copy the URL in Markdown image format."
echo " -h, --help Show this help message."
}
# Parse command-line options.
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
-e|--expire)
expire_input="$2" # Usr input.
# Check for 'no expiry value'.
if [[ "$expire_input" == "0" || "$expire_input" == "never" || "$expire_input" == 'none' ]]; then
expire_seconds="" # Unset for no expiration.
echo "Setting NO expiration."
else
# Proceed with parsing regular.
value="" unit="" seconds=""
# Regex to capture the number part and optional unit part (s,m,h,d)
if [[ "$expire_input" =~ ^([0-9]+)([smhd]?)$ ]]; then
value="${BASH_REMATCH[1]}" # The numeric part.
unit="${BASH_REMATCH[2]}" # The unit part.
# Default to minutes if no unit was provided.
if [ -z "$unit" ]; then unit="s"; fi
# Calculate total seconds based on the unit.
case "$unit" in
s) seconds=$((value)) ;;
m) seconds=$((value * 60)) ;;
h) seconds=$((value * 3600)) ;; # 60*60.
d) seconds=$((value * 86400)) ;; # 60*60*24.
*) # Not really requried given the regex, but hey-ho.
echo "Error: Internal error parsing unit '$unit' from '$expire_input'."
exit 1 ;;
esac
# Validate against ImgBB limits (60 seconds to 15552000 seconds / 180 days).
if (( seconds < 60 )) || (( seconds > 15552000 )); then
echo "Error: Calculated expiration ($seconds seconds) is outside of ImgBB's allowed range (60s - 15552000s)." >&2
exit 1
fi
# Store the final result.
expire_seconds="$seconds"
echo "Expiration set to $expire_seconds seconds ($expire_input)"
else
# Someone did funky input. Tell them to stop that!
echo "Error: Invalid expiration format '$expire_input'." >&2
echo "Use a number optionally followed by s, m, h or d OR use 0/none/never (e.g., 300, 5m, 2h, 7d)." >&2
print_usage # Maybe they need help.
exit 1
fi
fi
shift
shift
;;
-n|--name)
custom_name="$2"
shift
shift
;;
--markdown)
markdown_mode="true"
shift
;;
-h|--help)
print_usage
exit 0
;;
-*)
# Unknown option.
echo "Error: Unknown option '$1'" >&2
print_usage
exit 1
;;
*)
# Assume it's the filepath (only one allowed).
if [ -n "$filepath" ]; then
echo "Error: Multiple filepaths provided ($filepath, $1). Only one allowed." >&2
print_usage
exit 1
fi
filepath="$1"
shift
;;
esac
done
# Check if filepath exists and is readable if provided.
if [ -n "$filepath" ] && [ ! -r "$filepath" ]; then
echo "Error: Cannot read file '$filepath'" >&2
exit 1
fi
# === Read API Key. ===
API_KEY=""
if [[ -f "$API_KEY_FILE" ]]; then
API_KEY=$(cat "$API_KEY_FILE")
elif [[ -n "$IMGBB_API_KEY" ]]; then
API_KEY="$IMGBB_API_KEY"
fi
# Check if API key is actually set.
if [ -z "$API_KEY" ]; then
# Use function defined below if notify-send exists.
notify_cmd -u critical "ImgBB Upload Error" "API Key not found." &>/dev/null
echo "Error: API Key not found." >&2
echo "Please store your key in '$API_KEY_FILE' or set the IMGBB_API_KEY environment variable." >&2
exit 1
fi
# === Check Dependencies. ===
check_command() {
if ! command -v "$1" &> /dev/null; then
notify_cmd -u critical "ImgBB Upload Error" "'$1' command not found. Please install it." &>/dev/null
echo "Error: '$1' command not found. Please install it (e.g., sudo apt install $1)." >&2
exit 1
fi
}
# Define notify_cmd first based on whether notify-send exists.
if ! command -v notify-send &> /dev/null; then
notify_cmd() { :; } # No-op if not found.
echo "Warning: notify-send not found. Desktop notifications disabled." >&2
else
notify_cmd() { notify-send "$@"; } # Actual command if found.
fi
# Now check other dependencies.
check_command curl
check_command jq
# Only check xclip if we plan to use the clipboard.
if [ -z "$filepath" ]; then
check_command xclip
fi
# === Main Logic. ===
TMP_IMG="" # Path to the image file to upload.
image_source_description=""
# Setup trap *only* if using clipboard mode.
if [ -z "$filepath" ]; then
# === Clipboard Input Mode. ===
image_source_description="clipboard"
# Create temporary file(s).
TMP_IMG_PNG=$(mktemp --suffix=.png)
TMP_IMG_JPEG=$(mktemp --suffix=.jpg)
# Ensure temporary files are cleaned up on script exit.
trap 'echo "Cleaning up temp files..."; rm -f "$TMP_IMG_PNG" "$TMP_IMG_JPEG"' EXIT
# Try extracting PNG image from clipboard.
notify_cmd "ImgBB Uploader" "Getting image from clipboard..."
if xclip -selection clipboard -t image/png -o > "$TMP_IMG_PNG" 2>/dev/null && [ -s "$TMP_IMG_PNG" ]; then
echo "Retrieved PNG image from clipboard."
TMP_IMG="$TMP_IMG_PNG"
rm -f "$TMP_IMG_JPEG" # Remove unused JPEG temp file.
else
# If PNG fails or is empty, try JPEG.
echo "PNG failed or empty, trying JPEG..."
if xclip -selection clipboard -t image/jpeg -o > "$TMP_IMG_JPEG" 2>/dev/null && [ -s "$TMP_IMG_JPEG" ]; then
echo "Retrieved JPEG image from clipboard."
TMP_IMG="$TMP_IMG_JPEG"
rm -f "$TMP_IMG_PNG" # Remove unused PNG temp file.
else
# If both fail or are empty.
notify_cmd -u critical "ImgBB Upload Error" "Could not get PNG or JPEG image data from clipboard."
echo "Error: Could not get PNG or JPEG image data from clipboard." >&2
exit 1
fi
fi
else
# === File Input Mode. ===
image_source_description="file '$filepath'"
TMP_IMG="$filepath" # Use the provided file path directly.
echo "Using image from file: $filepath"
trap '' EXIT # Clear trap if we are not using temp files.
fi
# Build curl options.
curl_opts=(-s -L -X POST)
curl_opts+=(--form "key=$API_KEY")
curl_opts+=(--form "image=@$TMP_IMG")
if [ -n "$expire_seconds" ]; then
curl_opts+=(--form "expiration=$expire_seconds")
fi
if [ -n "$custom_name" ]; then
curl_opts+=(--form "name=$custom_name")
echo "Setting custom name to '$custom_name'."
fi
# Upload the image using curl.
notify_cmd "ImgBB Uploader" "Uploading image from $image_source_description..."
response=$(curl "${curl_opts[@]}" 'https://api.imgbb.com/1/upload')
# Check curl exit status.
if [ $? -ne 0 ]; then
notify_cmd -u critical "ImgBB Upload Error" "curl command failed during upload. Check network?"
echo "Error: curl command failed during upload. Check network connection." >&2
exit 1
fi
# Parse the JSON response using jq.
# Check for overall success status from ImgBB API.
success=$(echo "$response" | jq -r '.success')
if [ "$success" != "true" ]; then
error_msg=$(echo "$response" | jq -r '.error.message // "Unknown API error"')
notify_cmd -u critical "ImgBB Upload Error" "API Error: $error_msg"
echo "Error: ImgBB API returned an error - $error_msg" >&2
echo "Full response: $response" >&2
exit 1
fi
# Extract the direct image URL.
image_url=$(echo "$response" | jq -r '.data.url')
# Check if URL was successfully extracted.
if [ -z "$image_url" ] || [ "$image_url" == "null" ]; then
notify_cmd -u critical "ImgBB Upload Error" "Could not parse image URL from API response."
echo "Error: Could not parse image URL from API response." >&2
echo "Full response: $response" >&2
exit 1
fi
# Format output based on markdown flag.
output_url="$image_url"
if [ "$markdown_mode" = "true" ]; then
# Basic markdown image syntax - assumes filename is not needed for alt text here.
output_url="![](${image_url})"
echo "Formatting as Markdown."
fi
# Output the URL to terminal and copy to clipboard.
echo "Image URL:"
echo "$output_url"
# Use xclip only if we determined we are not uploading from file (i.e., we used clipboard input)
# Or always copy? Let's always copy for now.
if command -v xclip &> /dev/null; then
echo "$output_url" | xclip -selection clipboard
notify_cmd "ImgBB Uploader" "Success! URL copied: $output_url"
else
notify_cmd "ImgBB Uploader" "Success! URL: $output_url"
fi
# Temporary files are removed automatically by the 'trap' command on exit if they were created.
exit 0