Skip to content

Instantly share code, notes, and snippets.

@5paceToast 5paceToast/fedimg
Last active Jan 12, 2020

Embed
What would you like to do?
Fediverse (mastodon-api compatible) image and file status uploader
#!/bin/zsh
# deps: curl, mkdir(1p), jq
# return codes:
# 1: regular error, see stdout
# 2: media upload error
# 3: status post error
local app=${0:t}
usage() {
echo "$app [-a|-A <token>] [-i|-I <instance>] [-n] [-N <spoiler>] [-s <status>] -f <file>..."
echo '\t-a <token>: use oauth token <token>, do not create or read conf'
echo '\t-A <token>: use oauth token <token>, do not read conf, do create conf'
echo '\tneither -a nor -A: read conf, fail if none found'
echo
echo '\t-i <instance>: use instance <instance>, do not create or read conf'
echo '\t-I <instance>: use instance <instance>, do not read conf, do create conf'
echo '\tneither -i not -I: read conf, use default if none found'
echo
echo '\t-n: enable spoiler/nsfw, has a default spoiler'
echo '\t-N <spoiler>: set spoiler/subject to <spoiler>, implies -n'
echo
echo '\t-s <status>: set the status to <status>, otherwise use default'
echo
echo '\t-f <file>: upload file, at least one must be specified, repeatable'
return 0
}
local files=()
local instance='https://toast.cafe'
local post="Posted with $app"
local spoiler="Spoiler generated with $app"
local token=
# ---- auth
# -a <token>: use this token, do not create conf (alternative to -c)
# -A <token>: create a conf file with the token that will be loaded (perms 600)
# -i <instance>: work with the specified instance, do not create conf (alternative to -I)
# -I <instance>: create a conf file with the instance that will be loaded (different from -c)
# ---- post info
# -n: mark post as NSFW
# -N <text>: NSFW spoiler tag (implies -n)
# -s <status>: use a custom text status
# ---- these options are actually required
# -f <file>: file to upload. you can specify this as many times as you'd like
local confflag=0
local instflag=0
local nsfwflag=0
local name=
while getopts a:A:i:I:nN:s:f: name
do
case $name in
a) token=$OPTARG; confflag=0 ;;
c) token=$OPTARG; confflag=1 ;;
i) instance=$OPTARG; instflag=0 ;;
I) instance=$OPTARG; instflag=1 ;;
n) nsfwflag=1 ;;
N) spoiler=$OPTARG; nsfwflag=1 ;;
s) post=$OPTARG ;;
f) files+=( $OPTARG ) ;;
?) usage; return 1 ;;
esac
done
# state for the rest of stuff
: ${XDG_CONFIG_HOME:=~/.config}
: ${FEDIMG_CONFDIR:=$XDG_CONFIG_HOME/fedimg}
FEDIMG_TOKEN=$FEDIMG_CONFDIR/token.zsh
FEDIMG_INST=$FEDIMG_CONFDIR/instance.zsh
[[ -d $FEDIMG_CONFDIR ]] || mkdir -m 700 -p $FEDIMG_CONFDIR # please don't create it yourself
if (( confflag )); then
touch $FEDIMG_TOKEN
chmod 600 $FEDIMG_TOKEN
echo "token=$token" > $FEDIMG_TOKEN # please don't create it yourself
else
[[ -r $FEDIMG_TOKEN ]] && . $FEDIMG_TOKEN
fi
if (( instflag )); then
echo "instance=$instance" > $FEDIMG_INST # feel free to create it yourself (once the dir exists)
else
[[ -r $FEDIMG_INST ]] && . $FEDIMG_INST
fi
# let's check that everything is good!
if [[ -z $token ]]; then
echo TOKEN REQUIRED
return 1
fi
if ! (( #files )); then
echo NEED AT LEAST ONE FILE
return 1
fi
# ---- OK WE CAN START NOW
crl() {
curl -# -H "Authorization: Bearer $token" \
-X POST \
$@
}
local nsfwargs=()
if (( nsfwflag )); then
nsfwargs+=( -F sensitive=true -F "spoiler_text=$spoiler" )
fi
local idargs=()
local id=
for file in $files; do
id=$(crl -F file=@$file $instance/api/v1/media | jq .id) || return 2 # separate id for failure to upload media
idargs+=( -F "media_ids[]=$id" )
done
crl -o /dev/null -F status="$post" $idargs $nsfwargs "$instance/api/v1/statuses" || return 3 # separate id for status posting failure
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.