5.9 KiB
API для разработчиков: DM, файлы, push и сигналы звонков
Документ описывает публичные операции и endpoints, связанные с личными сообщениями, файлами для DM, WebPush и сигналами звонков.
Подробная логика DM и бинарного формата: Dev_Docs/Personal_Messages/README.md.
1. UpsertPushToken
Требует авторизации.
Запрос
{
"op": "UpsertPushToken",
"requestId": "push-upsert-001",
"payload": {
"sessionId": "SESSION_ID",
"endpoint": "https://push.example/...",
"p256dhKey": "BASE64",
"authKey": "BASE64",
"platform": "web",
"userAgent": "Mozilla/5.0 ..."
}
}
Успешный ответ
{
"op": "UpsertPushToken",
"requestId": "push-upsert-001",
"status": 200,
"ok": true,
"payload": {
"tokenId": "token-1",
"updatedAtMs": 1774700000123
}
}
2. SendTestWebPush
Требует авторизации.
Запрос
{
"op": "SendTestWebPush",
"requestId": "push-test-001",
"payload": {
"login": "alice",
"sessionId": "SESSION_ID",
"title": "Test",
"text": "Push body"
}
}
3. SendMessagePair и ReceiveOutcomingMessage
ReceiveOutcomingMessage — алиас SendMessagePair.
Назначение
Передаёт пару signed DM-блоков:
incomingBlobB64— блокtype=1илиtype=3outgoingBlobB64— блокtype=2илиtype=4
Для контентных сообщений type=1/2 внутри base64 лежит новый бинарный формат SHiNE_DM.
Запрос
{
"op": "SendMessagePair",
"requestId": "dm-pair-001",
"payload": {
"incomingBlobB64": "BASE64_INCOMING_SIGNED_BLOCK",
"outgoingBlobB64": "BASE64_OUTGOING_SIGNED_BLOCK"
}
}
Успешный ответ
{
"op": "SendMessagePair",
"requestId": "dm-pair-001",
"status": 200,
"ok": true,
"payload": {
"baseKey": "from|to|time|nonce",
"incomingKey": "from|to|time|nonce|1",
"outgoingKey": "from|to|time|nonce|2",
"deliveredWsSessions": 1,
"deliveredWebPushSessions": 0
}
}
Ошибки
400 / BAD_FIELDS— пустойincomingBlobB64илиoutgoingBlobB64400 / BAD_BLOCK_FORMAT— base64 или бинарный контейнер повреждён400 / BAD_CONTENT_FORMAT— для контентного сообщения пришёл неSHiNE_DM400 / TOO_MANY_ATTACHMENTS— больше 12 вложений400 / ATTACHMENT_NOT_FOUND— сообщение ссылается на blob, которого нет на сервере404 / USER_NOT_FOUND— один из логинов не найден460 / BAD_SIGNATURE— подпись блока не прошла проверку
4. AckSessionDelivery
Требует авторизации. Подтверждает доставку в текущую сессию.
Запрос
{
"op": "AckSessionDelivery",
"requestId": "ack-001",
"payload": {
"messageKey": "from|to|time|nonce|1"
}
}
5. Событие SignedMessageArrived
Сервер присылает его по WebSocket в активные сессии адресата.
Payload события
{
"messageKey": "from|to|time|nonce|1",
"baseKey": "from|to|time|nonce",
"fromLogin": "alice",
"toLogin": "bob",
"targetLogin": "bob",
"messageType": 1,
"timeMs": 1774700000123,
"nonce": 123456789,
"blobB64": "BASE64_SIGNED_BLOCK",
"backlog": false
}
Если это новая ревизия того же письма, messageKey остаётся тем же, а revisionTimeMs меняется внутри бинарного блока.
6. HTTP HEAD /f/<hashB64url>
Проверка, есть ли ciphertext-файл на сервере.
Ответы
200— файл существует404— файла нет
7. HTTP GET /f/<hashB64url>
Отдаёт ciphertext-файл.
Особенности
Content-Type: application/octet-stream- файл сейчас доступен публично
- имя файла на диске и в URL —
base64url(SHA-256(ciphertext))
8. HTTP POST /upload?hash=<hashB64url>&size=<bytes>
Загружает ciphertext-файл для будущего DM.
Тело запроса
Raw bytes ciphertext-файла.
Поведение сервера
- пересчитывает
SHA-256 - сверяет размер
- сохраняет blob в папку
f/, если его ещё не было - если blob уже есть, не перезаписывает его
- создаёт или обновляет запись в
dm_files
Успешный ответ
{
"ok": true,
"hash": "base64url_sha256",
"size": 245120,
"alreadyExists": false
}
Ошибки
400 / bad hash400 / bad size400 / SIZE_MISMATCH400 / HASH_MISMATCH400 / UPLOAD_TOO_LARGE500 / upload_failed
9. CallInviteBroadcast
Требует авторизации. Шлёт приглашение к звонку в активные сессии toLogin.
10. CallSignalToSession
Требует авторизации. Шлёт сигнал звонка в конкретную сессию.
11. Замечания
- Для нового DM-файла сценарий такой:
HEAD /f/<hash>→ при404POST /upload→ затемSendMessagePair. - Сервер хранит только последнюю версию контентного сообщения по
messageKey. - Удаление сообщения реализуется новой ревизией с пустым телом и нулём вложений.