#!/bin/sh
# A POSIX.1 shell client for sagegerard.com
# Run without arguments or with bad arguments to print help.
#
# Copyright (C) 2024 Sage Lennon Gerard

host='https://sagegerard.com'

help() {
${PAGER:-less} <<.
% curl $host/client.sh >client 

  Download the shell script that implements this message.


% sh client show public key

  Print an ASCII-armored public key used by Sage Lennon Gerard.


% sh client show public key | gpg

  Show public key details.


% sh client show public key | gpg --import

  Import public key into your keyring.
  Required for downloads to work.


% sh client show feed

  Print content feed for assets on the InterPlanetary File System.
  Sequences prefixed by \\ are tags. Use them to select downloads.


% sh client prepare COMMAND ARG ...

  Print a script that downloads selected files in sequence.
  Provide no COMMAND to select everything.

  A file gets selected when COMMAND ARG ... CID NAME SIZE WORDS ... exits with status 0.
  COMMAND runs once per feed line, where CID NAME SIZE WORDS ... are the words in a line.

  - CID is an IPFS content identifier used to locate the file.
  - NAME is a suggested name for the file on your disk.
  - SIZE is the number of bytes in the file.
  - WORDS ... summarize the file.

  % # Example: prepare everything with a \\pdf tag.
  % echo 'shift 3; echo \$@ | grep "\\pdf"' >pdfs
  % sh client prepare sh pdfs

  % # Example: prepare everything smaller than 1 MiB.
  % echo 'test \$3 -lt \$((1024*1024))' >small
  % sh client prepare sh small

  Social contract:
    - I always publish signed files, so NAME always ends in .gpg.
    - Signature verification may use any public key in your keyring.
.
}


main() {
  check_requirements || return $?

    if test "$1 $2 $3" = 'show public key'
  then show_public_key
  elif test "$1 $2" = 'show feed'
  then show_feed
  elif test "$1" = 'prepare'
  then shift 1
       test $# -eq 0 && set -- :
       show_feed | prepare "$@"
  else help
    fi
}


check_requirements() {
  needs_met=1
  require curl 'Install the "curl" command from https://curl.se'
  require gpg 'Install the "gpg" command from https://gnupg.org'
  require ipfs 'Install the "ipfs" command from https://dist.ipfs.tech'
  require tar 'Install the "tar" command from your operating system package source'

  set -- $needs_met
  unset -v needs_met
  test $1 -eq 1
}


require() {
  if ! command -v $1 >/dev/null
  then printf '%s\n' "$2" >&2
       needs_met=0
  fi
}


show_public_key() {
  curl -sL "$host"/gpgpubkey
}


show_feed() {
  ipfs cat --progress=false --length=64 "$(curl -sL "$host"/feed)"
}


prepare() {
  printf 'o() {
  if test -e "$2"
  then printf "%%s exists. Skipping.\\n" "$2" >&2
  else ipfs cat --length="$3" "$1" | gpg --output "$2" --decrypt
  fi
}

'

  while read cid name size summary
  do if $@ $cid $name $size $summary
     then printf 'o %s %s %d # %s\n'  "$cid" "$name" "$size" "$summary"
     else printf 'Excluding %s: %s\n' "$name" "$summary" >&2
     fi
  done

  unset -v cid name size summary
}

main "$@"
