uoeia/uoeia

165 lines
4.4 KiB
Bash
Executable File

#!/usr/bin/env bash
show_usage() {
printf """uoeia -- Universally Open Every Image Available
Usage: uoeia [OPTION]... [FILE|URL]
Displays the specified image using your preferred image viewer.
Can open remote urls of individual images, galleries, as well as local files at the same time.
Uses gallery-dl for remote gallery opening - so if gallery-dl can open it, so can your image viewer.
Options:
-v, --viewer Specify the image viewer to use.
-q, --quiet Don't display any output during normal operation.
-g, --gdlopts Pass through options to gallery-dl. Take care to fully quote each passed option.
-r, --replace Url patterns to replace in the format 'mypattern:::myreplacement'
-h, --help Show this help message and exit.
Examples:
uoeia my-image.jpg Display a local image file.
uoeia https://example.com/image Display an image/image gallery from a URL.
uoeia -v imv https://example.com/image Display an image from a URL using imv.
uoeia -g \"--range 1-10\" https://reddit.com/r/earthporn
Download and display the first 10 results.
uoeia -r 'nitter.net:::twitter.com' https://nitter.net/donttrythis/
Display images from twitter directly instead of its
open source interface nitter.
"
}
die() {
[ -n "$1" ] && printf '%s\n' "$*" >&2
exit 1
}
cleanup() {
rm -f -- "$cache_dir"/*
rm -r -- "$cache_dir"
}
from_local() {
fpath="$(realpath -e "$1")"
ln -s "$fpath" "$cache_dir"
}
# invokes single image downloading or gallery downloading depending on content type
from_remote() {
link="$(dereference "$1")"
if curl -sLI "$link" | grep -i '^Content-Type:' | grep -q image; then
get_single_image "$link"
else
get_gallery "$link"
fi
}
get_gallery() {
command -v gallery-dl 1>/dev/null 2>&1 || return
#shellcheck disable=2068
gallery-dl -D "$cache_dir" ${gal_args[@]} "$1"
}
get_single_image() {
pwd="$PWD"
cd "$cache_dir" && curl -sSLO "$1"
cd "$pwd" || exit 1
}
# unaliases urls which will not be downloaded correctly otherwise
dereference() {
local output
# default replacements:
# teddit to original redd.it hosted picture
output="${1//teddit.net\/pics\/w:null_/i.redd.it/}"
output="${output//teddit.net/reddit.com}"
# nitter to twitter
output="${output//nitter.net/twitter.com}"
# custom replacements:
for rep in "${replacements[@]}"; do
output="${output//${rep%:::*}/${rep#*:::}}"
done
echo "$output"
}
get_imageviewer() {
for cmd in nsxiv sxiv feh imv vimiv; do
if command -v "$cmd" 1>/dev/null 2>&1; then program="$cmd"; break; fi
done
echo "$program"
}
main() {
[ -n "$imageviewer" ] || die "Error: Could not find a suitable image viewer, set one manually with the '-v' option."
command -v "${imageviewer}" 1>/dev/null 2>&1 || die "Error: Opening images in ${imageviewer} requires ${imageviewer} to be installed and and on the path."
trap cleanup EXIT
[ -d "$cache_dir" ] || mkdir -p -- "$cache_dir" || die "Error: Can not create cache directory {$cache_dir}"
im_number=1
while [ -n "$1" ]; do
case "$1" in
*://*.*) from_remote "$1" ;;
*) from_local "$1" ;;
esac
im_number=$((im_number + 1))
shift
done
[ "$(find -L "$cache_dir" -type f -print | wc -l)" -ne 0 ] &&
${imageviewer} "$cache_dir"
}
cache_dir="$(mktemp -d)"
imageviewer="$(get_imageviewer)"
gal_args=()
replacements=()
while [[ $# -gt 0 ]]; do
case "$1" in
-h | --help)
show_usage
exit 0
;;
-q | --quiet)
gal_args+=("-q")
;;
-v | --viewer)
imageviewer=$2
shift 2
;;
-g | --gdlopts)
if [[ ! "$2" =~ ^- ]]; then
printf "Error: No valid option passed: %s" "$2"
break
fi
gal_args+=("$2")
shift 2
;;
-r | --replace)
replacements+=("$2")
shift 2
;;
--)
shift
break
;;
*)
if [[ "$1" =~ ^- ]]; then
printf "Error: Unrecognized option: %s" "$1"
show_usage
exit 1
fi
arguments+=("$1")
shift
;;
esac
done
arguments+=("$@")
main "${arguments[@]}"