# 群组订阅方法

[群组托管协议](../README.md) · [方法公共约定](conventions.md)

## `group.subscribe`

`group.subscribe` 原子替换当前 WebSocket 连接的群订阅集合。成功订阅后，连接可以接收相应的[群组通知](../notifications/README.md)。

| 项目 | 约定 |
|---|---|
| HTTP | 不支持 |
| 会话要求 | 设备会话 |
| WSS | `group.subscribe` |

### 请求参数

| 字段 | 类型 | 必需 | 语义与约束 |
|---|---|---|---|
| `group_ids` | array&lt;string&gt; | 是 | 这条 WebSocket 连接在调用成功后应订阅的完整群 ID 集合；数组可以为空，表示取消当前连接的全部群订阅；每个群都必须由当前中继托管且当前账户有读取权，ID 不得重复，数量按下文的订阅上限规则检查 |

### 响应对象

无。

### 处理与错误

#### 参数与会话校验

中继必须验证请求参数和设备会话。数组包含重复或非法群 ID，或者不满足下述数量规则时返回 `bad_request`；会话无效时返回 `unauthorized`；会话模式不符合要求时返回 `forbidden`。存在上述错误时，从实际发生的错误中选择一个返回，并省略 `error.data`。

数量检查以本次替换生效前、当前连接仍有效的群订阅集合为基准。请求包含任一尚未订阅的群时，完整新集合的数量不得超过 `relay.info.limits.max_group_subscriptions` 的当前值；没有新增群订阅时，不得仅因数量仍超过当前上限而拒绝。数组顺序不影响集合比较。取消后重新加入的群属于新增订阅。

#### 群归属与访问权限校验

中继还必须检查请求中每个群的归属和访问权限。群不存在、不由当前中继托管，或者调用账户不是当前成员或已被封禁时，该群不能订阅。请求参数及设备会话均有效时，任一群不能订阅就拒绝整个请求，并按下表返回错误：

| 情况 | 错误码 |
|---|---|
| 至少一个群不存在或不由当前中继托管 | `not_found` |
| 所有群均存在且由当前中继托管，但至少一个群不允许当前账户或设备访问 | `forbidden` |

这两类群校验错误必须在 [JSON-RPC 错误对象](../../methods/conventions.md#错误响应)的 `data` 中提供：

| 字段 | 类型 | 必需 | 语义与约束 |
|---|---|---|---|
| `group_ids` | array&lt;string&gt; | 是 | 本次请求中不能订阅的全部群 ID，包括归属与访问权限两类原因；非空、不重复，每项均来自请求的 `group_ids` |

调用失败时，原订阅集合和所有群的设备访问区间均保持不变。

#### 订阅生效与同步

全部群均可订阅时，中继以请求中的集合完整替换这条 WebSocket 连接原有的群订阅，并按[设备访问区间](../concepts/membership-and-access.md#设备访问区间)的规定建立所需区间。取消订阅不结束设备访问区间，也不改变群成员资格、状态、事件或密钥版本。重复提交相同集合成功时，保持该订阅集合和仍有效的访问起点；需要新区间时仍按上述规则建立。

订阅成功不主动返回当前状态或积压通知。建议客户端在成功订阅后对本次新增订阅的群调用 `group.sync`，补齐订阅生效前可能遗漏的事件；同一连接上持续有效且本次继续保留的订阅，不要求仅因集合调整或重复提交而额外同步。本地已完成位置不因断线或重新订阅而重置。

通知、已知历史缺口及其他状态恢复原因触发的事件补同步要求继续适用，持续订阅不免除这些要求。密钥材料按需通过 [`group.key.sync`](keys.md#groupkeysync) 补齐；本地已具备所需版本且通过原验证规则的材料可以复用。
