seabird 0.4.0-alpha.4

A simple client library for the seabird-chat ecosystem
Documentation
syntax = "proto3";

package common;

import "google/protobuf/timestamp.proto";

option java_package = "io.coded.seabird.common";
option go_package = ".;pb";

// All IDs come in two forms - relative and absolute. Relative IDs are sent only
// by chat backends, while Absolute IDs will only be seen by plugins. A backend
// will only see relative IDs, plugins will only see absolute IDs.
//
// Relative IDs are a string of any characters which can be properly urlencoded.
//
// Absolute IDs are a URL with the following parts representing different
// things:
// - Scheme refers to the backend type (irc, discord, etc)
// - Host refers to the ID of the backend
// - Path refers to the relative ID of this item. Note that this MUST be
//   properly urlencoded as it can contain characters which would cause it to
//   parse differently, such as `#`, often used by the IRC backend to represent
//   channels.
//
// An absolute ID MUST be unique among all items in that set, but they do not
// need to be unique globally.
//
// Note that absolute IDs do not match character-for-character between the
// different backend implementations, but they MUST decode to the same
// components.

// Tags are a set of key-value items which may expose additional information
// about the given Event.
//
// All tags SHOULD be prefixed with something unique to that plugin or backend.
// All tags starting with `seabird-core/` are reserved for use by seabird-core.
//
// Currently known tags:
// - proxy/skip - this can be set to '1' if the message should not be proxied.
//   Any other value means the message should be proxied. As an example, this is
//   useful for metadata which some backends may already provide. Generally if a
//   plugin uses this, it should respond to both normal events and the "send"
//   variant of that message (such as MessageEvent/SendMessageEvent or
//   ActionEvent/PerformActionEvent).
// - core/original-format - set by seabird-core on all message events to indicate
//   whether the message was originally provided with 'text' only or with 'blocks'.
//   Values are 'text' or 'blocks'. Useful for plugins that need to differentiate
//   between legacy text-only clients and modern block-aware clients.
//
// Currently proposed tags:
// - proxy/source-channel-id - set by the proxy plugin if a message is proxied,
//   it will contain the original source channel ID
// - proxy/source-channel-name - set by the proxy plugin if a message is
//   proxied, it will contain the original source channel name
// - proxy/source-user-id - set by the proxy plugin if a message is proxied, it
//   will contain the original source user ID
// - proxy/source-user-name - set by the proxy plugin if a message is proxied,
//   it will contain the original source user name.

// When sent by a chat backend, the ID MAY optionally be used as a hint to the
// frontend to get the same external ID on reconnection. When sent by core to a
// plugin, the ID MUST be an ID pointing to an exact backend instance.
message Backend {
  string id = 1;
  string type = 2;
}

// When sent by a chat backend, the ID MUST be unique across users in that running
// backend. Failure to follow this will result in incorrect information being
// sent to plugins. When sent by core to a plugin, the ID MUST be an ID pointing
// to an instance of a user on chat backend.
message User {
  string id = 1;
  string display_name = 2;
}

// When sent by a chat backend, the ID MUST be unique across channels in that
// running backend. Failure to follow this will result in incorrect information
// being sent to plugins. When sent by core to a plugin, the ID MUST be an ID
// pointing to an instance of a channel on chat backend.
message Channel {
  string id = 1;
  string display_name = 2;
  string topic = 3;
}

// ChannelSource represents where a message came from. Note that User is used
// rather than just an ID so any clients can have access to the name as well.
// This may change in the future.
message ChannelSource {
  string channel_id = 1;
  User user = 2;
}

// Common Events

// MessageEvent will be sent when a user sends a message to a channel.
//
// When ingesting, if blocks are provided, they will be used to re-hydrate the
// text string. If only text is provided, a new TextBlock with the text contents
// will be created.
//
// Clients can assume that both text and blocks will be provided for every
// message.
message MessageEvent {
  ChannelSource source = 1;
  string text = 2;
  Block root_block = 3;
}

// PrivateMessageEvent will be sent when a user sends a message directly to the
// chat backend.
message PrivateMessageEvent {
  common.User source = 1;
  string text = 2;
  Block root_block = 3;
}

