LiveLink Slack Bot
File: backend/livelink_slackbot.py
A small notifier service that watches the shared Redis cache and posts to a Slack workflow webhook whenever a tracked state key changes value. Lets the operations team see dive activity, OBS health, and operator toggle activity in Slack without needing to keep the dashboard open.
What it notifies on
Every key under each ship's Redis prefix (rcsn:* / dpkd:*) is
watched, except those ending in :lat, :lon, or :depth. Those
continuous telemetry channels would dominate the Slack channel without
saying anything actionable.
The watched keys and the messages they produce:
| Redis key change | Channel | Message |
|---|---|---|
state:streaming 0→1 |
info | {Ship}: live stream started. |
state:streaming 1→0 |
info | {Ship}: live stream stopped. |
rov:ctd:inwater 0→1 |
info | {Ship}: ROV entered the water. |
rov:ctd:inwater 1→0 |
info | {Ship}: ROV out of water. |
config:auto_stream change |
info | {Ship}: auto-stream {enabled\|disabled}. |
config:force_stream change |
info | {Ship}: force-stream {enabled\|disabled}. |
state:obs_ok 1→0 |
error | {Ship}: OBS connection lost — {error detail}. |
state:obs_ok 0→1 |
info | {Ship}: OBS connection restored. |
state:obs_last_error is intentionally not a notification source —
it's already surfaced via the state:obs_ok transitions, so watching
it independently would double-post on every failure.
Slack workflow payload
The bot expects to talk to a Slack workflow webhook (not an
incoming-webhook) configured with two text inputs: livelink_info and
livelink_error. Each POST body is a JSON object with exactly those
two keys; one is populated with the message text, the other is the
empty string. The Slack workflow then routes each populated key to its
configured downstream output (typically two different channels, or two
different message formats in the same channel).
If a Slack POST fails (rate limit, network hiccup, workflow disabled), the bot logs the error and continues polling. A failed notification is never retried — the next state change will produce a fresh message.
Startup behaviour
On the first poll, the bot records the current value of every watched key without sending any messages. This avoids a flurry of "X just turned on!" notifications every time the container restarts; the bot just resyncs with current reality and starts notifying on real changes from that point forward.
CLI reference
usage: livelink_slackbot.py [options]
--redis-host HOST Redis hostname (default: localhost)
--redis-port PORT Redis port (default: 6379)
--poll-interval SECS Seconds between Redis polls (default: 10)
--webhook-url URL Slack workflow webhook URL.
Alternatively set SLACK_WEBHOOK_URL.
--debug 0|1 Verbose logging (default: 0)
Without a webhook URL the process exits immediately with a clear error.
Container
Built via docker/livelink_slackbot.dockerfile and wired into the
compose stack as the livelink_slackbot service. Shares redisnet
with the other containers; never exposed to the outside.
Environment variables
| Variable | Default | Description |
|---|---|---|
REDIS_HOST |
redis |
Redis hostname inside compose. |
REDIS_PORT |
6379 |
Redis port. |
POLL_INTERVAL |
10 |
Seconds between polls. |
SLACK_WEBHOOK_URL |
(required) | Slack workflow webhook URL. |
DEBUG |
0 |
Set to 1 for verbose logging. |