forked from datawhale/whale-town-end
* **新增 Zulip 模块**:包含完整的集成服务,涵盖客户端池(client pool)、会话管理及事件处理。 * **新增 WebSocket 网关**:用于处理 Zulip 的实时事件监听与双向通信。 * **新增安全服务**:支持 API 密钥加密存储及凭据的安全管理。 * **新增配置管理服务**:支持配置热加载(hot-reload),实现动态配置更新。 * **新增错误处理与监控服务**:提升系统的可靠性与可观测性。 * **新增消息过滤服务**:用于内容校验及速率限制(流控)。 * **新增流初始化与会话清理服务**:优化资源管理与回收。 * **完善测试覆盖**:包含单元测试及端到端(e2e)集成测试。 * **完善详细文档**:包括 API 参考手册、配置指南及集成概述。 * **新增地图配置系统**:实现游戏地点与 Zulip Stream(频道)及 Topic(话题)的逻辑映射。 * **新增环境变量配置**:涵盖 Zulip 服务器地址、身份验证及监控相关设置。 * **更新 App 模块**:注册并启用新的 Zulip 集成模块。 * **更新 Redis 接口**:以支持增强型的会话管理功能。 * **实现 WebSocket 协议支持**:确保与 Zulip 之间的实时双向通信。
127 lines
4.0 KiB
JavaScript
127 lines
4.0 KiB
JavaScript
const io = require('socket.io-client');
|
||
|
||
// 使用用户 API Key 测试 Zulip 集成
|
||
async function testWithUserApiKey() {
|
||
console.log('🚀 使用用户 API Key 测试 Zulip 集成...');
|
||
console.log('📡 用户 API Key: lCPWCPfGh7WU...pqNfGF8');
|
||
console.log('📡 Zulip 服务器: https://zulip.xinghangee.icu/');
|
||
console.log('📡 游戏服务器: http://localhost:3000/game');
|
||
|
||
const socket = io('http://localhost:3000/game', {
|
||
transports: ['websocket'],
|
||
timeout: 20000
|
||
});
|
||
|
||
let testStep = 0;
|
||
|
||
socket.on('connect', () => {
|
||
console.log('✅ WebSocket 连接成功');
|
||
testStep = 1;
|
||
|
||
// 使用包含用户 API Key 的 token
|
||
const loginMessage = {
|
||
type: 'login',
|
||
token: 'lCPWCPfGh7...fGF8_user_token'
|
||
};
|
||
|
||
console.log('📤 步骤 1: 发送登录消息(使用用户 API Key)');
|
||
socket.emit('login', loginMessage);
|
||
});
|
||
|
||
socket.on('login_success', (data) => {
|
||
console.log('✅ 步骤 1 完成: 登录成功');
|
||
console.log(' 会话ID:', data.sessionId);
|
||
console.log(' 用户ID:', data.userId);
|
||
console.log(' 用户名:', data.username);
|
||
console.log(' 当前地图:', data.currentMap);
|
||
testStep = 2;
|
||
|
||
// 等待 Zulip 客户端初始化
|
||
console.log('⏳ 等待 3 秒让 Zulip 客户端初始化...');
|
||
setTimeout(() => {
|
||
const chatMessage = {
|
||
t: 'chat',
|
||
content: '🎮 【用户API Key测试】来自游戏的消息!\\n' +
|
||
'时间: ' + new Date().toLocaleString() + '\\n' +
|
||
'使用用户 API Key 发送此消息。',
|
||
scope: 'local'
|
||
};
|
||
|
||
console.log('📤 步骤 2: 发送消息到 Zulip(使用用户 API Key)');
|
||
console.log(' 目标 Stream: Whale Port');
|
||
socket.emit('chat', chatMessage);
|
||
}, 3000);
|
||
});
|
||
|
||
socket.on('chat_sent', (data) => {
|
||
console.log('✅ 步骤 2 完成: 消息发送成功');
|
||
console.log(' 响应:', JSON.stringify(data, null, 2));
|
||
|
||
// 只在第一次收到 chat_sent 时发送第二条消息
|
||
if (testStep === 2) {
|
||
testStep = 3;
|
||
|
||
setTimeout(() => {
|
||
// 先切换到 Pumpkin Valley 地图
|
||
console.log('📤 步骤 3: 切换到 Pumpkin Valley 地图');
|
||
const positionUpdate = {
|
||
t: 'position',
|
||
x: 150,
|
||
y: 400,
|
||
mapId: 'pumpkin_valley'
|
||
};
|
||
socket.emit('position_update', positionUpdate);
|
||
|
||
// 等待位置更新后发送消息
|
||
setTimeout(() => {
|
||
const chatMessage2 = {
|
||
t: 'chat',
|
||
content: '🎃 在南瓜谷发送的测试消息!',
|
||
scope: 'local'
|
||
};
|
||
|
||
console.log('📤 步骤 4: 在 Pumpkin Valley 发送消息');
|
||
socket.emit('chat', chatMessage2);
|
||
}, 1000);
|
||
}, 2000);
|
||
}
|
||
});
|
||
|
||
socket.on('chat_render', (data) => {
|
||
console.log('📨 收到来自 Zulip 的消息:');
|
||
console.log(' 发送者:', data.from);
|
||
console.log(' 内容:', data.txt);
|
||
console.log(' Stream:', data.stream || '未知');
|
||
console.log(' Topic:', data.topic || '未知');
|
||
});
|
||
|
||
socket.on('error', (error) => {
|
||
console.log('❌ 收到错误:', JSON.stringify(error, null, 2));
|
||
});
|
||
|
||
socket.on('disconnect', () => {
|
||
console.log('🔌 WebSocket 连接已关闭');
|
||
console.log('');
|
||
console.log('📊 测试结果:');
|
||
console.log(' 完成步骤:', testStep, '/ 4');
|
||
if (testStep >= 3) {
|
||
console.log(' ✅ 核心功能正常!');
|
||
console.log(' 💡 请检查 Zulip 中的 "Whale Port" 和 "Pumpkin Valley" Streams 查看消息');
|
||
}
|
||
process.exit(0);
|
||
});
|
||
|
||
socket.on('connect_error', (error) => {
|
||
console.error('❌ 连接错误:', error.message);
|
||
process.exit(1);
|
||
});
|
||
|
||
// 20秒后自动关闭(给足够时间完成测试)
|
||
setTimeout(() => {
|
||
console.log('⏰ 测试时间到,关闭连接');
|
||
socket.disconnect();
|
||
}, 20000);
|
||
}
|
||
|
||
console.log('🔧 准备测试环境...');
|
||
testWithUserApiKey().catch(console.error); |