feat(auth,privacy,web): step-by-step login, privacy settings persistence, TOTP QR, and API docs
Some checks failed
CI / test (push) Failing after 22s
Some checks failed
CI / test (push) Failing after 22s
This commit is contained in:
240
docs/realtime.md
Normal file
240
docs/realtime.md
Normal file
@@ -0,0 +1,240 @@
|
||||
# Realtime WebSocket API
|
||||
|
||||
WebSocket endpoint:
|
||||
|
||||
- `GET /api/v1/realtime/ws?token=<access_token>`
|
||||
|
||||
Authentication:
|
||||
|
||||
- Pass a valid **access token** as query parameter `token`.
|
||||
- If token is missing/invalid, server closes with `1008` (policy violation).
|
||||
|
||||
## 1. Message envelope
|
||||
|
||||
All incoming and outgoing events use the same envelope:
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "event_name",
|
||||
"payload": {},
|
||||
"timestamp": "2026-03-08T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
`timestamp` is present in outgoing events from the server.
|
||||
|
||||
## 2. Incoming events (client -> server)
|
||||
|
||||
## 2.1 `ping`
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "ping",
|
||||
"payload": {}
|
||||
}
|
||||
```
|
||||
|
||||
Server response: `pong`
|
||||
|
||||
## 2.2 `send_message`
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "send_message",
|
||||
"payload": {
|
||||
"chat_id": 10,
|
||||
"type": "text",
|
||||
"text": "Hello",
|
||||
"temp_id": "tmp-1",
|
||||
"client_message_id": "client-msg-1",
|
||||
"reply_to_message_id": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Supported `type` values:
|
||||
|
||||
- `text`, `image`, `video`, `audio`, `voice`, `file`, `circle_video`
|
||||
|
||||
## 2.3 `typing_start` / `typing_stop`
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "typing_start",
|
||||
"payload": {
|
||||
"chat_id": 10
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2.4 `message_delivered` / `message_read`
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "message_read",
|
||||
"payload": {
|
||||
"chat_id": 10,
|
||||
"message_id": 150
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 3. Outgoing events (server -> client)
|
||||
|
||||
## 3.1 `connect`
|
||||
|
||||
Sent after successful websocket registration:
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "connect",
|
||||
"payload": {
|
||||
"connection_id": "uuid"
|
||||
},
|
||||
"timestamp": "2026-03-08T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## 3.2 `pong`
|
||||
|
||||
Response to `ping`:
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "pong",
|
||||
"payload": {},
|
||||
"timestamp": "2026-03-08T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## 3.3 `receive_message`
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "receive_message",
|
||||
"payload": {
|
||||
"chat_id": 10,
|
||||
"message": {
|
||||
"id": 123,
|
||||
"chat_id": 10,
|
||||
"sender_id": 1,
|
||||
"reply_to_message_id": null,
|
||||
"forwarded_from_message_id": null,
|
||||
"type": "text",
|
||||
"text": "Hello",
|
||||
"created_at": "2026-03-08T12:00:00Z",
|
||||
"updated_at": "2026-03-08T12:00:00Z"
|
||||
},
|
||||
"temp_id": "tmp-1",
|
||||
"client_message_id": "client-msg-1",
|
||||
"sender_id": 1
|
||||
},
|
||||
"timestamp": "2026-03-08T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## 3.4 Typing events
|
||||
|
||||
`typing_start` and `typing_stop`:
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "typing_start",
|
||||
"payload": {
|
||||
"chat_id": 10,
|
||||
"user_id": 2
|
||||
},
|
||||
"timestamp": "2026-03-08T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## 3.5 Delivery/read events
|
||||
|
||||
`message_delivered` and `message_read`:
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "message_read",
|
||||
"payload": {
|
||||
"chat_id": 10,
|
||||
"message_id": 150,
|
||||
"user_id": 2,
|
||||
"last_delivered_message_id": 150,
|
||||
"last_read_message_id": 150
|
||||
},
|
||||
"timestamp": "2026-03-08T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## 3.6 Presence events
|
||||
|
||||
### `user_online`
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "user_online",
|
||||
"payload": {
|
||||
"chat_id": 10,
|
||||
"user_id": 2,
|
||||
"is_online": true
|
||||
},
|
||||
"timestamp": "2026-03-08T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### `user_offline`
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "user_offline",
|
||||
"payload": {
|
||||
"chat_id": 10,
|
||||
"user_id": 2,
|
||||
"is_online": false,
|
||||
"last_seen_at": "2026-03-08T12:00:00Z"
|
||||
},
|
||||
"timestamp": "2026-03-08T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## 3.7 `chat_updated`
|
||||
|
||||
Sent when chat metadata/membership/roles/title changes:
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "chat_updated",
|
||||
"payload": {
|
||||
"chat_id": 10
|
||||
},
|
||||
"timestamp": "2026-03-08T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## 3.8 `error`
|
||||
|
||||
Validation/runtime error during WS processing:
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "error",
|
||||
"payload": {
|
||||
"detail": "Invalid event payload"
|
||||
},
|
||||
"timestamp": "2026-03-08T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## 4. Disconnect behavior
|
||||
|
||||
- On disconnect, server unregisters connection.
|
||||
- When last connection for a user closes, server marks user offline and sends `user_offline` to related chats.
|
||||
|
||||
## 5. Practical client recommendations
|
||||
|
||||
- Keep one active socket per tab/session.
|
||||
- Send periodic `ping` and expect `pong`.
|
||||
- Reconnect with exponential backoff.
|
||||
- On `chat_updated`, refresh chat metadata via REST (`GET /api/v1/chats` or `GET /api/v1/chats/{chat_id}`).
|
||||
- Use REST message history endpoints for pagination; WS is realtime transport, not history source.
|
||||
|
||||
Reference in New Issue
Block a user