# 06. Channels Read API

## Человеко-читаемое объяснение
Эти функции — это **чтение данных каналов** для UI:

1. `ListSubscriptionsFeed` — отдает данные для экрана списка каналов:
   - ваши каналы (личный + созданные вами),
   - каналы пользователей, на кого вы подписаны,
   - отдельные каналы, на которые вы подписаны напрямую.

2. `GetChannelMessages` — отдает полную ленту одного канала (пока без курсоров, загружается сразу целиком),
   включая версии сообщений, лайки и ответы.

3. `GetMessageThread` — отдает дерево обсуждения вокруг конкретного сообщения:
   предки, фокус-сообщение, потомки.

4. `GetChannelsCounters` — отдает счетчики разделов каналов для пользователя.

5. `ListGroupChats200` — отдает список групповых чатов типа `200`.

6. `GetGroupDialog` — отдает сообщения конкретного группового чата типа `200`.

> На первом этапе мы **не используем курсоры** (`nextCursor`) и загружаем полные списки.

---

## 1) ListSubscriptionsFeed

### Request
```json
{
  "op": "ListSubscriptionsFeed",
  "requestId": "req-1",
  "payload": {
    "login": "Alice",
    "limit": 200
  }
}
```

### Response (success)
```json
{
  "op": "ListSubscriptionsFeed",
  "requestId": "req-1",
  "status": 200,
  "ok": true,
  "payload": {
    "login": "Alice",
    "ownedChannels": [
      {
        "channel": {
          "ownerLogin": "Alice",
          "ownerBlockchainName": "alice-001",
          "channelName": "0",
          "personal": true,
          "channelRoot": { "blockNumber": 0, "blockHash": "..." }
        },
        "messagesCount": 120,
        "lastMessage": {
          "messageRef": { "blockNumber": 921, "blockHash": "..." },
          "text": "последняя версия текста",
          "createdAtMs": 1760000000000,
          "authorLogin": "Alice",
          "authorBlockchainName": "alice-001"
        }
      }
    ],
    "followedUsersChannels": [
      {
        "channel": {
          "ownerLogin": "Bob",
          "ownerBlockchainName": "bob-001",
          "channelName": "0",
          "personal": true,
          "channelRoot": { "blockNumber": 0, "blockHash": "..." }
        },
        "messagesCount": 540,
        "lastMessage": {
          "messageRef": { "blockNumber": 922, "blockHash": "..." },
          "text": "последняя версия текста",
          "createdAtMs": 1760000100000,
          "authorLogin": "Bob",
          "authorBlockchainName": "bob-001"
        }
      }
    ],
    "followedChannels": [
      {
        "channel": {
          "ownerLogin": "Carl",
          "ownerBlockchainName": "carl-001",
          "channelName": "market",
          "personal": false,
          "channelRoot": { "blockNumber": 456, "blockHash": "..." }
        },
        "messagesCount": 90,
        "lastMessage": {
          "messageRef": { "blockNumber": 1002, "blockHash": "..." },
          "text": "актуальный текст",
          "createdAtMs": 1760001000000,
          "authorLogin": "Carl",
          "authorBlockchainName": "carl-001"
        }
      }
    ]
  }
}
```

---

## 2) GetChannelMessages

### Request
```json
{
  "op": "GetChannelMessages",
  "requestId": "req-2",
  "payload": {
    "channel": {
      "ownerBlockchainName": "bob-001",
      "channelRootBlockNumber": 123,
      "channelRootBlockHash": "..."
    },
    "limit": 200,
    "sort": "asc"
  }
}
```

### Response (success)
```json
{
  "op": "GetChannelMessages",
  "requestId": "req-2",
  "status": 200,
  "ok": true,
  "payload": {
    "channel": {
      "ownerLogin": "Bob",
      "ownerBlockchainName": "bob-001",
      "channelName": "news",
      "channelRoot": { "blockNumber": 123, "blockHash": "..." }
    },
    "messages": [
      {
        "messageRef": { "blockNumber": 140, "blockHash": "..." },
        "authorLogin": "Bob",
        "authorBlockchainName": "bob-001",
        "createdAtMs": 1760000000000,
        "text": "текущая версия",
        "likesCount": 12,
        "repliesCount": 3,
        "versionsTotal": 4,
        "versions": [
          { "versionIndex": 1, "blockNumber": 140, "blockHash": "...", "text": "v1", "createdAtMs": 1760000000000 },
          { "versionIndex": 2, "blockNumber": 155, "blockHash": "...", "text": "v2", "createdAtMs": 1760001000000 },
          { "versionIndex": 3, "blockNumber": 170, "blockHash": "...", "text": "v3", "createdAtMs": 1760002000000 },
          { "versionIndex": 4, "blockNumber": 199, "blockHash": "...", "text": "v4", "createdAtMs": 1760003000000 }
        ]
      }
    ]
  }
}
```

