[Add] Initial commit.
This commit is contained in:
parent
b1192f2013
commit
af1f264789
111
README.md
111
README.md
@ -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.
|
[](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: ``
|
||||||
|
* `-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
303
imgbb
Executable 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=""
|
||||||
|
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
|
Loading…
Reference in New Issue
Block a user