From 73f8ae2f828566ee82d16ae39e17190b7f9e369b Mon Sep 17 00:00:00 2001 From: KeeganForelight Date: Sun, 15 Jan 2023 17:30:17 -0500 Subject: [PATCH] fixed to just set API key locally --- server_weather.sh | 69 ---------- client_weather.sh => weather.sh | 217 ++++++++++++++++++++------------ 2 files changed, 137 insertions(+), 149 deletions(-) delete mode 100755 server_weather.sh rename client_weather.sh => weather.sh (57%) diff --git a/server_weather.sh b/server_weather.sh deleted file mode 100755 index a96bb79..0000000 --- a/server_weather.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/bin/bash - -# server version, calls server for actual API info -WORKING_DIR="$HOME/.local/share/weather" -KEY_FILE="$WORKING_DIR/.env" - -# set $API_KEY - -if [[ ! -e "$KEY_FILE" ]] ; then - echo "No API key found!" - exit 1 -fi - -source "$KEY_FILE" - -lookup_location() { - # search for a location - url="http://api.openweathermap.org/geo/1.0/direct?q=$SEARCH&appid=$API_KEY&limit=5" - res=$(curl --silent -fL "$url") - echo "$res" -} - -lookup_zipcode() { - # lookup based on zipcode - url="http://api.openweathermap.org/geo/1.0/zip?zip=$ZIPCODE&appid=$API_KEY&limit=5" - res=$(curl --silent -fL "$url") - echo "$res" -} - -get_weather() { - # calls server for weather based on $COORDS - LAT=$(echo "$COORDS" | awk -F , '{print $1}') - LON=$(echo "$COORDS" | awk -F , '{print $2}') - - url="https://api.openweathermap.org/data/2.5/weather?lat=$LAT&lon=$LON&appid=$API_KEY&units=$UNITS" - res=$(curl --silent -fL "$url") - echo "$res" -} - -while getopts "c:s:z:u:" opt; do - case "$opt" in - 'c' ) - COORDS="$OPTARG" - ;; - 's' ) - SEARCH="$OPTARG" - ;; - 'z' ) - ZIPCODE="$OPTARG" - ;; - 'u' ) - UNITS="$OPTARG" - ;; - '?' ) - echo "ERROR: UNRECOGNZIED ARGUMENT" - exit 1 - ;; - esac -done - -if [[ -n "$COORDS" ]] ; then - get_weather -elif [[ -n "$SEARCH" ]] ; then - lookup_location -elif [[ -n "$ZIPCODE" ]] ; then - lookup_zipcode -fi - -exit 0 diff --git a/client_weather.sh b/weather.sh similarity index 57% rename from client_weather.sh rename to weather.sh index d938324..1109ace 100755 --- a/client_weather.sh +++ b/weather.sh @@ -3,11 +3,13 @@ # client version, calls server for actual API info usage() { cat <][-i][-h] +usage: $0 [-a KEY][-s QUERY | -z ZIPCODE][-u ][-p][-i][-l][-h] Queries OpenWeatherMapAPI for weather or lat/long options: + -a, --apikey set the api key to use to KEY + -l, --location print the location being used -p, --pretty enables nerdfont symbols -z, --zipcode returns the weather for ZIPCODE -s, --search returns the weather for QUERY @@ -21,20 +23,13 @@ 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" -# URL -WEATHER_CALL="https://api.openweathermap.org/data/2.5/weather?lat=$LAT&lon=$LON&appid=$API_KEY&units=$UNITS" +WEATHER_FILE=".env" + TIMEOUT=60 # timeout for info TIME=$(date +%s) @@ -43,6 +38,9 @@ if [[ ! -d "$WORKING_DIR" ]] ; then mkdir -p "$WORKING_DIR" fi +# going to weather directory +cd "$WORKING_DIR" + print_weather() { # prints the weather @@ -64,84 +62,94 @@ print_weather() { 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" + printf '%.1f*%s %d%% RH in %s\n' $TEMPERATURE $UNIT $HUMIDITY "$CITY" fi # save before exiting save_info } +print_location() { + # prints the location being used for the weather + + # uses reverse geocoding + LOCATION_URL="https://api.openweathermap.org/geo/1.0/reverse?lat=$LAT&lon=$LON&appid=$API_KEY" + LOCATION=$(curl --silent -fL "$LOCATION_URL" | gojq '.[0] | del(.local_names)') + + name=$(echo "$LOCATION" | gojq '.name' | tr -d '"') + state=$(echo "$LOCATION" | gojq '.state' | tr -d '"') + country=$(echo "$LOCATION" | gojq '.country' | tr -d '"') + + printf 'Location is set to %s in %s, %s\n' "$name" "$state" "$country" +} + 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 - LOCATION_CALL="https://api.openweathermap.org/data/2.5/weather?$SEARCH&appid=$API_KEY" -g if [[ -n "$SEARCH" ]] ; then + if [[ -n "$SEARCH" ]] ; then # search - RESULTS=$($(curl --silent -fL "$LOCATION_CALL") | gojq "del(.[].local_names)") - NUM_RESULTS=$(echo "$RESULTS" | gojq '. | length') - SELECTION=0 + LOCATION_URL="https://api.openweathermap.org/geo/1.0/$SEARCH&appid=$API_KEY&limit=5" + RESULTS=$(curl --silent -fL "$LOCATION_URL") + # check if its an array + is_array=$(echo "$RESULTS" | gojq 'if type=="array" then 1 else 0 end') - if [[ $NUM_RESULTS -gt 1 ]] ; then - # create menu for user + if [[ $is_array -eq 1 ]] ; then + # returned result is an array - 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 + NUM_RESULTS=$(echo "$RESULTS" | gojq '. | length') + if [[ $NUM_RESULTS -gt 1 ]] ; then + # provide menu for multiple results + 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 + 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 + if [[ $exit_status -eq 1 || $exit_satus -eq 255 ]] ; then + # canceled or escaped + echo "Location not changed" + exit 0 + fi + + # fix index + SELECTION=$(($SELECTION - 1)) fi - - # fix index - SELECTION=$(($SELECTION - 1)) + # updating result + RESULTS=$(echo "$RESULTS" | gojq ".[$SELECTION]") 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") @@ -151,7 +159,7 @@ g if [[ -n "$SEARCH" ]] ; then # check if [[ -z "$LAT" || -z "$LON" ]] ; then - echo "No location found!" + echo "No location found!" >&2 exit 1 fi @@ -160,41 +168,65 @@ g if [[ -n "$SEARCH" ]] ; then } get_weather() { - # calls server for weather based on $LAT, $LONG + # calls api 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 + # units set to metric UNIT="C" UNITS="metric" - else - # imperial + elif [[ "$UNIT" =~ ^[Ff]$ || -z "$UNIT" ]] ; then + # imperial (default) UNIT="F" UNITS="imperial" + else + printf 'Unit %s unrecognized\n' "$UNIT" >&2 + exit 1 fi - WEATHER=$($WEATHER_CALL "-c $LAT,$LON -u $UNITS") - echo "$WEATHER" | gojq '.' + WEATHER_URL="https://api.openweathermap.org/data/2.5/weather?lat=$LAT&lon=$LON&appid=$API_KEY&units=$UNITS" + + WEATHER=$(curl --silent -fL "$WEATHER_URL") + 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" +} + +update_key() { + # updates the API key used + + printf 'Testing API key %s... ' "$API_KEY" + WEATHER_URL="https://api.openweathermap.org/data/2.5/weather?lat=42.3736&lon=71.1097&appid=$API_KEY" + CODE=$(curl --silent "$WEATHER_URL" | gojq '.cod' | tr -d '"') + + if [[ $CODE -eq 401 ]] ; then + # API_KEY error + printf 'Error: Invalid API Key "%s"!\n' "$API_KEY" >&2 + exit 1 + fi + printf 'Success: Key Updated!\n' + + # saving new key + save_info } save_info() { - # saves set env vars to files + # saves set env vars to file printf '%s\n' \ -"API_KEY=$API_KEY" +"API_KEY=$API_KEY" \ +"PARSER=$PARSER" \ "LAT=$LAT" \ "LON=$LON" \ "CITY=$CITY" \ "TEMPERATURE=$TEMPERATURE" \ "HUMIDITY=$HUMIDITY" \ +"UNIT=$UNIT" \ "WEATHER_ICON=$WEATHER_ICON" \ "EXPIRATION=$EXPIRATION" > "$WEATHER_FILE" } @@ -202,15 +234,22 @@ save_info() { load_info() { # loads env vars if [[ ! -e "$WEATHER_FILE" ]] ; then - # generates blank info + # generates blank info on fresh installs + + # test for gojq + PARSER=gojq + if ! command -v $PARSER ; then + # test for jq + PARSER=jq + if ! command -v $PARSER ; then + echo "$1 depends on jq or gojq" + exit 1 + fi + fi save_info fi source $WEATHER_FILE - if [[ -z "$API_KEY" ]] ; then - echo "No API Key found!" - exit 1 - fi } get_icon() { @@ -290,6 +329,8 @@ for arg in "$@"; do shift case "$arg" in '--zipcode') set -- "$@" "-z" ;; + '--location') set -- "$@" "-l" ;; + '--apikey') set -- "$@" "-a" ;; '--coords') set -- "$@" "-c" ;; '--search') set -- "$@" "-s" ;; '--units') set -- "$@" "-u" ;; @@ -300,16 +341,27 @@ for arg in "$@"; do esac done -while getopts "chpiz:s:u:" opt; do +# loading the info +load_info + +while getopts "chpliz:s:u:a:" opt; do case "$opt" in + 'a' ) + API_KEY="$OPTARG" + update_key + ;; 'u' ) UNIT="$OPTARG" ;; + 'l' ) + print_location + exit 0 + ;; 'z' ) - [ -n "$ZIPCODE" ] && usage 1 || ZIPCODE="zip=$OPTARG" + [ -n "$SEARCH" ] && usage 1 || SEARCH="/zip?zip=$OPTARG" ;; 's' ) - [ -n "$SEARCH" ] && usage 1 || SEARCH="q=$OPTARG" + [ -n "$SEARCH" ] && usage 1 || SEARCH="/direct?q=$OPTARG" ;; 'p' ) PRETTY=true @@ -327,12 +379,17 @@ while getopts "chpiz:s:u:" opt; do esac done -load_info +# test for APIKEY +if [[ -z "$API_KEY" ]] ; then + echo "No API Key found!" + exit 1 +fi -if [[ -n "$ZIPCODE" || -n "$SEARCH" ]] ; then +if [[ -n "$SEARCH" ]] ; then # perform search get_location fi -# print the weather -print_weather +if [[ -z "$QUIET" ]] ; then + print_weather +fi