refactor: rename telegram tool to pos-communication-telegram-sender; drop --send legacy alias
The --send flag duplicated the send subcommand — completion suggested both. Now 'pos communication telegram <TAB>' completes to just 'sender' and 'listener'. send is the single canonical action. - git mv bin/pos-communication-telegram bin/pos-communication-telegram-sender - remove --send branch + POS_FLAGS entry; add --markdown to completion - lib/notify.sh: notify_sender_name() maps platform telegram -> telegram-sender (notify_send otherwise looks for bin/pos-communication-telegram) - pos-system-health --send 'sent:' check + pos-entertainment-send use the new name and the send subcommand - completion: keys with nested tools but no direct tool complete to the group suffixes (sender/listener); --type/--parse-mode value completion moved to the new word positions - docs updated (POS.md, AGENT_Context, DEV.md, SCRIPTS.md, notify.env, HOWTO.md, postinstall.sh); removed phantom webhook/log/broadcast subcommands from howto/communication.md
This commit is contained in:
@@ -16,6 +16,8 @@ summary (newest last).
|
||||
|
||||
## Done
|
||||
|
||||
- **2026-08-09** — `pos-communication-telegram` → `pos-communication-telegram-sender`: one canonical `send` (dropped the legacy `--send` flag, which duplicated the `send` subcommand in completion). `pos communication telegram <TAB>` now completes to just `sender listener`. `lib/notify.sh` maps platform `telegram` → `telegram-sender` via `notify_sender_name()`; entertainment-send + health `--send` check updated. Removed phantom subcommands from howto/communication.md (webhook/logs/broadcast/file never existed).
|
||||
|
||||
- **2026-08-09** — Structure/convention audit fix: `--dry-run` now truly dry (`spawn()` honors `DRY_RUN`, install.sh exports it to child phases, postinstall mutations run-wrapped); `gen-docs.sh` no longer chmods regenerated files to 0600; `make check` now syntax-checks apps/entertainment/features/templates; `.gitignore` protects `config/authorized_keys` + `config/rclone.conf`; honest `--send` confirmation; docs refreshed (notify.sh in lib lists, pos-health systemd units, tsui, scripts/, INTERACTIVE_CMDS).
|
||||
|
||||
- **2026-08-07** — `pos system health --send` notification-only; listener `@quiet` prefix (run mapped command without replying, for commands that self-notify). `/status=@quiet pos system health --send` = exactly one digest.
|
||||
|
||||
@@ -59,7 +59,7 @@ Linux_post_install/
|
||||
│ ├── pos # Main dispatcher — smart arg matching to pos-* scripts
|
||||
<!-- GEN:START tree -->
|
||||
│ ├── pos-communication-telegram-listener # Telegram bot listener: map /command → bash, run them on chat messages
|
||||
│ ├── pos-communication-telegram # Send Telegram messages/files/links/stickers via Bot API (send, test, config set)
|
||||
│ ├── pos-communication-telegram-sender # Send Telegram messages/files/links/stickers via Bot API (send, test, config set)
|
||||
│ ├── pos-docker-compose # Docker Compose service manager (ls/up/down/restart/logs/update/config)
|
||||
│ ├── pos-docker-health # One-glance container health dashboard (exits 1 if unhealthy)
|
||||
│ ├── pos-docker-ps # Enhanced container overview (health, IPs, ports, uptime)
|
||||
@@ -250,7 +250,7 @@ All non-interactive `pos` commands log output to `~/.local/share/linux_post_inst
|
||||
|----------|---------|--------|-------------|
|
||||
<!-- GEN:START dispatch -->
|
||||
| communication | telegram-listener | `pos-communication-telegram-listener` | Telegram bot listener: map /command → bash, run them on chat messages |
|
||||
| communication | telegram | `pos-communication-telegram` | Send Telegram messages/files/links/stickers via Bot API (send, test, config set) |
|
||||
| communication | telegram-sender | `pos-communication-telegram-sender` | Send Telegram messages/files/links/stickers via Bot API (send, test, config set) |
|
||||
| docker | compose | `pos-docker-compose` | Docker Compose service manager (ls/up/down/restart/logs/update/config) |
|
||||
| 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) |
|
||||
@@ -318,7 +318,7 @@ source "$(dirname "$0")/../lib/common.sh"
|
||||
|
||||
**Scripts that do NOT source common.sh** (self-contained):
|
||||
<!-- GEN:START selfcontained -->
|
||||
`pos`, `pos-communication-telegram`, `pos-communication-telegram-listener`, `pos-network-checkport`, `pos-network-hotspot`, `pos-network-ip`, `pos-network-scan`, `pos-ssh-load-keys`, `pos-system-firewall`.
|
||||
`pos`, `pos-communication-telegram-listener`, `pos-communication-telegram-sender`, `pos-network-checkport`, `pos-network-hotspot`, `pos-network-ip`, `pos-network-scan`, `pos-ssh-load-keys`, `pos-system-firewall`.
|
||||
<!-- GEN:END selfcontained -->
|
||||
|
||||
---
|
||||
@@ -404,7 +404,7 @@ Public-API "entertainment" plugins (weather, joke, gold) that can auto-send thei
|
||||
- **Library:** `lib/entertainment-lib.sh` — config-file helpers, ENABLED-list parsing, plugin lookup, and scheduler sync (systemd user timers, crontab fallback).
|
||||
- **Plugins:** `entertainment/*.sh` — standalone scripts that fetch a public API and **print the message to stdout** (what gets sent). Each declares its name with a `# POS_PLUGIN: <name>` header; a new plugin is auto-discovered.
|
||||
- **Config:** `~/.config/linux_post_install/entertainment.env` (ENABLED auto-trigger list, weather location). Template: `config/entertainment.env`, auto-installed by postinstall.
|
||||
- **Sending:** `pos entertainment send <plugin> [--print] [--markdown]` runs the plugin and delivers via `pos communication telegram --send`.
|
||||
- **Sending:** `pos entertainment send <plugin> [--print] [--markdown]` runs the plugin and delivers via `pos communication telegram sender send`.
|
||||
- **Auto-trigger:** `pos entertainment enable <plugin> <interval>` writes the plugin into ENABLED and syncs a systemd user timer (allowed intervals: `5m 10m 15m 30m 45m hourly 2h 6h 12h daily weekly`, or `OnCalendar=…`); `disable` removes it.
|
||||
- **Docs:** DEV.md "Adding an Entertainment Plugin" (§1 step list) and POS.md [entertainment](#entertainment).
|
||||
|
||||
@@ -552,7 +552,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
|
||||
<!-- GEN:START filetable -->
|
||||
| `bin/pos` | 267 | CLI dispatcher with smart arg matching + logging + category help |
|
||||
| `bin/pos-communication-telegram-listener` | 433 | Telegram bot listener: map /command → bash, run them on chat messages |
|
||||
| `bin/pos-communication-telegram` | 275 | Send Telegram messages/files/links/stickers via Bot API (send, test, config set) |
|
||||
| `bin/pos-communication-telegram-sender` | 269 | Send Telegram messages/files/links/stickers via Bot API (send, test, config set) |
|
||||
| `bin/pos-docker-compose` | 365 | 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-ps` | 128 | Enhanced container overview (health, IPs, ports, uptime) |
|
||||
@@ -571,11 +571,11 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
|
||||
| `bin/pos-ssh-load-keys` | 31 | Load all SSH keys into the agent |
|
||||
| `bin/pos-system-backup` | 125 | Encrypted (AES-256) folder snapshots (tar + gpg) |
|
||||
| `bin/pos-system-firewall` | 291 | Interactive UFW management |
|
||||
| `bin/pos-system-health` | 272 | Host health dashboard (disk, RAM, services, backup age, fail2ban, docker); exit 1 if any FAIL |
|
||||
| `bin/pos-system-health` | 273 | Host health dashboard (disk, RAM, services, backup age, fail2ban, docker); exit 1 if any FAIL |
|
||||
| `bin/pos-system-nfs-client` | 138 | Mount NFS shares (ephemeral or persistent systemd mount units) |
|
||||
| `bin/pos-system-nfs-server` | 134 | Manage the NFS kernel server (status, share/unshare exports, enable/disable) |
|
||||
| `bin/pos-usb-server` | 218 | USB Redirector server control (--ls, --share; prompts when args omitted) |
|
||||
| `completions/pos.bash` | 215 | Dynamic bash completion |
|
||||
| `completions/pos.bash` | 250 | Dynamic bash completion |
|
||||
<!-- GEN:END filetable -->
|
||||
| `apps/install.sh` | 171 | App install/uninstall picker/orchestrator |
|
||||
|
||||
|
||||
+4
-4
@@ -50,7 +50,7 @@ pos docker compose up jellyfin
|
||||
|
||||
All non-interactive commands log to `~/.local/share/linux_post_install/logs/`.
|
||||
|
||||
`pos help <full command>` shows a tool's help, e.g. `pos help communication telegram` (all words joined with dashes → `pos-communication-telegram --help`). `pos <category>` or `pos <category> --help` shows a category's subcommands (derived from the `pos-<category>-*` filenames in `bin/` — no script execution, so it works even for root-only/interactive tools like `system-firewall`).
|
||||
`pos help <full command>` shows a tool's help, e.g. `pos help communication telegram-sender` (all words joined with dashes → `pos-communication-telegram-sender --help`). `pos <category>` or `pos <category> --help` shows a category's subcommands (derived from the `pos-<category>-*` filenames in `bin/` — no script execution, so it works even for root-only/interactive tools like `system-firewall`).
|
||||
|
||||
**When adding a command, `bin/pos` itself has one thing to keep in sync:**
|
||||
|
||||
@@ -150,7 +150,7 @@ PACKAGES=(
|
||||
Two kinds of config, don't mix them up:
|
||||
|
||||
- **Machine defaults shipped by the installer:** place the file in `config/` and add copy logic to `postinstall.sh`. If it contains secrets, add to `.gitignore` and document in `DOC/`.
|
||||
- **Runtime tool config set by the user:** `~/.config/linux_post_install/<tool>.env` with `chmod 600`. Load it with env-var precedence (flags > environment > file). Patterns: `pos-docker-compose` (`compose.env`), `pos-communication-telegram` (`telegram.env`, token masked in `config` output), and the shared ones below. Never store tokens in the repo.
|
||||
- **Runtime tool config set by the user:** `~/.config/linux_post_install/<tool>.env` with `chmod 600`. Load it with env-var precedence (flags > environment > file). Patterns: `pos-docker-compose` (`compose.env`), `pos-communication-telegram-sender` (`telegram.env`, token masked in `config` output), and the shared ones below. Never store tokens in the repo.
|
||||
- `system.env` — shared "system" settings loaded by `pos-system-*` tools via `load_system_env()` in `lib/common.sh` (currently `BACKUP_SERVICE_ROOTS`, `HEALTH_BACKUP_MAX_AGE_DAYS`). Env already exported wins over the file.
|
||||
- `notify.env` — alerting platform selection (`NOTIFY_PLATFORM=telegram,matrix`), read by `lib/notify.sh`.
|
||||
|
||||
@@ -297,7 +297,7 @@ notify_send "**disk full**" --markdown
|
||||
pos-communication-<platform> send <value> [--markdown] # exit 0 on delivery
|
||||
```
|
||||
|
||||
then listing it in `NOTIFY_PLATFORM`. `pos-communication-telegram` already follows this (`--markdown` is an alias for `--parse-mode markdown`). No changes to `lib/notify.sh` are needed for a new platform.
|
||||
then listing it in `NOTIFY_PLATFORM`. Platform keys map to tool names via `notify_sender_name()` in `lib/notify.sh` — the telegram platform key stays `telegram` but its tool is `pos-communication-telegram-sender`. `pos-communication-telegram-sender` already follows this (`--markdown` is an alias for `--parse-mode markdown`). No changes to `lib/notify.sh` are needed for a new platform.
|
||||
|
||||
### Idempotency
|
||||
|
||||
@@ -334,7 +334,7 @@ run sudo apt install -y git
|
||||
|
||||
- Never hardcode secrets — put them in `config/` (gitignored) or, for runtime tool config, `~/.config/linux_post_install/<tool>.env`
|
||||
- `chmod 600` for sensitive files
|
||||
- Mask secrets in `config` output (see `pos-communication-telegram`'s `mask_token`)
|
||||
- Mask secrets in `config` output (see `pos-communication-telegram-sender`'s `mask_token`)
|
||||
- Validate input before shell commands
|
||||
- Use `sudo` only where needed
|
||||
|
||||
|
||||
+2
-2
@@ -40,8 +40,8 @@ templates (without overwriting an existing file):
|
||||
| `entertainment.env` | `pos entertainment *` | plugin keys (`WEATHER_LAT`…), `ENABLED` |
|
||||
|
||||
```bash
|
||||
pos communication telegram config set TELEGRAM_BOT_TOKEN=123:ABC
|
||||
pos communication telegram config set TELEGRAM_CHAT_ID=98765
|
||||
pos communication telegram sender config set TELEGRAM_BOT_TOKEN=123:ABC
|
||||
pos communication telegram sender config set TELEGRAM_CHAT_ID=98765
|
||||
pos entertainment config set WEATHER_LAT=36.51 WEATHER_LON=40.75
|
||||
```
|
||||
|
||||
|
||||
+13
-14
@@ -193,25 +193,24 @@ Subcommands that need input prompt interactively when args are omitted.
|
||||
|
||||
| Command | File | Purpose | Configuration |
|
||||
|---------|------|---------|---------------|
|
||||
| `pos communication telegram send "text"` | `bin/pos-communication-telegram` | Send a message, link, or media file (auto-detects the type) to a Telegram chat via the Bot API | Token + chat ID from `~/.config/linux_post_install/telegram.env` (`TELEGRAM_BOT_TOKEN`, `TELEGRAM_CHAT_ID`, chmod 600). Precedence: `--token`/`--chat-id` flags > env > config file |
|
||||
| `pos communication telegram sender send "text"` | `bin/pos-communication-telegram-sender` | Send a message, link, or media file (auto-detects the type) to a Telegram chat via the Bot API | Token + chat ID from `~/.config/linux_post_install/telegram.env` (`TELEGRAM_BOT_TOKEN`, `TELEGRAM_CHAT_ID`, chmod 600). Precedence: `--token`/`--chat-id` flags > env > config file |
|
||||
| `pos communication telegram listener` | `bin/pos-communication-telegram-listener` | Telegram bot listener: map `/command` → bash commands and run them from chat; interactive editor for the map | Same `telegram.env` (the bot is the owner, `TELEGRAM_CHAT_ID`). Map lives in `~/.config/linux_post_install/telegram_commands.env` (`/cmd=bash command` lines, chmod 600) |
|
||||
|
||||
`pos communication telegram` in detail:
|
||||
`pos communication telegram sender` in detail:
|
||||
|
||||
| Command | Behavior |
|
||||
|---------|----------|
|
||||
| `pos communication telegram send "text"` | POSTs `sendMessage` to the Bot API (60s timeout); prints `[+] message sent to chat <id>` or fails with a nonzero exit |
|
||||
| `pos communication telegram send <value>` | **Auto-detects the type** when `--type` is omitted: existing file → `file` (except `.webp` → sticker, `.gif` → animation, images → photo, video/audio/voice extensions → their type), value starting with `http://`/`https://`/`www.` → `link`, otherwise `message` |
|
||||
| `pos communication telegram send <path> --type file [--caption "…"]` | Uploads a file as a `sendDocument` via multipart (`document=@path`); `--caption` adds a caption. Path must exist and be readable |
|
||||
| `pos communication telegram send <path> [--caption "…"]` | Media uploads via their Bot API endpoint: `--type photo` → `sendPhoto`, `video` → `sendVideo`, `audio` → `sendAudio`, `voice` → `sendVoice`, `animation` → `sendAnimation`, `sticker` (`.webp`) → `sendSticker` (captions not supported for stickers) |
|
||||
| `pos communication telegram send "url" --type link [--no-preview]` | Sends a link as a message (URLs auto-linkify); `--no-preview` adds `disable_web_page_preview=true` |
|
||||
| `pos communication telegram send "text" --parse-mode <mode>` | Send with Telegram formatting; `<mode>` is `plain` (default), `markdown`, or `html` (passed as `parse_mode` to the API — also applies to captions). Markdown/HTML use raw Telegram syntax — unescaped characters may be rejected by the API (400) |
|
||||
| `pos communication telegram send … --token <t> --chat-id <id>` | One-shot override of token/chat ID |
|
||||
| `pos communication telegram --send "text"` | Legacy alias for `send "text"` (kept for the entertainment runner) |
|
||||
| `pos communication telegram test` | Sends a canned test message using the current config |
|
||||
| `pos communication telegram config` | Shows current config (bot token masked) |
|
||||
| `pos communication telegram config set TELEGRAM_BOT_TOKEN=...` | Saves a bot token (600 perms) |
|
||||
| `pos communication telegram config set TELEGRAM_CHAT_ID=...` | Saves the target chat ID |
|
||||
| `pos communication telegram sender send "text"` | POSTs `sendMessage` to the Bot API (60s timeout); prints `[+] message sent to chat <id>` or fails with a nonzero exit |
|
||||
| `pos communication telegram sender send <value>` | **Auto-detects the type** when `--type` is omitted: existing file → `file` (except `.webp` → sticker, `.gif` → animation, images → photo, video/audio/voice extensions → their type), value starting with `http://`/`https://`/`www.` → `link`, otherwise `message` |
|
||||
| `pos communication telegram sender send <path> --type file [--caption "…"]` | Uploads a file as a `sendDocument` via multipart (`document=@path`); `--caption` adds a caption. Path must exist and be readable |
|
||||
| `pos communication telegram sender send <path> [--caption "…"]` | Media uploads via their Bot API endpoint: `--type photo` → `sendPhoto`, `video` → `sendVideo`, `audio` → `sendAudio`, `voice` → `sendVoice`, `animation` → `sendAnimation`, `sticker` (`.webp`) → `sendSticker` (captions not supported for stickers) |
|
||||
| `pos communication telegram sender send "url" --type link [--no-preview]` | Sends a link as a message (URLs auto-linkify); `--no-preview` adds `disable_web_page_preview=true` |
|
||||
| `pos communication telegram sender send "text" --parse-mode <mode>` | Send with Telegram formatting; `<mode>` is `plain` (default), `markdown`, or `html` (passed as `parse_mode` to the API — also applies to captions). Markdown/HTML use raw Telegram syntax — unescaped characters may be rejected by the API (400) |
|
||||
| `pos communication telegram sender send … --token <t> --chat-id <id>` | One-shot override of token/chat ID |
|
||||
| `pos communication telegram sender test` | Sends a canned test message using the current config |
|
||||
| `pos communication telegram sender config` | Shows current config (bot token masked) |
|
||||
| `pos communication telegram sender config set TELEGRAM_BOT_TOKEN=...` | Saves a bot token (600 perms) |
|
||||
| `pos communication telegram sender config set TELEGRAM_CHAT_ID=...` | Saves the target chat ID |
|
||||
|
||||
`send` option validation: `--caption` is only valid with media types (file/photo/video/audio/voice/animation), `--no-preview` only with `--type message`/`link`, and `--type` only accepts `message|file|link|sticker|photo|video|audio|voice|animation`. An explicit `--type` always overrides auto-detection.
|
||||
|
||||
|
||||
+1
-1
@@ -186,7 +186,7 @@ notify_send "Backup completed"
|
||||
notify_send "**disk full**" --markdown
|
||||
```
|
||||
|
||||
Platform selection: `~/.config/linux_post_install/notify.env` (`NOTIFY_PLATFORM=telegram,matrix`, comma-separated = fan out; env var wins over the file). Adding a platform = drop a `bin/pos-communication-<platform>` sender + list it — no change to `lib/notify.sh`.
|
||||
Platform selection: `~/.config/linux_post_install/notify.env` (`NOTIFY_PLATFORM=telegram,matrix`, comma-separated = fan out; env var wins over the file). Adding a platform = drop a `bin/pos-communication-<platform>` sender + list it — no change to `lib/notify.sh`. The telegram platform key maps to tool `pos-communication-telegram-sender` via `notify_sender_name()`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+22
-35
@@ -1,52 +1,40 @@
|
||||
# How-To: `pos communication`
|
||||
|
||||
Telegram messaging and alerts. Tools: `telegram`, `matrix`.
|
||||
Telegram messaging and alerts. Tools: `telegram-sender`, `telegram-listener`,
|
||||
`matrix`.
|
||||
|
||||
| Tool | What it does |
|
||||
|------|--------------|
|
||||
| `pos communication telegram` | Send messages/files, manage config, webhook state, message logs |
|
||||
| `pos communication telegram sender` | Send messages/files/links/stickers, test, config (token + chat id) |
|
||||
| `pos communication telegram listener` | Bot listener: map `/command` → bash and run it from chat (systemd user daemon) |
|
||||
| `pos communication matrix` | Matrix/Synapse sender (extensible; not yet implemented) |
|
||||
|
||||
`telegram` is the workhorse: it backs the whole **notify system** — health
|
||||
digests, backup alerts, firewall changes — and can be used directly.
|
||||
`telegram-sender` is the workhorse: it backs the whole **notify system** —
|
||||
health digests, backup alerts, firewall changes — and can be used directly.
|
||||
|
||||
---
|
||||
|
||||
## `pos communication telegram`
|
||||
## `pos communication telegram sender`
|
||||
|
||||
### One-time setup
|
||||
|
||||
```bash
|
||||
pos communication telegram config set TELEGRAM_BOT_TOKEN=123456:ABC...
|
||||
pos communication telegram config set TELEGRAM_CHAT_ID=987654321
|
||||
pos communication telegram config set TELEGRAM_DISABLE_WEBHOOK=true # if used with webhooks
|
||||
pos communication telegram config
|
||||
pos communication telegram sender config set TELEGRAM_BOT_TOKEN=123456:ABC...
|
||||
pos communication telegram sender config set TELEGRAM_CHAT_ID=987654321
|
||||
pos communication telegram sender config
|
||||
# config lives in ~/.config/linux_post_install/telegram.env (chmod 600)
|
||||
```
|
||||
|
||||
The bot token comes from @BotFather, the chat ID from @userinfobot (or by
|
||||
starting a chat and reading it). To set your display name once: message
|
||||
`/start` to your bot, then `pos communication telegram chat-id` prints it.
|
||||
starting a chat and reading it). `sender config` shows the configured chat id.
|
||||
|
||||
### Send
|
||||
|
||||
```bash
|
||||
pos communication telegram send "hello from my server" # plain text
|
||||
pos communication telegram send --markdown "**bold** ok" # parse as markdown
|
||||
pos communication telegram send --help # list all flags
|
||||
pos communication telegram file /path/to/report.pdf # send a document
|
||||
pos communication telegram broadcast "restarting in 5min" # to all known chat IDs
|
||||
```
|
||||
|
||||
### State & logs
|
||||
|
||||
```bash
|
||||
pos communication telegram getwebhookinfo # current webhook + pending count
|
||||
pos communication telegram setwebhook https://... # point a webhook URL (or "")
|
||||
pos communication telegram deletemenu # clear the bot menu
|
||||
pos communication telegram logs # recent send history (logs dir)
|
||||
pos communication telegram clear-logs # wipe message logs
|
||||
pos communication telegram sender send "hello from my server" # plain text
|
||||
pos communication telegram sender send --markdown "**bold** ok" # parse as markdown
|
||||
pos communication telegram sender send --help # list all flags
|
||||
pos communication telegram sender send /path/to/report.pdf # auto-detects file
|
||||
```
|
||||
|
||||
**Recipes:**
|
||||
@@ -54,21 +42,20 @@ pos communication telegram clear-logs # wipe message logs
|
||||
`notify_send` (below) on success *and* failure.
|
||||
- **Warn before a service update:**
|
||||
```bash
|
||||
pos communication telegram send "Maintenance: docker compose down in 2min"
|
||||
pos communication telegram sender send "Maintenance: docker compose down in 2min"
|
||||
```
|
||||
- **On-call file drop:** `pos communication telegram file ~/log/nginx-error.log`
|
||||
- **On-call file drop:** `pos communication telegram sender send ~/log/nginx-error.log`
|
||||
|
||||
**Troubleshooting:**
|
||||
- "Not configured (no token or chat id)" → run `config set` for both values.
|
||||
- "Not configured (no token or chat id)" → run `sender config set` for both values.
|
||||
- Send succeeds but nothing arrives → the chat must have started the bot
|
||||
(press `Start` / send `/start` once).
|
||||
- **Markdown silently empty** → Telegram uses its own MarkdownV2; unmatched
|
||||
syntax makes the message vanish. Use `--markdown` only when the text is
|
||||
Telegram-safe (the health digest output is).
|
||||
- **Webhook vs getUpdates:** if your bot has an active webhook, `send` may
|
||||
still work (we disable the webhook automatically when it owns it) — but if
|
||||
another process registered the webhook, polls fail; `deletemenu`/webhook
|
||||
state shows ownership. See `getwebhookinfo`.
|
||||
- **Webhook vs getUpdates:** the sender uses polling (`getUpdates`), so a
|
||||
webhook registered on the bot (e.g. via BotFather) blocks sends; remove it
|
||||
with BotFather's `/deletewebhook`.
|
||||
|
||||
---
|
||||
|
||||
@@ -108,8 +95,8 @@ pos communication telegram listener --disable # remove it
|
||||
**Troubleshooting:**
|
||||
- Bot doesn't answer → send `/help`; if silent, check the service with
|
||||
`systemctl --user status pos-telegram-listener.service`.
|
||||
- A webhook on the bot blocks `getUpdates` → delete it with
|
||||
`pos communication telegram setwebhook ""`.
|
||||
- A webhook on the bot blocks `getUpdates` → remove it with BotFather's
|
||||
`/deletewebhook`.
|
||||
- Needs `jq` (in preinstall PACKAGES).
|
||||
|
||||
---
|
||||
|
||||
@@ -162,7 +162,7 @@ EXAMPLES
|
||||
|
||||
pos usb server --ls List USB devices + connected clients
|
||||
|
||||
pos communication telegram --send "Backup done"
|
||||
pos communication telegram sender send "Backup done"
|
||||
Send a Telegram message
|
||||
pos communication telegram listener Edit the /command → bash map
|
||||
pos communication telegram listener --enable
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
# POS: communication telegram — Send Telegram messages/files/links/stickers via Bot API (send, test, config set)
|
||||
# POS_FLAGS: --send --type --caption --parse-mode --no-preview --token --chat-id
|
||||
# POS: communication telegram-sender — Send Telegram messages/files/links/stickers via Bot API (send, test, config set)
|
||||
# POS_FLAGS: --type --caption --parse-mode --no-preview --token --chat-id --markdown
|
||||
# POS_SUBCMDS: send test config
|
||||
|
||||
CONFIG_DIR="$HOME/.config/linux_post_install"
|
||||
@@ -10,7 +10,7 @@ API="https://api.telegram.org"
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: pos communication telegram [command] [args]
|
||||
Usage: pos communication telegram sender [command] [args]
|
||||
|
||||
Send Telegram messages via the Bot API.
|
||||
|
||||
@@ -46,14 +46,13 @@ Keys: TELEGRAM_BOT_TOKEN | TELEGRAM_CHAT_ID
|
||||
Precedence: CLI flags > environment > config file.
|
||||
|
||||
Examples:
|
||||
pos communication telegram send "Backup finished"
|
||||
pos communication telegram send "/path/to/report.pdf" --caption "Daily report"
|
||||
pos communication telegram send "/path/to/photo.jpg" --caption "Sunset"
|
||||
pos communication telegram send "/path/to/sticker.webp"
|
||||
pos communication telegram send "https://example.com" --no-preview
|
||||
pos communication telegram send "/path/to/video.mp4" --type video
|
||||
pos communication telegram --send "Old style text message"
|
||||
pos communication telegram test
|
||||
pos communication telegram sender send "Backup finished"
|
||||
pos communication telegram sender send "/path/to/report.pdf" --caption "Daily report"
|
||||
pos communication telegram sender send "/path/to/photo.jpg" --caption "Sunset"
|
||||
pos communication telegram sender send "/path/to/sticker.webp"
|
||||
pos communication telegram sender send "https://example.com" --no-preview
|
||||
pos communication telegram sender send "/path/to/video.mp4" --type video
|
||||
pos communication telegram sender test
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
@@ -250,11 +249,6 @@ case "$cmd" in
|
||||
shift
|
||||
cmd_send "$@"
|
||||
;;
|
||||
--send)
|
||||
shift
|
||||
[ $# -ge 1 ] || usage
|
||||
cmd_send "$@"
|
||||
;;
|
||||
test)
|
||||
load_config
|
||||
send_message "Test message from pos $(date '+%Y-%m-%d %H:%M:%S')"
|
||||
@@ -269,7 +263,7 @@ case "$cmd" in
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: Unknown telegram command '$cmd'"
|
||||
echo "Run 'pos communication telegram --help' for usage."
|
||||
echo "Run 'pos communication telegram-sender --help' for usage."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -82,12 +82,12 @@ if [ "$PRINT" -eq 1 ]; then
|
||||
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"
|
||||
telegram="$(dirname "$0")/pos-communication-telegram-sender"
|
||||
[ -x "$telegram" ] || telegram="$(command -v pos-communication-telegram-sender 2>/dev/null || true)"
|
||||
[ -n "$telegram" ] && [ -x "$telegram" ] || err "pos-communication-telegram-sender not found next to this script"
|
||||
|
||||
if [ "$MARKDOWN" -eq 1 ]; then
|
||||
exec "$telegram" --send "$output" --parse-mode markdown
|
||||
exec "$telegram" send "$output" --parse-mode markdown
|
||||
else
|
||||
exec "$telegram" --send "$output"
|
||||
exec "$telegram" send "$output"
|
||||
fi
|
||||
|
||||
@@ -256,9 +256,10 @@ ${line}"
|
||||
for p in "${platforms[@]}"; do
|
||||
p="${p// /}"
|
||||
[ -n "$p" ] || continue
|
||||
if command -v "pos-communication-$p" &>/dev/null \
|
||||
|| [ -x "$(dirname "$0")/pos-communication-$p" ] \
|
||||
|| [ -x "$(dirname "$0")/../bin/pos-communication-$p" ]; then
|
||||
sname="$(notify_sender_name "$p")"
|
||||
if command -v "pos-communication-$sname" &>/dev/null \
|
||||
|| [ -x "$(dirname "$0")/pos-communication-$sname" ] \
|
||||
|| [ -x "$(dirname "$0")/../bin/pos-communication-$sname" ]; then
|
||||
delivered=1
|
||||
fi
|
||||
done
|
||||
|
||||
+50
-15
@@ -4,7 +4,7 @@
|
||||
# GEN:START posflags
|
||||
declare -A _pos_flags
|
||||
_pos_flags[communication-telegram-listener]="--enable --disable --status --run"
|
||||
_pos_flags[communication-telegram]="--send --type --caption --parse-mode --no-preview --token --chat-id"
|
||||
_pos_flags[communication-telegram-sender]="--type --caption --parse-mode --no-preview --token --chat-id --markdown"
|
||||
_pos_flags[entertainment-send]="--print --markdown"
|
||||
_pos_flags[network-hotspot]="--foreground"
|
||||
_pos_flags[system-backup]="--service"
|
||||
@@ -13,7 +13,7 @@ _pos_flags[usb-server]="--ls --ls-shared --share --unshare --auto-share --callba
|
||||
# GEN:END posflags
|
||||
# GEN:START possubcmds
|
||||
declare -A _pos_subcmds
|
||||
_pos_subcmds[communication-telegram]="send test config listener"
|
||||
_pos_subcmds[communication-telegram-sender]="send test config"
|
||||
_pos_subcmds[docker-compose]="ls installed up down restart logs update config"
|
||||
_pos_subcmds[docker-vbox]="create enter stop start rm ls"
|
||||
# GEN:END possubcmds
|
||||
@@ -82,18 +82,36 @@ _pos() {
|
||||
COMPREPLY=($(compgen -W "${cat_cmds[$cat]:-} --help" -- "$cur"))
|
||||
}
|
||||
|
||||
# Nested sub-tool group (pos-<key>-* with no direct tool) → suggest suffixes.
|
||||
_pos_complete_group() {
|
||||
local key="$1" out=() f
|
||||
for f in "$pos_dir"/pos-"$key"-*; do
|
||||
[ -x "$f" ] || continue
|
||||
out+=("${f##*/pos-$key-}")
|
||||
done
|
||||
COMPREPLY=($(compgen -W "${out[*]} --help" -- "$cur"))
|
||||
}
|
||||
|
||||
# Complete subcommands + flags + --help for a tool chain, walking up to
|
||||
# the nearest tool that declares anything (e.g. "telegram send" → telegram flags).
|
||||
# the nearest tool that declares anything. A key that is a group of nested
|
||||
# sub-tools (no direct tool) completes to the group's suffixes.
|
||||
_pos_complete_tool() {
|
||||
local key="$1" k opts
|
||||
if [ -n "${_pos_subcmds[$key]:-}" ] || [ -n "${_pos_flags[$key]:-}" ]; then
|
||||
opts="${_pos_subcmds[$key]:-} ${_pos_flags[$key]:-} --help"
|
||||
COMPREPLY=($(compgen -W "$opts" -- "$cur"))
|
||||
return
|
||||
fi
|
||||
for f in "$pos_dir"/pos-"$key"-*; do
|
||||
if [ -x "$f" ]; then
|
||||
_pos_complete_group "$key"
|
||||
return
|
||||
fi
|
||||
done
|
||||
k="$key"
|
||||
while [ -n "$k" ]; do
|
||||
if [ -n "${_pos_subcmds[$k]:-}" ] || [ -n "${_pos_flags[$k]:-}" ]; then
|
||||
if [ "$k" = "$key" ]; then
|
||||
opts="${_pos_subcmds[$k]:-} ${_pos_flags[$k]:-} --help"
|
||||
else
|
||||
opts="${_pos_flags[$k]:-} --help"
|
||||
fi
|
||||
opts="${_pos_flags[$k]:-} --help"
|
||||
COMPREPLY=($(compgen -W "$opts" -- "$cur"))
|
||||
return
|
||||
fi
|
||||
@@ -196,15 +214,32 @@ _pos() {
|
||||
esac
|
||||
;;
|
||||
6)
|
||||
case "${words[1]}-${words[2]}" in
|
||||
docker-compose)
|
||||
case "${words[3]}" in
|
||||
up|down|restart|logs)
|
||||
_pos_complete_compose_services
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
docker-vbox)
|
||||
case "${words[3]}" in
|
||||
create|enter|stop|start|rm)
|
||||
_pos_complete_docker_vbox_names
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
_pos_complete_tool "${words[1]}-${words[2]}-${words[3]}-${words[4]}"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
7)
|
||||
case "${words[1]}-${words[2]}" in
|
||||
communication-telegram)
|
||||
case "${words[3]}:${words[4]}" in
|
||||
send:--type|--send:--type)
|
||||
COMPREPLY=($(compgen -W "message file link sticker photo video audio voice animation" -- "$cur"))
|
||||
;;
|
||||
send:--parse-mode|--send:--parse-mode)
|
||||
COMPREPLY=($(compgen -W "plain markdown html" -- "$cur"))
|
||||
;;
|
||||
case "${words[5]}" in
|
||||
--type) COMPREPLY=($(compgen -W "message file link sticker photo video audio voice animation" -- "$cur")) ;;
|
||||
--parse-mode) COMPREPLY=($(compgen -W "plain markdown html" -- "$cur")) ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -4,5 +4,7 @@
|
||||
# them). Each platform must have a bin/pos-communication-<platform> tool that
|
||||
# implements the sender contract:
|
||||
# pos-communication-<platform> send <value> [--markdown]
|
||||
# The telegram platform key maps to pos-communication-telegram-sender
|
||||
# (via notify_sender_name() in lib/notify.sh).
|
||||
# Default: telegram
|
||||
#NOTIFY_PLATFORM=telegram,matrix
|
||||
|
||||
+15
-4
@@ -16,6 +16,8 @@
|
||||
# that MUST implement:
|
||||
# pos-communication-<platform> send <value> [--markdown]
|
||||
# (exit 0 on delivery; non-zero on failure)
|
||||
# NOTE: the telegram sender tool is named `pos-communication-telegram-sender`;
|
||||
# notify_sender_name() maps the platform key "telegram" → "telegram-sender".
|
||||
# To add a platform (e.g. Matrix/Synapse), add `bin/pos-communication-matrix`
|
||||
# implementing that interface and put `matrix` in NOTIFY_PLATFORM.
|
||||
#
|
||||
@@ -24,6 +26,14 @@
|
||||
|
||||
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/linux_post_install"
|
||||
|
||||
# Platform key → sender tool name (bin/pos-communication-<name>).
|
||||
notify_sender_name() {
|
||||
case "${1:-}" in
|
||||
telegram) echo telegram-sender ;;
|
||||
*) echo "${1:-}" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Effective platform list (env > notify.env > "telegram").
|
||||
notify_platforms() {
|
||||
local p="${NOTIFY_PLATFORM:-}"
|
||||
@@ -51,15 +61,16 @@ notify_send() {
|
||||
local -a plist
|
||||
IFS=',' read -r -a plist <<< "$(notify_platforms)"
|
||||
|
||||
local p sender
|
||||
local p sender sname
|
||||
for p in "${plist[@]}"; do
|
||||
p="${p// /}"
|
||||
[ -n "$p" ] || continue
|
||||
sender="$(command -v "pos-communication-${p}" 2>/dev/null)" || \
|
||||
sender="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")/../bin/pos-communication-${p}"
|
||||
sname="$(notify_sender_name "$p")"
|
||||
sender="$(command -v "pos-communication-${sname}" 2>/dev/null)" || \
|
||||
sender="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")/../bin/pos-communication-${sname}"
|
||||
|
||||
if [ ! -x "$sender" ]; then
|
||||
warn "notify_send: pos-communication-${p} not found, notification skipped" 2>/dev/null || true
|
||||
warn "notify_send: pos-communication-${sname} not found, notification skipped" 2>/dev/null || true
|
||||
continue
|
||||
fi
|
||||
|
||||
|
||||
+1
-1
@@ -137,7 +137,7 @@ if [ -d systemd ] && [ -n "$(ls -A systemd/*.service 2>/dev/null)" ]; then
|
||||
run sudo systemctl enable pos-health.timer
|
||||
log "Daily health digest timer enabled for $DIGEST_USER"
|
||||
else
|
||||
warn "Telegram not configured — skipping health digest timer (run 'pos communication telegram config set ...' then re-run postinstall)"
|
||||
warn "Telegram not configured — skipping health digest timer (run 'pos communication telegram sender config set ...' then re-run postinstall)"
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user