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;
}