imsh-clients

Clients for imsh screenshot/screencast sharing service
git clone https://git.echoz.io/imsh-clients.git
Log | Files | Refs

imsh-shot.sh (5097B)


      1 #!/usr/bin/env bash
      2 
      3 argv0="imsh-shot"
      4 
      5 usage() {
      6 cat <<EOF
      7 $argv0 - Capture and optionally upload a screenshot to an imsh server
      8 
      9 Usage: $argv0 target [options...]
     10 
     11 Targets:
     12   active
     13     Currently active window.
     14 
     15   screen
     16     All visible outputs.
     17 
     18   output
     19     Currently active output.
     20 
     21   area
     22     Manually select a region or window.
     23 
     24 Options:
     25   -u, --upload
     26     Uploads the screenshot to imsh.
     27 
     28   -a, --api-key=key|@file|%cmd
     29     API key for uploading to imsh.
     30     Prefix with "@" to read from a file.
     31     Prefix with "%" to run a command.
     32 
     33   -e, --endpoint=url
     34     The imsh endpoint to upload to.
     35     Defaults to https://scrn.is/api/v1/upload
     36 
     37   -o, --output=path-pattern
     38     Path to write captured screenshot to. Gets passed through date and
     39     supports the same format strings.
     40 
     41   -U, --utc
     42     Call date with -u to use UTC for added privacy when sharing.
     43 
     44   -C, --copy
     45     Copy the captured screenshot to the clipboard. If uploading, instead
     46     copy the returned URL.
     47 
     48   -f, --freeze
     49     Freezes the screen before area selection.
     50     Only works when target is area.
     51 
     52   -w, --wait=n
     53     Wait for n seconds before taking a screenshot.
     54 
     55   -s, --scale=n
     56     Passes the -s argument to grim.
     57 
     58   -c, --cursor
     59     Include cursors in the screenshot.
     60 
     61   -t, --filetype=type
     62     Output filetype. Supports png, ppm, jpeg.
     63     Only png works with the -C option.
     64     Default: png
     65 
     66   -h, --help
     67     Display this message.
     68 EOF
     69 }
     70 
     71 fatalUser() {
     72 cat <<EOF
     73 Error: $1
     74 
     75 See $argv0 --help for more information.
     76 EOF
     77 exit 2
     78 }
     79 
     80 fatal() {
     81   printf "Error: %s\n" "$1" >&2
     82   exit 1
     83 }
     84 
     85 check() {
     86   err=()
     87   while [[ $# -gt 0 ]]; do
     88     msg="$1"; shift
     89     cond="$1"; shift
     90     value="$1"; shift
     91     [[ "$cond" -ne 0 ]] && [[ -z "$value" ]] && err+=("$msg" ", ")
     92   done
     93   if [[ ${#err[@]} -gt 0 ]]; then
     94     IFS=""
     95     fatalUser "${err[*]::${#err[@]}-1}" >&2
     96   fi
     97 }
     98 
     99 optsWithArgs=(
    100   -a --api-key
    101   -e --endpoint
    102   -o --output
    103   -w --wait
    104   -s --scale
    105   -t --filetype
    106 )
    107 
    108 # Preprocess options:
    109 # Expand -fff to -f -f -f.
    110 # Expand -kv to -k v.
    111 # Expand --key=value to --key value.
    112 # Stop preprocessing once -- is observed.
    113 argv=()
    114 ignoreOpts=
    115 while [[ $# -gt 0 ]]; do
    116   case "$ignoreOpts$1" in
    117     --) argv+=("$1"); ignoreOpts=1;;
    118     --*=*)
    119       argv+=("${1%%=*}" "${1#*=}")
    120       (IFS="|"; [[ "|${optsWithArgs[*]}" = *"|${1%%=*}"* ]]) \
    121         || fatalUser "invalid option: $1"
    122       ;;
    123     --*) argv+=("$1");;
    124     -*)
    125       for ((i=1; i < ${#1}; ++i)); do
    126         argv+=("-${1:i:1}");
    127         if (IFS="|"; [[ "|${optsWithArgs[*]}" = *"|-${1:i:1}"* ]]) && [[ -n "${1:i+1}" ]]; then
    128           argv+=("${1:i+1}")
    129           break
    130         fi
    131       done;;
    132     *) argv+=("$1");;
    133   esac
    134   shift
    135 done
    136 set -- "${argv[@]}"
    137 
    138 upload=
    139 apiKey=
    140 endpoint=https://scrn.is/api/v1/upload
    141 out=
    142 save=
    143 copy=
    144 filetype=png
    145 dateArgs=()
    146 grimblastArgs=()
    147 
    148 positional=()
    149 ignoreOpts=
    150 while [[ $# -gt 0 ]]; do
    151   case "$ignoreOpts$1" in
    152     -u|--upload) upload=1;;
    153     -a|--api-key) apiKey="$2"; shift;;
    154     -e|--endpoint) endpoint="$2"; shift;;
    155     -o|--output) out="$2"; save=1; shift;;
    156     -U|--utc) dateArgs+=(-u);;
    157     -C|--copy) copy=1;;
    158     -f|--freeze) grimblastArgs+=(--freeze);;
    159     -w|--wait) grimblastArgs+=(--wait "$2"); shift;;
    160     -s|--scale) grimblastArgs+=(--scale "$2"); shift;;
    161     -c|--cursor) grimblastArgs+=(--cursor);;
    162     -t|--filetype) grimblastArgs+=(--filetype "$2"); filetype="$2"; shift;;
    163     -h|--help) usage; exit 0;;
    164     --) ignoreOpts=1;;
    165     -*) fatalUser "invalid option $1";;
    166     *) positional+=("$1");;
    167   esac
    168   shift
    169 done
    170 set -- "${positional[@]}"
    171 
    172 target="$1"; shift
    173 action=
    174 case 1 in
    175   $((copy && !upload))) action+="copy";;&
    176   $((save || upload))) action+="save";;
    177 esac
    178 grimblastArgs+=("$action" "$target")
    179 
    180 check \
    181   "extraneous positional arguments ($*)" $# ""\
    182   "missing target" 1 "$target" \
    183   "missing one of --copy --output --upload" 1 "$action" \
    184   "missing value for --api-key" "$upload" "$apiKey" \
    185   "missing value for --output" "$save" "$out" \
    186 
    187 if [[ $((!save && upload)) -ne 0 ]]; then
    188   out="$(mktemp --suffix ".$filetype" "$(printf 'X%.0s' {1..8})")"
    189   trap "$(trap -P EXIT)"$'\n rm -f "$out"' EXIT
    190 elif [[ "$save" -ne 0 ]]; then
    191   out="$(date "${dateArgs[@]}" "+${out/#\~/$HOME}")" \
    192     || fatal "date returned non-zero status"
    193 fi
    194 [[ -n "$out" ]] && grimblastArgs+=("$out")
    195 
    196 if [[ "$upload" -ne 0 ]]; then
    197   case "${apiKey:0:1}" in
    198     @|%) apiKey=${apiKey:1};;&
    199     @)
    200       apiKeyRaw="$(<"${apiKey/#\~/$HOME}")" \
    201         || fatal "could not read API key from file: ${apiKey}"
    202       ;;
    203     %)
    204       apiKeyRaw="$(bash -c "${apiKey}")" \
    205         || fatal "API key command returned non-zero status: ${apiKey}"
    206       ;;
    207     *) apiKeyRaw="$apiKey";;
    208   esac
    209   apiKey="$(tr -d '[:space:]' <<<"$apiKeyRaw")"
    210 fi
    211 
    212 set -eo pipefail
    213 mkdir -p "$(dirname "$out")"
    214 grimblast "${grimblastArgs[@]}" >/dev/null
    215 
    216 if [[ "$upload" -ne 0 ]]; then
    217   response="$(curl -sS --fail-with-body \
    218     "$endpoint" \
    219     -F "image=@$out" \
    220     -H "Authorization: Bearer $apiKey")"
    221   url="$(jq -r .url <<<"$response")"
    222   printf "%s" "$url"
    223   if [[ "$copy" -ne 0 ]]; then
    224     tr -d '[:space:]' <<<"$url" | wl-copy
    225   fi
    226 fi