---

## 3) GetMessageThread

### Request
```json
{
  "op": "GetMessageThread",
  "requestId": "req-3",
  "payload": {
    "message": {
      "blockchainName": "bob-001",
      "blockNumber": 333,
      "blockHash": "..."
    },
    "depthUp": 20,
    "depthDown": 2,
    "limitChildrenPerNode": 50
  }
}
```

### Response (success)
```json
{
  "op": "GetMessageThread",
  "requestId": "req-3",
  "status": 200,
  "ok": true,
  "payload": {
    "ancestors": [MessageNode],
    "focus": MessageNode,
    "descendants": [MessageNodeTree]
  }
}
```

### MessageNode (дополнение)
- `MessageNode` расширяет формат сообщения из `GetChannelMessages` и дополнительно содержит:
  - `channelInfo` — мета-информация о канале (если применимо);
  - `rawBlockB64` — сырой `block_bytes` текущего блока в Base64.
- Поле `rawBlockB64` присутствует у узлов во всех частях ответа `GetMessageThread`: `focus`, `ancestors[]`, `descendants[]`.
- В `GetChannelMessages` поле `rawBlockB64` **не добавляется** (лента канала без сырого блока, чтобы не раздувать ответ).

---

## 4) GetChannelsCounters

### Request
```json
{
  "op": "GetChannelsCounters",
  "requestId": "req-4",
  "payload": {
    "login": "Alice"
  }
}
```

### Response (success)
```json
{
  "op": "GetChannelsCounters",
  "requestId": "req-4",
  "status": 200,
  "ok": true,
  "payload": {
    "login": "Alice",
    "feedCount": 12,
    "dialogs100Count": 3,
    "groupChats200Count": 4,
    "myChannelsCount": 2
  }
}
```

---

## 5) ListGroupChats200

### Request
```json
{
  "op": "ListGroupChats200",
  "requestId": "req-5",
  "payload": {
    "login": "Alice"
  }
}
```

### Response (success)
```json
{
  "op": "ListGroupChats200",
  "requestId": "req-5",
  "status": 200,
  "ok": true,
  "payload": {
    "login": "Alice",
    "chats": [
      {
        "ownerLogin": "Alice",
        "ownerBlockchainName": "alice-001",
        "channelRootBlockNumber": 123,
        "channelRootBlockHash": "...",
        "channelName": "team",
        "chatTitle": "Team chat",
        "membersCount": 3,
        "updatedAtMs": 1760000000000
      }
    ]
  }
}
```

---

## 6) GetGroupDialog

### Request
```json
{
  "op": "GetGroupDialog",
  "requestId": "req-6",
  "payload": {
    "login": "Alice",
    "group": {
      "ownerBlockchainName": "alice-001",
      "channelRootBlockNumber": 123
    }
  }
}
```

### Response (success)
```json
{
  "op": "GetGroupDialog",
  "requestId": "req-6",
  "status": 200,
  "ok": true,
  "payload": {
    "group": {
      "ownerLogin": "Alice",
      "ownerBlockchainName": "alice-001",
      "channelRootBlockNumber": 123,
      "channelName": "team",
      "chatTitle": "Team chat"
    },
    "messages": [
      {
        "authorLogin": "Bob",
        "authorBlockchainName": "bob-001",
        "blockNumber": 140,
        "blockHash": "...",
        "createdAtMs": 1760000000000,
        "text": "Привет"
      }
    ]
  }
}
```

---

## Reason codes
- `bad_fields`
- `user_not_found`
- `channel_not_found`
- `message_not_found`
- `limit_too_large`
- `channel_name_already_exists`
- `internal_error`
