feat: add entertainment module — public-API plugins (weather, joke) sent via Telegram by default (pos entertainment send)
This commit is contained in:
@@ -40,6 +40,7 @@ Linux_post_install/
|
|||||||
│ ├── pos-docker-health # One-glance container health dashboard (exits 1 if unhealthy)
|
│ ├── pos-docker-health # One-glance container health dashboard (exits 1 if unhealthy)
|
||||||
│ ├── pos-docker-ps # Enhanced container overview (health, IPs, ports, uptime)
|
│ ├── pos-docker-ps # Enhanced container overview (health, IPs, ports, uptime)
|
||||||
│ ├── pos-docker-vbox # Disposable Docker-based VMs (create/enter/start/stop/rm/ls)
|
│ ├── pos-docker-vbox # Disposable Docker-based VMs (create/enter/start/stop/rm/ls)
|
||||||
|
│ ├── pos-entertainment-send # Run a public-API plugin and send its output via Telegram (default sender)
|
||||||
│ ├── pos-media-mp3 # Download audio as MP3 (yt-dlp)
|
│ ├── pos-media-mp3 # Download audio as MP3 (yt-dlp)
|
||||||
│ ├── pos-media-mp4 # Download video as MP4 (interactive format select)
|
│ ├── pos-media-mp4 # Download video as MP4 (interactive format select)
|
||||||
│ ├── pos-network-checkport # Check TCP port connectivity
|
│ ├── pos-network-checkport # Check TCP port connectivity
|
||||||
@@ -61,6 +62,10 @@ Linux_post_install/
|
|||||||
├── features/ # User-customizable scripts (installed via --feature)
|
├── features/ # User-customizable scripts (installed via --feature)
|
||||||
│ └── autostart.sh # Boot-time script (via systemd, flag-gated)
|
│ └── autostart.sh # Boot-time script (via systemd, flag-gated)
|
||||||
│
|
│
|
||||||
|
├── entertainment/ # Public-API plugins for pos entertainment send (→ /usr/local/share/linux_post_install/entertainment)
|
||||||
|
│ ├── weather.sh # Current weather via Open-Meteo (no API key)
|
||||||
|
│ └── joke.sh # Random dad joke via icanhazdadjoke (no API key)
|
||||||
|
│
|
||||||
├── templates/ # Dev-only scaffolds — NOT installed by install.sh
|
├── templates/ # Dev-only scaffolds — NOT installed by install.sh
|
||||||
│ ├── pos-tool.sh # New `pos` CLI tool (→ bin/pos-<cat>-<cmd>)
|
│ ├── pos-tool.sh # New `pos` CLI tool (→ bin/pos-<cat>-<cmd>)
|
||||||
│ ├── app.sh # New optional app installer (→ apps/<cat>/<name>.sh)
|
│ ├── app.sh # New optional app installer (→ apps/<cat>/<name>.sh)
|
||||||
@@ -205,6 +210,7 @@ All non-interactive `pos` commands log output to `~/.local/share/linux_post_inst
|
|||||||
| docker | health | `pos-docker-health` | One-glance container health dashboard (exits 1 if unhealthy) |
|
| docker | health | `pos-docker-health` | One-glance container health dashboard (exits 1 if unhealthy) |
|
||||||
| docker | ps | `pos-docker-ps` | Enhanced container overview (health, IPs, ports, uptime) |
|
| docker | ps | `pos-docker-ps` | Enhanced container overview (health, IPs, ports, uptime) |
|
||||||
| docker | vbox | `pos-docker-vbox` | Disposable Docker-based VMs (create/enter/start/stop/rm/ls) |
|
| docker | vbox | `pos-docker-vbox` | Disposable Docker-based VMs (create/enter/start/stop/rm/ls) |
|
||||||
|
| entertainment | send | `pos-entertainment-send` | Run a public-API plugin and send its output via Telegram (default sender) |
|
||||||
| media | mp3 | `pos-media-mp3` | Download audio as MP3 (yt-dlp) |
|
| media | mp3 | `pos-media-mp3` | Download audio as MP3 (yt-dlp) |
|
||||||
| media | mp4 | `pos-media-mp4` | Download video as MP4 (interactive format select) |
|
| media | mp4 | `pos-media-mp4` | Download video as MP4 (interactive format select) |
|
||||||
| network | checkport | `pos-network-checkport` | Check TCP port connectivity |
|
| network | checkport | `pos-network-checkport` | Check TCP port connectivity |
|
||||||
@@ -470,12 +476,13 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
|
|||||||
| `bin/flag-clear` | 21 | Unset a flag |
|
| `bin/flag-clear` | 21 | Unset a flag |
|
||||||
| `features/autostart.sh` | 14 | Boot-time feature (moved from `bin/`, flag-gated service) |
|
| `features/autostart.sh` | 14 | Boot-time feature (moved from `bin/`, flag-gated service) |
|
||||||
<!-- GEN:START filetable -->
|
<!-- GEN:START filetable -->
|
||||||
| `bin/pos` | 208 | CLI dispatcher with smart arg matching + logging + category help |
|
| `bin/pos` | 211 | CLI dispatcher with smart arg matching + logging + category help |
|
||||||
| `bin/pos-communication-telegram` | 140 | Send Telegram messages via Bot API (--send, test, config set) |
|
| `bin/pos-communication-telegram` | 150 | Send Telegram messages via Bot API (--send, test, config set) |
|
||||||
| `bin/pos-docker-compose` | 364 | Docker Compose service manager (ls/up/down/restart/logs/update/config) |
|
| `bin/pos-docker-compose` | 364 | Docker Compose service manager (ls/up/down/restart/logs/update/config) |
|
||||||
| `bin/pos-docker-health` | 110 | One-glance container health dashboard (exits 1 if unhealthy) |
|
| `bin/pos-docker-health` | 110 | One-glance container health dashboard (exits 1 if unhealthy) |
|
||||||
| `bin/pos-docker-ps` | 128 | Enhanced container overview (health, IPs, ports, uptime) |
|
| `bin/pos-docker-ps` | 128 | Enhanced container overview (health, IPs, ports, uptime) |
|
||||||
| `bin/pos-docker-vbox` | 157 | Disposable Docker-based VMs (create/enter/start/stop/rm/ls) |
|
| `bin/pos-docker-vbox` | 157 | Disposable Docker-based VMs (create/enter/start/stop/rm/ls) |
|
||||||
|
| `bin/pos-entertainment-send` | 122 | Run a public-API plugin and send its output via Telegram (default sender) |
|
||||||
| `bin/pos-media-mp3` | 35 | Download audio as MP3 (yt-dlp) |
|
| `bin/pos-media-mp3` | 35 | Download audio as MP3 (yt-dlp) |
|
||||||
| `bin/pos-media-mp4` | 38 | Download video as MP4 (interactive format select) |
|
| `bin/pos-media-mp4` | 38 | Download video as MP4 (interactive format select) |
|
||||||
| `bin/pos-network-checkport` | 45 | Check TCP port connectivity |
|
| `bin/pos-network-checkport` | 45 | Check TCP port connectivity |
|
||||||
@@ -486,7 +493,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
|
|||||||
| `bin/pos-system-backup` | 117 | Encrypted (AES-256) folder snapshots (tar + gpg) |
|
| `bin/pos-system-backup` | 117 | Encrypted (AES-256) folder snapshots (tar + gpg) |
|
||||||
| `bin/pos-system-firewall` | 285 | Interactive UFW management |
|
| `bin/pos-system-firewall` | 285 | Interactive UFW management |
|
||||||
| `bin/pos-usb-server` | 218 | USB Redirector server control (--ls, --share; prompts when args omitted) |
|
| `bin/pos-usb-server` | 218 | USB Redirector server control (--ls, --share; prompts when args omitted) |
|
||||||
| `completions/pos.bash` | 146 | Dynamic bash completion |
|
| `completions/pos.bash` | 150 | Dynamic bash completion |
|
||||||
<!-- GEN:END filetable -->
|
<!-- GEN:END filetable -->
|
||||||
| `apps/install.sh` | 171 | App install/uninstall picker/orchestrator |
|
| `apps/install.sh` | 171 | App install/uninstall picker/orchestrator |
|
||||||
|
|
||||||
|
|||||||
+36
@@ -33,6 +33,7 @@ Each phase is independent and runs only if the corresponding script exists.
|
|||||||
| `apps/<category>/` | Optional desktop app installers | run on demand |
|
| `apps/<category>/` | Optional desktop app installers | run on demand |
|
||||||
| `lib/` | Shared library (`common.sh`) | sourced at build time |
|
| `lib/` | Shared library (`common.sh`) | sourced at build time |
|
||||||
| `config/` | Gitignored user config files | `~/.config/<app>/` (via postinstall) |
|
| `config/` | Gitignored user config files | `~/.config/<app>/` (via postinstall) |
|
||||||
|
| `entertainment/` | Public-API plugins for the entertainment module | `/usr/local/share/linux_post_install/entertainment` (via install.sh Phase 2) |
|
||||||
| `compose/` | ScaleTail templates (git submodule) | `/usr/local/share/linux_post_install/scale-tail` |
|
| `compose/` | ScaleTail templates (git submodule) | `/usr/local/share/linux_post_install/scale-tail` |
|
||||||
| `systemd/` | Systemd unit files | `/etc/systemd/system/` (via postinstall) |
|
| `systemd/` | Systemd unit files | `/etc/systemd/system/` (via postinstall) |
|
||||||
|
|
||||||
@@ -176,6 +177,41 @@ make check # full self-consistency gate (syntax, exec bits, d
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Adding an Entertainment Plugin
|
||||||
|
|
||||||
|
The `entertainment` module routes public-API data to Telegram via the single runner `pos entertainment send <plugin>` (`bin/pos-entertainment-send`).
|
||||||
|
|
||||||
|
### 1. Create the plugin
|
||||||
|
|
||||||
|
Drop an executable script in `entertainment/<name>.sh`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
err() { echo "ERROR: $*" >&2; exit 1; }
|
||||||
|
|
||||||
|
command -v curl &>/dev/null || err "curl not found"
|
||||||
|
|
||||||
|
data="$(curl -fsS --max-time 20 https://api.example.com/foo)"
|
||||||
|
printf 'Title: %s\n' "$data"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Contract:** plugins are **self-contained** — do **not** source `lib/common.sh`. Its `log`/`warn`/`ok` helpers print to **stdout**, and the runner captures stdout as the message to send (helper chatter would be sent to Telegram). All stdout is the message; errors go to stderr and exit nonzero. Plugins must be non-interactive (no prompts) — the module is designed for cron/systemd timers.
|
||||||
|
|
||||||
|
### 2. Config (if needed)
|
||||||
|
|
||||||
|
Read runtime values from `~/.config/linux_post_install/entertainment.env` (chmod 600, env precedence) — same pattern as `telegram.env`. Example: `weather.sh` uses `WEATHER_LAT`/`WEATHER_LON`.
|
||||||
|
|
||||||
|
### 3. Deps
|
||||||
|
|
||||||
|
`curl` and `jq` are already in `preinstall.sh` PACKAGES. Anything else: guard with `command -v … || err "…"` and, if apt-available, add to PACKAGES.
|
||||||
|
|
||||||
|
### 4. Done
|
||||||
|
|
||||||
|
Plugins are not `pos-*` tools, so `make gen`/`make check` don't scan them — verify with `bash -n entertainment/<name>.sh` and a live `pos entertainment send <name> --print` run. Document the plugin in `DOC/POS.md`'s entertainment plugin table.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Adding an Optional App
|
## Adding an Optional App
|
||||||
|
|
||||||
Start from the template: `cp templates/app.sh apps/<category>/<name>.sh`.
|
Start from the template: `cp templates/app.sh apps/<category>/<name>.sh`.
|
||||||
|
|||||||
+26
@@ -12,6 +12,7 @@
|
|||||||
- [ssh](#ssh)
|
- [ssh](#ssh)
|
||||||
- [usb](#usb)
|
- [usb](#usb)
|
||||||
- [communication](#communication)
|
- [communication](#communication)
|
||||||
|
- [entertainment](#entertainment)
|
||||||
- [flags](#flags)
|
- [flags](#flags)
|
||||||
- [Legacy wrappers](#legacy-wrappers)
|
- [Legacy wrappers](#legacy-wrappers)
|
||||||
|
|
||||||
@@ -203,6 +204,31 @@ Subcommands that need input prompt interactively when args are omitted.
|
|||||||
|
|
||||||
The bot token is a secret — it is stored only in `~/.config/linux_post_install/telegram.env` and never in the repo. Requires network access to `api.telegram.org`.
|
The bot token is a secret — it is stored only in `~/.config/linux_post_install/telegram.env` and never in the repo. Requires network access to `api.telegram.org`.
|
||||||
|
|
||||||
|
### entertainment
|
||||||
|
|
||||||
|
**File:** `bin/pos-entertainment-send`
|
||||||
|
**Purpose:** run a public-API plugin and send its output to Telegram by default. Plugins are standalone scripts in `entertainment/` that fetch a public API and **print the message to stdout** — that stdout is what gets sent.
|
||||||
|
|
||||||
|
| Command | Behavior |
|
||||||
|
|---------|----------|
|
||||||
|
| `pos entertainment send` | List available plugins + usage |
|
||||||
|
| `pos entertainment send <plugin> [--print] [--markdown] [args…]` | Run the plugin, send its output to Telegram (silent) |
|
||||||
|
| `pos entertainment send <plugin> --print` | Print the output locally; do not send |
|
||||||
|
| `pos entertainment send <plugin> --markdown` | Send with `--parse-mode markdown` (via `pos communication telegram`) |
|
||||||
|
|
||||||
|
**Plugin lookup order:** `$ENTERTAINMENT_DIR` → repo `entertainment/` → `/usr/local/share/linux_post_install/entertainment/` (installed by `install.sh` Phase 2). A plugin name matches the file name with or without the `.sh` suffix.
|
||||||
|
|
||||||
|
Plugins:
|
||||||
|
|
||||||
|
| Plugin | Source API | Config |
|
||||||
|
|--------|-----------|--------|
|
||||||
|
| `weather` | Open-Meteo (no API key) | `~/.config/linux_post_install/entertainment.env`: `WEATHER_LAT`, `WEATHER_LON` (required), `WEATHER_CITY` (optional label) |
|
||||||
|
| `joke` | icanhazdadjoke.com (no API key) | None |
|
||||||
|
|
||||||
|
**Adding a plugin:** drop an executable script in `entertainment/` (e.g. `myfeed.sh`). It must be non-interactive and print the message to stdout; errors go to stderr (exit nonzero). If it needs coordinates/tokens, read them from `~/.config/linux_post_install/entertainment.env` (chmod 600, env precedence). No registration needed. Dependencies beyond `curl`/`jq` (both in `preinstall.sh` PACKAGES) should be guarded with `command -v … || exit 1`.
|
||||||
|
|
||||||
|
**Automation:** the runner is headless/timer-friendly — no TTY prompts, exit 0 on success / 1 on failure. A systemd timer (e.g. hourly) can call `pos entertainment send weather` directly. Note the config files live under the user's `$HOME`, so the timer must run as that user (a systemd **user** unit, or a system unit with `Environment=HOME=/home/<user>`).
|
||||||
|
|
||||||
### flags
|
### flags
|
||||||
|
|
||||||
Feature-flag management CLIs (see [SCRIPTS.md → lib/flags.sh](SCRIPTS.md#libflagssh--feature-flags)):
|
Feature-flag management CLIs (see [SCRIPTS.md → lib/flags.sh](SCRIPTS.md#libflagssh--feature-flags)):
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ It is a **personal toolkit** — a bootstrap script, a unified `pos` CLI for eve
|
|||||||
**What you get:**
|
**What you get:**
|
||||||
|
|
||||||
- 25+ system packages installed automatically
|
- 25+ system packages installed automatically
|
||||||
- The `pos` CLI: network, Docker (compose + vbox VMs), media, system, SSH, USB, and communication (Telegram) tools
|
- The `pos` CLI: network, Docker (compose + vbox VMs), media, system, SSH, USB, communication (Telegram), and entertainment (public-API plugins → Telegram) tools
|
||||||
- Wi-Fi hotspot tools (`create_ap`, `wihotspot-gui`) via `pos network hotspot`
|
- Wi-Fi hotspot tools (`create_ap`, `wihotspot-gui`) via `pos network hotspot`
|
||||||
- 15 optional desktop apps (VS Code, Brave, OBS, Tailscale, …) — pick what you want
|
- 15 optional desktop apps (VS Code, Brave, OBS, Tailscale, …) — pick what you want
|
||||||
- 119+ self-hosted services with Tailscale access (Jellyfin, Home Assistant, …)
|
- 119+ self-hosted services with Tailscale access (Jellyfin, Home Assistant, …)
|
||||||
|
|||||||
@@ -81,8 +81,8 @@ usage() {
|
|||||||
cat <<EOF
|
cat <<EOF
|
||||||
pos — Personal OS Toolkit
|
pos — Personal OS Toolkit
|
||||||
|
|
||||||
A unified CLI for network, docker, media, system,
|
A unified CLI for network, docker, media, system, SSH,
|
||||||
and SSH tools on Debian/Ubuntu.
|
USB, communication, and entertainment tools on Debian/Ubuntu.
|
||||||
|
|
||||||
USAGE
|
USAGE
|
||||||
pos <category> <command> [args]
|
pos <category> <command> [args]
|
||||||
@@ -114,6 +114,9 @@ EXAMPLES
|
|||||||
pos communication telegram --send "Backup done"
|
pos communication telegram --send "Backup done"
|
||||||
Send a Telegram message
|
Send a Telegram message
|
||||||
|
|
||||||
|
pos entertainment send weather Fetch Open-Meteo weather → Telegram
|
||||||
|
pos entertainment send joke --print Preview a joke locally (no send)
|
||||||
|
|
||||||
pos docker vbox create lab1 Create disposable Docker VM
|
pos docker vbox create lab1 Create disposable Docker VM
|
||||||
pos docker vbox create lab1 --dir . Create VM using current directory
|
pos docker vbox create lab1 --dir . Create VM using current directory
|
||||||
pos docker vbox enter lab1 Shell into a Docker VM
|
pos docker vbox enter lab1 Shell into a Docker VM
|
||||||
|
|||||||
Executable
+122
@@ -0,0 +1,122 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
# POS: entertainment send — Run a public-API plugin and send its output via Telegram (default sender)
|
||||||
|
# POS_FLAGS: --print --markdown
|
||||||
|
|
||||||
|
source "$(dirname "$0")/../lib/common.sh" 2>/dev/null || source "$(dirname "$0")/common.sh"
|
||||||
|
|
||||||
|
# ── Plugin directory lookup ─────────────────────────────────────
|
||||||
|
plugin_dir() {
|
||||||
|
if [ -n "${ENTERTAINMENT_DIR:-}" ]; then
|
||||||
|
echo "$ENTERTAINMENT_DIR"
|
||||||
|
elif [ -d "$(dirname "$0")/../entertainment" ]; then
|
||||||
|
echo "$(cd "$(dirname "$0")/../entertainment" && pwd)"
|
||||||
|
elif [ -d "/usr/local/share/linux_post_install/entertainment" ]; then
|
||||||
|
echo "/usr/local/share/linux_post_install/entertainment"
|
||||||
|
else
|
||||||
|
err "entertainment plugin dir not found (set ENTERTAINMENT_DIR)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
list_plugins() {
|
||||||
|
local dir="$1" f
|
||||||
|
for f in "$dir"/*; do
|
||||||
|
[ -f "$f" ] && [ -x "$f" ] && echo "$(basename "$f")"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve_plugin() {
|
||||||
|
local dir="$1" name="$2" f
|
||||||
|
[ -n "$name" ] || err "No plugin given"
|
||||||
|
for f in "$dir/$name" "$dir/$name.sh"; do
|
||||||
|
if [ -f "$f" ] && [ -x "$f" ]; then
|
||||||
|
echo "$f"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
err "Plugin '$name' not found in $dir — try one of: $(list_plugins "$dir" | tr '\n' ' ')"
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
local dir plugins
|
||||||
|
dir="$(plugin_dir 2>/dev/null)" || dir=""
|
||||||
|
if [ -n "$dir" ]; then
|
||||||
|
plugins="$(list_plugins "$dir" | sed 's/^/ /')"
|
||||||
|
else
|
||||||
|
plugins=" (plugin directory not found — set ENTERTAINMENT_DIR)"
|
||||||
|
fi
|
||||||
|
cat <<EOF
|
||||||
|
Usage: pos entertainment send <plugin> [--print] [--markdown] [plugin args...]
|
||||||
|
|
||||||
|
Run an entertainment plugin, capture its output, and send it via Telegram.
|
||||||
|
|
||||||
|
Plugins are scripts that fetch a public API and print the message to stdout —
|
||||||
|
that stdout is what gets sent.
|
||||||
|
|
||||||
|
Modes:
|
||||||
|
(default) Send the plugin output to Telegram (silent)
|
||||||
|
--print Print the output locally instead of sending
|
||||||
|
--markdown Send with Markdown parse_mode (via pos communication telegram)
|
||||||
|
|
||||||
|
Available plugins:
|
||||||
|
$plugins
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
ENTERTAINMENT_DIR Override the plugin directory
|
||||||
|
|
||||||
|
Config (per plugin): ~/.config/linux_post_install/entertainment.env
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
pos entertainment send weather
|
||||||
|
pos entertainment send weather --print
|
||||||
|
pos entertainment send joke --markdown
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
-h|--help|"") usage ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# ── Parse runner flags ──────────────────────────────────────────
|
||||||
|
PRINT=0
|
||||||
|
MARKDOWN=0
|
||||||
|
plugin_args=()
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
--print) PRINT=1; shift ;;
|
||||||
|
--markdown) MARKDOWN=1; shift ;;
|
||||||
|
-h|--help) usage ;;
|
||||||
|
*) plugin_args+=("$1"); shift ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
[ ${#plugin_args[@]} -ge 1 ] || usage
|
||||||
|
plugin="${plugin_args[0]}"
|
||||||
|
unset 'plugin_args[0]'
|
||||||
|
|
||||||
|
# ── Run the plugin ──────────────────────────────────────────────
|
||||||
|
dir="$(plugin_dir)"
|
||||||
|
script="$(resolve_plugin "$dir" "$plugin")"
|
||||||
|
|
||||||
|
if ! output="$("$script" "$@")"; then
|
||||||
|
err "Plugin '$plugin' failed (exit $?)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -n "$output" ] || { warn "Plugin '$plugin' produced no output — nothing to send"; exit 0; }
|
||||||
|
|
||||||
|
# ── Route the output ────────────────────────────────────────────
|
||||||
|
if [ "$PRINT" -eq 1 ]; then
|
||||||
|
printf '%s\n' "$output"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
telegram="$(dirname "$0")/pos-communication-telegram"
|
||||||
|
[ -x "$telegram" ] || telegram="$(command -v pos-communication-telegram 2>/dev/null || true)"
|
||||||
|
[ -n "$telegram" ] && [ -x "$telegram" ] || err "pos-communication-telegram not found next to this script"
|
||||||
|
|
||||||
|
if [ "$MARKDOWN" -eq 1 ]; then
|
||||||
|
exec "$telegram" --send "$output" --parse-mode markdown
|
||||||
|
else
|
||||||
|
exec "$telegram" --send "$output"
|
||||||
|
fi
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
# GEN:START posflags
|
# GEN:START posflags
|
||||||
declare -A _pos_flags
|
declare -A _pos_flags
|
||||||
_pos_flags[communication-telegram]="--send"
|
_pos_flags[communication-telegram]="--send"
|
||||||
|
_pos_flags[entertainment-send]="--print --markdown"
|
||||||
_pos_flags[network-hotspot]="--foreground"
|
_pos_flags[network-hotspot]="--foreground"
|
||||||
_pos_flags[system-backup]="--service"
|
_pos_flags[system-backup]="--service"
|
||||||
_pos_flags[usb-server]="--ls --ls-shared --share --unshare --auto-share --callback --close-callback --auto-connect --disconnect --nickname --timeout --port --info --version"
|
_pos_flags[usb-server]="--ls --ls-shared --share --unshare --auto-share --callback --close-callback --auto-connect --disconnect --nickname --timeout --port --info --version"
|
||||||
@@ -114,6 +115,9 @@ _pos() {
|
|||||||
communication-telegram)
|
communication-telegram)
|
||||||
_pos_complete_flags communication-telegram
|
_pos_complete_flags communication-telegram
|
||||||
;;
|
;;
|
||||||
|
entertainment-send)
|
||||||
|
_pos_complete_flags entertainment-send
|
||||||
|
;;
|
||||||
network-hotspot)
|
network-hotspot)
|
||||||
_pos_complete_flags network-hotspot
|
_pos_complete_flags network-hotspot
|
||||||
;;
|
;;
|
||||||
|
|||||||
Executable
+32
@@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Entertainment plugin: random dad joke via icanhazdadjoke.com (no API key).
|
||||||
|
# Contract: stdout is the message sent by 'pos entertainment send joke'.
|
||||||
|
|
||||||
|
err() { echo "ERROR: $*" >&2; exit 1; }
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
-h|--help)
|
||||||
|
cat <<EOF
|
||||||
|
Usage: pos entertainment send joke
|
||||||
|
|
||||||
|
Random dad joke from icanhazdadjoke.com (no API key).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
pos entertainment send joke --print
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
command -v curl &>/dev/null || err "curl not found"
|
||||||
|
command -v jq &>/dev/null || err "jq not found"
|
||||||
|
|
||||||
|
if ! joke="$(curl -fsS --max-time 20 -H 'Accept: application/json' \
|
||||||
|
https://icanhazdadjoke.com/ | jq -r '.joke')"; then
|
||||||
|
err "Failed to fetch a joke from icanhazdadjoke.com"
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -n "$joke" ] || err "No joke received"
|
||||||
|
printf '%s\n' "$joke"
|
||||||
Executable
+83
@@ -0,0 +1,83 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Entertainment plugin: current weather via Open-Meteo (no API key).
|
||||||
|
# Contract: stdout is the message sent by 'pos entertainment send weather'.
|
||||||
|
|
||||||
|
err() { echo "ERROR: $*" >&2; exit 1; }
|
||||||
|
|
||||||
|
CONFIG_FILE="$HOME/.config/linux_post_install/entertainment.env"
|
||||||
|
|
||||||
|
load_config() {
|
||||||
|
[ -f "$CONFIG_FILE" ] || return 0
|
||||||
|
local k v
|
||||||
|
while IFS='=' read -r k v; do
|
||||||
|
[ -n "$k" ] || continue
|
||||||
|
case "$k" in
|
||||||
|
\#*) continue ;;
|
||||||
|
esac
|
||||||
|
v="${v%\"}"; v="${v#\"}"; v="${v%\'}"; v="${v#\'}"
|
||||||
|
if [ -z "${!k:-}" ]; then
|
||||||
|
export "$k"="$v"
|
||||||
|
fi
|
||||||
|
done < <(grep -E '^[A-Z_]+=' "$CONFIG_FILE" || true)
|
||||||
|
}
|
||||||
|
|
||||||
|
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" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
-h|--help)
|
||||||
|
cat <<EOF
|
||||||
|
Usage: pos entertainment send weather
|
||||||
|
|
||||||
|
Current weather via Open-Meteo (no API key).
|
||||||
|
|
||||||
|
Config: $CONFIG_FILE (chmod 600)
|
||||||
|
WEATHER_LAT, WEATHER_LON Required — coordinates
|
||||||
|
WEATHER_CITY Optional label (e.g. "Berlin")
|
||||||
|
|
||||||
|
Example:
|
||||||
|
WEATHER_LAT=52.52 WEATHER_LON=13.41 pos entertainment send weather --print
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
command -v curl &>/dev/null || err "curl not found"
|
||||||
|
command -v jq &>/dev/null || err "jq not found"
|
||||||
|
|
||||||
|
load_config
|
||||||
|
|
||||||
|
[ -n "${WEATHER_LAT:-}" ] || err "WEATHER_LAT not set — add it to $CONFIG_FILE"
|
||||||
|
[ -n "${WEATHER_LON:-}" ] || err "WEATHER_LON not set — add it to $CONFIG_FILE"
|
||||||
|
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}¤t=temperature_2m,relative_humidity_2m,apparent_temperature,weather_code,wind_speed_10m")"; then
|
||||||
|
err "Failed to fetch weather from Open-Meteo"
|
||||||
|
fi
|
||||||
|
|
||||||
|
temp="$(jq -r '.current.temperature_2m' <<<"$json")"
|
||||||
|
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")"
|
||||||
|
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"
|
||||||
+10
@@ -114,6 +114,16 @@ if should_run 2 scripts; then
|
|||||||
run sudo install -m 644 lib/common.sh /usr/local/bin/common.sh
|
run sudo install -m 644 lib/common.sh /usr/local/bin/common.sh
|
||||||
run sudo install -m 644 lib/flags.sh /usr/local/bin/flags.sh
|
run sudo install -m 644 lib/flags.sh /usr/local/bin/flags.sh
|
||||||
|
|
||||||
|
# ── Entertainment plugins ────────────────────────────────
|
||||||
|
run sudo mkdir -p /usr/local/share/linux_post_install/entertainment
|
||||||
|
pcount=0
|
||||||
|
for f in entertainment/*.sh; do
|
||||||
|
[ -f "$f" ] || continue
|
||||||
|
run sudo install -m 755 "$f" /usr/local/share/linux_post_install/entertainment/
|
||||||
|
pcount=$((pcount + 1))
|
||||||
|
done
|
||||||
|
ok "$pcount entertainment plugins -> /usr/local/share/linux_post_install/entertainment"
|
||||||
|
|
||||||
# ── Precompiled architecture binaries ─────────────────────
|
# ── Precompiled architecture binaries ─────────────────────
|
||||||
# Manually-compiled binaries (not available on the internet),
|
# Manually-compiled binaries (not available on the internet),
|
||||||
# copied straight into /usr/local/bin for the matching arch.
|
# copied straight into /usr/local/bin for the matching arch.
|
||||||
|
|||||||
+1
-1
@@ -132,7 +132,7 @@ regen_block() {
|
|||||||
regen_block "$ctx" tree
|
regen_block "$ctx" tree
|
||||||
regen_block "$ctx" dispatch
|
regen_block "$ctx" dispatch
|
||||||
regen_block "$ctx" selfcontained
|
regen_block "$ctx" selfcontained
|
||||||
regen_block "$ctx" filetable
|
|
||||||
regen_block "$comp" posflags
|
regen_block "$comp" posflags
|
||||||
|
regen_block "$ctx" filetable
|
||||||
|
|
||||||
echo "gen-docs: $mode OK"
|
echo "gen-docs: $mode OK"
|
||||||
|
|||||||
Reference in New Issue
Block a user