# WorkTool 后端通信协议文档

本文档详细描述了 WorkTool 机器人（客户端）与后台服务器（服务端）之间的通信协议。

## 1. 连接方式

WorkTool 使用 WebSocket 协议与服务端进行长连接通信。

*   **WebSocket URL**: `ws://<服务器IP>:<端口>/webserver/wework/<链接号>`
    *   `<链接号>` (robotId): 机器人的唯一标识，由用户在 APP 端设置。
*   **通信格式**: JSON
*   **心跳机制**: 客户端每 5 秒发送一次心跳包 `{"type": 11}`，服务端可忽略或回复。

## 2. 数据包结构

所有的通信数据（发送和接收）都包裹在 `WeworkMessageListBean` 结构中。

### 2.1 外层包装 (WeworkMessageListBean)

服务端发送给客户端的 JSON 必须符合以下结构：

```json
{
  "socketType": 2,          // 消息类型：2 表示下发指令列表
  "list": [                 // 指令列表，可包含多个指令
    {
      "type": 203,          // 具体指令类型 (例如 203=发送消息)
      "messageId": "uuid",  // 消息ID (可选，用于回调对应)
      ...                   // 指令参数 (详见下文)
    }
  ],
  "encryptType": 0          // 加密类型：0=不加密, 1=AES加密 (默认0)
}
```

### 2.2 消息确认

当客户端收到服务端消息后，会回复一个确认包（通常服务端不需要处理）：
```json
{
    "socketType": 1,        // SOCKET_TYPE_MESSAGE_CONFIRM
    "messageId": "..."      // 收到的消息ID
}
```

## 3. 常用指令详解

以下列出常用的指令及其 JSON 参数示例。参数放在 `list` 数组的对象中。

### 3.1 发送文本消息 (SEND_MESSAGE)
*   **Type**: `203`
*   **说明**: 在指定房间（群或好友）发送文本。

```json
{
  "type": 203,
  "titleList": ["张三", "技术交流群"],  // 接收者名称列表 (群名或好友名)
  "receivedContent": "你好，这是测试消息", // 消息内容
  "at": "李四"                         // (可选) 需要 @ 的人昵称，仅在群聊有效
}
```

### 3.2 转发消息 (RELAY_MESSAGE)
*   **Type**: `205`
*   **说明**: 将某人的消息转发给其他人。

```json
{
  "type": 205,
  "titleList": ["来源群名"],           // 消息来源房间名
  "receivedName": "张三",             // 消息发送者昵称
  "originalContent": "原消息内容",     // 用于匹配消息内容
  "textType": 1,                      // 消息类型 (1=文本, 2=图片, 详见附录)
  "nameList": ["目标群1", "李四"],     // 转发目标列表
  "extraText": "这是转发的消息"         // (可选) 转发时的附加留言
}
```

### 3.3 推送文件/图片 (PUSH_FILE)
*   **Type**: `218`
*   **说明**: 发送网络文件或图片。

```json
{
  "type": 218,
  "titleList": ["张三"],
  "objectName": "文件名.jpg",         // 保存的文件名
  "fileUrl": "http://example.com/a.jpg", // 文件下载地址
  "fileType": "image",                // 文件类型 (image, video, file)
  "extraText": "请查收图片"            // (可选) 附加留言
}
```

### 3.4 推送链接 (PUSH_LINK)
*   **Type**: `224`
*   **说明**: 发送卡片链接。

```json
{
  "type": 224,
  "titleList": ["张三"],
  "objectName": "百度一下",           // 链接标题
  "receivedContent": "你就知道",       // 链接描述/副标题
  "originalContent": "https://www.baidu.com", // 跳转链接
  "fileUrl": "http://example.com/icon.png"    // 链接图标地址
}
```

### 3.5 获取最近聊天列表 (GET_RECENT_LIST)
*   **Type**: `505`
*   **说明**: 获取消息列表首页的最近聊天记录。

```json
{
  "type": 505
}
```

### 3.6 获取群信息 (GET_GROUP_INFO)
*   **Type**: `501`
*   **说明**: 获取指定群的成员列表等信息。

```json
{
  "type": 501,
  "selectList": ["技术交流群"]        // 要查询的群名列表
}
```

## 4. 执行结果回调

当机器人执行完指令后，会向服务端发送执行结果。

*   **SocketType**: `3` (SOCKET_TYPE_RAW_CONFIRM)
*   **数据结构**:

