{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "Author": {
      "properties": {
        "avatar_url": {
          "description": "Profile picture URL (YouTube only).",
          "type": [
            "string",
            "null"
          ]
        },
        "badges": {
          "description": "Badge names, e.g. `moderator`, `subscriber`, `member`, `vip`.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "color": {
          "description": "Name color chosen by the user, as `#rrggbb` (Twitch only).",
          "type": [
            "string",
            "null"
          ]
        },
        "id": {
          "description": "Platform-specific user id (Twitch user id, YouTube channel id).",
          "type": "string"
        },
        "name": {
          "description": "Display name.",
          "type": "string"
        }
      },
      "required": [
        "id",
        "name",
        "color",
        "badges",
        "avatar_url"
      ],
      "type": "object"
    },
    "ChatMessage": {
      "properties": {
        "author": {
          "$ref": "#/definitions/Author"
        },
        "emotes": {
          "description": "Emotes used in `text`, each listed once. Occurrences in `text` are\nwritten exactly as `code`.",
          "items": {
            "$ref": "#/definitions/EmoteRef"
          },
          "type": "array"
        },
        "id": {
          "description": "Platform-assigned message id; delete events refer to it.",
          "type": "string"
        },
        "kind": {
          "$ref": "#/definitions/MessageKind"
        },
        "platform": {
          "$ref": "#/definitions/ChatPlatform"
        },
        "text": {
          "description": "What the user typed; may be empty (e.g. a raid or a resub without a\nmessage). Descriptions of the event itself live in `kind`.",
          "type": "string"
        },
        "timestamp": {
          "description": "When the message was sent (RFC 3339, UTC).",
          "format": "date-time",
          "type": "string"
        }
      },
      "required": [
        "id",
        "platform",
        "author",
        "text",
        "emotes",
        "timestamp",
        "kind"
      ],
      "type": "object"
    },
    "ChatPlatform": {
      "enum": [
        "twitch",
        "youtube",
        "rplay"
      ],
      "type": "string"
    },
    "EmoteRef": {
      "description": "Emotes are stored with each message because their images can differ per\nchannel or change over time: this keeps code and image in sync.",
      "properties": {
        "code": {
          "description": "The emote as it appears in the text, e.g. `Kappa` or `:_hype:`.",
          "type": "string"
        },
        "url": {
          "description": "Image URL.",
          "type": "string"
        }
      },
      "required": [
        "code",
        "url"
      ],
      "type": "object"
    },
    "MessageKind": {
      "description": "What kind of message this is. The names match the `kind` values of the\noverlay template (with `_` instead of `-`).",
      "oneOf": [
        {
          "description": "Normal chat.",
          "properties": {
            "type": {
              "const": "text",
              "type": "string"
            }
          },
          "required": [
            "type"
          ],
          "type": "object"
        },
        {
          "description": "Only emotes and whitespace; which ones is in `emotes`.",
          "properties": {
            "type": {
              "const": "emote_only",
              "type": "string"
            }
          },
          "required": [
            "type"
          ],
          "type": "object"
        },
        {
          "description": "Paid message: Twitch bits, YouTube Super Chat.",
          "properties": {
            "amount": {
              "description": "As displayed by the platform: \"€5.00\", \"100 bits\".",
              "type": "string"
            },
            "tier": {
              "description": "See [`MessageKind::Special`]'s `tier`.",
              "format": "uint32",
              "minimum": 0,
              "type": [
                "integer",
                "null"
              ]
            },
            "type": {
              "const": "donation",
              "type": "string"
            }
          },
          "required": [
            "type",
            "amount",
            "tier"
          ],
          "type": "object"
        },
        {
          "description": "Paid visual items: YouTube Super Stickers and gifts, later maybe\nTwitch giant emotes.",
          "properties": {
            "amount": {
              "description": "\"€2.00\", \"10 jewels\"",
              "type": [
                "string",
                "null"
              ]
            },
            "image_url": {
              "description": "Image, if the platform provides one (Super Stickers: no).",
              "type": [
                "string",
                "null"
              ]
            },
            "info": {
              "description": "Name or description of the item, e.g. the sticker's alt text.",
              "type": [
                "string",
                "null"
              ]
            },
            "tier": {
              "description": "How big the amount is on the platform's own scale, from 1 (the\nsmallest) up; `null` if the platform has none. Scales differ per\nplatform, so compare tiers only within one platform:\n- YouTube Super Chats and Stickers: YouTube's tier (its colour in\n  YouTube's chat: 1 blue, 2 cyan, 3 teal, 4 yellow, 5 orange,\n  6 magenta, 7 red), whatever the currency.\n- Twitch bits: the cheer tiers, 1 (1+ bits), 2 (100+),\n  3 (1,000+), 4 (5,000+), 5 (10,000+).",
              "format": "uint32",
              "minimum": 0,
              "type": [
                "integer",
                "null"
              ]
            },
            "type": {
              "const": "special",
              "type": "string"
            }
          },
          "required": [
            "type",
            "image_url",
            "amount",
            "info",
            "tier"
          ],
          "type": "object"
        },
        {
          "description": "New subscriber/member, resub, membership milestone.",
          "properties": {
            "info": {
              "description": "The platform's description, e.g. \"subscribed for 12 months\".",
              "type": "string"
            },
            "months": {
              "description": "How many months they've been a member, for a resub or milestone;\n`null` for a new subscriber/member.",
              "format": "uint32",
              "minimum": 0,
              "type": [
                "integer",
                "null"
              ]
            },
            "type": {
              "const": "membership",
              "type": "string"
            }
          },
          "required": [
            "type",
            "info",
            "months"
          ],
          "type": "object"
        },
        {
          "description": "Gifted subs (Twitch) or memberships (YouTube).",
          "properties": {
            "count": {
              "description": "Number of gifted subs/memberships.",
              "format": "uint",
              "minimum": 0,
              "type": "integer"
            },
            "type": {
              "const": "gift",
              "type": "string"
            }
          },
          "required": [
            "type",
            "count"
          ],
          "type": "object"
        },
        {
          "description": "Raids, announcements, watch streaks, etc.: platform events without a\nkind of their own.",
          "properties": {
            "info": {
              "description": "The platform's description.",
              "type": "string"
            },
            "type": {
              "const": "notice",
              "type": "string"
            }
          },
          "required": [
            "type",
            "info"
          ],
          "type": "object"
        }
      ]
    }
  },
  "description": "Everything a source can report. Moderation actions are separate\nvariants rather than message kinds: they have no author or text, and\nconsumers must remove already-displayed messages when they arrive.",
  "oneOf": [
    {
      "allOf": [
        {
          "$ref": "#/definitions/ChatMessage"
        }
      ],
      "description": "A chat message or a platform event (donation, sub, raid, ...).",
      "properties": {
        "type": {
          "const": "message",
          "type": "string"
        }
      },
      "required": [
        "type"
      ],
      "type": "object"
    },
    {
      "description": "A single message was deleted by a moderator.",
      "properties": {
        "message_id": {
          "description": "The `id` of the deleted message.",
          "type": "string"
        },
        "platform": {
          "$ref": "#/definitions/ChatPlatform"
        },
        "type": {
          "const": "delete",
          "type": "string"
        }
      },
      "required": [
        "type",
        "platform",
        "message_id"
      ],
      "type": "object"
    },
    {
      "description": "All messages by one user should go (ban or timeout).",
      "properties": {
        "platform": {
          "$ref": "#/definitions/ChatPlatform"
        },
        "type": {
          "const": "clear_user",
          "type": "string"
        },
        "user_id": {
          "description": "The `author.id` whose messages should be removed.",
          "type": "string"
        }
      },
      "required": [
        "type",
        "platform",
        "user_id"
      ],
      "type": "object"
    },
    {
      "description": "The whole chat of this platform was cleared.",
      "properties": {
        "platform": {
          "$ref": "#/definitions/ChatPlatform"
        },
        "type": {
          "const": "clear_all",
          "type": "string"
        }
      },
      "required": [
        "type",
        "platform"
      ],
      "type": "object"
    }
  ],
  "title": "ChatEvent"
}
