Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

endpoint/logic adjustment - back in working state #46

Closed
wants to merge 11 commits into from
132 changes: 58 additions & 74 deletions ticker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@ LC_NUMERIC=C
: ${TMPDIR:=/tmp}
SESSION_DIR="${TMPDIR%/}/ticker.sh-$(whoami)"
COOKIE_FILE="${SESSION_DIR}/cookies.txt"
CRUMB_FILE="${SESSION_DIR}/crumb.txt"
API_ENDPOINT="https://query1.finance.yahoo.com/v8/finance/chart/"
API_SUFFIX="?interval=1d"

# Check if NO_COLOR is set to disable colorization
if [ -z "$NO_COLOR" ]; then
: "${COLOR_GREEN:=$'\e[32m'}"
: "${COLOR_RED:=$'\e[31m'}"
: "${COLOR_RESET:=$'\e[00m'}"
fi

SYMBOLS=("$@")

Expand All @@ -16,99 +24,75 @@ if ! $(type jq > /dev/null 2>&1); then
exit 1
fi

# Adding bc check for colors correct. Thank you @milanico2309
if ! $(type bc > /dev/null 2>&1); then
echo "'bc' is not in the PATH. (See: https://www.gnu.org/software/bc/)"
exit 1
fi

if [ -z "$SYMBOLS" ]; then
echo "Usage: ./ticker.sh AAPL MSFT GOOG BTC-USD"
exit
fi

FIELDS=(symbol marketState regularMarketPrice regularMarketChange regularMarketChangePercent \
preMarketPrice preMarketChange preMarketChangePercent postMarketPrice postMarketChange postMarketChangePercent)
API_ENDPOINT="https://query1.finance.yahoo.com/v7/finance/quote?lang=en-US&region=US&corsDomain=finance.yahoo.com"

if [ -z "$NO_COLOR" ]; then
: "${COLOR_BOLD:=\e[1;37m}"
: "${COLOR_GREEN:=\e[32m}"
: "${COLOR_RED:=\e[31m}"
: "${COLOR_RESET:=\e[00m}"
fi

symbols=$(IFS=,; echo "${SYMBOLS[*]}")
fields=$(IFS=,; echo "${FIELDS[*]}")

[ ! -d "$SESSION_DIR" ] && mkdir -m 700 "$SESSION_DIR"

preflight () {
# rather than "finance", use the "fc" subdomain which doesn't redirect to a consent page
curl --silent --output /dev/null --cookie-jar "$COOKIE_FILE" "https://fc.yahoo.com" \
-H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"
curl --silent -b "$COOKIE_FILE" "https://query1.finance.yahoo.com/v1/test/getcrumb" \
> "$CRUMB_FILE"
curl --silent --output /dev/null --cookie-jar "$COOKIE_FILE" "https://finance.yahoo.com" \
-H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"
}

fetch_quotes () {
curl --silent -b "$COOKIE_FILE" "$API_ENDPOINT&fields=$fields&symbols=$symbols&crumb=$(cat "$CRUMB_FILE")"
fetch_chart () {
local symbol=$1
local url="${API_ENDPOINT}${symbol}${API_SUFFIX}"
curl --silent -b "$COOKIE_FILE" "$url"
}

[ ! -f "$COOKIE_FILE" -o ! -f "$CRUMB_FILE" ] && preflight
results=$(fetch_quotes)
if $(echo "$results" | grep -q '"code":"Unauthorized"'); then
preflight
results=$(fetch_quotes)
fi
[ ! -f "$COOKIE_FILE" ] && preflight

results=$(echo $results | jq '.quoteResponse .result')
# Initialize an array to hold background process IDs
pids=()

query () {
echo $results | jq -r ".[] | select(.symbol == \"$1\") | .$2"
}
for symbol in "${SYMBOLS[@]}"; do
(
# Running in subshell
results=$(fetch_chart "$symbol")

currentPrice=$(echo "$results" | jq -r '.chart.result[0].meta.regularMarketPrice')
previousClose=$(echo "$results" | jq -r '.chart.result[0].meta.chartPreviousClose')
currency=$(echo "$results" | jq -r '.chart.result[0].meta.currency')
symbol=$(echo "$results" | jq -r '.chart.result[0].meta.symbol')

for symbol in $(IFS=' '; echo "${SYMBOLS[*]}" | tr '[:lower:]' '[:upper:]'); do
marketState="$(query $symbol 'marketState')"
# see https://github.com/pstadler/ticker.sh/issues/40
[ "$previousClose" = "null" ] && previousClose="1.0"

priceChange=$(awk -v currentPrice="$currentPrice" -v previousClose="$previousClose" 'BEGIN {printf "%.2f", currentPrice - previousClose}')
percentChange=$(awk -v currentPrice="$currentPrice" -v previousClose="$previousClose" 'BEGIN {printf "%.2f", ((currentPrice - previousClose) / previousClose) * 100}')

if [ -z $marketState ]; then
printf 'No results for symbol "%s"\n' $symbol
continue
if (( $(echo "$priceChange >= 0" | bc -l) )); then
color="$COLOR_GREEN"
elif (( $(echo "$priceChange < 0" | bc -l) )); then
color="$COLOR_RED"
fi

preMarketChange="$(query $symbol 'preMarketChange')"
postMarketChange="$(query $symbol 'postMarketChange')"

if [ $marketState = "PRE" ] \
&& [ $preMarketChange != "0" ] \
&& [ $preMarketChange != "null" ]; then
nonRegularMarketSign='*'
price=$(query $symbol 'preMarketPrice')
diff=$preMarketChange
percent=$(query $symbol 'preMarketChangePercent')
elif [ $marketState != "REGULAR" ] \
&& [ $postMarketChange != "0" ] \
&& [ $postMarketChange != "null" ]; then
nonRegularMarketSign='*'
price=$(query $symbol 'postMarketPrice')
diff=$postMarketChange
percent=$(query $symbol 'postMarketChangePercent')
if [ -z "$NO_COLOR" ]; then
printf "%s%-10s%8.2f%10.2f%8s%6.2f%%%s\n" \
"$color" "$symbol" \
"$currentPrice" "$priceChange" "$color" "$percentChange" \
"$COLOR_RESET"
else
nonRegularMarketSign=''
price=$(query $symbol 'regularMarketPrice')
diff=$(query $symbol 'regularMarketChange')
percent=$(query $symbol 'regularMarketChangePercent')
fi
printf "%-10s%8.2f%10.2f%9.2f%%\n" \
"$symbol" \
"$currentPrice" "$priceChange" "$percentChange"
fi
) &

# see https://github.com/pstadler/ticker.sh/issues/40
[ "$diff" = "null" ] && diff="0.0"
[ "$percent" = "null" ] && percent="0.0"
# Stack PIDs
pids+=($!)

if [ "$diff" = "0" ] || [ "$diff" = "0.0" ]; then
color=
elif ( echo "$diff" | grep -q ^- ); then
color=$COLOR_RED
else
color=$COLOR_GREEN
fi
done

if [ "$price" != "null" ]; then
printf "%-10s$COLOR_BOLD%8.2f$COLOR_RESET" $symbol $price
printf "$color%10.2f%12s$COLOR_RESET" $diff $(printf "(%.2f%%)" $percent)
printf " %s\n" "$nonRegularMarketSign"
fi
# Wait for all background processes to finish
for pid in "${pids[@]}"; do
wait "$pid"
done