SHiNE-server/Dev_Docs/API/12_Direct_Messages_Push_Calls_API.md

5.9 KiB
Raw Blame History

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=3
  • outgoingBlobB64 — блок 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 или outgoingBlobB64
  • 400 / BAD_BLOCK_FORMAT — base64 или бинарный контейнер повреждён
  • 400 / BAD_CONTENT_FORMAT — для контентного сообщения пришёл не SHiNE_DM
  • 400 / 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 hash
  • 400 / bad size
  • 400 / SIZE_MISMATCH
  • 400 / HASH_MISMATCH
  • 400 / UPLOAD_TOO_LARGE
  • 500 / upload_failed

9. CallInviteBroadcast

Требует авторизации. Шлёт приглашение к звонку в активные сессии toLogin.

10. CallSignalToSession

Требует авторизации. Шлёт сигнал звонка в конкретную сессию.

11. Замечания

  • Для нового DM-файла сценарий такой: HEAD /f/<hash> → при 404 POST /upload → затем SendMessagePair.
  • Сервер хранит только последнюю версию контентного сообщения по messageKey.
  • Удаление сообщения реализуется новой ревизией с пустым телом и нулём вложений.