Files
IRC-kosmi-relay/docs/POLL.md
cottongin c5e0fe06b0 feat: announce poll lifecycle events to IRC and Kosmi
Handle poll.start, poll.ending, voting.ended, and poll.ending.cancelled
WebSocket messages from the upstream GamePicker API. Broadcasts opening,
closing-countdown, and closed announcements with per-bridge bold
formatting (IRC control codes vs asterisks for Kosmi).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 22:48:01 -04:00

3.9 KiB

Poll WebSocket Messages

Overview

Poll messages manage the lifecycle of viewer polls over the upstream WebSocket connection. They are session-scoped — you must be subscribed to the relevant session to send or receive them.

All messages use the standard envelope:

{
  "type": "<message-type>",
  "data": { ... }
}

Message Flow

poll.start  ──►  (poll is open, viewers are voting)
                          │
                    poll.ending  ──►  (countdown active)
                          │
              ┌───────────┴───────────┐
              │                       │
       voting.ended          poll.ending.cancelled
      (poll is closed)       (countdown aborted,
                              poll stays open)

Client → Server

poll.start

Triggers poll generation for the active session.

{
  "type": "poll.start",
  "sessionId": 3
}
Field Type Required Description
type string yes "poll.start"
sessionId number no Included for protocol consistency. The server uses its internally tracked session ID.

Any existing active poll is deactivated and replaced.

poll.leading

Sent by the client to report the current leading option. Typically sent whenever the lead changes.

{
  "type": "poll.leading",
  "sessionId": 3,
  "gameId": 17,
  "label": "Quiplash 3",
  "votes": 12
}
Field Type Required Description
type string yes "poll.leading"
sessionId number yes Active session ID
gameId number yes Game ID of the leading option (0 for "Other")
label string yes Display label of the leading option
votes number yes Current vote count for the leader

Server → Client

poll.ending

Signals that voting will close after a countdown. Sent when the server initiates poll closure.

{
  "type": "poll.ending",
  "data": {
    "sessionId": 3,
    "endsAt": "2026-05-13T02:20:30.123456789Z",
    "delaySeconds": 30
  }
}
Field Type Description
sessionId number Active session ID
endsAt string RFC 3339 timestamp when voting closes
delaySeconds number Seconds remaining until voting closes

poll.ending.cancelled

The previously announced countdown has been cancelled. Voting remains open.

{
  "type": "poll.ending.cancelled",
  "data": {
    "sessionId": 3
  }
}
Field Type Description
sessionId number Active session ID

voting.ended

Voting has closed. The active poll is finalized.

{
  "type": "voting.ended"
}

No data payload. The server does not include results — consumers should query their own tallies or rely on the preceding poll.leading updates for the final state.


Lifecycle Notes

  • A poll.start always replaces any existing active poll.
  • poll.ending may be followed by either voting.ended (normal close) or poll.ending.cancelled (countdown aborted).
  • After voting.ended, no further vote-related messages are sent until the next poll.start.
  • game.started implicitly deactivates any active poll — no explicit poll message is sent.