// MentionEvent will be sent when a user mentions the chat backend's user at the
// start of a message in a channel.
//
// This has been deprecated in favor of MessageEvents containing a MentionBlock.
message MentionEvent {
  ChannelSource source = 1;
  string text = 2;
  Block root_block = 3;
}

// CommandEvent will be sent when a user issues a command in a channel. Commands
// cannot currently be issued via private message. If a message is parsed as a
// command, it MUST NOT be also sent as another message type.
message CommandEvent {
  ChannelSource source = 1;
  string command = 2;
  string arg = 3;
}

// ActionEvent will be sent when a user takes an action in a channel. This is
// often triggered with /me.
message ActionEvent {
  ChannelSource source = 1;
  string text = 2;
  Block root_block = 3;
}

// PrivateActionEvent will be sent when a user takes an action in a private
// message. This is often triggered with /me.
message PrivateActionEvent {
  common.User source = 1;
  string text = 2;
  Block root_block = 3;
}

// Block defines the base message format. It is essentially a tree
message Block {
  // Having a raw string on the Block type allows us to add additional types to
  // the inner block, while allowing existing clients to fall back to the raw
  // string.
  //
  // Seabird will always re-hydrate the "plain" property from the blocks.

  // The parsed text with all formatting removed
  string plain = 1;

  oneof inner {
    TextBlock text = 2;
    ItalicsBlock italics = 3;
    BoldBlock bold = 4;
    UnderlineBlock underline = 5;
    StrikethroughBlock strikethrough = 6;
    InlineCodeBlock inline_code = 7;
    FencedCodeBlock fenced_code = 8;
    SpoilerBlock spoiler = 9;
    ListBlock list = 10;
    LinkBlock link = 11;
    BlockquoteBlock blockquote = 12;
    TimestampBlock timestamp = 13;
    ContainerBlock container = 14;
    HeadingBlock heading = 15;
  }
}

// TextBlock is a simple text block. It does not have any child blocks.
message TextBlock {
  string text = 1;
}

// ItalicsBlock is a formatting block, applying the formatting to all blocks
// inside it.
message ItalicsBlock {
  Block inner = 1;
}

// BoldBlock is a formatting block, applying the formatting to all blocks
// inside it.
message BoldBlock {
  Block inner = 1;
}

// UnderlineBlock is a formatting block, applying the formatting to all blocks
// inside it.
message UnderlineBlock {
  Block inner = 1;
}

// StrikethroughBlock is a formatting block, applying the formatting to all blocks
// inside it.
message StrikethroughBlock {
  Block inner = 1;
}

// InlineCodeBlock is a formatting block, applying the formatting to all blocks
// inside it.
message InlineCodeBlock {
  string text = 1;
}

// FencedCodeBlock is a formatting block, applying the formatting to all blocks
// inside it.
message FencedCodeBlock {
  string info = 1;
  string text = 2;
}

// SpoilerBlock is a formatting block, applying the formatting to all blocks
// inside it.
message SpoilerBlock {
  Block inner = 2;
}

// ListBlock is a container block, signifying that the inner blocks are all list
// items.
message ListBlock {
  repeated Block inner = 1;
}

// LinkBlock represents a link. The URL is the URL, and the inner blocks are the
// link text.
message LinkBlock {
  string url = 1;
  Block inner = 2;
}

// BlockquoteBlock is a container block, signifying that the inner blocks are
// all in a blockquote.
message BlockquoteBlock {
  Block inner = 1;
}

// ContainerBlock is a container block with no formatting, signifying that the
// inner blocks are grouped together, but nothing more. It is useful for
// ListBlocks.
message ContainerBlock {
  repeated Block inner = 1;
}

// TimestampBlock represents a timestamp. It can be used on platforms which
// support timezone-aware timestamps.
message TimestampBlock {
  google.protobuf.Timestamp inner = 1;
}

// HeadingBlock represents a heading. It is stored along with an arbitrary
// heading level.
message HeadingBlock {
  int32 level = 1;
  Block inner = 2;
}