getquote

Getquote implementation for ledger(1)
Log | Files | Refs | README

getquote (2946B)


      1 #!/bin/sh
      2 #
      3 # Getquote implementation for ledger(1)
      4 #
      5 # Copyright (c) 2026 Jacob R. Edwards <jacob@jacobedwards.org>
      6 #
      7 # Permission to use, copy, modify, and distribute this software for any
      8 # purpose with or without fee is hereby granted, provided that the above
      9 # copyright notice and this permission notice appear in all copies.
     10 #
     11 # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     12 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     14 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     17 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18 
     19 twelve_query() (
     20 	domain=api.twelvedata.com
     21 	printenv TWELVE_DATA_API_KEY >/dev/null || {
     22 		# Let shell do error handling
     23 		TWELVE_DATA_API_KEY="$(cat "$rcdir"/keys/$domain)"
     24 	}
     25 
     26 	func="${1:?function}"
     27 	shift
     28 	IFS='&'
     29 	debug curl -Ss "https://$domain/$func?$*&apikey=${TWELVE_DATA_API_KEY:?key}" |
     30 	    jq -r 'if (.status == "error") then error("API Error: \(.code) (\(.message))") end'
     31 )
     32 
     33 twelve_quote() {
     34 	twelve_query price symbol="$1" |
     35 	    jq -r '
     36 		if (.price == null) then
     37 			error("Unable to get price")
     38 		else
     39 			[ '"\"$1\""', .price, "USD" ] | join("	")
     40 		end'
     41 }
     42 
     43 twelve_exchange() {
     44 	to="${2:-USD}"
     45 	twelve_quote "${1:?symbol}/$to" |
     46 	    awk -vfr="$1" -vto="$to" '{ $1 = fr; $NF = to; print }'
     47 }
     48 
     49 quote() {
     50 	twelve_quote "$@"
     51 }
     52 
     53 exchange() {
     54 	twelve_exchange "$@"
     55 }
     56 
     57 err() {
     58 	echo "$@" 1>&2
     59 	return 1
     60 }
     61 
     62 ledger_prices() (
     63 	IFS=' 	
     64 '
     65 	while read symbol price symbol2 err
     66 	do
     67 		test -n "$err" &&
     68 			err 'Extra input'
     69 		expr "$price" : '^[0-9][0-9]*\(\.[0-9][0-9]*\)\{0,1\}$' >/dev/null ||
     70 			err "'$price': Invalid price ${price:-(empty)}"
     71 		debug date "+%F $symbol $price $symbol2"
     72 	done
     73 )
     74 
     75 fifo() {
     76 	true &
     77 	f=/tmp/fifo$$.$!
     78 	mkfifo "$f"
     79 	echo "$f"
     80 }
     81 
     82 action() {
     83 	: "${1:?symbol}" 
     84 	test -f "$rcdir"/symbols ||
     85 		echo "$1"
     86 	debug getquoteaction "$1" < "$rcdir"/symbols
     87 }
     88 
     89 getquote() (
     90 	action "${1:?symbol}" | {
     91 		read -r symbol action
     92 		case $action in
     93 		('')
     94 			exchange "$symbol" ${2:+"$2"} 2>/dev/null || {
     95 				test "$#" -gt 1 -a "$2" '!=' '$' -a "$2" '!=' 'USD' &&
     96 					err "$2: Expected '$' or 'USD'"
     97 				quote "$symbol"
     98 			} ;;
     99 		(quote|exchange) $action "$symbol" ${2:+"$2"}
    100 		esac
    101 	} | awk -vs="$1" '{ $1 = s; print }'
    102 )
    103 
    104 main() {
    105 	set -e
    106 
    107 	case "$#${1%%[!-]*}" in
    108 	([12]) getquote "$@" ;;
    109 	(*) err 'usage: getquote symbol [exchange_to]' ;;
    110 	esac | ledger_prices
    111 }
    112 
    113 if printenv GETQUOTE_DEBUG >/dev/null
    114 then
    115 	debug() (
    116 		f="$(fifo)"
    117 		trap 'rm -f "$f"' 0
    118 		echo ":! $@" 1>&2
    119 		sed 's/^/:/' < "$f" >&2 &
    120 		"$@" | tee "$f"
    121 	)
    122 	set -x
    123 else
    124 	debug() {
    125 		"$@"
    126 	}
    127 fi
    128 
    129 rcdir="${XDG_CONFIG_HOME:-"$HOME"/.local/config}"/getquote
    130 
    131 set -o pipefail
    132 printenv GETQUOTE_INCLUDE >/dev/null || main "$@"