Files
Owlbot-Extra-Modules/chat_archive
LogalDeveloper 5d113eecaa
Audit / Dependencies (push) Successful in 8s
CI / Formatting (push) Successful in 4s
CI / Linting (push) Successful in 5s
CI / Tests (Python 3.12) (push) Successful in 9s
CI / Tests (Python 3.13) (push) Successful in 12s
CI / Tests (Python 3.14) (push) Successful in 10s
CI / Type Checking (push) Successful in 10s
CI / Spelling (push) Successful in 7s
Initial commit.
2026-05-27 10:32:49 -04:00
..
2026-05-27 10:32:49 -04:00
2026-05-27 10:32:49 -04:00

chat_archive

This package contains an Owlbot module that writes Owncast chat activity and stream context updates to JSON files for later processing.

Behavior

An archive is the JSON file this module writes for one live stream. The module starts an archive when Owlbot sees a live stream, including streams that are already live when the module loads.

While an archive is active, the module records chat messages, user joins, user parts, name changes, stream title updates, and message visibility updates in the order Owlbot dispatches them. Events outside an active stream are ignored.

Archive files are stream-scoped. When a stream ends, the active archive is finalized, and the next live stream starts a new archive file. Module unload also finalizes the active archive.

Configuration

modules:
  chat_archive:
    enabled: true
    archive_dir: "data/chat_archives"
    pretty_json: true
  • archive_dir: directory where archive files are written. The module creates it if needed.
  • pretty_json: when true, write indented JSON. When false, write compact JSON.

Archive Format

Archive filenames are based on the detected stream start time when available:

chat-archive-20260526T120000Z.json

If a file already exists for that timestamp, the module adds a suffix such as chat-archive-20260526T120000Z-2.json.

Each archive is a single JSON document with these top-level fields:

  • archive_start_reason: one of module_startup or stream_started_event.
  • archive_started_at: ISO 8601 timestamp for when the archive file was started.
  • archive_updated_at: ISO 8601 timestamp for the most recent archive write.
  • archive_stopped_at: ISO 8601 timestamp for when the archive was finalized, or null while the archive is active.
  • archive_stop_reason: reason the archive was finalized, or null while the archive is active. Current values are stream_stopped_event, module_teardown, and replaced_by_stream_started_event.
  • stream_title: stream title when the archive started, or null if unavailable.
  • stream_stopped_at: stream stop timestamp recorded when finalized by a stream stop event, or null otherwise.
  • event_count: number of objects in events.
  • events: ordered list of captured activity events.

Each object in events contains:

  • event_type: one of CHAT, USER_JOINED, USER_PARTED, NAME_CHANGE, STREAM_TITLE_UPDATED, or VISIBILITY-UPDATE.
  • archived_at: ISO 8601 timestamp for when the event was written.
  • event_data: parsed Owlbot event data converted to JSON-compatible values. The exact fields depend on event_type.

Abridged example archive:

{
  "archive_start_reason": "stream_started_event",
  "archive_started_at": "2026-05-26T12:00:01.000000+00:00",
  "archive_updated_at": "2026-05-26T12:01:00.000000+00:00",
  "archive_stopped_at": null,
  "archive_stop_reason": null,
  "stream_title": "Game Night",
  "stream_stopped_at": null,
  "event_count": 1,
  "events": [
    {
      "event_type": "CHAT",
      "archived_at": "2026-05-26T12:01:00.000000+00:00",
      "event_data": {
        "message_id": "msg-1",
        "raw_body": "hello chat",
        "body": "hello chat",
        "is_visible": true
      }
    }
  ]
}

Owlbot modules receive parsed event dataclasses rather than the untouched Owncast webhook payload. event_data stores that parsed event data after converting values such as datetimes and sets into JSON-compatible values.

The archive is rewritten after each captured event through a temporary sibling file and atomic replace. For an existing archive file, readers should see either the previous complete JSON document or the next complete JSON document.