aboutsummaryrefslogtreecommitdiffstats
path: root/examples/tools/weather.sh
blob: 7af4964bfddb9711f3e17e4e839b00854e4d6b30 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#!/bin/bash
# desktop-assistant tool: weather from OpenWeatherMap.
# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# weather.sh [PLACE] [WHEN]: PLACE empty = home, WHEN now (default), today
# or tomorrow. WEATHER_ENV names an env file with KEY, CITY, COUNTRY and
# UNITS (the conky-theme-udt format). Home "now" reuses that project's
# cache when it is under 30 minutes old, so it costs no request.
# ponytail: wind is converted as metric (m/s to km/h); UNITS=imperial
# would need mph instead.

set -uo pipefail

env_file="${WEATHER_ENV:-$HOME/.config/udt/weather.env}"
[ -r "$env_file" ] || { echo "no weather env file at $env_file" >&2; exit 1; }
# shellcheck source=/dev/null
. "$env_file"
[ -n "${KEY:-}" ] || { echo "KEY is empty in $env_file" >&2; exit 1; }

place="${1:-}"
when="${2:-}"
q="${place:-$CITY,$COUNTRY}"

get() {
    curl -fsS --max-time 8 --get "https://api.openweathermap.org/data/2.5/$1" \
        --data-urlencode "appid=$KEY" --data-urlencode "units=${UNITS:-metric}" \
        --data-urlencode "q=$q" \
        || { echo "weather request failed for $q" >&2; exit 1; }
}

case "${when:-now}" in
now)
    cache="${XDG_CACHE_HOME:-$HOME/.cache}/udt/weather.json"
    if [ -z "$place" ] && [ -n "$(find "$cache" -mmin -30 2>/dev/null)" ]; then
        json=$(cat "$cache")
    else
        json=$(get weather) || exit 1
    fi
    jq -r '"\(.name), \(.sys.country): \(.weather[0].description), \(.main.temp|round) degrees, feels like \(.main.feels_like|round), humidity \(.main.humidity)%, wind \(.wind.speed*3.6|round) km/h"' <<<"$json"
    ;;
today|tomorrow)
    day=$(date -d "$when" +%F)
    json=$(get forecast) || exit 1
    jq -r --arg day "$day" '
        "\(.city.name), \(.city.country)" as $c
        | [.list[] | select((.dt | localtime | strftime("%Y-%m-%d")) == $day)]
        | if length == 0 then "no forecast for \($c) on \($day)"
          else "\($c) \($day): " + (map("\(.dt | localtime | strftime("%H:%M")) \(.weather[0].description) \(.main.temp|round) degrees") | join(", "))
          end' <<<"$json"
    ;;
*)
    echo "when must be now, today or tomorrow" >&2
    exit 1
    ;;
esac