```json
{
  "socketType": 3,
  "messageId": "原始指令的messageId",
  "list": [
    {
      "errorCode": 0,               // 0 表示成功，非 0 表示失败
      "errorReason": "",            // 失败原因
      "successList": ["张三"],       // 执行成功的对象列表
      "failList": [],               // 执行失败的对象列表
      "rawMsg": "{...}",            // 原始指令 JSON
      "runTime": 1670000000000,     // 开始执行时间戳
      "timeCost": 1.5               // 耗时 (秒)
    }
  ]
}
```

### 常见错误码 (ErrorCode)
*   `0`: 成功
*   `201102`: 发送消息失败
*   `201104`: 目标寻找失败 (未找到群或联系人)
*   `501000`: 其他未知错误

## 附录：消息类型定义 (textType)
*   1: 文本 (TEXT_TYPE_PLAIN)
*   2: 图片 (TEXT_TYPE_IMAGE)
*   3: 语音 (TEXT_TYPE_VOICE)
*   5: 视频 (TEXT_TYPE_VIDEO)
*   8: 链接 (TEXT_TYPE_LINK)
*   9: 文件 (TEXT_TYPE_FILE)
*   15: 引用回复 (TEXT_TYPE_REPLY)

## 附录：自动通过好友请求

当 APP 开启"自动通过好友请求"开关后，有新好友添加成功时会主动上传好友信息到服务端。

### 上传时机
*   自动通过好友请求成功后
*   手动通过好友请求成功后

### 消息类型
*   **Type**: `502` (GET_FRIEND_INFO)

### 数据结构
```json
{
  "type": 502,
  "friend": {
    "name": "张三",                    // 好友昵称
    "newFriend": true,                 // 标记为新好友
    "wechatId": "zhangsan123",         // 微信号
    "phone": "13800138000",            // 手机号
    "corpName": "XX科技有限公司",       // 企业名称
    "department": "技术部",             // 部门
    "position": "工程师",               // 职位
    "email": "zhangsan@example.com",   // 邮箱
    "markName": "张工",                 // 备注名
    "gender": 1,                       // 性别: 1男 2女 0未知
    "leavingMsg": "请求添加好友时的留言"  // 留言/验证消息
  }
}
```

### 服务端接收示例
服务端只需监听 WebSocket 消息，当 `type=502` 且 `friend.newFriend=true` 时，表示有新好友添加成功。

---

## 附录：接收消息列表 (101)

客户端监听到新消息时，会主动上传消息列表到服务端。

### 消息类型
*   **Type**: `101` (TYPE_RECEIVE_MESSAGE_LIST)

### 数据结构（群聊）
```json
{
  "type": 101,
  "roomType": 1,
  "titleList": ["技术交流群"],
  "messageList": [
    {
      "sender": 0,
      "textType": 1,
      "nameList": ["张三"],
      "itemMessageList": [
        {"feature": 2, "text": "你好，这是消息内容"}
      ]
    },
    {
      "sender": 1,
      "textType": 1,
      "itemMessageList": [
        {"feature": 2, "text": "收到"}
      ]
    }
  ]
}
```

### 数据结构（单聊）
```json
{
  "type": 101,
  "roomType": 2,
  "titleList": ["张三"],
  "contact": {
    "name": "张三",
    "wechatId": "zhangsan123",
    "phone": "13800138000",
    "corpName": "XX科技有限公司",
    "department": "技术部",
    "position": "工程师",
    "email": "zhangsan@example.com",
    "markName": "张工"
  },
  "messageList": [
    {
      "sender": 0,
      "textType": 1,
      "itemMessageList": [
        {"feature": 2, "text": "你好"}
      ]
    }
  ]
}
```

### 字段说明

| 字段 | 类型 | 说明 |
|------|------|------|
| type | int | 消息类型：101=接收的消息列表 |
| roomType | int | 房间类型：1=外部群, 2=外部联系人, 3=内部群, 4=内部联系人 |
| titleList | Array | 聊天对象名称（群名或好友名） |
| contact | Object | 联系人信息（仅单聊时有效） |
| messageList | Array | 消息列表 |

### messageList 每条消息

| 字段 | 类型 | 说明 |
|------|------|------|
| sender | int | 发送者：0=其他人, 1=自己, 2=系统消息 |
| textType | int | 消息类型：1=文本, 2=图片, 3=语音, 5=视频, 8=链接, 9=文件 |
| nameList | Array | 发送者名称列表（群聊时有效） |
| itemMessageList | Array | 消息内容列表 |

### contact 联系人信息

| 字段 | 类型 | 说明 |
|------|------|------|
| name | String | 好友昵称 |
| wechatId | String | 微信号 |
| phone | String | 手机号 |
| corpName | String | 企业名称 |
| department | String | 部门 |
| position | String | 职位 |
| email | String | 邮箱 |
| markName | String | 备注名 |
| gender | int | 性别：1=男, 2=女, 0=未知 |
