# API 文档


## 通用约定

### 统一响应格式

所有 API 均返回以下 JSON 结构：

```jsonc
{
  "code": 200,           // 业务状态码
  "message": "success",  // 状态描述
  "data": { /* ... */ },  // 响应数据（可选）
  "pagination": {        // 分页元数据（仅分页接口）
    "page": 1,
    "size": 6,
    "total": 100,
    "totalPages": 17
  }
}
```

### 状态码说明

| code | 含义 | 说明 |
|------|------|------|
| 200  | 成功 | 请求处理成功 |
| 400  | 参数错误 | 缺少必要参数或格式错误 |
| 404  | 未找到 | 请求的资源不存在 |
| 500  | 服务器错误 | 服务端内部异常 |

### 分页参数

分页接口通过 Query String 传参：

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `page` | number | 1 | 页码（从 1 开始） |
| `page_size` | number | 6 | 每页数量（最大 100） |

---

## API 端点

### 1. 健康检查

```
GET /api/health
```

服务健康状态探针，用于负载均衡和监控。

**响应示例：**

```json
{
  "status": "ok",
  "timestamp": "2025-01-01T00:00:00.000Z"
}
```

---

### 2. 分类列表

```
GET /api/v2/categories
```

获取所有分类信息，按群聊数量降序排列。固定每页 50 条。

**Query 参数：** `page`（可选）

**响应示例：**

```json
{
  "code": 200,
  "message": "success",
  "data": {
    "categories": [
      {
        "id": 1,
        "name": "游戏",
        "slug": "youxi",
        "description": "游戏相关群聊",
        "group_count": 42,
        "updated_at": "2025-01-01T12:00:00.000Z"
      }
    ]
  },
  "pagination": {
    "page": 1,
    "size": 50,
    "total": 10,
    "totalPages": 1
  }
}
```

---

### 3. 群聊列表

```
GET /api/v2/groups
```

获取群聊列表，按创建时间倒序排列，支持分页。每个群聊包含其关联分类信息。

**Query 参数：** `page`、`page_size`

**响应示例：**

```json
{
  "code": 200,
  "message": "success",
  "data": {
    "groups": [
      {
        "group_number": "123456789",
        "group_name": "示例群",
        "group_desc": "这是一个示例群聊",
        "group_icon_url": "https://example.com/icon.png",
        "group_member_cnt": 500,
        "owner_name": "群主",
        "owner_icon_url": "https://example.com/owner.png",
        "group_available": true,
        "categories": [
          {
            "id": 1,
            "name": "游戏",
            "slug": "youxi",
            "description": "游戏相关群聊",
            "updated_at": "2025-01-01T12:00:00.000Z"
          }
        ],
        "created_at": "2025-01-01T00:00:00.000Z",
        "updated_at": "2025-01-01T12:00:00.000Z",
        "group_schema": "snssdk1128://im/group_invite_dialog?..."
      }
    ],
    "category": null
  },
  "pagination": {
    "page": 1,
    "size": 6,
    "total": 100,
    "totalPages": 17
  }
}
```

---

### 4. 按分类获取群聊列表

```
GET /api/v2/groups/:slug
```

获取指定分类下的群聊列表，逻辑与群聊列表相同，但会筛选指定分类。

**路径参数：**

| 参数 | 类型 | 说明 |
|------|------|------|
| `slug` | string | 分类 slug（如 `youxi`） |

**Query 参数：** `page`、`page_size`

**响应示例：** 与群聊列表相同，`data.category` 字段会包含当前分类信息：

```json
{
  "code": 200,
  "data": {
    "groups": [ /* ... */ ],
    "category": {
      "id": 1,
      "name": "游戏",
      "slug": "youxi",
      "description": "游戏相关群聊",
      "updated_at": "2025-01-01T12:00:00.000Z",
      "group_count": 42
    }
  },
  "pagination": { /* ... */ }
}
```

**错误响应：** 分类不存在时返回 `404`。

---

### 5. 获取群聊详情

```
GET /api/v2/group_detail/:groupNumber
```

根据群聊编号获取群聊详细信息，包含关联分类。

**路径参数：**

| 参数 | 类型 | 说明 |
|------|------|------|
| `groupNumber` | string | 群聊编号 |

**响应示例：**

```json
{
  "code": 200,
  "message": "success",
  "data": {
    "group_number": "123456789",
    "group_name": "示例群",
    "group_desc": "这是一个示例群聊",
    "group_icon_url": "https://example.com/icon.png",
    "group_member_cnt": 500,
    "owner_name": "群主",
    "owner_icon_url": "https://example.com/owner.png",
    "group_available": true,
    "categories": [
      {
        "name": "游戏",
        "slug": "youxi",
        "description": "游戏相关群聊",
        "group_count": 42,
        "updated_at": "2025-01-01T12:00:00.000Z"
      }
    ],
    "created_at": "2025-01-01T00:00:00.000Z",
    "updated_at": "2025-01-01T12:00:00.000Z",
    "group_schema": "snssdk1128://im/group_invite_dialog?..."
  }
}
```

**错误响应：**

| code | 说明 |
|------|------|
| 400  | 缺少 groupNumber 参数 |
| 404  | 群聊不存在 |

---

### 6. 生成群信息图片

```
GET /api/v2/group_card/:groupNumber
```

以 PNG 图片形式返回群信息卡片，适用于社交媒体分享、即时通讯等不支持富 HTML 预览的场景。

数据来源：优先从 MySQL 获取，未命中时回退到抖音外部 API 实时获取。

**路径参数：**

| 参数 | 类型 | 说明 |
|------|------|------|
| `groupNumber` | string | 群号，1-20 位纯数字 |

**请求示例：**

```bash
curl -o group.png http://localhost:3000/api/v2/group_card/709536885516
```

**成功响应（正常/已失效卡片）** — HTTP 200:

```
Content-Type: image/png
Content-Disposition: inline; filename="group-709536885516.png"
Cache-Control: 见下表
```

Body: PNG 二进制数据

**错误/边界响应（群不存在/暂时不可用）** — HTTP 200:

同样返回 `image/png` 格式的提示图片（含原因说明），而非 JSON 错误。这确保 `<img>` 标签和社交媒体爬虫正常解析。

**缓存策略：**

| 数据来源 | Cache-Control |
|----------|---------------|
| MySQL 数据 | `public, max-age=300, s-maxage=600` |
| 抖音 API 实时数据 | `public, max-age=120, s-maxage=300` |
| 群不存在 | `public, max-age=60` |
| 服务暂时不可用 | `no-store` |

**JSON 错误响应：**

| code | 说明 |
|------|------|
| 400  | groupNumber 参数格式错误（返回 JSON） |
| 500  | 图片生成过程中发生内部错误（返回 JSON） |
