332 lines
9.1 KiB
Bash
Executable File
332 lines
9.1 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# client version, calls server for actual API info
|
|
usage() {
|
|
cat <<EOF
|
|
usage: $0 [-p][-s QUERY | -z ZIPCODE][-u <c|f>][-i][-h]
|
|
|
|
Queries OpenWeatherMapAPI for weather or lat/long
|
|
|
|
options:
|
|
-p, --pretty enables nerdfont symbols
|
|
-z, --zipcode returns the weather for ZIPCODE
|
|
-s, --search returns the weather for QUERY
|
|
-u, --units sets the temperature units
|
|
-i, --icon_test tests the icons used
|
|
-h, --help displays this message
|
|
|
|
ZIPCODE sets the location to the given zipcode
|
|
to narrow results, include the ISO country code
|
|
ex) -z "02139,US"
|
|
|
|
QUERY sets the location to the search
|
|
QUERY format is "CITY,REGION,COUNTRY" where
|
|
CITY is any city
|
|
REGION is Region or State
|
|
COUNTRY is ISO Country Code
|
|
to narrow results, try more specific searches
|
|
ex) -s "Cambridge" will return places in the UK
|
|
ex) -s "Cambridge,US" will return Cambridge, MA
|
|
EOF
|
|
exit $1
|
|
}
|
|
|
|
WORKING_DIR="$HOME/.local/share/weather"
|
|
WEATHER_FILE="$WORKING_DIR/.env"
|
|
WEATHER_CALL="ssh spinach@git.keegandeppe.com weather"
|
|
TIMEOUT=60 # timeout for info
|
|
TIME=$(date +%s)
|
|
|
|
|
|
if [[ ! -d "$WORKING_DIR" ]] ; then
|
|
mkdir -p "$WORKING_DIR"
|
|
fi
|
|
|
|
print_weather() {
|
|
# prints the weather
|
|
|
|
# check to see if it is expired
|
|
check_expiration
|
|
|
|
# trimming state
|
|
if [[ "$PRETTY" = true ]] ; then
|
|
# print with NF icons
|
|
icon=$(get_icon "$WEATHER_ICON")
|
|
|
|
# checking units
|
|
if [[ "$UNIT" == "C" ]] ; then
|
|
temp_icon=$(echo -e '\ufa03')
|
|
else
|
|
temp_icon=$(echo -e '\ufa04')
|
|
fi
|
|
# printing
|
|
printf '%s %.1f%s%d\ue373 in %s\n' $icon $TEMPERATURE "$temp_icon" "$HUMIDITY" "$CITY"
|
|
else
|
|
# default printing
|
|
printf "%.1f *$UNIT %d%% Humidity in %s\n" $TEMPERATURE $HUMIDITY "$CITY"
|
|
fi
|
|
|
|
# save before exiting
|
|
save_info
|
|
}
|
|
|
|
check_expiration() {
|
|
# checks if the info is expired
|
|
if [[ $TIME -gt $EXPIRATION ]] ; then
|
|
# expired
|
|
echo "expired"
|
|
get_weather
|
|
fi
|
|
}
|
|
|
|
get_location() {
|
|
# searching for user location
|
|
|
|
if [[ -n "$SEARCH" ]] ; then
|
|
# search
|
|
RESULTS=$($WEATHER_CALL -s "$SEARCH" | gojq "del(.[].local_names)")
|
|
NUM_RESULTS=$(echo "$RESULTS" | gojq '. | length')
|
|
SELECTION=0
|
|
|
|
if [[ $NUM_RESULTS -gt 1 ]] ; then
|
|
# create menu for user
|
|
|
|
for ((i=0; i < $NUM_RESULTS; i++)); do
|
|
# adding options
|
|
res=$(echo "$RESULTS" | gojq ".[$i]")
|
|
name=$(echo "$res" | gojq '.name' | tr -d '"')
|
|
state=$(echo "$res" | gojq '.state' | tr -d '"')
|
|
country=$(echo "$res" | gojq '.country' | tr -d '"')
|
|
opt=$(printf '%s %s, %s' "$name" "$state" "$country")
|
|
OPTIONS+=($(($i+1)) "$opt")
|
|
done
|
|
|
|
# executing dialog menu
|
|
exec 3>&1
|
|
SELECTION=$(dialog \
|
|
--title 'Multiple Locations Found!' \
|
|
--clear \
|
|
--cancel-label 'Exit' \
|
|
--ok-label 'Select' \
|
|
--menu 'Please select the desired location. If none of the options look correct, try making refining your search by including a country code and/or region' 0 0 4 \
|
|
"${OPTIONS[@]}" \
|
|
2>&1 1>&3)
|
|
exit_status=$?
|
|
exec 3>&-
|
|
clear
|
|
|
|
if [[ $exit_status -eq 1 || $exit_satus -eq 255 ]] ; then
|
|
# canceled or escaped
|
|
echo "Try again: $0 -s 'CITY,REGION,COUNTRY'"
|
|
exit 0
|
|
fi
|
|
|
|
# fix index
|
|
SELECTION=$(($SELECTION - 1))
|
|
fi
|
|
|
|
# Update info
|
|
|
|
LAT=$(echo "$RESULTS" | gojq ".[$SELECTION].lat")
|
|
LON=$(echo "$RESULTS" | gojq ".[$SELECTION].lon")
|
|
CITY=$(echo "$RESULTS" | gojq ".[$SELECTION].name" | tr -d '"')
|
|
|
|
elif [[ -n "$ZIPCODE" ]] ; then
|
|
# searching for zipcode
|
|
|
|
RESULTS=$($WEATHER_CALL -z "$ZIPCODE")
|
|
LAT=$(echo "$RESULTS" | gojq ".lat")
|
|
LON=$(echo "$RESULTS" | gojq ".lon")
|
|
CITY=$(echo "$RESULTS" | gojq ".name" | tr -d '"')
|
|
|
|
else
|
|
# no search, default to user IP
|
|
url="http://ip-api.com/csv/?fields=252"
|
|
res=$(curl --silent -fL "$url")
|
|
LAT=$(awk -F , '{print $5}' <<<"$res")
|
|
LON=$(awk -F , '{print $6}' <<<"$res")
|
|
CITY=$(awk -F , '{print $3}' <<<"$res")
|
|
fi
|
|
|
|
# check
|
|
if [[ -z "$LAT" || -z "$LON" ]] ; then
|
|
echo "No location found!"
|
|
exit 1
|
|
fi
|
|
|
|
# force refresh
|
|
EXPIRED=0
|
|
}
|
|
|
|
get_weather() {
|
|
# calls server for weather based on $LAT, $LONG
|
|
if [[ -z "$LAT" || -z "$LON" ]] ; then
|
|
# no lat or lon
|
|
get_location
|
|
fi
|
|
|
|
# only update weather every 30 seconds
|
|
if [[ "$UNIT" =~ ^[Cc]$ ]] ; then
|
|
# units set to celsius
|
|
UNIT="C"
|
|
UNITS="metric"
|
|
else
|
|
# imperial
|
|
UNIT="F"
|
|
UNITS="imperial"
|
|
fi
|
|
|
|
WEATHER=$($WEATHER_CALL "-c $LAT,$LON -u $UNITS")
|
|
echo "$WEATHER" | gojq '.'
|
|
TEMPERATURE=$(echo $WEATHER | gojq -r '.main.temp')
|
|
HUMIDITY=$(echo $WEATHER | gojq -r '.main.humidity')
|
|
WEATHER_ICON=$(echo $WEATHER | gojq -r '.weather[0].icon')
|
|
EXPIRATION=$(($TIME+$TIMEOUT))
|
|
echo "$TEMPERATURE $HUMIDITY $WEATHER_ICON"
|
|
}
|
|
|
|
save_info() {
|
|
# saves set env vars to files
|
|
printf '%s\n' \
|
|
"LAT=$LAT" \
|
|
"LON=$LON" \
|
|
"CITY=$CITY" \
|
|
"TEMPERATURE=$TEMPERATURE" \
|
|
"HUMIDITY=$HUMIDITY" \
|
|
"WEATHER_ICON=$WEATHER_ICON" \
|
|
"EXPIRATION=$EXPIRATION" > "$WEATHER_FILE"
|
|
}
|
|
|
|
load_info() {
|
|
# loads env vars
|
|
if [[ ! -e "$WEATHER_FILE" ]] ; then
|
|
# generates blank info
|
|
save_info
|
|
fi
|
|
source $WEATHER_FILE
|
|
}
|
|
|
|
get_icon() {
|
|
# sets NF symbols
|
|
tod=$(echo "$1" | sed --expression='s/[0-9]//g')
|
|
conditions=$(echo "$1" | sed --expression='s/[^0-9]//g')
|
|
|
|
# getting icon
|
|
if [[ "$tod" == "d" ]] ; then
|
|
# day icons
|
|
case "$conditions" in
|
|
"01") echo -e '\ue30d' ;; # clear
|
|
"02") echo -e '\ue30c' ;; # scattered clouds
|
|
"03") echo -e '\ue302' ;; # broken clouds
|
|
"04") echo -e '\ue312' ;; # cloudy
|
|
"09") echo -e '\ue309' ;; # showers
|
|
"10") echo -e '\ue308' ;; # rain
|
|
"11") echo -e '\ue30f' ;; # thunderstorm
|
|
"13") echo -e '\uf2dc' ;; # snow
|
|
"50") echo -e '\ue303' ;; # mist
|
|
* ) echo -e '\ue374' ;; # unknown
|
|
esac
|
|
elif [[ "$tod" == "n" ]] ; then
|
|
# night icons
|
|
case "$conditions" in
|
|
"01") echo -e '\ue32b' ;; # clear
|
|
"02") echo -e '\ue379' ;; # scattered clouds
|
|
"03") echo -e '\ue37e' ;; # broken clouds
|
|
"04") echo -e '\ue312' ;; # cloudy
|
|
"09") echo -e '\ue326' ;; # showers
|
|
"10") echo -e '\ue325' ;; # rain
|
|
"11") echo -e '\ue32a' ;; # thunderstorm
|
|
"13") echo -e '\uf2dc' ;; # snow
|
|
"50") echo -e '\ue346' ;; # mist
|
|
* ) echo -e '\ue374' ;; # unknown
|
|
esac
|
|
else
|
|
echo "TOD not recognized"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
icon_test() {
|
|
#tests icons
|
|
printf 'Testing weather icons\nIf any look broken, check that NerdFont is installed\n'
|
|
|
|
printf '\nDay:\n'
|
|
printf 'Clear: \ue30d\n'
|
|
printf 'Partly Cloudy: \ue30c\n'
|
|
printf 'Cloudy: \ue302\n'
|
|
printf 'Very Cloudy: \ue312\n'
|
|
printf 'Showers: \ue309\n'
|
|
printf 'Rain: \ue308\n'
|
|
printf 'Thunderstorm: \ue30f\n'
|
|
printf 'Snow: \uf2dc\n'
|
|
printf 'Fog: \ue303\n'
|
|
# night icons
|
|
printf '\nNight:\n'
|
|
printf 'Clear: \ue32b\n'
|
|
printf 'Partly Cloudy: \ue379\n'
|
|
printf 'Cloudy: \ue37e\n'
|
|
printf 'Very Cloudy: \ue312\n'
|
|
printf 'Showers: \uf2dc\n'
|
|
printf 'Rain: \ue325\n'
|
|
printf 'Thunderstorm: \ue32a\n'
|
|
printf 'Snow: \uf2dc\n'
|
|
printf 'Fog: \ue346\n'
|
|
|
|
printf '\nAssorted:\n'
|
|
printf 'Degrees (F) \ufa04\n'
|
|
printf 'Degrees (C) \ufa03\n'
|
|
printf '%% Humidity \ue373\n'
|
|
}
|
|
|
|
# shifting longform
|
|
for arg in "$@"; do
|
|
shift
|
|
case "$arg" in
|
|
'--zipcode') set -- "$@" "-z" ;;
|
|
'--coords') set -- "$@" "-c" ;;
|
|
'--search') set -- "$@" "-s" ;;
|
|
'--units') set -- "$@" "-u" ;;
|
|
'--pretty') set -- "$@" "-p" ;;
|
|
'--icon_test') set -- "$@" "-i" ;;
|
|
'--help') set -- "$@" "-h" ;;
|
|
*) set -- "$@" "$arg" ;;
|
|
esac
|
|
done
|
|
|
|
while getopts "chpiz:s:u:" opt; do
|
|
case "$opt" in
|
|
'u' )
|
|
UNIT="$OPTARG"
|
|
;;
|
|
'z' )
|
|
[ -n "$ZIPCODE" ] && usage 1 || ZIPCODE="$OPTARG"
|
|
;;
|
|
's' )
|
|
[ -n "$SEARCH" ] && usage 1 || SEARCH="$OPTARG"
|
|
;;
|
|
'p' )
|
|
PRETTY=true
|
|
;;
|
|
'i' )
|
|
icon_test
|
|
exit 0
|
|
;;
|
|
'h' )
|
|
usage 0
|
|
;;
|
|
'?' )
|
|
usage 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
load_info
|
|
|
|
if [[ -n "$ZIPCODE" || -n "$SEARCH" ]] ; then
|
|
# perform search
|
|
get_location
|
|
fi
|
|
|
|
# print the weather
|
|
print_weather
|