-
-
Save ar-nelson/75cb64f1f0986ef36d4754fd3115f5c1 to your computer and use it in GitHub Desktop.
Chatterbox API definition as of September 2025
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| syntax = "proto3"; | |
| package chatterbox.api.v1; | |
| import "google/protobuf/timestamp.proto"; | |
| import "google/protobuf/empty.proto"; | |
| import "google/protobuf/any.proto"; | |
| import "google/protobuf/descriptor.proto"; | |
| /* | |
| * The Chatterbox API is a WebSocket protocol that performs RPC by sending `ChatterboxRequest`s and receiving `ChatterboxResponse`s. | |
| * | |
| * This protocol is designed with simplicity and ease of implementation as the highest priority. | |
| * Consequently, it does not use Protobuf's service definition syntax (which would require a custom compilation step). | |
| * Instead, it uses simple custom RPC: each `ChatterboxRequest` is replied to with at least one `ChatterboxResponse` with the same `id`. | |
| * | |
| * === STAGE 1: WELCOME === | |
| * | |
| * After a client connects to a host's WebSocket endpoint, the host will send a `Welcome` message. | |
| * The client should not send anything until it receives this message. | |
| */ | |
| message Welcome { | |
| uint32 version = 1; // Major version of Chatterbox protocol | |
| string host = 2; | |
| optional string notice = 3; | |
| bool federated = 4; | |
| bool pubkey_registration = 5; | |
| bool password_registration = 6; | |
| bool email_required = 7; | |
| repeated string registration_questions = 8; | |
| } | |
| /* | |
| * === STAGE 2: AUTHENTICATION === | |
| * | |
| * After receiving a `Welcome`, the client must send an `AuthRequest`. | |
| * The server will reply with an `AuthResponse`, which may require more `AuthRequest`s. | |
| * Once the server has sent an `AuthResponse` whose `payload` is `authenticated`, | |
| * the connection progresses to stage 3, and the client may begin sending `ChatterboxRequest`s. | |
| * | |
| * Pubkey authentication flow: | |
| * request `pubkey` -> response `pubkey_challenge` -> request `challenge_solution` -> response `authenticated` | |
| */ | |
| message AuthRequest { | |
| uint64 id = 1; | |
| oneof payload { | |
| bytes token = 2; | |
| Pubkey pubkey = 3; | |
| Password password = 4; | |
| ChallengeSolution challenge_solution = 5; | |
| Register register = 6; | |
| } | |
| message Pubkey { | |
| string user = 1; | |
| optional string host = 2; | |
| bytes pubkey = 3; | |
| } | |
| message Password { | |
| string username = 1; | |
| string password = 2; | |
| } | |
| message ChallengeSolution { | |
| bytes nonce = 1; | |
| optional bytes pow_suffix = 2; | |
| } | |
| message Register { | |
| string name = 1; | |
| optional string email = 2; | |
| repeated string answers = 3; | |
| oneof auth { | |
| bytes pubkey = 4; | |
| string password = 5; | |
| } | |
| } | |
| } | |
| message AuthResponse { | |
| uint64 id = 1; | |
| oneof payload { | |
| google.protobuf.Empty authenticated = 2; | |
| string error = 3; | |
| PubkeyChallenge pubkey_challenge = 4; | |
| } | |
| message PubkeyChallenge { | |
| bytes challenge = 1; | |
| optional uint32 pow_difficulty = 2; | |
| optional string pow_message = 3; | |
| } | |
| } | |
| /* | |
| * === STAGE 3: CHATTERBOX API === | |
| * | |
| * Once authenticated, the client communicates by sending `ChatterboxRequest`s and receiving `ChatterboxResponse`s. | |
| * The host MUST respond to each request with at least one response with the same `id`. | |
| * Some requests can reply with streams, consisting of multiple responses with the same `id`. | |
| * (Empty streams are represented by a single response of type `unit`.) | |
| * Responses have a `state` field describing the state of the stream: DONE, ACTIVE, or WAITING. | |
| * Single responses or ends of streams have a state of DONE. | |
| * Active streams, which continue on their own unless closed, have a state of ACTIVE. | |
| * Passive streams, which must be continued by the client, have a state of WAITING. | |
| */ | |
| message ChatterboxRequest { | |
| uint64 id = 1; | |
| oneof payload { | |
| /// === 2-9: Stream Control === | |
| // When a `ChatterboxResponse` has a `state` of `STREAM_WAITING`, the client must send this request to continue the stream. | |
| // Value is the `id` of the `ChatterboxResponse` stream to continue. Response is `unit`. | |
| uint64 continue_stream = 2; | |
| // When a `ChatterboxResponse` is an open stream (`state` is not `STREAM_DONE`), the client may send this request to close the stream early. | |
| // A stream closed this way will send one more response, of type `error`. | |
| // Value is the `id` of the `ChatterboxResponse` stream to close. Response is `unit`. | |
| uint64 close_stream = 3; | |
| /// === 10-19: Common Host Functions === | |
| // Get generic information about the host. Response is `host_info`. | |
| google.protobuf.Empty host_get_info = 10; | |
| // List all signed statements about a user, optionally filtered by type. | |
| // Response is a stream of `statement`. | |
| HostGetStatements host_get_statements = 11; | |
| // Publish a signed statement to this host. | |
| // This call is used by users to publish their own statements, as well as by other servers to propagate statements. | |
| // Users with custodial private keys must use `current_user_sign_and_publish_statement` instead. | |
| // The host MUST act upon a valid statement upon receiving it, updating users' keys, names, etc. accordingly. | |
| // If the statement is invalid (bad signature, signed for the wrong user, etc.), the call MUST fail with an error. | |
| // Response is `unit`. | |
| SignedStatement host_publish_statement = 12; | |
| // Invite a local user to a DM conversation. | |
| // DMs and group chats occur in the "zero server", a server with an all-0 UUID that always exists on each host. | |
| // The user will receive a notification in the zero server and have the option to accept or reject the invite. | |
| // Response is `unit`. | |
| Identifier host_dm_invite = 13; | |
| // Respond to a DM invite, with the UUID of an already-created DM room. | |
| // This should be called on BOTH the invite sender's host and the invite recipient's host. | |
| // DM rooms can be created with `room_get_dm_room`. | |
| // If `room_uuid` is present, the invite was accepted; if the room does not already exist, it will be created. | |
| // If `room_uuid` is absent, the invite was rejected. | |
| // Cross-host DMs create rooms with the same UUID on each host, and sync them via their room event streams. | |
| // The host SHOULD enforce that the newly created room's UUIDv7 timestamp is recent, to avoid collisions. | |
| // Response is `unit`. | |
| HostDMResponse host_dm_respond_to_invite = 14; | |
| // Invite a local user to a group chat. | |
| // Group chats occur in the "zero server", a server with an all-0 UUID that always exists on each host. | |
| // The invite will create an empty local copy of the group room if it does not already exist. | |
| // The user will receive a notification in the zero server and have the option to accept or reject the invite. | |
| // Response is `unit`. | |
| HostGroupInvite host_group_invite = 15; | |
| // Respond to a group chat invite; the `accept` field denotes whether the invite was accepted. | |
| // This should be called on BOTH the invite sender's host and the invite recipient's host. | |
| // If the invite was accepted, the host should begin syncing the group room's events with other members' hosts. | |
| // Response is `unit`. | |
| HostGroupResponse host_group_respond_to_invite = 16; | |
| /// === 20-29: Admin Functions === | |
| // Set the `HostRole` of a user. Used to promote or moderate users for the entire host. | |
| // Setting a user to `HOST_ROLE_BANNED` will automatically kick them from the host. | |
| // The `until` field sets a timeout to return to `HOST_ROLE_USER`, but only for certain roles: | |
| // `HOST_ROLE_BANNED`, `HOST_ROLE_QUARANTINED` | |
| // Response is `unit`. | |
| AdminUserSetRole admin_user_set_role = 20; | |
| // Purge a user from the host | |
| // This deletes all data associated with the user, including all messages and uploaded media. | |
| // Response is `unit`. | |
| Identifier admin_user_purge = 21; | |
| // List all known users on the host, optionally filtered by name, host, role, and join time. | |
| // This includes any user that has ever connected, even if the user has not joined a server. | |
| // Response is a stream of `user`. | |
| AdminUserList admin_user_list = 22; | |
| /// === 30-39: Host List Management === | |
| // A host list is simply a list of strings (domain names) representing hosts. | |
| // All local users have host lists for joined servers and blocked servers. | |
| // Additionally, admins can set host lists for federation allow and block lists. | |
| // Get all hosts in a given host list. | |
| // Response is `host_list`. Note that, despite being a list, this is a single non-stream response. | |
| HostListType host_list_get = 30; | |
| // Add a host to a host list. If it already exists, this does nothing. | |
| // Hosts MUST check that `host` is a valid domain name, and fail with an error if it is not. | |
| // Hosts MUST normalize `host` to lowercase and convert Unicode domains to Punycode. | |
| // Response is `unit`. | |
| HostListEntry host_list_add = 31; | |
| // Remove a host from a host list. If it does not exist, this does nothing. | |
| // Hosts MUST normalize `host` to lowercase and convert Unicode domains to Punycode. | |
| // Response is `unit`. | |
| HostListEntry host_list_remove = 32; | |
| /// === 40-49: File Management === | |
| /// Users may upload files to the host. Files have a few uses: icons, emoji packs, and attachments. | |
| /// Files are identified by a `FileType` and a BLAKE3 hash of their contents. | |
| /// Hosts SHOULD limit image formats to PNG and JPEG, audio formats to Opus, and video formats to WebM+VP9+Opus. | |
| /// Conversion to these formats should happen in the client. | |
| /// Hosts MAY limit file sizes arbitrarily and delete unused files after a period of time. | |
| // Start a new file upload. ONLY ONE upload may be in progress at a time per WebSocket. | |
| // Once this call returns a `unit` response, the client may send `file_upload_chunk` requests. | |
| // When the upload is complete, this call will return the file hash as a second response (type `binary`). | |
| // Attempting to start an upload while another is in progress will cause both to fail with an error. | |
| // Response is a stream of two entries (`unit`, then `binary`). | |
| FileBeginUpload file_begin_upload = 40; | |
| // Upload a chunk of a file, if an upload is currently in progress (see `file_begin_upload`). | |
| // Response is `unit`. | |
| FileChunk file_upload_chunk = 41; | |
| // Download a file by hash and type. Response is a stream of `file_chunk`. | |
| FileDownload file_download = 42; | |
| // Delete a file by hash and type. Users can only delete their own files; host admins can delete any file. | |
| // Response is `unit`. | |
| FileDownload file_delete = 43; | |
| /// === 100-199: Current User Functions === | |
| // Open a stream of `UserEvent`s for the current user. | |
| // If `since` is present, the stream will start with all past events after `since` before continuing with current events. | |
| // The host MAY delete old events, but, if any events after `since` have been deleted, this call MUST fail with an error. | |
| // Response is an active stream of `UserEvent`s. | |
| CurrentUserEventStream current_user_event_stream = 100; | |
| // When the user has a custodial private key, this request is used to sign auth challenges from other hosts. | |
| // This MUST fail with an error if the user does not have a custodial private key. | |
| // Response is `binary`. | |
| bytes current_user_sign_challenge = 101; | |
| // Get miscellaneous information about the current user. Response is `current_user_state`. | |
| google.protobuf.Empty current_user_get_state = 102; | |
| // Get the current user's profile for a given server. Response is `user`. | |
| bytes current_user_get_server_member = 103; | |
| // Set the current user's status message, with an optional timeout. | |
| // If `server_uuids` is absent, the status is set for all servers, and becomes the default for new servers. | |
| // Response is `unit`. | |
| CurrentUserSetStatus current_user_set_status = 104; | |
| // Updates some fields of the current user's profile. | |
| // If `server_uuids` is absent, the fields are set for all servers, and become the default for new servers. | |
| // Response is `unit`. | |
| CurrentUserUpdateServerMember current_user_update_server_member = 105; | |
| // Delete the current user. | |
| // This will kick the current user from the host, ending the WebSocket connection. | |
| // Unlike `current_user_purge`, this does not delete messages or uploaded media. | |
| // No response, because this closes the connection. | |
| google.protobuf.Empty current_user_delete = 106; | |
| // Delete the current user and all past messages and uploaded media. | |
| // This will kick the current user from the host, ending the WebSocket connection. | |
| // No response, because this closes the connection. | |
| google.protobuf.Empty current_user_purge = 107; | |
| // Publish a statement about the current user to the host. | |
| // If the statement is not about the current user, the call MUST fail with an error. | |
| // The host should sign the statement with the custodial private key. | |
| // Afterward, it should publish the statement in the same manner as `host_publish_statement`. | |
| // Response is `statement`. (the signed statement) | |
| Statement current_user_sign_and_publish_statement = 108; | |
| // Set which events cause notifications for a given server or room. Response is `unit`. | |
| CurrentUserUpdateNotifyMode current_user_update_notify_mode = 109; | |
| /// === 200-299: Server Functions === | |
| /// In Chatterbox terminology, a "server" does not refer to a specific instance of the backend software. | |
| /// Instead, a server is a collection of users and rooms. A host (instance) may contain multiple servers. | |
| /// This is similar to what Discord calls a "server", or what Matrix calls a "space". | |
| /// Servers are identified by a UUID, and may be replicated across multiple hosts. | |
| // Open a stream of `ServerEvent`s for a given server. | |
| // If `since` is present, the stream will start with all past events after `since` before continuing with current events. | |
| // The host MAY delete old events, but, if any events after `since` have been deleted, this call MUST fail with an error. | |
| // Response is an active stream of `ServerEvent`s. | |
| ServerEventStream server_event_stream = 200; | |
| // Create a new server on this host. Response is `binary` (the server UUID). | |
| ServerCreate server_create = 201; | |
| // Get a server by UUID, including its list of visible rooms. Response is `server`. | |
| bytes server_get = 202; | |
| // List all known/public servers on this host. Response is a stream of `server`. | |
| ServerList server_list = 203; | |
| // Update some metadata fields of a server. Response is `unit`. | |
| ServerUpdate server_update = 204; | |
| // Delete a server. Note that this is a destructive operation and cannot be undone. | |
| // Response is `unit`. | |
| bytes server_delete = 205; | |
| // Join a server. If the current user is already a member, this does nothing. | |
| // If the current user has role `SERVER_ROLE_VISITOR`, this will upgrade it to `SERVER_ROLE_MEMBER`. | |
| // Response is `unit`. | |
| bytes server_join = 206; | |
| // Leave a server. If the current user is not a member, this does nothing. | |
| // Can also be used to remove oneself from invited servers where the user has role `SERVER_ROLE_VISITOR`. | |
| // Response is `unit`. | |
| bytes server_leave = 207; | |
| // Invite a user to a server. | |
| // The invitation appears as a notification to the user, and the user is added to the server with role `SERVER_ROLE_VISITOR`. | |
| // Response is `unit`. | |
| ServerInvite server_invite = 208; | |
| // Get a specific server member's profile, identified by `name@host`. | |
| // Response is `user`. | |
| ServerMemberGet server_member_get = 209; | |
| // List all members of a server, optionally filtered by name, host, role, and join time. | |
| // Users with roles below `SERVER_ROLE_MODERATOR` may not be able to see invited visitors. | |
| // Response is a stream of `user`. | |
| ServerMemberList server_member_list = 210; | |
| // Set the `ServerRole` of a user. Used to promote or moderate users for a given server. | |
| // Only usable by host role >= `HOST_ROLE_ADMIN` or server role >= `SERVER_ROLE_MODERATOR`. | |
| // Setting a user to `SERVER_ROLE_BANNED` will automatically kick them from the server. | |
| // The `until` field sets a timeout to return to `SERVER_ROLE_MEMBER`, but only for certain roles: | |
| // `SERVER_ROLE_BANNED`, `SERVER_ROLE_MUTED`. | |
| // Response is `unit`. | |
| ServerMemberSetRole server_member_set_role = 211; | |
| // List past notifications for a server. Response is a stream of `notification`. | |
| ServerNotificationList server_notification_list = 212; | |
| // Mark a notification as read. Response is `unit`. | |
| ServerNotificationMarkRead server_notification_mark_read = 213; | |
| // List all emoji packs for a server (value is server UUID). | |
| // Response is a stream of `emoji_pack`. | |
| bytes server_emoji_pack_list = 214; | |
| // Import an emoji pack from a file and add it to this server. | |
| // Only usable by host role >= `HOST_ROLE_ADMIN` or server role >= `SERVER_ROLE_MODERATOR`. | |
| // The file must be a ZIP file uploaded with type `FILE_TYPE_EMOJI_PACK`. | |
| // The ZIP file must contain only PNG files; each PNG file's name (minus extension) is its shortcode. | |
| // Clients SHOULD support animated PNGs and SHOULD convert GIFs in uploaded emoji pack ZIPs to PNGs. | |
| // Response is `unit`. | |
| ServerEmojiPackImport server_emoji_pack_import = 215; | |
| // Delete an emoji pack by name. If the pack does not exist, this does nothing. | |
| // Only usable by host role >= `HOST_ROLE_ADMIN` or server role >= `SERVER_ROLE_MODERATOR`. | |
| // Does not delete the file the pack is based on, though the server may delete it after a period of time. | |
| // Note that this may break custom emojis in existing messages. | |
| // Response is `unit`. | |
| ServerEmojiPackDelete server_emoji_pack_delete = 216; | |
| /// === 300-399: Room Functions === | |
| // Open a stream of `RoomEvent`s for a given room. | |
| // If `since` is present, the stream will start with all past events after `since` before continuing with current events. | |
| // The host MAY delete old events, but, if any events after `since` have been deleted, this call MUST fail with an error. | |
| // Response is an active stream of `RoomEvent`s. | |
| RoomEventStream room_event_stream = 300; | |
| // Create a new room in a given server. | |
| // Only usable by host role >= `HOST_ROLE_ADMIN` or server role >= `SERVER_ROLE_MODERATOR`. | |
| // If the new room is public, all users in the server will be automatically added to the room. | |
| // Response is `binary` (the room UUID). | |
| RoomCreate room_create = 301; | |
| // Get a room by UUID. The current user must have permission to view the room. Response is `room`. | |
| bytes room_get = 302; | |
| // Update some metadata fields of a room. | |
| // Only usable by host role >= `HOST_ROLE_ADMIN` or server role >= `SERVER_ROLE_MODERATOR`. | |
| // Response is `unit`. | |
| RoomUpdate room_update = 303; | |
| // Update the topic of a room. | |
| // Only usable by host role >= `HOST_ROLE_ADMIN` or server role >= `SERVER_ROLE_MODERATOR`. | |
| // This sends an ephemeral event to the room that includes the current user's name. | |
| // Response is `unit`. | |
| StringUpdate room_update_topic = 304; | |
| // Delete a room. Note that this is a destructive operation and cannot be undone. | |
| // Only usable by host role >= `HOST_ROLE_ADMIN` or server role >= `SERVER_ROLE_MODERATOR`. | |
| // Response is `unit`. | |
| bytes room_delete = 305; | |
| // Join a private room. If the current user is already a member, this does nothing. | |
| // The current user must have been invited to the room, or must be a moderator. | |
| // Response is `unit`. | |
| bytes room_join = 306; | |
| // Leave a private room. If the current user is not a member, this does nothing. | |
| // The current user retains the ability to view and rejoin the room, unless a moderator calls `room_kick`. | |
| // Response is `unit`. | |
| bytes room_leave = 307; | |
| // Invite a user to a private room. | |
| // The current user must already be a member of the room. | |
| // The invitation appears as a notification to the user, and the user gains permission to view the room. | |
| // Permission to view the room remains until a moderator calls `room_kick`. | |
| // Response is `unit`. | |
| RoomInvite room_invite = 308; | |
| // Kick a user from a private room. | |
| // Only usable by host role >= `HOST_ROLE_ADMIN` or server role >= `SERVER_ROLE_MODERATOR`. | |
| // The user loses permission to view the room, and must be re-invited to join. | |
| // Response is `unit`. | |
| RoomInvite room_kick = 309; | |
| // Get a specific room member's profile, identified by `name@host`. | |
| // Response is `user`. | |
| RoomMemberGet room_member_get = 310; | |
| // List all members of a private room, optionally filtered by name, host, role, and join time. | |
| // Users with roles below `SERVER_ROLE_MODERATOR` may not be able to see invited visitors. | |
| // Response is a stream of `user`. | |
| RoomMemberList room_member_list = 311; | |
| // Get the direct message room for a given user, creating it if it does not exist. | |
| // Only works if the current user is local. The DM room is always in the zero server. | |
| // Response is `binary` (room UUID). | |
| Identifier room_get_dm_room = 312; | |
| // Sends a "User is typing" event for the current user to the given room. | |
| // Typing notifications last for 5 seconds or until a message is sent. | |
| // Clients should debounce key events to roughly once per second when sending repeated requests. | |
| // Response is `unit`. | |
| bytes room_notify_typing = 313; | |
| // Get the last-read markers for up to the given number of users in the given room and thread. | |
| // Should try to intellegently choose users who are recently active. | |
| // Response is `last_read`. | |
| RoomLastReadGet room_last_read_get = 314; | |
| // Set the last-read marker for the current user in the given room and thread. | |
| // Last read is cumulative; reading a message implies that you have read all previous messages in the thread. | |
| // Response is `unit`. | |
| RoomLastReadSet room_last_read_set = 315; | |
| /// === 400-499: Message Functions === | |
| // Send a message to a room. | |
| // Response is `binary` (the message UUID). | |
| MessageSend message_create = 400; | |
| // Send a command in a room. | |
| // Commands are messages starting with /. They are only visible to the sender and the app that receives them. | |
| // The command is handled by the app's owner, which is usually a bot. | |
| // The command's prefix must be defined in one of the apps in the room's server. | |
| // Response is `binary` (the event UUID). | |
| MessageCommandSend message_command_send = 401; | |
| // Send an action to an app. | |
| // Actions are defined as buttons or other controls on annotations. | |
| // Interacting with these controls sends actions, which are handled by the user that owns the app. | |
| // Response is `binary` (the event UUID). | |
| MessageActionSend message_action_send = 402; | |
| // Get a message by UUID. The current user must have permission to view the message. | |
| // Response is `message`. | |
| bytes message_get = 403; | |
| // List a subset of the message history of a room or thread. | |
| // Used to reconstruct history when joining a room or when `room_event_stream` does not go back far enough. | |
| // Includes only messages in their most recent form, not additional events like join/leave, edit, delete, etc. | |
| // The response may be different between users: annotations hidden from the current user will not be included. | |
| // Response is a stream of `message`. | |
| MessageListHistory message_list_history = 404; | |
| // Update specific fields of a message. | |
| // The current user must be the message's sender or a moderator. | |
| // Response is `unit`. | |
| MessageUpdate message_update = 405; | |
| // Delete a message. | |
| // The current user must be the message's sender or a moderator. | |
| // Response is `unit`. | |
| bytes message_delete = 406; | |
| // React to a message with an emoji. If a matching reaction already exists, does nothing. | |
| // Response is `unit`. | |
| MessageReact message_react = 407; | |
| // Remove an emoji reaction from a message. If no such reaction exists, does nothing. | |
| // The current user must be the reaction's sender or a moderator. | |
| // Response is `unit`. | |
| MessageReact message_unreact = 408; | |
| /// === 500-599: App and Annotation Functions === | |
| /// Chatterbox supports plugin-like functionality via apps and bots. | |
| /// A user with host role >= `HOST_ROLE_BOT` can own one or more apps. | |
| /// The owner of an app can attach annotations to messages, and can receive commands and actions from users. | |
| /// Servers can activate an app by inviting the app's owning bot user. | |
| /// Bots can use this functionality to add features like link previews, automoderation, and more. | |
| // Create a new app, assigned to a specific bot user. | |
| // The app should have a unique name. App names are case-insensitive and should be in reverse-URL format, e.g. "com.example.app". | |
| // The current user must have host role >= `HOST_ROLE_ADMIN`. | |
| // Response is `unit`. | |
| AppDescription app_create = 500; | |
| // Look up an app by name. | |
| // Response is `app`. | |
| string app_get = 501; | |
| // List all apps available on this host. | |
| // Response is a stream of `app`. | |
| AppList app_list = 502; | |
| // Update some fields of an app's metadata. | |
| // The current user must have host role >= `HOST_ROLE_ADMIN`. | |
| // Response is `unit`. | |
| AppUpdate app_update = 503; | |
| // Delete an app by (case-insensitive) name. | |
| // The current user must have host role >= `HOST_ROLE_ADMIN`. | |
| // Response is `unit`. | |
| string app_delete = 504; | |
| // Create an annotation associated with an app and attach it to a message. | |
| // Only the owner of an app can create annotations for that app. | |
| // Response is `binary` (the annotation UUID). | |
| AppAnnotationCreate app_annotation_create = 510; | |
| // Send an annotation message to a room. | |
| // An annotation message is a message containing only an annotation, no content. | |
| // The message is only visible to the users who can see the annotation. | |
| // Only the owner of an app can send annotation messages for that app. | |
| // Response is `binary` (the message and annotation UUIDs. which are the same). | |
| AppAnnotationMessageSend app_annotation_message_send = 511; | |
| // Get an annotation by UUID. The current user must have permission to view the annotation. | |
| // Response is `annotation`. | |
| bytes app_annotation_get = 512; | |
| // Update some fields of an annotation. | |
| // Only the owner of an app can update annotations for that app. | |
| // Response is `unit`. | |
| AppAnnotationUpdate app_annotation_update = 513; | |
| // Delete an annotation by UUID. | |
| // Annotations can be deleted by the owner of the annotation's app, the owner of the annotated message, and moderators. | |
| // Response is `unit`. | |
| bytes app_annotation_delete = 514; | |
| }; | |
| message HostGetStatements { | |
| Identifier user = 1; | |
| repeated StatementType types = 2; | |
| } | |
| message HostDMResponse { | |
| Identifier inviter = 1; | |
| optional bytes room_uuid = 2; | |
| } | |
| message HostGroupInvite { | |
| Identifier recipient = 1; | |
| bytes room_uuid = 2; | |
| repeated string group_hosts = 3; | |
| string display_name = 4; | |
| optional string topic = 5; | |
| } | |
| message HostGroupResponse { | |
| Identifier inviter = 1; | |
| bytes room_uuid = 2; | |
| bool accept = 3; | |
| } | |
| message AdminUserSetRole { | |
| Identifier user = 1; | |
| HostRole role = 2; | |
| optional google.protobuf.Timestamp until = 3; | |
| optional string reason = 4; | |
| } | |
| message AdminUserList { | |
| optional string name_match = 1; | |
| optional string email_match = 2; | |
| optional string host_match = 3; | |
| optional bool local = 4; | |
| optional google.protobuf.Timestamp joined_before = 5; | |
| optional google.protobuf.Timestamp joined_after = 6; | |
| repeated HostRole roles = 7; | |
| } | |
| message CurrentUserEventStream { | |
| optional google.protobuf.Timestamp since = 1; | |
| } | |
| message CurrentUserSetStatus { | |
| repeated bytes server_uuids = 1; | |
| UserStatus status = 2; | |
| optional string message = 3; | |
| optional EmojiReference emoji = 4; | |
| optional google.protobuf.Timestamp until = 5; | |
| } | |
| message CurrentUserUpdateServerMember { | |
| repeated bytes server_uuids = 1; | |
| optional StringUpdate display_name = 2; | |
| optional FileReferenceUpdate icon = 3; | |
| optional StringUpdate bio = 4; | |
| } | |
| message CurrentUserUpdateNotifyMode { | |
| oneof subject { | |
| bytes server_uuid = 1; | |
| bytes room_uuid = 2; | |
| }; | |
| NotifyMode notify_mode = 3; | |
| } | |
| message HostListEntry { | |
| HostListType list = 1; | |
| string host = 2; | |
| } | |
| message FileBeginUpload { | |
| FileType type = 1; | |
| optional string mime_type = 2; | |
| uint64 size_in_bytes = 3; | |
| } | |
| message FileDownload { | |
| bytes hash = 1; | |
| optional FileType type = 2; | |
| } | |
| message ServerEventStream { | |
| bytes server_uuid = 1; | |
| optional google.protobuf.Timestamp since = 2; | |
| } | |
| message ServerCreate { | |
| string display_name = 1; | |
| optional string description = 2; | |
| optional string rules = 3; | |
| optional FileReference icon = 4; | |
| bool private = 5; | |
| bool anyone_can_invite = 6; | |
| repeated string languages = 7; | |
| } | |
| message ServerList { | |
| Sort sort = 1; | |
| bool ascending = 2; | |
| optional string filter = 3; | |
| enum Sort { | |
| SERVER_SORT_NAME = 0; | |
| SERVER_SORT_MEMBERS = 1; | |
| SERVER_SORT_CREATED_AT = 2; | |
| SERVER_SORT_LAST_ACTIVE = 3; | |
| } | |
| } | |
| message ServerUpdate { | |
| bytes server_uuid = 1; | |
| optional StringUpdate display_name = 2; | |
| optional StringUpdate description = 3; | |
| optional StringUpdate rules = 4; | |
| optional FileReferenceUpdate icon = 5; | |
| optional bool private = 6; | |
| optional bool anyone_can_invite = 7; | |
| optional StringList languages = 8; | |
| } | |
| message ServerInvite { | |
| bytes server_uuid = 1; | |
| Identifier user = 2; | |
| optional string message = 3; | |
| } | |
| message ServerMemberGet { | |
| bytes server_uuid = 1; | |
| Identifier user = 2; | |
| } | |
| message ServerMemberList { | |
| bytes server_uuid = 1; | |
| optional string name_match = 2; | |
| optional string host_match = 3; | |
| optional google.protobuf.Timestamp joined_before = 4; | |
| optional google.protobuf.Timestamp joined_after = 5; | |
| repeated ServerRole roles = 6; | |
| } | |
| message ServerNotificationList { | |
| bytes server_uuid = 1; | |
| optional google.protobuf.Timestamp since = 2; | |
| bool unread_only = 3; | |
| repeated NotificationType types = 4; | |
| } | |
| message ServerNotificationMarkRead { | |
| bytes server_uuid = 1; | |
| bytes notification_uuid = 2; | |
| } | |
| message ServerMemberSetRole { | |
| bytes server_uuid = 1; | |
| Identifier user = 2; | |
| ServerRole role = 3; | |
| optional google.protobuf.Timestamp until = 4; | |
| optional string reason = 5; | |
| } | |
| message ServerEmojiPackImport { | |
| bytes server_uuid = 1; | |
| string name = 2; | |
| bytes file_hash = 3; | |
| } | |
| message ServerEmojiPackDelete { | |
| bytes server_uuid = 1; | |
| string name = 2; | |
| } | |
| message RoomEventStream { | |
| bytes room_uuid = 1; | |
| optional google.protobuf.Timestamp since = 2; | |
| } | |
| message RoomCreate { | |
| bytes server_uuid = 1; | |
| string display_name = 2; | |
| RoomType type = 3; | |
| bool private = 4; | |
| optional string topic = 5; | |
| optional string category = 6; | |
| optional google.protobuf.FileDescriptorSet custom_fields_descriptor = 7; | |
| optional FileReference icon = 8; | |
| optional int32 sort_order = 9; | |
| repeated Identifier group_members = 10; | |
| } | |
| message RoomUpdate { | |
| bytes room_uuid = 1; | |
| optional string display_name = 2; | |
| optional bool private = 3; | |
| optional StringUpdate category = 4; | |
| optional int32 sort_order = 5; | |
| optional FileReferenceUpdate icon = 6; | |
| } | |
| message RoomInvite { | |
| bytes room_uuid = 1; | |
| Identifier user = 2; | |
| optional string message = 3; | |
| } | |
| message RoomMemberGet { | |
| bytes room_uuid = 1; | |
| Identifier user = 2; | |
| } | |
| message RoomMemberList { | |
| bytes room_uuid = 1; | |
| optional string name_match = 2; | |
| optional string host_match = 3; | |
| optional google.protobuf.Timestamp joined_before = 4; | |
| optional google.protobuf.Timestamp joined_after = 5; | |
| repeated ServerRole roles = 6; | |
| } | |
| message RoomLastReadSet { | |
| bytes room_uuid = 1; | |
| bytes message_uuid = 2; | |
| } | |
| message RoomLastReadGet { | |
| bytes room_uuid = 1; | |
| optional bytes thread_uuid = 2; | |
| optional google.protobuf.Timestamp since = 3; | |
| optional uint32 limit = 4; | |
| } | |
| message MessageSend { | |
| bytes room_uuid = 1; | |
| optional bytes thread_uuid = 2; | |
| optional bytes in_reply_to_message_uuid = 3; | |
| bool top_level = 4; | |
| string content = 5; | |
| optional string spoiler = 6; | |
| repeated google.protobuf.Any custom_fields = 7; | |
| repeated Attachment attachments = 8; | |
| } | |
| message MessageCommandSend { | |
| bytes room_uuid = 1; | |
| optional bytes thread_uuid = 2; | |
| string prefix = 3; | |
| string suffix = 4; | |
| } | |
| message MessageActionSend { | |
| bytes annotation_uuid = 1; | |
| string action = 2; | |
| repeated string arguments = 3; | |
| } | |
| message MessageListHistory { | |
| bytes room_uuid = 1; | |
| optional bytes thread_uuid = 2; | |
| optional bytes start = 3; | |
| bool inclusive = 4; | |
| bool ascending = 5; | |
| } | |
| message MessageUpdate { | |
| bytes message_uuid = 1; | |
| optional bool top_level = 2; | |
| optional string content = 3; | |
| optional StringUpdate spoiler = 4; | |
| optional AttachementsUpdate attachments = 5; | |
| message AttachementsUpdate { | |
| repeated Attachment attachments = 1; | |
| } | |
| } | |
| message MessageReact { | |
| bytes message_uuid = 1; | |
| oneof emoji { | |
| string unicode = 2; | |
| string custom = 3; | |
| } | |
| } | |
| message AppList { | |
| optional Identifier owner = 1; | |
| optional string name_match = 2; | |
| optional string metadata_match = 3; | |
| } | |
| message AppUpdate { | |
| string name = 1; | |
| optional string display_name = 2; | |
| optional Identifier owner = 3; | |
| optional string description = 4; | |
| optional StringUpdate link = 5; | |
| optional FileReferenceUpdate icon = 6; | |
| optional CommandsUpdate commands = 7; | |
| message CommandsUpdate { | |
| repeated CommandDescription commands = 1; | |
| } | |
| } | |
| message AppAnnotationCreate { | |
| string app = 1; | |
| bytes message_uuid = 2; | |
| optional string click_anywhere_link = 3; | |
| optional string text_content = 4; | |
| optional string html_embed = 5; | |
| repeated google.protobuf.Any custom_fields = 6; | |
| repeated Attachment attachments = 7; | |
| repeated Action actions = 8; | |
| repeated Identifier visible_to = 9; | |
| } | |
| message AppAnnotationMessageSend { | |
| string app = 1; | |
| bytes room_uuid = 2; | |
| optional bytes thread_uuid = 3; | |
| optional bytes in_reply_to_message_uuid = 4; | |
| optional string click_anywhere_link = 5; | |
| optional string text_content = 6; | |
| optional string html_embed = 7; | |
| repeated google.protobuf.Any custom_fields = 8; | |
| repeated Attachment attachments = 9; | |
| repeated Action actions = 10; | |
| repeated Identifier visible_to = 11; | |
| } | |
| message AppAnnotationUpdate { | |
| bytes annotation_uuid = 1; | |
| optional string click_anywhere_link = 2; | |
| optional string text_content = 3; | |
| optional string html_embed = 4; | |
| repeated google.protobuf.Any custom_fields = 5; | |
| repeated Attachment attachments = 6; | |
| repeated Action actions = 7; | |
| repeated Identifier visible_to = 8; | |
| } | |
| } | |
| message ChatterboxResponse { | |
| uint64 id = 1; | |
| StreamState state = 2; | |
| oneof payload { | |
| google.protobuf.Empty unit = 3; | |
| Error error = 4; | |
| bytes binary = 5; | |
| UserEvent user_event = 6; | |
| ServerEvent server_event = 7; | |
| RoomEvent room_event = 8; | |
| HostInfo host_info = 10; | |
| CurrentUserState current_user_state = 11; | |
| Statement statement = 12; | |
| StringList host_list = 13; | |
| FileChunk file_chunk = 14; | |
| User user = 15; | |
| ServerDetail server = 16; | |
| RoomDetail room = 17; | |
| EmojiPack emoji_pack = 18; | |
| Notification notification = 19; | |
| Message message = 20; | |
| LastRead last_read = 21; | |
| AppDescription app = 22; | |
| } | |
| enum StreamState { | |
| STREAM_DONE = 0; | |
| STREAM_ACTIVE = 1; | |
| STREAM_WAITING = 2; | |
| } | |
| enum ErrorType { | |
| // 0: Covers all errors that don't fit other types | |
| ERROR_UNKNOWN = 0; | |
| /// 1X errors: protocol errors | |
| // 10: ID of a ChatterboxRequest is already used or out of range | |
| ERROR_BAD_ID = 10; | |
| // 11: continue_stream or close_stream refers to closed or invalid stream | |
| ERROR_BAD_STREAM = 11; | |
| // 12: streams send this when closed abnormally or by close_stream | |
| ERROR_STREAM_CLOSED = 12; | |
| // 13: streams send this when left open long enough to auto-timeout | |
| ERROR_STREAM_TIMEOUT = 13; | |
| /// 2X errors: non-retryable request errors | |
| // 20: request is malformed or invalid | |
| ERROR_BAD_REQUEST = 20; | |
| // 21: feature is not implemented by this host | |
| ERROR_NOT_IMPLEMENTED = 21; | |
| // 22: user is not authorized to perform this action | |
| ERROR_FORBIDDEN = 22; | |
| // 23: some resource (user, server, room, message, etc.) is not found | |
| ERROR_NOT_FOUND = 23; | |
| /// 3X errors: retryable request errors | |
| // 30: unspecified spurious host error (use ERROR_UNKNOWN for true unanticipated errors) | |
| ERROR_HOST_FAILURE = 30; | |
| // 31: rate limited, try again later | |
| ERROR_RATE_LIMITED = 31; | |
| } | |
| message Error { | |
| ErrorType type = 1; | |
| optional string message = 2; | |
| } | |
| message HostInfo { | |
| uint32 version = 1; | |
| string host = 2; | |
| optional string name = 3; | |
| optional string rules = 4; | |
| optional bytes default_server_uuid = 5; | |
| optional string voice_platform = 6; | |
| optional string voice_host = 7; | |
| bool open_registration = 8; | |
| bool open_federation = 9; | |
| bool anyone_can_create_servers = 10; | |
| bool anyone_can_create_public_servers = 11; | |
| bool can_send_email = 12; | |
| uint32 user_count = 13; | |
| uint32 server_count = 14; | |
| uint32 event_expiration_days = 15; | |
| repeated string registration_questions = 16; | |
| repeated string languages = 17; | |
| repeated Identifier admins = 18; | |
| } | |
| message CurrentUserState { | |
| Identifier user = 1; | |
| bytes pubkey = 2; | |
| bool local_account = 3; | |
| bool custodial_private_key = 4; | |
| repeated bytes joined_local_servers = 5; | |
| } | |
| message ServerDetail { | |
| Server server = 1; | |
| bool joined = 2; | |
| bool has_unread = 3; | |
| int32 notification_count = 4; | |
| NotifyMode notify_mode = 5; | |
| int32 members = 6; | |
| repeated string room_categories = 7; | |
| repeated bytes room_uuids = 8; | |
| repeated string apps = 9; | |
| } | |
| message RoomDetail { | |
| Room room = 1; | |
| bool joined = 2; | |
| bool has_unread = 3; | |
| int32 notification_count = 4; | |
| NotifyMode notify_mode = 5; | |
| int32 sort_order = 6; | |
| optional string category = 7; | |
| google.protobuf.Timestamp last_active = 8; | |
| int32 members = 9; | |
| } | |
| message LastReadEntry { | |
| repeated LastRead entries = 1; | |
| } | |
| message LastRead { | |
| Identifier user = 1; | |
| bytes message_uuid = 2; | |
| } | |
| message EmojiPack { | |
| string name = 1; | |
| repeated CustomEmojiReference emoji = 2; | |
| } | |
| } | |
| /* | |
| * === EVENTS === | |
| */ | |
| message UserEvent { | |
| bytes uuid = 1; | |
| oneof event { | |
| StatementEvent statement_published = 2; | |
| ServerReferenceEvent server_invite = 3; | |
| ServerReferenceEvent server_joined = 4; | |
| ServerReferenceEvent server_left = 5; | |
| ServerConfigEvent server_config = 6; | |
| RoomReferenceEvent room_invite = 7; | |
| RoomReferenceEvent room_joined = 8; | |
| RoomReferenceEvent room_left = 9; | |
| RoomConfigEvent room_config = 10; | |
| NotificationEvent notification = 11; | |
| HostRoleUpdatedEvent host_role_updated = 12; | |
| } | |
| } | |
| message ServerEvent { | |
| bytes uuid = 1; | |
| oneof event { | |
| RoomAddedEvent room_added = 2; | |
| RoomAddedEvent room_updated = 3; | |
| RoomDeletedEvent room_deleted = 4; | |
| Server server_updated = 5; | |
| UserJoinedEvent user_joined = 6; | |
| UserLeftEvent user_left = 7; | |
| UserUpdatedEvent user_updated = 8; | |
| UserStatusUpdatedEvent user_status_updated = 9; | |
| MemberRoleUpdatedEvent member_role_updated = 10; | |
| StatementEvent user_statement_published = 11; | |
| } | |
| } | |
| message RoomEvent { | |
| bytes uuid = 1; | |
| oneof event { | |
| Message message_created = 2; | |
| MessageUpdated message_updated = 3; | |
| MessageDeleted message_deleted = 4; | |
| ReactionReference reaction_created = 5; | |
| ReactionReference reaction_deleted = 6; | |
| MessageAnnotated message_annotated = 7; | |
| Annotation annotation_updated = 8; | |
| bytes annotation_deleted = 9; | |
| CommandEvent command = 10; | |
| ActionEvent action = 11; | |
| UserJoinedEvent user_joined = 12; | |
| UserLeftEvent user_left = 13; | |
| Identifier user_typing = 14; | |
| LastReadUpdated last_read_updated = 15; | |
| } | |
| message MessageUpdated { | |
| bytes message_uuid = 1; | |
| Identifier updated_by = 2; | |
| optional string reason = 3; | |
| optional string content = 4; // only absent for annotation messages | |
| optional string spoiler = 5; | |
| repeated google.protobuf.Any custom_fields = 6; | |
| repeated Attachment attachments = 7; | |
| repeated Identifier mentions = 8; | |
| } | |
| message MessageDeleted { | |
| bytes message_uuid = 1; | |
| Identifier deleted_by = 2; | |
| optional string reason = 3; | |
| } | |
| message ReactionReference { | |
| bytes message_uuid = 1; | |
| Reaction reaction = 2; | |
| } | |
| message MessageAnnotated { | |
| bytes message_uuid = 1; | |
| Annotation annotation = 2; | |
| } | |
| message CommandEvent { | |
| Identifier sender = 1; | |
| optional bytes thread_uuid = 2; | |
| string prefix = 3; | |
| string suffix = 4; | |
| } | |
| message ActionEvent { | |
| Identifier sender = 1; | |
| bytes annotation_uuid = 2; | |
| string action = 3; | |
| repeated string arguments = 4; | |
| } | |
| message LastReadUpdated { | |
| Identifier user = 1; | |
| optional bytes thread_uuid = 2; | |
| bytes read_message_uuid = 3; | |
| } | |
| } | |
| message NotificationEvent { | |
| bytes server_uuid = 1; | |
| Notification notification = 2; | |
| } | |
| message StatementEvent { | |
| Identifier user = 1; | |
| SignedStatement statement = 2; | |
| google.protobuf.Timestamp published_at = 3; | |
| } | |
| message RoomAddedEvent { | |
| Room room = 1; | |
| int32 sort_order = 2; | |
| optional string category = 3; | |
| } | |
| message RoomUpdatedEvent { | |
| Room room = 1; | |
| optional Identifier updated_by = 2; | |
| } | |
| message RoomDeletedEvent { bytes uuid = 1; } | |
| message UserJoinedEvent { | |
| Identifier id = 1; | |
| User user = 2; | |
| } | |
| message UserLeftEvent { Identifier id = 1; } | |
| message UserUpdatedEvent { | |
| Identifier id = 1; | |
| optional string display_name = 2; | |
| optional FileReference icon = 3; | |
| optional string bio = 4; | |
| } | |
| message UserStatusUpdatedEvent { | |
| Identifier id = 1; | |
| UserStatus status = 2; | |
| optional string status_message = 3; | |
| } | |
| message HostRoleUpdatedEvent { | |
| HostRole role = 1; | |
| optional string reason = 2; | |
| optional google.protobuf.Timestamp until = 3; | |
| } | |
| message MemberRoleUpdatedEvent { | |
| Identifier id = 1; | |
| oneof role { | |
| ServerRole server_role = 2; | |
| HostRole host_role = 3; | |
| } | |
| optional Identifier updated_by = 4; | |
| optional string reason = 5; | |
| optional google.protobuf.Timestamp until = 6; | |
| } | |
| message ServerReferenceEvent { | |
| bytes uuid = 1; | |
| repeated string replica_hosts = 2; | |
| uint32 sort_order = 3; | |
| } | |
| message RoomReferenceEvent { | |
| bytes server_uuid = 1; | |
| repeated string server_replica_hosts = 2; | |
| bytes room_uuid = 3; | |
| optional string category = 4; | |
| } | |
| message ServerConfigEvent { repeated ServerConfigUpdate updates = 1; } | |
| message ServerConfigUpdate { | |
| bytes server_uuid = 1; | |
| oneof action { | |
| NotifyMode notify_mode = 2; | |
| int32 sort_order = 3; | |
| StringList hosts = 4; | |
| } | |
| } | |
| message RoomConfigEvent { repeated RoomConfigUpdate updates = 1; } | |
| message RoomConfigUpdate { | |
| bytes room_uuid = 1; | |
| oneof action { NotifyMode notify_mode = 2; } | |
| } | |
| /* | |
| * === COMMON TYPES === | |
| */ | |
| enum RoomType { | |
| // Basic room for text chat. | |
| ROOM_TYPE_TEXT = 0; | |
| // Like ROOM_TYPE_TEXT but only SERVER_ROLE_BOT and higher can post. | |
| ROOM_TYPE_ANNOUNCEMENTS = 1; | |
| // Autogenerated direct message room in zero server. Like ROOM_TYPE_TEXT. | |
| ROOM_TYPE_DM = 2; | |
| // Group chat room in zero server. Like ROOM_TYPE_TEXT. | |
| ROOM_TYPE_GROUP = 3; | |
| // Self chat room in zero server. Like ROOM_TYPE_TEXT. | |
| ROOM_TYPE_SELF = 4; | |
| // Voice chat room with no text component. | |
| // This is the only type that is significantly functionally different: it cannot contain messages at all. | |
| ROOM_TYPE_VOICE = 5; | |
| // Text room where all top-level posts must be threads. | |
| ROOM_TYPE_FORUM = 6; | |
| // Client-specific custom room type determined by custom metadata. | |
| ROOM_TYPE_CUSTOM = 7; | |
| } | |
| enum UserStatus { | |
| // User is offline on all devices. | |
| USER_STATUS_OFFLINE = 0; | |
| // User is online but should appear offline to other users. | |
| // Methods that fetch server members or room members should display `USER_STATUS_OFFLINE` instead. | |
| USER_STATUS_INVISIBLE = 1; | |
| // User is online but does not want to be disturbed, may not receive notifications. | |
| USER_STATUS_DO_NOT_DISTURB = 2; | |
| // User is online but has not been active on any device recently. | |
| USER_STATUS_IDLE = 3; | |
| // User is online and recently active on at least one device. | |
| USER_STATUS_ONLINE = 4; | |
| } | |
| enum HostRole { | |
| // User cannot connect to the host. | |
| HOST_ROLE_BANNED = 0; | |
| // User can connect to the host but cannot interact or join servers. | |
| HOST_ROLE_QUARANTINED = 1; | |
| // Like HOST_ROLE_USER but the user is a proxy for a user on another platform or host. | |
| HOST_ROLE_PROXY = 2; | |
| // User is an ordinary user. | |
| HOST_ROLE_USER = 3; | |
| // User is a bot, can own apps. | |
| HOST_ROLE_BOT = 4; | |
| // User is an admin, can moderate users at the host level and change host settings. | |
| HOST_ROLE_ADMIN = 5; | |
| // User is the system user (there can only be one), can perform federation operations. | |
| HOST_ROLE_SYSTEM = 6; | |
| } | |
| enum ServerRole { | |
| // User cannot join the server. | |
| SERVER_ROLE_BANNED = 0; | |
| // User can view posts but cannot post or react. (due to moderation) | |
| SERVER_ROLE_MUTED = 1; | |
| // User can view posts but cannot post or react. (invited but not joined) | |
| SERVER_ROLE_VISITOR = 2; | |
| // User is an ordinary user. | |
| SERVER_ROLE_MEMBER = 3; | |
| // User is a bot, can annotate and receive events for owned apps assigned to the server. | |
| SERVER_ROLE_BOT = 4; | |
| // User is a moderator, can moderate users, create and delete rooms. | |
| SERVER_ROLE_MODERATOR = 5; | |
| // User is an admin, has moderator permissions and can edit server settings. | |
| SERVER_ROLE_ADMIN = 6; | |
| } | |
| enum FileType { | |
| // Downloadable files of any MIME type. | |
| FILE_TYPE_DOWNLOAD = 0; | |
| // Icons for users, servers, rooms, etc. Must be square PNG or JPEG. | |
| FILE_TYPE_ICON = 1; | |
| // Images attached to messages; must be PNG or JPEG. | |
| FILE_TYPE_IMAGE = 2; | |
| // Audio files attached to messages; must be Opus. | |
| FILE_TYPE_AUDIO = 3; | |
| // Video files attached to messages; must be WebM container with VP9 video and Opus audio. | |
| FILE_TYPE_VIDEO = 4; | |
| // Thumbnails for images and videos. This is a special category that cannot be uploaded by users. | |
| // Whenever an image or video is uploaded, the host generates a PNG or JPEG thumbnail and stores it. | |
| // Thumbnails always have the same hash as the file they represent. | |
| // Thumbnails cannot be deleted directly, but are deleted when their associated file is deleted. | |
| FILE_TYPE_THUMBNAIL = 5; | |
| // ZIP files containing emoji packs. An emoji pack is a ZIP containing only PNG files, which may be animated. | |
| // `server_emoji_pack_import` can be called to import an emoji pack. | |
| // Each file in the ZIP will become a custom emoji, with its extensionless filename as the shortcode. | |
| FILE_TYPE_EMOJI_PACK = 6; | |
| // Custom emoji. This is a special category that cannot be uploaded by users. | |
| // Custom emoji files are generated by the host when an emoji pack is imported. | |
| // Emojis are always PNG files, and may be animated. | |
| // Emojis cannot be deleted directly, but are deleted when their associated emoji pack is deleted. | |
| FILE_TYPE_EMOJI = 7; | |
| } | |
| enum NotificationType { | |
| NOTIFICATION_TYPE_UNKNOWN = 0; | |
| NOTIFICATION_TYPE_MENTION = 1; | |
| NOTIFICATION_TYPE_EVERYONE = 2; | |
| NOTIFICATION_TYPE_THREAD = 3; | |
| NOTIFICATION_TYPE_DM = 4; | |
| NOTIFICATION_TYPE_DM_INVITE = 5; | |
| NOTIFICATION_TYPE_GROUP_INVITE = 6; | |
| NOTIFICATION_TYPE_SERVER_INVITE = 7; | |
| NOTIFICATION_TYPE_ROOM_INVITE = 8; | |
| } | |
| enum NotifyMode { | |
| // Inherit from parent notification settings, default to `NOTIFY_MODE_MENTIONS_AND_THREADS`. | |
| NOTIFY_MODE_UNSET = 0; | |
| // Notify when anyone posts. | |
| NOTIFY_MODE_ALL = 1; | |
| // Notify when current user is mentioned or someone replies to a thread current user has participated in. | |
| NOTIFY_MODE_MENTIONS_AND_THREADS = 2; | |
| // Do not notify about anything. | |
| NOTIFY_MODE_MUTE = 3; | |
| } | |
| enum AttachmentType { | |
| ATTACHMENT_TYPE_DOWNLOAD = 0; | |
| ATTACHMENT_TYPE_IMAGE = 1; | |
| ATTACHMENT_TYPE_AUDIO = 2; | |
| ATTACHMENT_TYPE_VIDEO = 3; | |
| } | |
| enum HostListType { | |
| // List of hosts that a local user has joined servers on. | |
| // Used to restart federation when a user reconnects to their main host. | |
| // Users who manage their own private keys may store this locally instead. | |
| HOST_LIST_TYPE_USER_JOINED = 0; | |
| // List of hosts that a local user has blocked. | |
| // The user will not receive DM requests from these hosts. | |
| HOST_LIST_TYPE_USER_BLOCK = 1; | |
| // Admin-controlled list of hosts allowed to federate with this host. | |
| // Only local users and users from these hosts can connect to this host. | |
| // Only used when the host is in limited federation mode. | |
| HOST_LIST_TYPE_FEDERATION_ALLOW = 2; | |
| // Admin-controlled list of hosts blocked from federating with this host. | |
| // Users from these hosts cannot connect to this host. | |
| // Only used when the host is in open federation mode. | |
| HOST_LIST_TYPE_FEDERATION_BLOCK = 3; | |
| } | |
| message Identifier { | |
| string name = 1; | |
| string host = 2; | |
| } | |
| message User { | |
| string name = 1; | |
| optional string display_name = 2; | |
| bytes pubkey = 3; | |
| HostRole host_role = 4; | |
| ServerRole server_role = 5; | |
| optional FileReference icon = 6; | |
| optional string bio = 7; | |
| UserStatus status = 8; | |
| optional string status_message = 9; | |
| optional EmojiReference status_emoji = 10; | |
| optional google.protobuf.Timestamp status_until = 11; | |
| optional string voice_id = 12; | |
| google.protobuf.Timestamp created_at = 13; | |
| google.protobuf.Timestamp last_seen_at = 14; | |
| google.protobuf.Timestamp joined_at = 15; | |
| bool custodial_private_key = 16; | |
| optional bytes last_update_event_uuid = 17; | |
| optional bytes last_status_update_event_uuid = 18; | |
| } | |
| message Server { | |
| bytes uuid = 1; | |
| string host = 2; | |
| string display_name = 3; | |
| string description = 4; | |
| optional string rules = 5; | |
| optional FileReference icon = 6; | |
| google.protobuf.Timestamp created_at = 7; | |
| bool private = 8; | |
| bool federated = 9; | |
| bool anyone_can_invite = 10; | |
| repeated string languages = 11; | |
| repeated string replica_hosts = 12; | |
| optional bytes last_update_event_uuid = 13; | |
| } | |
| message Room { | |
| bytes uuid = 1; | |
| bytes server_uuid = 2; | |
| string display_name = 3; | |
| optional string topic = 4; | |
| RoomType type = 5; | |
| optional string voice_id = 6; | |
| optional google.protobuf.FileDescriptorSet custom_fields_descriptor = 7; | |
| optional FileReference icon = 8; | |
| google.protobuf.Timestamp created_at = 9; | |
| bool private = 10; | |
| optional bytes last_update_event_uuid = 11; | |
| } | |
| message ThreadSummary { | |
| uint32 reply_count = 1; | |
| google.protobuf.Timestamp last_reply_at = 2; | |
| repeated Identifier some_reply_authors = 3; | |
| } | |
| message Message { | |
| bytes uuid = 1; | |
| oneof thread { | |
| bytes parent = 2; | |
| ThreadSummary replies = 3; | |
| } | |
| bool top_level = 4; | |
| Identifier author = 5; | |
| optional string content = 6; // only absent for annotation messages | |
| optional string spoiler = 7; | |
| google.protobuf.Timestamp created_at = 8; | |
| optional bytes last_update_event_uuid = 9; | |
| repeated google.protobuf.Any custom_fields = 10; | |
| repeated Attachment attachments = 11; | |
| repeated Annotation annotations = 12; | |
| repeated Identifier mentions = 13; | |
| repeated ReactionSummary reactions = 14; | |
| } | |
| message Attachment { | |
| FileReference file = 1; | |
| AttachmentType attachment_type = 2; | |
| optional string name = 3; | |
| uint64 size_in_bytes = 4; | |
| optional uint32 width = 5; | |
| optional uint32 height = 6; | |
| optional uint64 length_in_seconds = 7; | |
| } | |
| message Action { | |
| string name = 1; | |
| string caption = 2; | |
| bool primary = 3; | |
| } | |
| message Annotation { | |
| bytes uuid = 1; | |
| Identifier author = 2; | |
| optional string app_name = 3; | |
| optional FileReference app_icon = 4; | |
| google.protobuf.Timestamp created_at = 5; | |
| optional bytes last_update_event_uuid = 6; | |
| optional string click_anywhere_link = 7; | |
| optional string text_content = 8; | |
| optional string html_embed = 9; | |
| repeated google.protobuf.Any custom_fields = 10; | |
| repeated Attachment attachments = 11; | |
| repeated Action actions = 12; | |
| repeated Identifier visible_to = 13; | |
| } | |
| message Reaction { | |
| Identifier author = 1; | |
| EmojiReference emoji = 2; | |
| google.protobuf.Timestamp created_at = 3; | |
| } | |
| message ReactionSummary { | |
| EmojiReference emoji = 1; | |
| uint32 count = 2; | |
| optional string yours = 3; | |
| repeated Identifier some_authors = 4; | |
| } | |
| message Notification { | |
| bytes uuid = 1; | |
| optional bytes room_uuid = 2; | |
| bool read = 3; | |
| NotificationType notification_type = 4; | |
| oneof referent { | |
| Message message = 5; | |
| Identifier user = 6; | |
| bytes ref_uuid = 7; | |
| } | |
| } | |
| message CommandDescription { | |
| string prefix = 1; | |
| string name = 2; | |
| string usage = 3; | |
| string description = 4; | |
| } | |
| message AppDescription { | |
| string name = 1; | |
| string display_name = 2; | |
| Identifier owner = 3; | |
| string description = 4; | |
| optional string link = 5; | |
| optional FileReference icon = 6; | |
| repeated CommandDescription commands = 7; | |
| } | |
| message FileReference { | |
| bytes file_hash = 1; | |
| repeated string hosts = 2; | |
| optional bytes thumbhash = 3; | |
| } | |
| message CustomEmojiReference { | |
| bytes file_hash = 1; | |
| repeated string hosts = 2; | |
| string shortcode = 3; | |
| } | |
| message EmojiReference { | |
| oneof reference { | |
| string unicode = 1; | |
| string grouped_unicode = 2; | |
| CustomEmojiReference custom = 3; | |
| } | |
| } | |
| message FileChunk { | |
| bytes chunk = 1; | |
| bool done = 2; | |
| } | |
| message StringList { | |
| repeated string strings = 1; | |
| } | |
| message StringUpdate { | |
| optional string value = 1; | |
| } | |
| message FileReferenceUpdate { | |
| optional FileReference value = 1; | |
| } | |
| /* | |
| * === SIGNED STATEMENTS === | |
| * | |
| * Some actions, such as key rotation and account migration, require a statement signed with the user's private key. | |
| * This provides proof that the user approved the action, even if the user's original host is no longer available. | |
| * These statements can be propagated among federated servers with a gossip protocol. | |
| */ | |
| enum StatementType { | |
| STATEMENT_TYPE_UNSPECIFIED = 0; | |
| STATEMENT_TYPE_KEY_ROTATION = 1; | |
| STATEMENT_TYPE_KEY_REVOCATION = 2; | |
| STATEMENT_TYPE_MIGRATION = 3; | |
| } | |
| message SignedStatement { | |
| StatementType statement_type = 1; | |
| bytes statement = 2; | |
| bytes signature = 3; | |
| } | |
| message Statement { | |
| oneof statement { | |
| KeyRotationStatement key_rotation = 1; | |
| KeyRevocationStatement key_revocation = 2; | |
| MigrationStatement migration = 3; | |
| } | |
| } | |
| message KeyRotationStatement { | |
| Identifier user = 1; | |
| bytes old_pubkey = 2; | |
| bytes new_pubkey = 3; | |
| google.protobuf.Timestamp effective_at = 4; | |
| bool custodial_private_key = 5; | |
| optional string reason = 6; | |
| } | |
| message KeyRevocationStatement { | |
| Identifier user = 1; | |
| bytes pubkey = 2; | |
| google.protobuf.Timestamp effective_at = 3; | |
| optional string reason = 4; | |
| } | |
| message MigrationStatement { | |
| Identifier old_user = 1; | |
| Identifier new_user = 2; | |
| bytes pubkey = 3; | |
| optional bytes new_pubkey = 4; | |
| google.protobuf.Timestamp effective_at = 5; | |
| bool custodial_private_key = 6; | |
| optional string reason = 7; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment