From 688779fbc61d48046199d1f45549720e289ce417 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Thu, 21 May 2026 18:56:19 +0200 Subject: Added support for user generated shell scripts: - create a director with shell scripts - call them within the chat with @ - four sample scripts --- cmd/fx | 44 ++++++++++++++++++++++++++++++++++++++++++++ cmd/todo | 16 ++++++++++++++++ cmd/uptime | 29 +++++++++++++++++++++++++++++ cmd/weather | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+) create mode 100755 cmd/fx create mode 100755 cmd/todo create mode 100755 cmd/uptime create mode 100755 cmd/weather (limited to 'cmd') diff --git a/cmd/fx b/cmd/fx new file mode 100755 index 0000000..407c2d0 --- /dev/null +++ b/cmd/fx @@ -0,0 +1,44 @@ +#!/bin/sh +# @fx - exchange rates between USD, EUR, PLN and THB (no arguments) +# +# One keyless request to open.er-api.com (base USD); the six cross-rates +# are derived from it. JSON is parsed with awk so no 'jq' is needed. + +json=$(curl -fsS --max-time 8 "https://open.er-api.com/v6/latest/USD" \ + | tr -d '\n\r') || { echo "fx: rate lookup failed"; exit 1; } + +case "$json" in + *'"result":"success"'*) ;; + *) echo "fx: rate service returned an error"; exit 1 ;; +esac + +printf '%s' "$json" | awk ' +function rate(cur, s) { + if (match($0, "\"" cur "\":[0-9.]+")) { + s = substr($0, RSTART, RLENGTH) + sub(/^.*:/, "", s) + return s + 0 + } + return -1 +} +{ + e = rate("EUR"); p = rate("PLN"); t = rate("THB") + if (e <= 0 || p <= 0 || t <= 0) { + print "fx: incomplete rate data" + exit 1 + } + if (match($0, /"time_last_update_utc":"[^"]*"/)) { + d = substr($0, RSTART, RLENGTH) + sub(/^.*:"/, "", d) + sub(/"$/, "", d) + split(d, w, " ") + print "FX rates " w[1] " " w[2] " " w[3] " " w[4] + } + printf "1 USD = %.4g EUR\n", e + printf "1 USD = %.4g PLN\n", p + printf "1 USD = %.4g THB\n", t + printf "1 EUR = %.4g PLN\n", p / e + printf "1 EUR = %.4g THB\n", t / e + printf "1 PLN = %.4g THB\n", t / p +} +' diff --git a/cmd/todo b/cmd/todo new file mode 100755 index 0000000..7fb796b --- /dev/null +++ b/cmd/todo @@ -0,0 +1,16 @@ +#!/bin/sh +# @todo - print the shared to-do list +# +# The list lives in todo.md next to this script (cmd/todo.md). Edit that +# file directly - on the server or by scp - to change it; @todo only +# reads it, and the next call reflects the edit (no restart). + +file="$(dirname "$0")/todo.md" + +if [ ! -f "$file" ]; then + echo "todo: no list yet - create $file" +elif [ ! -s "$file" ]; then + echo "todo: the list is empty" +else + cat "$file" +fi diff --git a/cmd/uptime b/cmd/uptime new file mode 100755 index 0000000..fef74a8 --- /dev/null +++ b/cmd/uptime @@ -0,0 +1,29 @@ +#!/bin/sh +# @uptime - how long the xmppcb bot has been running +# +# The bot exec's this script directly, so its parent process ($PPID) is +# the xmppcb process itself; ps tells us how long that process has run. + +secs=$(ps -o etimes= -p "$PPID" 2>/dev/null | tr -cd '0-9') + +if [ -n "$secs" ]; then + d=$(( secs / 86400 )) + h=$(( secs % 86400 / 3600 )) + m=$(( secs % 3600 / 60 )) + s=$(( secs % 60 )) + if [ "$d" -gt 0 ]; then up="${d}d ${h}h ${m}m ${s}s" + elif [ "$h" -gt 0 ]; then up="${h}h ${m}m ${s}s" + elif [ "$m" -gt 0 ]; then up="${m}m ${s}s" + else up="${s}s" + fi + echo "xmppcb up: $up" +else + # fallback for a ps without 'etimes': raw elapsed string [dd-]hh:mm:ss + et=$(ps -o etime= -p "$PPID" 2>/dev/null | tr -d ' ') + if [ -n "$et" ]; then + echo "xmppcb up: $et" + else + echo "uptime: cannot read bot process (pid $PPID)" + exit 1 + fi +fi diff --git a/cmd/weather b/cmd/weather new file mode 100755 index 0000000..ee21233 --- /dev/null +++ b/cmd/weather @@ -0,0 +1,38 @@ +#!/bin/sh +# @weather [location] - condition, temperature and local time +# +# In chat: @weather -> default: Bangkok and Warsaw +# @weather Wroclaw -> just that location +# @weather New York -> the whole argument arrives as "$1" +# +# Weather comes from wttr.in. Its %T (time) field is served from a cache +# and goes stale, so we take only the timezone name (%Z, which is +# static) from wttr.in and compute the current local time with date. + +fmt='%l:+%c+%t+%Z' + +one() { + loc=$(printf '%s' "$1" | tr ' ' '+') + out=$(curl -fsS --max-time 8 "https://wttr.in/${loc}?format=${fmt}") || { + printf 'weather: lookup failed for %s\n' "$1" + return + } + tz=${out##* } # last token: timezone name, e.g. Asia/Bangkok + wx=${out% *} # the rest: location, condition, temperature + case "$tz" in + */*) + now=$(TZ="$tz" date '+%H:%M') + printf '%s, %s\n' "$wx" "$now" + ;; + *) + printf '%s\n' "$out" # no usable timezone: show as-is + ;; + esac +} + +if [ -n "$1" ]; then + one "$1" +else + one Bangkok + one Warsaw +fi -- cgit v1.3