WebSocket для клиентов

Реалтайм-события для клиентского приложения через WebSocket-соединение.

Подключение

ws://your-server:8082/ws/chat?token=JWT_TOKEN

Токен передаётся в query-параметре token. Используется тот же JWT access token, что и для REST API.

При невалидном или отсутствующем токене соединение закрывается с кодом 1008 (Policy Violation).

Что происходит при подключении

  1. Сервер верифицирует JWT-токен

  2. Создаётся сессия для пользователя

  3. Пользователь автоматически подписывается на все каналы, в которых состоит

  4. Начинается рассылка событий

Один пользователь может иметь несколько одновременных WebSocket-сессий.

Отправка от клиента

Клиент может отправлять JSON-сообщения серверу.

Typing-индикатор

{ "type": "typing", "channelId": "channel-uuid" }

Рассылается другим участникам канала как событие typing.

Входящие события

Все события приходят в формате JSON с полем type.

message.new

Новое сообщение в канале.

{ "type": "message.new", "channelId": "channel-uuid", "messageId": "message-uuid", "authorId": "user-uuid", "authorFederation": "https://auth.example.com", "content": "Привет!", "createdAt": "2025-01-15T10:30:00Z" }

message.edited

Сообщение отредактировано.

{ "type": "message.edited", "channelId": "channel-uuid", "messageId": "message-uuid", "content": "Исправленный текст", "editedAt": "2025-01-15T10:35:00Z" }

message.deleted

Сообщение удалено.

{ "type": "message.deleted", "channelId": "channel-uuid", "messageId": "message-uuid" }

member.joined

Пользователь вступил в канал.

{ "type": "member.joined", "channelId": "channel-uuid", "userId": "user-uuid", "federation": "https://auth.example.com" }

member.left

Пользователь покинул канал.

{ "type": "member.left", "channelId": "channel-uuid", "userId": "user-uuid", "federation": "https://auth.example.com" }

typing

Пользователь печатает.

{ "type": "typing", "channelId": "channel-uuid", "userId": "user-uuid", "federation": "https://auth.example.com" }

voice.joined

Пользователь подключился к голосовому каналу.

{ "type": "voice.joined", "channelId": "channel-uuid", "userId": "user-uuid", "federation": "https://auth.example.com" }

voice.left

Пользователь отключился от голосового канала.

{ "type": "voice.left", "channelId": "channel-uuid", "userId": "user-uuid", "federation": "https://auth.example.com" }

voice.muted

Изменился статус мьюта участника.

{ "type": "voice.muted", "channelId": "channel-uuid", "userId": "user-uuid", "federation": "https://auth.example.com", "muted": true }

voice.deafened

Изменился статус заглушения входящего звука.

{ "type": "voice.deafened", "channelId": "channel-uuid", "userId": "user-uuid", "federation": "https://auth.example.com", "deafened": true }

voice.screen-sharing

Изменился статус демонстрации экрана.

{ "type": "voice.screen-sharing", "channelId": "channel-uuid", "userId": "user-uuid", "federation": "https://auth.example.com", "active": true }

post.new

Новый пост в канале (CHANNEL/FORUM).

{ "type": "post.new", "channelId": "channel-uuid", "postId": "post-uuid", "authorId": "user-uuid", "authorFederation": "https://auth.example.com", "title": "Заголовок", "content": "Текст поста", "createdAt": "2025-01-15T10:30:00Z" }

post.edited

Пост отредактирован.

{ "type": "post.edited", "channelId": "channel-uuid", "postId": "post-uuid", "title": "Новый заголовок", "content": "Обновлённый текст", "editedAt": "2025-01-15T10:35:00Z" }

post.deleted

Пост удалён.

{ "type": "post.deleted", "channelId": "channel-uuid", "postId": "post-uuid" }

comment.new

Новый комментарий к посту.

{ "type": "comment.new", "channelId": "channel-uuid", "postId": "post-uuid", "commentId": "comment-uuid", "authorId": "user-uuid", "authorFederation": "https://auth.example.com", "content": "Текст комментария", "createdAt": "2025-01-15T11:00:00Z" }

Жизненный цикл

  • При отключении клиента сессия удаляется и отписывается от всех каналов

  • При вступлении в канал через REST API — автоматическая подписка во всех активных сессиях

  • При выходе из канала — автоматическая отписка