feat: emoji-visualized gold + weather entertainment plugins

gold: headline price is now USD per gram (XAU/oz divided by 31.1034768),
ounce + bid/ask as reference, timestamp cleaned of timezone/fraction.
weather: per-WMO-code emoji (day/night-aware clear sky), temp + feels
like, humidity, wind. Both verified live; safe in default plain send mode.
This commit is contained in:
Your Name
2026-08-09 14:14:14 +00:00
parent 0acdf3b346
commit f8b5c08ee5
3 changed files with 50 additions and 19 deletions
+2
View File
@@ -16,6 +16,8 @@ summary (newest last).
## Done
- **2026-08-09** — Entertainment plugins `gold` + `weather` now emit emoji-visualized Telegram messages. Gold: headline is USD/**gram** (XAU/oz ÷ 31.1034768), ounce as reference, bid/ask, cleaned timestamp (`+00:00`/fractional seconds stripped). Weather: per-WMO-code emoji (☀️/🌙 day-night aware for clear sky), °C + feels-like, humidity, wind with unit spacing. Both verified live; emojis are safe in the default plain send mode.
- **2026-08-09** — `pos tree`: prints the live `pos` command tree (categories → commands → subcommands) by deriving the hierarchy from `bin/pos-*` filenames + `# POS:` / `# POS_SUBCMDS:` headers, so it always matches what the dispatcher can run. Category-less like `pos-config`; `--depth N` limit; `pos help tree` works. Docs: POS.md `tree` section, `bin/pos` usage example, `make gen` regenerated the AGENT_Context tree/dispatch/filetable + `_pos_flags[tree]`.
- **2026-08-09** — Telegram sender `config` / `config set` removed — redundant with `pos config telegram` (same `# POS_CONFIG:` registry, masked token display + input, chat-id validation, chmod 600); sender/listener error hints now point there. Deep-review bugfixes in the same commit: mapped `/command` values containing `|` are no longer truncated (`load_map` switched from a `|` to a `\x1f` delimiter — previously `/up=echo hi | head` silently ran `echo hi `); `pos entertainment send <plugin> [args…]` actually forwards the extra args (every arg was `shift`ed in the flag loop, so `$@` was empty) and passes `--` before the message so leading-`-` plugin output isn't parsed as an option; `write_config_key` (entertainment-lib) and `cfg_write` (config-ui) replaced unescaped `sed -i "s|^K=.*|K=\"$v\"|"` with grep-v+append so values with `&`/`|`/`\` no longer mangle (also the path all telegram config now flows through); `sync_systemd` daemon-reloads after removing timer units; `digits` config validation accepts negative group/supergroup chat ids (`-100…`).
+11 -5
View File
@@ -2,6 +2,7 @@
set -euo pipefail
# Entertainment plugin: gold spot price (XAU/USD) via goldprice.dev (no API key).
# Headline price is USD per gram; the ounce quote is shown as reference.
# POS_PLUGIN: gold
# Contract: stdout is the message sent by 'pos entertainment send gold'.
@@ -29,15 +30,20 @@ if ! json="$(curl -fsS --max-time 20 \
err "Failed to fetch gold price from goldprice.dev"
fi
symbol="$(jq -r '.symbols[0].symbol' <<<"$json")"
price="$(jq -r '.symbols[0].price' <<<"$json")"
bid="$(jq -r '.symbols[0].bid' <<<"$json")"
ask="$(jq -r '.symbols[0].ask' <<<"$json")"
unit="$(jq -r '.symbols[0].unit' <<<"$json")"
when="$(jq -r '.symbols[0].computed_at' <<<"$json")"
when="${when/T/ }"; when="${when%Z}"
when="${when:0:19}"
when="${when/T/ }"
[ -n "$price" ] || err "No price received"
printf 'Gold spot (%s/USD): %s USD/%s\nBid %s · Ask %s\nas of %s UTC\n' \
"$symbol" "$price" "$unit" "$bid" "$ask" "$when"
# XAU spot is quoted per troy ounce (31.1034768 g) — convert to USD/gram.
per_g="$(awk -v p="$price" -v o="31.1034768" 'BEGIN{printf "%.2f", p/o}')"
printf '🪙 Gold (XAU/USD)\n'
printf '💰 1 gram $%s\n' "$per_g"
printf '⚖️ 1 oz $%s\n' "$price"
printf '📉 Bid $%s · 📈 Ask $%s\n' "$bid" "$ask"
printf '🕐 %s UTC\n' "$when"
+37 -14
View File
@@ -2,6 +2,7 @@
set -euo pipefail
# Entertainment plugin: current weather via Open-Meteo (no API key).
# Emoji + em-dash layout for Telegram; day/night-aware for clear skies.
# POS_PLUGIN: weather
# POS_KEYS: WEATHER_LAT <latitude> (required)
# POS_KEYS: WEATHER_LON <longitude> (required)
@@ -27,19 +28,36 @@ load_config() {
done < <(grep -E '^[A-Z_]+=' "$CONFIG_FILE" || true)
}
# First arg: weather code; second arg: is_day (1=day). Prints the emoji.
wmo_emoji() {
case "$1" in
0) [ "${2:-1}" = "1" ] && echo "☀️" || echo "🌙" ;;
1) echo "🌤️" ;;
2) echo "⛅" ;;
3) echo "☁️" ;;
45|48) echo "🌫️" ;;
51|53|55) echo "🌦️" ;;
61|63|65) echo "🌧️" ;;
71|73|75) echo "❄️" ;;
80|81|82) echo "🌧️" ;;
95|96|99) echo "⛈️" ;;
*) echo "🌡️" ;;
esac
}
wmo_desc() {
case "$1" in
0) echo "clear sky" ;;
1) echo "mainly clear" ;;
2) echo "partly cloudy" ;;
3) echo "overcast" ;;
45|48) echo "fog" ;;
51|53|55) echo "drizzle" ;;
61|63|65) echo "rain" ;;
71|73|75) echo "snow" ;;
80|81|82) echo "rain showers" ;;
95|96|99) echo "thunderstorm" ;;
*) echo "weather code $1" ;;
0) echo "Clear sky" ;;
1) echo "Mainly clear" ;;
2) echo "Partly cloudy" ;;
3) echo "Overcast" ;;
45|48) echo "Fog" ;;
51|53|55) echo "Drizzle" ;;
61|63|65) echo "Rain" ;;
71|73|75) echo "Snow" ;;
80|81|82) echo "Rain showers" ;;
95|96|99) echo "Thunderstorm" ;;
*) echo "Weather code $1" ;;
esac
}
@@ -71,7 +89,7 @@ load_config
label="${WEATHER_CITY:-$WEATHER_LAT,$WEATHER_LON}"
if ! json="$(curl -fsS --max-time 20 \
"https://api.open-meteo.com/v1/forecast?latitude=${WEATHER_LAT}&longitude=${WEATHER_LON}&current=temperature_2m,relative_humidity_2m,apparent_temperature,weather_code,wind_speed_10m")"; then
"https://api.open-meteo.com/v1/forecast?latitude=${WEATHER_LAT}&longitude=${WEATHER_LON}&current=temperature_2m,relative_humidity_2m,apparent_temperature,weather_code,wind_speed_10m,is_day")"; then
err "Failed to fetch weather from Open-Meteo"
fi
@@ -80,8 +98,13 @@ feels="$(jq -r '.current.apparent_temperature' <<<"$json")"
humidity="$(jq -r '.current.relative_humidity_2m' <<<"$json")"
code="$(jq -r '.current.weather_code' <<<"$json")"
wind="$(jq -r '.current.wind_speed_10m' <<<"$json")"
is_day="$(jq -r '.current.is_day' <<<"$json")"
unit_temp="$(jq -r '.current_units.temperature_2m' <<<"$json")"
unit_wind="$(jq -r '.current_units.wind_speed_10m' <<<"$json")"
printf 'Weather in %s: %s, %s%s (feels like %s%s), humidity %s%%, wind %s%s\n' \
"$label" "$(wmo_desc "$code")" "$temp" "$unit_temp" "$feels" "$unit_temp" "$humidity" "$wind" "$unit_wind"
emoji="$(wmo_emoji "$code" "$is_day")"
printf '%s %s · %s\n' "$emoji" "$(wmo_desc "$code")" "$label"
printf '🌡️ %s%s (feels like %s%s)\n' "$temp" "$unit_temp" "$feels" "$unit_temp"
printf '💧 Humidity %s%%\n' "$humidity"
printf '💨 Wind %s %s\n' "$wind" "$unit_wind"