/** * 测试通过 WebSocket 接收 Zulip 消息 * * 设计理念: * - Zulip API Key 永不下发到客户端 * - 所有 Zulip 交互通过游戏服务器的 WebSocket 进行 * - 客户端只接收 chat_render 消息,不直接调用 Zulip API * * 功能: * 1. 登录游戏服务器获取 JWT Token * 2. 通过 WebSocket 连接游戏服务器 * 3. 在当前地图 (Whale Port) 接收消息 * 4. 切换到 Pumpkin Valley 接收消息 * 5. 统计接收到的消息数量 * * 使用方法: * node docs/systems/zulip/quick_tests/test-get-messages.js */ const axios = require('axios'); const io = require('socket.io-client'); // 配置 const GAME_SERVER = 'http://localhost:3000'; const TEST_USER = { username: 'angtest123', password: 'angtest123', email: 'angjustinl@163.com' }; // 测试配置 const TEST_CONFIG = { whalePortWaitTime: 10000, // 在 Whale Port 等待 10 秒 pumpkinValleyWaitTime: 10000, // 在 Pumpkin Valley 等待 10 秒 totalTimeout: 30000 // 总超时时间 30 秒 }; /** * 登录游戏服务器获取用户信息 */ async function loginToGameServer() { console.log('📝 步骤 1: 登录游戏服务器'); console.log(` 用户名: ${TEST_USER.username}`); try { const response = await axios.post(`${GAME_SERVER}/auth/login`, { identifier: TEST_USER.username, password: TEST_USER.password }); if (response.data.success) { console.log('✅ 登录成功'); console.log(` 用户ID: ${response.data.data.user.id}`); console.log(` 邮箱: ${response.data.data.user.email}`); return { userId: response.data.data.user.id, username: response.data.data.user.username, email: response.data.data.user.email, token: response.data.data.access_token }; } else { throw new Error(response.data.message || '登录失败'); } } catch (error) { console.error('❌ 登录失败:', error.response?.data?.message || error.message); throw error; } } /** * 通过 WebSocket 接收消息 */ async function receiveMessagesViaWebSocket(userInfo) { console.log('\n📡 步骤 2: 通过 WebSocket 连接并接收消息'); console.log(` 连接到: ${GAME_SERVER}/game`); return new Promise((resolve, reject) => { const socket = io(`${GAME_SERVER}/game`, { transports: ['websocket'], timeout: 20000 }); const receivedMessages = { whalePort: [], pumpkinValley: [] }; let currentMap = 'whale_port'; let testPhase = 0; // 0: 连接中, 1: Whale Port, 2: Pumpkin Valley, 3: 完成 // 连接成功 socket.on('connect', () => { console.log('✅ WebSocket 连接成功'); // 发送登录消息 const loginMessage = { type: 'login', token: userInfo.token }; console.log('📤 发送登录消息...'); socket.emit('login', loginMessage); }); // 登录成功 socket.on('login_success', (data) => { console.log('✅ 登录成功'); console.log(` 会话ID: ${data.sessionId}`); console.log(` 用户ID: ${data.userId}`); console.log(` 当前地图: ${data.currentMap}`); testPhase = 1; currentMap = data.currentMap || 'whale_port'; console.log(`\n📬 步骤 3: 在 Whale Port 接收消息 (等待 ${TEST_CONFIG.whalePortWaitTime / 1000} 秒)`); console.log(' 💡 提示: 请在 Zulip 的 "Whale Port" Stream 发送测试消息'); // 在 Whale Port 等待一段时间 setTimeout(() => { console.log(`\n📊 Whale Port 接收到 ${receivedMessages.whalePort.length} 条消息`); // 切换到 Pumpkin Valley console.log(`\n📤 步骤 4: 切换到 Pumpkin Valley`); const positionUpdate = { t: 'position', x: 150, y: 400, mapId: 'pumpkin_valley' }; socket.emit('position_update', positionUpdate); testPhase = 2; currentMap = 'pumpkin_valley'; console.log(`\n📬 步骤 5: 在 Pumpkin Valley 接收消息 (等待 ${TEST_CONFIG.pumpkinValleyWaitTime / 1000} 秒)`); console.log(' 💡 提示: 请在 Zulip 的 "Pumpkin Valley" Stream 发送测试消息'); // 在 Pumpkin Valley 等待一段时间 setTimeout(() => { console.log(`\n📊 Pumpkin Valley 接收到 ${receivedMessages.pumpkinValley.length} 条消息`); testPhase = 3; console.log('\n📊 测试完成,断开连接...'); socket.disconnect(); }, TEST_CONFIG.pumpkinValleyWaitTime); }, TEST_CONFIG.whalePortWaitTime); }); // 接收到消息 (chat_render) socket.on('chat_render', (data) => { const timestamp = new Date().toLocaleTimeString('zh-CN'); console.log(`\n📨 [${timestamp}] 收到消息:`); console.log(` ├─ 发送者: ${data.from}`); console.log(` ├─ 内容: ${data.txt}`); console.log(` ├─ Stream: ${data.stream || '未知'}`); console.log(` ├─ Topic: ${data.topic || '未知'}`); console.log(` └─ 当前地图: ${currentMap}`); // 记录消息 const message = { from: data.from, content: data.txt, stream: data.stream, topic: data.topic, timestamp: new Date(), map: currentMap }; if (testPhase === 1) { receivedMessages.whalePort.push(message); } else if (testPhase === 2) { receivedMessages.pumpkinValley.push(message); } }); // 错误处理 socket.on('error', (error) => { console.error('❌ 收到错误:', JSON.stringify(error, null, 2)); }); // 连接断开 socket.on('disconnect', () => { console.log('\n🔌 WebSocket 连接已关闭'); resolve(receivedMessages); }); // 连接错误 socket.on('connect_error', (error) => { console.error('❌ 连接错误:', error.message); reject(error); }); // 总超时保护 setTimeout(() => { if (socket.connected) { console.log('\n⏰ 测试超时,关闭连接'); socket.disconnect(); } }, TEST_CONFIG.totalTimeout); }); } /** * 主测试流程 */ async function runTest() { console.log('🚀 开始测试通过 WebSocket 接收 Zulip 消息'); console.log('='.repeat(60)); console.log('📋 设计理念: Zulip API Key 永不下发到客户端'); console.log('📋 所有消息通过游戏服务器的 WebSocket (chat_render) 接收'); console.log('='.repeat(60)); try { // 步骤1: 登录游戏服务器 const userInfo = await loginToGameServer(); // 步骤2-5: 通过 WebSocket 接收消息 const receivedMessages = await receiveMessagesViaWebSocket(userInfo); // 步骤6: 统计信息 console.log('\n' + '='.repeat(60)); console.log('📊 测试结果汇总'); console.log('='.repeat(60)); console.log(`✅ Whale Port: ${receivedMessages.whalePort.length} 条消息`); console.log(`✅ Pumpkin Valley: ${receivedMessages.pumpkinValley.length} 条消息`); console.log(`📝 总计: ${receivedMessages.whalePort.length + receivedMessages.pumpkinValley.length} 条消息`); // 显示详细消息列表 if (receivedMessages.whalePort.length > 0) { console.log('\n📬 Whale Port 消息列表:'); receivedMessages.whalePort.forEach((msg, index) => { console.log(` ${index + 1}. [${msg.timestamp.toLocaleTimeString()}] ${msg.from}: ${msg.content.substring(0, 50)}${msg.content.length > 50 ? '...' : ''}`); }); } if (receivedMessages.pumpkinValley.length > 0) { console.log('\n📬 Pumpkin Valley 消息列表:'); receivedMessages.pumpkinValley.forEach((msg, index) => { console.log(` ${index + 1}. [${msg.timestamp.toLocaleTimeString()}] ${msg.from}: ${msg.content.substring(0, 50)}${msg.content.length > 50 ? '...' : ''}`); }); } console.log('='.repeat(60)); console.log('\n🎉 测试完成!'); console.log('💡 提示: 客户端通过 WebSocket 接收消息,无需直接访问 Zulip API'); console.log('💡 提示: 访问 https://zulip.xinghangee.icu 查看完整消息历史'); process.exit(0); } catch (error) { console.error('\n❌ 测试失败:', error.message); process.exit(1); } } // 运行测试 runTest();