Files
angjustinl 6ad8d80449 feat(zulip): Add Zulip account management and integrate with auth system
- Add ZulipAccountsEntity, repository, and module for persistent Zulip account storage
- Create ZulipAccountService in core layer for managing Zulip account lifecycle
- Integrate Zulip account creation into login flow via LoginService
- Add comprehensive test suite for Zulip account creation during user registration
- Create quick test script for validating registered user Zulip integration
- Update UsersEntity to support Zulip account associations
- Update auth module to include Zulip and ZulipAccounts dependencies
- Fix WebSocket connection protocol from ws:// to wss:// in API documentation
- Enhance LoginCoreService to coordinate Zulip account provisioning during authentication
2026-01-05 17:41:54 +08:00

286 lines
5.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
```