Добавить состояние чтения каналов

This commit is contained in:
AidarKC
2026-09-09 18:59:54 +03:00
parent 2d059e9ff5
commit 8e86872aa7
29 changed files with 2538 additions and 231 deletions
+76 -7
View File
@@ -21,9 +21,11 @@
6. `GetChannelsCounters` — отдает счетчики разделов каналов для пользователя.
7. `ListGroupChats200` — отдает список групповых чатов типа `200`.
7. `SetChannelReadState` — сохраняет подписанный watermark чтения канала и возвращает новый unread-счетчик.
8. `GetGroupDialog` — отдает сообщения конкретного группового чата типа `200`.
8. `ListGroupChats200` — отдает список групповых чатов типа `200`.
9. `GetGroupDialog` — отдает сообщения конкретного группового чата типа `200`.
> На первом этапе мы **не используем курсоры** (`nextCursor`) и загружаем полные списки.
>
@@ -110,6 +112,8 @@
"channelRoot": { "blockNumber": 456, "blockHash": "..." }
},
"messagesCount": 90,
"unreadCount": 0,
"readStateInitialized": false,
"lastMessage": {
"messageRef": { "blockNumber": 1002, "blockHash": "..." },
"text": "актуальный текст",
@@ -274,7 +278,7 @@
Возвращает пользователей, которые поставили лайк конкретному сообщению канала.
- `message.blockchainName`, `message.blockNumber`, `message.blockHash` должны указывать на исходное сообщение.
- `limit` ограничивается сервером сверху значением `1000`.
- `limit` в текущей реализации не требуется: сервер возвращает полный найденный список лайков.
- Пользователи группируются по состоянию профиля:
- `shining``account_role=primary` и `shine_status=shining`;
- `official``account_role=primary`, но без `shine_status=shining`;
@@ -290,8 +294,7 @@
"blockchainName": "bob-001",
"blockNumber": 140,
"blockHash": "..."
},
"limit": 1000
}
}
}
```
@@ -322,6 +325,8 @@
- `bad_hash``message.blockHash` не является корректным hex-хэшем блока.
- `internal_error` — внутренняя ошибка чтения.
`truncated` сейчас всегда `false`; поле оставлено в ответе для совместимости с UI и возможной будущей пагинацией.
---
## 5) GetPersonalDiary
@@ -379,7 +384,69 @@
---
## 7) ListGroupChats200
## 7) SetChannelReadState
Сохраняет подписанную позицию чтения для одного канала, на который пользователь подписан.
- Требует авторизованное WebSocket-соединение.
- `login` должен совпадать с текущим авторизованным пользователем.
- Подпись строится client key пользователя по строке:
```text
SHiNe/ChannelReadState:<login>|<owner_bch_name>|<channel_name>|<time_ms>|<read_count>
```
### Request
```json
{
"op": "SetChannelReadState",
"requestId": "req-7",
"payload": {
"login": "Alice",
"owner_bch_name": "bob-001",
"channel_name": "news",
"read_count": 90,
"time_ms": 1760000000000,
"client_key": "<base64-client-public-key>",
"signature": "<base64-ed25519-signature>"
}
}
```
### Response (success)
```json
{
"op": "SetChannelReadState",
"requestId": "req-7",
"status": 200,
"ok": true,
"payload": {
"login": "Alice",
"owner_bch_name": "bob-001",
"channel_name": "news",
"read_count": 90,
"unread_count": 0,
"time_ms": 1760000000000,
"applied": true
}
}
```
### Ошибки
- `NOT_AUTHENTICATED` — нет авторизованной сессии.
- `BAD_FIELDS` — не переданы обязательные поля.
- `LOGIN_MISMATCH``login` не совпадает с текущей сессией.
- `BAD_TIME` — время подписи слишком далеко в будущем.
- `BAD_BASE64``client_key` или `signature` не являются корректным Base64.
- `DEVICE_KEY_MISMATCH``client_key` не совпадает с текущим client key пользователя.
- `INVALID_SIGNATURE` — подпись watermark не прошла проверку.
- `CHANNEL_NOT_FOLLOWED` — пользователь не подписан на канал.
- `CHANNEL_NOT_FOUND` — канал не найден.
- `INTERNAL_ERROR` — внутренняя ошибка записи.
---
## 8) ListGroupChats200
### Request
```json
@@ -419,7 +486,7 @@
---
## 8) GetGroupDialog
## 9) GetGroupDialog
### Request
```json
@@ -474,6 +541,8 @@
- `message_not_found`
- `limit_too_large`
- `channel_name_already_exists`
- `CHANNEL_NOT_FOLLOWED`
- `CHANNEL_NOT_FOUND`
- `internal_error`
---
+30 -4
View File
@@ -9,6 +9,7 @@
- `GetChannelMessages` — сообщения конкретного канала.
- `GetMessageThread` — дерево обсуждения для сообщения.
- `GetMessageLikes` — списки пользователей, поставивших лайк сообщению.
- `SetChannelReadState` — подписанный watermark чтения канала.
2. **UI вкладки Каналы**:
- при открытии пытается загрузить реальный feed с сервера;
@@ -35,13 +36,15 @@
2. Для канала `ownedChannels[0]` вызвать `GetChannelMessages`.
3. Для первого `messages[0]` вызвать `GetMessageThread`.
4. Для первого `messages[0]` вызвать `GetMessageLikes`.
5. Для подписанного канала вызвать `SetChannelReadState` с текущим `messagesCount`.
### Ошибки
1. `ListSubscriptionsFeed` с пустым login -> `bad_fields`.
2. `GetChannelMessages` с битым channel payload -> `bad_fields`.
3. `GetMessageThread` с несуществующим block -> `message_not_found`.
4. `GetMessageLikes` с битым `message.blockHash` -> `bad_hash`.
5. `AddBlock(CreateChannel)` с уже существующим именем -> `channel_name_already_exists`.
5. `SetChannelReadState` без активной подписки -> `CHANNEL_NOT_FOLLOWED`.
6. `AddBlock(CreateChannel)` с уже существующим именем -> `channel_name_already_exists`.
---
@@ -104,8 +107,24 @@
"blockchainName": "TestUser1-001",
"blockNumber": 123,
"blockHash": "<hash-from-GetChannelMessages>"
},
"limit": 1000
}
}
}
```
## 3.5 SetChannelReadState
```json
{
"op": "SetChannelReadState",
"requestId": "debug-read-state-1",
"payload": {
"login": "TestUser1",
"owner_bch_name": "TestUser2-001",
"channel_name": "news",
"read_count": 25,
"time_ms": 1760000000000,
"client_key": "<base64-client-public-key>",
"signature": "<base64-ed25519-signature>"
}
}
```
@@ -120,6 +139,8 @@
- у каждой записи есть:
- `channel.channelRoot.blockNumber`,
- `messagesCount`,
- `unreadCount`,
- `readStateInitialized`,
- `lastMessage` (может быть null, если сообщений нет).
### GetChannelMessages
@@ -137,7 +158,12 @@
### GetMessageLikes
- `payload.shining[]`, `payload.official[]`, `payload.others[]` — группы пользователей.
- у каждого пользователя есть `login`, `firstName`, `lastName`, `avatarAr`.
- `payload.truncated=true` означает, что сервер обрезал список по `limit`.
- `payload.truncated` сейчас всегда `false`; поле оставлено для совместимости и будущей пагинации.
### SetChannelReadState
- `payload.read_count` — сохраненная позиция чтения.
- `payload.unread_count` — пересчитанный unread для канала.
- `payload.applied=false` означает, что на сервере уже была более новая signed-позиция.
### Важно по совместимости
- `rawBlockB64` добавлен только в `GetMessageThread`.
+1
View File
@@ -49,6 +49,7 @@
| `GetMessageLikes` | `06_Channels_Read_API.md` | списки пользователей, поставивших лайк сообщению |
| `GetPersonalDiary` | `06_Channels_Read_API.md` | виртуальный канал `Личный дневник` из STATUS_ACTION |
| `GetChannelsCounters` | `06_Channels_Read_API.md` | счетчики разделов каналов |
| `SetChannelReadState` | `06_Channels_Read_API.md` | подписанный watermark чтения канала |
| `ListGroupChats200` | `06_Channels_Read_API.md` | список групповых чатов типа `200` |
| `GetGroupDialog` | `06_Channels_Read_API.md` | сообщения группового чата типа `200` |
| `UpsertUserParam` | `10_User_Params_API.md` | запись параметра пользователя |