OpenKakao

Watching Messages

Monitor real-time messages with auto-reconnect, read receipts, and local hooks.

Use watch when you need real-time behavior, but keep the mental model small: it is a message watcher with simple sinks, not a workflow engine.

Basic Watch

# Watch all chats
openkakao-rs watch

# Filter by chat
openkakao-rs watch --chat-id <chat_id>

# Show raw BSON body
openkakao-rs watch --raw

Read Receipts

Send NOTIREAD (read receipts) for incoming messages, so the sender sees their message was read:

openkakao-rs --unattended --allow-watch-side-effects watch --read-receipt

Auto-Reconnect

The watch command automatically reconnects on network failures with exponential backoff:

# Default: 5 reconnect attempts
openkakao-rs watch

# Custom max attempts
openkakao-rs watch --max-reconnect 10

# Disable reconnect (exit on first error)
openkakao-rs watch --max-reconnect 0

Reconnect behavior:

  • Auth errors (-950, -999): Immediate exit
  • Network errors: Exponential backoff (1s, 2s, 4s, 8s, ... max 32s)
  • CHANGESVR: Automatic reconnect to new server
  • PING failure: Treated as disconnect, triggers reconnect

Auto-Download Media

Automatically download media attachments (photos, videos, audio, files) as they arrive:

openkakao-rs watch --download-media

# Custom download directory
openkakao-rs watch --download-media --download-dir ./media

Files are saved as {download_dir}/{chat_id}/{log_id}_{filename}.

Local Command Hooks

The first hook layer is local-only. watch can invoke a shell command for matched MSG events without sending chat content to an external webhook by default.

openkakao-rs --unattended --allow-watch-side-effects watch \
  --hook-cmd 'jq -r ".chat_name + ": " + .message" >> ~/kakao-watch.log' \
  --hook-chat-id 382416827148557 \
  --hook-keyword urgent \
  --hook-type 1

Available filters:

  • --hook-chat-id
  • --hook-keyword
  • --hook-type

What the hook gets:

  • full event JSON on stdin
  • metadata via env vars such as OPENKAKAO_CHAT_ID and OPENKAKAO_MESSAGE_TYPE

If a hook exits non-zero, watch logs the failure and continues by default. Use --hook-fail-fast when you want hook failures to stop the watcher.

This is the recommended default because it keeps message content on the same machine and makes debugging simpler.

Webhook Sink

If you do want to forward matched events out of the machine, watch can POST the same normalized event JSON to a webhook URL.

openkakao-rs --unattended --allow-watch-side-effects watch \
  --webhook-url https://hooks.example.com/openkakao \
  --webhook-header 'Authorization: Bearer token' \
  --webhook-signing-secret 'super-secret' \
  --hook-chat-id 382416827148557 \
  --hook-keyword urgent \
  --hook-type 1

This expands the trust boundary beyond your local machine. Treat it as a deliberate decision, especially if the destination is a hosted service.

If signing is enabled, receivers can verify:

  • X-OpenKakao-Timestamp
  • X-OpenKakao-Signature

The signature covers timestamp.payload using HMAC-SHA256.

Receiver checklist:

  • require HTTPS
  • validate X-OpenKakao-Timestamp against a short time window (recommended: reject timestamps that differ from server time by more than ±5 minutes)
  • recompute X-OpenKakao-Signature
  • log delivery failures separately from business logic failures
  • make the receiver idempotent if duplicate events would hurt

Timestamp Validation

The X-OpenKakao-Timestamp header contains the Unix epoch (seconds) when the event was signed. To prevent replay attacks, your receiver should reject requests where the timestamp differs from the server's current time by more than a reasonable window.

A 5-minute window is a practical default. It is wide enough to absorb clock skew and network latency, but narrow enough to reject most replays:

import time

MAX_AGE_SECONDS = 300  # 5 minutes

def validate_timestamp(header_timestamp: str) -> bool:
    try:
        ts = int(header_timestamp)
    except (ValueError, TypeError):
        return False  # reject malformed or missing timestamps
    return abs(time.time() - ts) < MAX_AGE_SECONDS

If your receiver runs on infrastructure with well-synchronized clocks (NTP), you can tighten this to 60 seconds. If clock skew is a concern, keep the 5-minute default and monitor for rejected requests before tightening.

Combining Options

openkakao-rs --unattended --allow-watch-side-effects watch \
  --chat-id <chat_id> \
  --read-receipt \
  --download-media \
  --download-dir ./media \
  --hook-cmd 'jq . > /tmp/openkakao-event.json' \
  --hook-type 1 \
  --max-reconnect 10

Output Format

Each message is printed as:

[ChatTitle] Sender: message content

For JSON processing, hooks are a better fit than --raw, because they pass normalized event JSON rather than BSON internals.

Where To Stop

This is a good place to stop your automation stack unless real usage proves you need more.

OpenKakao currently does not try to be:

  • a durable event queue
  • a rule engine with multiple hook definitions
  • an exactly-once delivery system
  • a hosted integration layer

Build those pieces outside the CLI only after you have a concrete operational need.

On this page