diff --git a/icerbox.sh b/icerbox.sh new file mode 100644 index 0000000..c10bc2c --- /dev/null +++ b/icerbox.sh @@ -0,0 +1,143 @@ +#!/usr/bin/env bash +set -ueo pipefail + +api='https://icerbox.com/api/v1/' +jwt='/dev/shm/icerbox.token' +cfg=~/.icerbox.conf + +err() { + echo "$1" >/dev/stderr + exit 1 +} + +warn() { + echo "$1" >/dev/stderr +} + +icerbox_handle_response() { + test -n "$1" || err "empty http status code" + test -s "$2" || err "empty json reponse body" + if [ "$1" -ne 200 ]; then + jq -r '.status_code?' "${2}" >/dev/stderr + jq -r '.message?' "${2}" >/dev/stderr + err "request failed with http ${1}" + fi +} + +icerbox_auth_login() { + out='/dev/shm/icerbox.auth.login.json' + test -f "$out" && rm "$out" + code=$(curl -s -w '%{http_code}' -H 'Content-Type: application/json' -o "$out" -d "email=${1}" -d "password=${2}" "${api}auth/login") + test $? -eq 0 || err "curl request failed" + icerbox_handle_response "$code" "$out" + token=$(jq -r '.token?' "$out") + test -n "$token" || err "empty jwt token" + echo "$token" +} + +icerbox_auth_refresh() { + out='/dev/shm/icerbox.auth_refresh.json' + test -f "$out" && rm "$out" + # force POST without --data + code=$(curl -s -w '%{http_code}' -XPOST -H "Authorization: Bearer ${1}" -H 'Content-Type: application/json' -o "$out" "${api}auth/refresh") + test $? -eq 0 || err "curl request failed" + icerbox_handle_response "$code" "$out" + token=$(jq -r '.token?' "$out") + test -n "$token" || err "empty jwt token" + echo "$token" +} + +icerbox_user_account() { + out='/dev/shm/icerbox.user.account.json' + test -f "$out" && rm "$out" + code=$(curl -s -w '%{http_code}' -H "Authorization: Bearer ${1}" -H 'Content-Type: application/json' -o "$out" "${api}user/account") + test $? -eq 0 || err "curl request failed" + icerbox_handle_response "$code" "$out" +} + +icerbox_file() { + out='/dev/shm/icerbox.file.json' + test -f "$out" && rm "$out" + code=$(curl -s -w '%{http_code}' -H "Authorization: Bearer ${1}" -H 'Content-Type: application/json' -o "$out" -d id="$2" -G "${api}file") + test $? -eq 0 || err "curl request failed" + icerbox_handle_response "$code" "$out" + status=$(jq -r '.data?.status?' "$out") + test $? -eq 0 || err "failed parsing json" + test -n "$status" || err "empty status" + if [ "$status" != "active" ]; then + warn "file ${2} is not active" + return 1 + else + return 0 + fi +} + +icerbox_dl_ticket() { + out='/dev/shm/icerbox.dl.ticket.json' + test -f "$out" && rm "$out" + # endpoint does not accept file parameter with json as content type + code=$(curl -s -w '%{http_code}' -H "Authorization: Bearer ${1}" -o "$out" -d file="$2" "${api}dl/ticket") + test $? -eq 0 || err "curl request failed" + icerbox_handle_response "$code" "$out" + url=$(jq -r '.url?' "$out") + test $? -eq 0 || err "failed parsing json" + test -n "$url" || err "empty ticket url" + echo "$url" +} + +icerbox_file_id() { + test -n "$1" || err "empty url" + test "${1:0:20}" = "https://icerbox.com/" || err "not a icerbox url: $1" + test "${#1}" -ge 28 || err "url $1 does not contain valid file id" + echo "${1:20:8}" +} + +test "$#" -eq 0 && err "usage $0 https://icerbox.com/abcdefgh https://icerbox.com/abcdefgh ..." +test -f "$cfg" && source "$cfg" || err "please set 'email' and 'password' in ${cfg}" +test -n "$email" || err "email not set" +test -n "$password" || err "password not set" +type curl >/dev/null || err "need curl" +type jq >/dev/null || err "need jq" + +if [ -f $jwt ] && [ -s $jwt ]; then + token=$(< $jwt) + token_age=$(stat --format=%Y "$jwt") + now=$(date +%s) + if [ $token_age -le $(( $now - 1800 )) ]; then + token=$(icerbox_auth_refresh "$token") + echo "$token" > "${jwt}.tmp" + mv "${jwt}.tmp" "$jwt" + echo "session refreshed" + else + echo "using active session" + fi +else + token=$(icerbox_auth_login "$email" "$password") + echo "$token" > "${jwt}.tmp" + mv "${jwt}.tmp" "${jwt}" + echo "new session acquired" +fi + +test -n "$token" || echo "no session token" + +#icerbox_user_account "$token" + +tickets=() +for url in $@; do + file_id=$(icerbox_file_id "$url") + icerbox_file "$token" "$file_id" + if [ $? -ne 0 ]; then + echo "Skipping $url" + continue + else + dl_url=$(icerbox_dl_ticket "$token" "$file_id") + tickets+=(-OJL "$dl_url") + fi +done + +if [ ${#tickets} -gt 0 ]; then + curl --progress-bar --parallel-max 10 -Z "${tickets[@]}" +else + err "nothing to download" +fi +