Silly bash shell scripts for APIs

Recently, I've been using various APIs from the bash shell. It's an exercise in response to, "can it be done?"  There is no other point. These are loosely tested and probably insecure in various ways. Buyer beware. YMMV.

Parsing RSS feeds

On FreeBSD:
curl -s https://lewman.blog/feed/ | xml sel -t -m "/rss/channel/item" -n -v "title" -o ": " -v "link"

On linuxes:
curl -s https://lewman.blog/feed/ | xmlstarlet sel -t -m "/rss/channel/item" -n -v "title" -o ": " -v "link"

Output is:

Honored to speak at HTCIA International Conference 2018: https://lewman.blog/2018/08/20/honored-to-speak-at-htcia-international-conference-2018/
Flying over Chicago: https://lewman.blog/2018/08/19/flying-over-chicago/
Cycling makes you more healthy and fit.: https://lewman.blog/2018/08/18/treehugger/
Welcome to Vegas.: https://lewman.blog/2018/08/06/welcome-to-vegas/
Goodnight Sun: https://lewman.blog/2018/08/05/goodnight-sun/
Scenes from the bike: https://lewman.blog/2018/08/04/scenes-from-the-bike/
Who makes carbon frames for bicycles?: https://lewman.blog/2018/07/25/who-makes-carbon-frames-for-bicycles/
The Dogs of Amazon: https://lewman.blog/2018/07/16/the-dogs-of-amazon/
The 9-year bicycle: https://lewman.blog/2018/07/12/the-9-year-bicycle/

Posting to mastodon

Simply set the ACCESSTOKEN and INSTANCE variables.


#!/usr/bin/env bash

tempfiles=( )
cleanup() {
rm -f "${tempfiles[@]}"
}
trap cleanup 0

error() {
local parent_lineno="$1"
local message="$2"
local code="${3:-1}"
if [[ -n "$message" ]] ; then
echo "Error on or near line ${parent_lineno}: ${message}; exiting with status ${code}"
else
echo "Error on or near line ${parent_lineno}; exiting with status ${code}"
fi
exit "${code}"
}
trap 'error ${LINENO}' ERR

if [ ! $# == 1 ]; then
echo "You need to specify a status to post."
echo "Usage: $0 status"
exit 1
fi
#Via admin interface, create an app, put the access token here
ACCESSTOKEN=""
#which mastodon instance are we using?
INSTANCE=""

if [ -z "${ACCESSTOKEN}" -o -z "${INSTANCE}" ]; then
echo "Please add your ACCESSTOKEN and INSTANCE to the script."
exit 1
fi
#make the magic happen by using jq to create valid JSON to post
STATUS=$(jq -n --arg status "$1" ' { "status": $status } ')
#load it all up and post. the jq at the end is for reading the json post output
curl -d "${STATUS}" -H "Content-Type: application/json" -H "Authorization: Bearer ${ACCESSTOKEN}" -sS -X POST https://${INSTANCE}/api/v1/statuses/ | jq '.'
#test for result of curl post
res=$?
if test "${res}" != "0"; then
echo "the curl command failed with: ${res}"
fi

Using DarkOwl's API

The API docs are at https://amp.darkowl.com. The output is JSON, so just use jq or whatever you like to parse it.


#!/bin/bash

General error trap and output

tempfiles=( )
cleanup() {
rm -f "${tempfiles[@]}"
}
trap cleanup 0

error() {
local parent_lineno="$1"
local message="$2"
local code="${3:-1}"
if [[ -n "$message" ]] ; then
echo "Error on or near line ${parent_lineno}: ${message}; exiting with status ${code}"
else
echo "Error on or near line ${parent_lineno}; exiting with status ${code}"
fi
exit "${code}"
}
trap 'error ${LINENO}' ERR

if [ ! $# == 2 ]; then
echo "You need to specify an endpoint to use and the raw query parameters to pass to the API; e.g search q=allCards:1234*"
echo "Usage: $0 endpoint query"
exit 1
fi
#set your darkowl api keys here
APIPUBLIC=""
APIPRIVATE=""

if [ -z "${APIPUBLIC}" -o -z "${APIPRIVATE}" ]; then
echo "Please add your APIKEY and SECRET to the script."
exit 1
fi

OPENSSL=/usr/bin/openssl
CURL=/usr/bin/curl
RFC1123DATE=$(date -u +%a,\ %d\ %b\ %Y\ %H:%M:%S\ GMT)
ENDPOINT="$1"
QUERY="$2"
SERVER="https://api.darkowl.com"
case "$1" in
documents/) URIPATH="/api/v1/${ENDPOINT}${QUERY}";;
*) URIPATH="/api/v1/${ENDPOINT}?${QUERY}";;
esac
AUTH=$(printf GET"$URIPATH""$RFC1123DATE" | ${OPENSSL} dgst -sha1 -hmac "$APIPRIVATE" -binary | base64)
#This just returns the results (-s), add -l -v for verbose headers, or just -i for response headers<
${CURL} -s -H "Authorization: OWL ${APIPUBLIC}:${AUTH}" -H "Date: ${RFC1123DATE}" ${SERVER}${URIPATH}