# Zulip 集成系统 API 文档

## WebSocket 连接

### 连接地址

```
wss://localhost:3000/game
```

### 连接参数

连接时无需额外参数，认证通过 `login` 消息完成。

## 消息类型

### 1. 登录 (login)

**请求:**
```json
{
  "type": "login",
  "token": "user_game_token"
}
```

**成功响应:**
```json
{
  "t": "login_success",
  "sessionId": "session_abc123",
  "currentMap": "novice_village",
  "username": "player_name"
}
```

**失败响应:**
```json
{
  "t": "error",
  "code": "AUTH_FAILED",
  "message": "Token 验证失败"
}
```

### 2. 发送聊天消息 (chat)

**请求:**
```json
{
  "t": "chat",
  "content": "Hello, world!",
  "scope": "local"
}
```

**参数说明:**
| 参数 | 类型 | 必填 | 说明 |
|-----|------|-----|------|
| t | string | 是 | 固定值 "chat" |
| content | string | 是 | 消息内容，最大 1000 字符 |
| scope | string | 是 | 消息范围: "local" 或具体 topic 名称 |

**成功响应:**
```json
{
  "t": "chat_sent",
  "messageId": "msg_123",
  "timestamp": 1703500800000
}
```

**失败响应:**
```json
{
  "t": "error",
  "code": "RATE_LIMIT",
  "message": "消息发送过于频繁，请稍后再试"
}
```

### 3. 接收聊天消息 (chat_render)

**服务器推送:**
```json
{
  "t": "chat_render",
  "from": "other_player",
  "txt": "Hi there!",
  "bubble": true,
  "timestamp": 1703500800000
}
```

**参数说明:**
| 参数 | 类型 | 说明 |
|-----|------|------|
| t | string | 固定值 "chat_render" |
| from | string | 发送者名称 |
| txt | string | 消息内容 |
| bubble | boolean | 是否显示气泡 |
| timestamp | number | 消息时间戳 |

### 4. 位置更新 (position_update)

**请求:**
```json
{
  "t": "position",
  "x": 150,
  "y": 200,
  "mapId": "novice_village"
}
```

**参数说明:**
| 参数 | 类型 | 必填 | 说明 |
|-----|------|-----|------|
| t | string | 是 | 固定值 "position" |
| x | number | 是 | X 坐标 |
| y | number | 是 | Y 坐标 |
| mapId | string | 是 | 地图 ID |

**响应:**
```json
{
  "t": "position_updated",
  "stream": "Novice Village",
  "topic": "General"
}
```

### 5. 登出 (logout)

**请求:**
```json
{
  "type": "logout"
}
```

**响应:**
```json
{
  "t": "logout_success"
}
```

## 错误码

| 错误码 | HTTP 等效 | 说明 | 处理建议 |
|-------|----------|------|---------|
| `AUTH_FAILED` | 401 | 认证失败，Token 无效或过期 | 重新获取 Token 并登录 |
| `RATE_LIMIT` | 429 | 消息发送频率超限 | 等待 60 秒后重试 |
| `CONTENT_FILTERED` | 400 | 消息内容被过滤 | 修改消息内容后重试 |
| `CONTENT_TOO_LONG` | 400 | 消息内容超长 | 缩短消息长度 |
| `PERMISSION_DENIED` | 403 | 权限不足 | 检查用户权配置 |
| `SESSION_EXPIRED` | 401 | 会话已过期 | 重新登录 |
| `SESSION_NOT_FOUND` | 404 | 会话不存在 | 重新登录 |
| `ZULIP_ERROR` | 502 | Zulip 服务错误 | 系统自动重试，无需处理 |
| `INTERNAL_ERROR` | 500 | 内部服务器错误 | 联系管理员 |

## 频率限制

### 消息发送限制

- 默认限制: 10 条/分钟
- 超限后返回 `RATE_LIMIT` 错误
- 限制窗口: 滑动窗口，60 秒

### 连接限制

- 单用户最大连接数: 3
- 超限后新连接被拒绝

## 消息过滤规则

### 内容过滤

1. **敏感词过滤**: 包含敏感词的消息将被拒绝
2. **长度限制**: 消息最大 1000 字符
3. **重复检测**: 连续发送相同内容将被拒绝

### 权限验证

1. **位置验证**: 只能向当前所在地图对应的 Stream 发送消息
2. **Stream 权限**: 只能访问配置中允许的 Stream

## 示例代码

### JavaScript/TypeScript

```typescript
// 连接 WebSocket
const socket = new WebSocket('ws://localhost:3000/game');

// 连接成功
socket.onopen = () => {
  // 发送登录消息
  socket.send(JSON.stringify({
    type: 'login',
    token: 'your_game_token'
  }));
};

// 接收消息
socket.onmessage = (event) => {
  const data = JSON.parse(event.data);
  
  switch (data.t) {
    case 'login_success':
      console.log('登录成功:', data.sessionId);
      break;
    case 'chat_render':
      console.log(`${data.from}: ${data.txt}`);
      break;
    case 'error':
      console.error(`错误 [${data.code}]: ${data.message}`);
      break;
  }
};

// 发送聊天消息
function sendChat(content: string) {
  socket.send(JSON.stringify({
    t: 'chat',
    content: content,
    scope: 'local'
  }));
}

// 更新位置
function updatePosition(x: number, y: number, mapId: string) {
  socket.send(JSON.stringify({
    t: 'position',
    x: x,
    y: y,
    mapId: mapId
  }));
}
```

## 健康检查接口

### GET /health

检查系统健康状态。

**响应:**
```json
{
  "status": "healthy",
  "components": {
    "websocket": "healthy",
    "zulip": "healthy",
    "redis": "healthy"
  },
  "metrics": {
    "activeConnections": 42,
    "activeSessions": 40,
    "messagesSentLastMinute": 156
  }
}
```

### GET /metrics

获取系统指标（Prometheus 格式）。

**响应:**
```
# HELP zulip_connections_active Active WebSocket connections
# TYPE zulip_connections_active gauge
zulip_connections_active 42

# HELP zulip_messages_sent_total Total messages sent
# TYPE zulip_messages_sent_total counter
zulip_messages_sent_total 15678

# HELP zulip_message_latency_seconds Message processing latency
# TYPE zulip_message_latency_seconds histogram
zulip_message_latency_seconds_bucket{le="0.1"} 14500
zulip_message_latency_seconds_bucket{le="0.5"} 15600
zulip_message_latency_seconds_bucket{le="1"} 15678
```
