Files
dotfiles/hyprland/.local/bin/weather.sh
T

56 lines
2.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# Print the current weather as a short icon+temp string, e.g. "🌦️ +83°F",
# plus -- in --json mode (for waybar) a multi-line "current conditions"
# tooltip. A single cached wttr.in response is served immediately -- even when
# stale -- and refreshed in the background, so a slow network never delays the
# lock screen's first frame or waybar's tooltip. Override the location with
# WEATHER_CITY or edit CITY below.
set -u
CITY="${WEATHER_CITY:-Denver}"
CACHE_DIR="${XDG_RUNTIME_DIR:-/tmp}"
CACHE="${CACHE_DIR}/wttr.cache"
CACHE_MAX_AGE=1800 # 30 minutes
# First line is the waybar text; the following lines are the hover tooltip.
FORMAT='%c+%t%5Cn%5Cn%C%5CnTemperature:+%t+%28feels+like+%f%29%5CnHumidity:+%h%5CnWind:+%w%5CnPrecipitation:+%p%5CnPressure:+%P%5CnUV+index:+%u'
URL="https://wttr.in/${CITY}?format=${FORMAT}"
fetch() {
TMP="${CACHE}.tmp.$$"
if curl -fsS --connect-timeout 2 --max-time 5 "${URL}" > "${TMP}" 2>/dev/null; then
mv "${TMP}" "${CACHE}"
cat "${CACHE}"
else
rm -f "${TMP}" || true
return 1
fi
}
# Fresh cache: use it as-is.
if [ -f "${CACHE}" ] && [ "$(( $(date +%s) - $(stat -c %Y "${CACHE}") ))" -lt "${CACHE_MAX_AGE}" ]; then
BODY="$(cat "${CACHE}")"
# Stale cache: use it immediately, then refresh in the background so the
# caller never blocks. flock keeps a pile-up of refreshes from several clients
# (lock screen, waybar) from running concurrent curls.
elif [ -f "${CACHE}" ]; then
BODY="$(cat "${CACHE}")"
(
exec 9>"${CACHE}.lock"
flock -n 9 || exit 0
fetch >/dev/null 2>&1
) &
disown
# No cache at all: fetch synchronously, but with tight timeouts.
else
BODY="$(fetch)"
fi
if [ "${1:-text}" = "--json" ]; then
TEXT="$(printf '%s' "${BODY}" | head -n 1)"
TOOLTIP="$(printf '%s' "${BODY}" | tail -n +2)"
jq -nc --arg text "${TEXT}" --arg tip "${TOOLTIP}" '{text: $text, tooltip: $tip}'
exit 0
fi
printf '%s' "${BODY}" | head -n 1