aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2026-08-26 05:36:12 -0400
committerB. Watson <urchlay@slackware.uk>2026-08-26 05:36:12 -0400
commit2ec1b6ee59066d79f93a119f1f8eac95e31b2345 (patch)
tree7102362bfd30982106e721ee2ff8b1487daa0657
parent6773d6ca7fe8ae6ca8c202db774944dd63aa3822 (diff)
downloadmisc-scripts-2ec1b6ee59066d79f93a119f1f8eac95e31b2345.tar.gz
litterbox: Added. Wrapper for litter.catbox.moe temporary file storage API.
-rwxr-xr-xlitterbox264
1 files changed, 264 insertions, 0 deletions
diff --git a/litterbox b/litterbox
new file mode 100755
index 0000000..826619a
--- /dev/null
+++ b/litterbox
@@ -0,0 +1,264 @@
+#!/bin/bash
+
+# API spec: https://litterbox.catbox.moe/tools.php
+# curl -F "reqtype=fileupload" -F "time=1h" -F "fileToUpload=@filename" \
+# https://litterbox.catbox.moe/resources/internals/api.php
+# time can be 1h, 12h, 24h, or 72h
+# The following file types are currently not allowed:
+# .exe, .scr, .cpl, .doc*, .jar
+# ...so this script will gzip those automatically. otherwise, use -z
+# to gzip and -Z to zip.
+
+SELF="$( basename $0 )"
+APIURL="https://litterbox.catbox.moe/resources/internals/api.php"
+URLS=""
+EXPIRE="1"
+DELAY="${DELAY:-2}"
+UPLOAD_COUNT=0
+
+die() {
+ echo "$SELF: fatal: $@" 1>&2
+ exit 1
+}
+
+warn() {
+ echo "$SELF: warning: $@" 1>&2
+}
+
+info() {
+ [ "$VERBOSE" = "1" ] && echo "$SELF: info: $@" 1>&2
+}
+
+usage() {
+ cat <<EOF
+$SELF: upload files to litterbox.catbox.moe
+
+Usage: $SELF [-e hours] [-g] [-z] [-c] [-v] file <file ...>
+
+Each file can be a filename, a directory name, or "-" for standard
+input. If no files are given, $SELF reads from standard input.
+
+Once a file is uploaded, its URL is printed on stdout.
+If xsel is installed, it's also copied to the X paste buffer.
+
+When uploading multiple files, all the URLs are copied to
+the X buffer (separated by spaces). Also, a delay of $DELAY
+seconds is added between uploads, to avoid hammering the site.
+
+Options:
+ -e Set expiration time in hours. Allowed values are 1, 12,
+ 24, or 72. Default is $EXPIRE.
+
+ -g Upload gzipped files. This is automatically enabled
+ when uploading files whose names end in .exe, .scr,
+ .cpl, .doc*, .jar (unless -z is given). Also, directories
+ are automatically tarred/gzipped (unless -z is given).
+
+ -z Upload zipped files or dirs.
+
+ -t Upload tarred and gzipped directory. Won't work with
+ single files (use -g or -z for those).
+
+ -c Upload encrypted file. Currently this means the file
+ is encrypted with 'openssl enc -pbkdf2 -aes-256-cbc', and
+ you're prompted for an encryption key. Whoever downloads
+ the encrypted file will have to decrypt it manually,
+ e.g. with:
+ openssl enc -d -pbkdf2 -aes-256-cbc < file.encrypted > file.decrypt
+
+ -v Verbose operation.
+
+Author: B. Watson <urchlay@slackware.uk>
+License: WTFPL (Do WTF you want with this)
+EOF
+}
+
+set_expiration() {
+ case "$1" in
+ 1|12|24|72) ;; # OK
+ *) die "invalid expiration time, allowed values are: 1 12 24 72" ;;
+ esac
+ EXPIRE="$1"
+}
+
+add_url() {
+ if [ "$URLS" = "" ]; then
+ URLS="$1"
+ else
+ URLS+=" $1"
+ fi
+ : $(( UPLOAD_COUNT++ ))
+}
+
+copy_urls() {
+ if ! xsel --version &>/dev/null; then
+ warn "xsel not found in PATH, not copying URL(s) to clipboard"
+ return
+ fi
+
+ if [ "$DISPLAY" = "" ]; then
+ warn "DISPLAY not set in env, not copying URL(s) to clipboard"
+ return
+ fi
+
+ echo -n "$URLS" | xsel -i
+}
+
+compress_file() {
+ local ext
+ local basefile
+ local is_dir
+
+ [ -d "$FILE" ] && is_dir=1
+
+ if [ "$ZIP" = "1" ]; then
+ ext=.zip
+ else
+ ext=.gz
+ fi
+
+ basefile="$( basename "$FILE" )"
+
+ # TODO: create a random tmp dir, don't use /tmp!
+ TMPFILE="${TMP:-/tmp}/$basefile$ext"
+ rm -f "$TMPFILE"
+ if [ "$ZIP" = "1" ]; then
+ zip -qr "$TMPFILE" "$FILE"
+ info "zipped $FILE as $TMPFILE"
+ else
+ if [ "$is_dir" = 1 ]; then
+ tar cfz "$TMPFILE" "$FILE"
+ info "tarred up $FILE as $TMPFILE"
+ else
+ gzip -9 < "$FILE" > "$TMPFILE"
+ info "gzipped $FILE as $TMPFILE"
+ fi
+ fi
+ FILE="$TMPFILE"
+}
+
+# TODO: curl options:
+# --max-time --retry --retry-max-time
+upload_file() {
+ local url
+ local use_compression
+
+ info "preparing to upload $FILE"
+
+ case "$FILE" in
+ *.exe|*.scr|*.cpl|*.doc*|*.jar)
+ warn "forbidden file extension, compression forced"
+ use_compression=1 ;;
+ *)
+ use_compression="$COMPRESS" ;;
+ esac
+
+ if [ "$use_compression" = 1 ]; then
+ # can't easily zip stdin, write it to a file
+ if [ "$FILE" = "-" ]; then
+ FILE="${TMP:-/tmp}/$SELF.stdin"
+ cat > "$FILE"
+ if [ "$?" != 0 ]; then
+ rm -f "$FILE"
+ return
+ fi
+ fi
+ compress_file # resets FILE, sets TMPFILE
+ fi
+
+ # at this point, we have an actual file, even if input was stdin,
+ # so we can encrypt it.
+ if [ "$ENC" = "1" ]; then
+ CRYPTFILE="$FILE.aes"
+ openssl enc -pbkdf2 -aes-256-cbc < "$FILE" > "$CRYPTFILE"
+ if [ "$?" != "0" ]; then
+ warn "encryption failed, skipping file"
+ return
+ fi
+ FILE="$CRYPTFILE"
+ fi
+
+ if [ "$URLS" != "" ]; then
+ info "sleeping $DELAY sec between uploads"
+ sleep "$DELAY"
+ fi
+
+ info "uploading $FILE"
+
+ url="$(
+ cat "$FILE" | \
+ curl --silent \
+ -F "reqtype=fileupload" \
+ -F "time=${EXPIRE}h" \
+ -F "fileToUpload=@-" \
+ "$APIURL"
+ )"
+ # TODO: check curl's exit status!
+
+ case "$url" in
+ https://litter.catbox.moe/*) add_url "$url" ;;
+ *) warn "upload failed" ;;
+ esac
+}
+
+# main()
+if [ "$1" = "--help" ]; then
+ usage ; exit 0
+fi
+
+while getopts ":e:gzcv" OPT; do
+ case "$OPT" in
+ e) set_expiration "$OPTARG" ;;
+ g) GZIP=1 ;;
+ z) ZIP=1 ;;
+ c) ENC=1 ;;
+ v) VERBOSE=1 ;;
+ *) die "invalid option -$OPTARG, try --help" ;;
+ esac
+done
+
+[ "$GZIP" = 1 -a "$ZIP" = 1 ] && die "can't give both -g and -z"
+[ "$GZIP" = 1 -o "$ZIP" = 1 ] && COMPRESS=1
+
+info "expire time set to $EXPIRE hour(s)"
+
+shift $(($OPTIND - 1))
+
+[ "$1" = "" ] && set -- -
+for arg; do
+ TMPFILE=""
+ CRYPTFILE=""
+
+ if [ "$arg" = "-" -o -f "$arg" ]; then
+ FILE="$arg"
+ elif [ -d "$arg" ]; then
+ FILE="$arg"
+ compress_file # sets FILE
+ else
+ warn "$arg not a regular file, ignoring"
+ continue
+ fi
+
+ upload_file
+
+ if [ "$TMPFILE" != "" ]; then
+ info "removing temp file $TMPFILE"
+ rm -f "$TMPFILE"
+ fi
+
+ if [ "$TMPFILE" != "" ]; then
+ info "removing temp encrypted file $CRYPTFILE"
+ rm -f "$CRYPTFILE"
+ fi
+done
+
+if [ "$UPLOAD_COUNT" = "0" ]; then
+ die "no files uploaded"
+fi
+
+echo "$URLS"
+copy_urls
+
+info "$UPLOAD_COUNT file(s) uploaded"
+
+exit 0