#!/usr/bin/env rc flag e + API=https://api.pushover.net/1/messages.json fn usage { echo 'usage: pushover.rcsh [send] [-t title] [-p priority] [-s sound] [-d device] [-u url] [-U url_title] [--retry seconds] [--expire seconds] [--html | --monospace] [--dry-run] message...' >[1=2] echo ' pushover.rcsh validate [-d device]' >[1=2] echo ' pushover.rcsh receipt RECEIPT' >[1=2] echo ' pushover.rcsh cancel-receipt RECEIPT' >[1=2] echo >[1=2] echo environment: >[1=2] echo ' PUSHOVER_TOKEN application API token' >[1=2] echo ' PUSHOVER_USER user or group key' >[1=2] echo >[1=2] echo examples: >[1=2] echo ' pushover.rcsh -t "Traefik alert" "Traefik is not 3/3 ready"' >[1=2] echo ' pushover.rcsh -p 1 -s siren "High-priority ingress alert"' >[1=2] exit 1 } fn post { curl -sS $* } fn invalid { echo $* >[1=2] exit 1 } fn validate_priority { if (! ~ $1 -2 -1 0 1 2) { invalid 'Invalid priority: '^$1^' (expected -2, -1, 0, 1, or 2)' } } fn validate_uint { if (! ~ `{printf %s $2 | awk '/^[0-9]+$/ { print "ok" }'} ok) { invalid 'Invalid '^$1^': '^$2^' (expected a positive integer)' } if (~ $2 0) { invalid 'Invalid '^$1^': '^$2^' (expected a positive integer)' } } fn validate_url { if (~ $1 *' '* *' '*) { invalid 'Invalid URL: '^$1^' (must not contain whitespace)' } if (! ~ $1 http://?* https://?*) { invalid 'Invalid URL: '^$1^' (expected http://... or https://...)' } } fn validate_sound { if (! ~ $1 pushover bike bugle cashregister classical cosmic falling gamelan incoming intermission magic mechanical pianobar siren spacealarm tugboat alien climb persistent echo updown vibrate none) { invalid 'Invalid sound: '^$1^' (expected a built-in Pushover sound name)' } } fn validate_device { if (~ $1 ()) { return } if (! whatis jq >/dev/null >[2=1]) { invalid 'Cannot validate device without jq in PATH' } ok=`{curl -sS --max-time 5 \ --form-string token=^$PUSHOVER_TOKEN \ --form-string user=^$PUSHOVER_USER \ --form-string device=^$1 \ https://api.pushover.net/1/users/validate.json \ | jq -r 'if .status == 1 then "ok" else "bad" end'} if (! ~ $ok ok) { invalid 'Invalid device: '^$1 } } if (~ $PUSHOVER_TOKEN ()) { echo PUSHOVER_TOKEN is required >[1=2] exit 1 } if (~ $PUSHOVER_USER ()) { echo PUSHOVER_USER is required >[1=2] exit 1 } cmd=send if (~ $1 send validate receipt cancel-receipt) { cmd=$1 shift } switch($cmd) { case validate device=() while(! ~ $1 ()) { switch($1) { case -d --device shift device=$1 case -h --help usage case * echo Unknown argument: $1 >[1=2] exit 1 } shift } form=(--form-string token=^$PUSHOVER_TOKEN --form-string user=^$PUSHOVER_USER) if (! ~ $device ()) { form=($form --form-string device=^$device) } post $form https://api.pushover.net/1/users/validate.json exit $status case receipt if (! ~ $#* 1) { usage } post --form-string token=^$PUSHOVER_TOKEN https://api.pushover.net/1/receipts/$1.json exit $status case cancel-receipt if (! ~ $#* 1) { usage } post --form-string token=^$PUSHOVER_TOKEN https://api.pushover.net/1/receipts/$1/cancel.json exit $status } host=`{hostname} title=$host^' cli alert' priority=0 sound=() device=() url=() url_title=() retry=60 expire=3600 html=0 monospace=0 dry_run=0 while(! ~ $1 ()) { switch($1) { case -t --title shift title=$1 case -p --priority shift priority=$1 validate_priority $priority case -s --sound shift sound=$1 validate_sound $sound case -d --device shift device=$1 case -u --url shift url=$1 validate_url $url case -U --url-title shift url_title=$1 case --retry shift retry=$1 case --expire shift expire=$1 case --html html=1 case --monospace monospace=1 case --dry-run dry_run=1 case -h --help usage case * break } shift } if (~ $#* 0) { usage } validate_priority $priority validate_uint retry $retry validate_uint expire $expire if (~ $priority 2) { if (! ~ $retry [3-9][0-9] [1-9][0-9][0-9]* ) { invalid 'Invalid retry: '^$retry^' (priority 2 requires at least 30 seconds)' } if (! ~ $expire [1-9] [1-9][0-9] [1-9][0-9][0-9] [1-9][0-9][0-9][0-9] 10[0-7][0-9][0-9] 10800) { invalid 'Invalid expire: '^$expire^' (priority 2 requires at most 10800 seconds)' } } if (! ~ $priority 2) { if (! ~ $retry 60) { invalid '--retry is only valid with priority 2' } if (! ~ $expire 3600) { invalid '--expire is only valid with priority 2' } } if (! ~ $url ()) { validate_url $url } if (~ $url () && ! ~ $url_title ()) { invalid '--url-title requires --url' } if (~ $html 1 && ~ $monospace 1) { invalid '--html and --monospace cannot be used together' } if (! ~ $sound ()) { validate_sound $sound } validate_device $device message=$"*#" form=(--form-string token=^$PUSHOVER_TOKEN \ --form-string user=^$PUSHOVER_USER \ --form-string title=^$"title \ --form-string message=^$"message \ --form-string priority=^$priority) if (! ~ $sound ()) { form=($form --form-string sound=^$sound) } if (! ~ $device ()) { form=($form --form-string device=^$device) } if (! ~ $url ()) { form=($form --form-string url=^$url) } if (! ~ $url_title ()) { form=($form --form-string url_title=^$"url_title) } if (~ $html 1) { form=($form --form-string html=1) } if (~ $monospace 1) { form=($form --form-string monospace=1) } if (~ $priority 2) { form=($form --form-string retry=^$retry --form-string expire=^$expire) } if (~ $dry_run 1) { echo token='(redacted)' echo user='(redacted)' echo title=$"title echo message=$"message echo priority=$priority if (! ~ $sound ()) { echo sound=$sound } if (! ~ $device ()) { echo device=$device } if (! ~ $url ()) { echo url=$url } if (! ~ $url_title ()) { echo url_title=$"url_title } if (~ $html 1) { echo html=1 } if (~ $monospace 1) { echo monospace=1 } if (~ $priority 2) { echo retry=$retry echo expire=$expire } exit 0 } post $form $API