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 --rawRead 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-receiptAuto-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 0Reconnect 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 ./mediaFiles 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 1Available 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_IDandOPENKAKAO_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 1This 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-TimestampX-OpenKakao-Signature
The signature covers timestamp.payload using HMAC-SHA256.
Receiver checklist:
- require HTTPS
- validate
X-OpenKakao-Timestampagainst 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_SECONDSIf 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 10Output Format
Each message is printed as:
[ChatTitle] Sender: message contentFor 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.