Skip to content

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).

{
  "livelink_info":  "R/V Rachel Carson: live stream started.",
  "livelink_error": ""
}

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.

Local run

SLACK_WEBHOOK_URL="https://hooks.slack.com/triggers/..." \
uv run backend/livelink_slackbot.py \
  --redis-host localhost --poll-interval 5