Spaces:
Sleeping
Sleeping
File size: 5,871 Bytes
2bf7a2b e9a82dd 2bf7a2b e9a82dd 2bf7a2b 138f7fd 2bf7a2b b2c8885 2bf7a2b 997f2d0 138f7fd 2bf7a2b b2c8885 2bf7a2b b2c8885 2bf7a2b b2c8885 2bf7a2b b2c8885 2bf7a2b b2c8885 2bf7a2b b2c8885 2bf7a2b b2c8885 2bf7a2b b2c8885 2bf7a2b b2c8885 2bf7a2b b2c8885 2bf7a2b b2c8885 2bf7a2b 997f2d0 b2c8885 2bf7a2b b2c8885 997f2d0 7afb7eb 997f2d0 2bf7a2b 7afb7eb a697003 7afb7eb 2bf7a2b 17bd284 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
require('dotenv').config();
const express = require('express');
const path = require('path');
const { WebSocketServer } = require('ws');
const http = require('http');
const Database = require('./database');
const ConnectionManager = require('./websocket');
const { verifyApiKey, requireAdminKey, requireRegularOrAdminKey, requireAnyKey, requireServerKey } = require('./auth');
const createKeysRouter = require('./routes/keys');
const createEventsRouter = require('./routes/events');
const createHealthRouter = require('./routes/health');
const createServerRouter = require('./routes/server');
const createAIRouter = require('./routes/ai');
const HOST = process.env.SERVER_HOST || '0.0.0.0';
const PORT = parseInt(process.env.SERVER_PORT || '8000');
const app = express();
const server = http.createServer(app);
const wss = new WebSocketServer({ noServer: true });
const db = new Database(process.env.DATABASE_PATH || 'minecraft_ws.db');
const manager = new ConnectionManager();
app.use(express.json());
// Request Logging Middleware
app.use((req, res, next) => {
const start = Date.now();
const timestamp = new Date().toISOString();
// Log request
console.log(`[${timestamp}] \x1b[36m${req.method}\x1b[0m ${req.url}`);
// Capture response finish
res.on('finish', () => {
const duration = Date.now() - start;
const statusColor = res.statusCode >= 400 ? '\x1b[31m' : (res.statusCode >= 300 ? '\x1b[33m' : '\x1b[32m');
console.log(`[${timestamp}] ${statusColor}${res.statusCode}\x1b[0m ${req.method} ${req.url} - ${duration}ms`);
});
next();
});
app.use('/dashboard', express.static(path.join(__dirname, '../dashboard/public')));
app.get('/', (req, res) => {
res.json({
message: 'Minecraft WebSocket API Server (Node.js)',
dashboard: '/dashboard',
websocket: 'ws://' + req.get('host') + '/ws',
version: '1.0.0'
});
});
app.use('/manage/keys', verifyApiKey(db), createKeysRouter(db, requireAdminKey));
app.use('/api/events', verifyApiKey(db), requireAnyKey, createEventsRouter(db, manager, requireAnyKey));
app.use('/api/server', verifyApiKey(db), createServerRouter(db, manager, requireRegularOrAdminKey));
app.use('/api/ai', verifyApiKey(db), createAIRouter(db, manager, requireAdminKey, requireAnyKey));
app.use('/health', createHealthRouter(db, manager));
server.on('upgrade', async (request, socket, head) => {
const url = new URL(request.url, `http://${request.headers.host}`);
if (url.pathname === '/ws') {
const apiKey = url.searchParams.get('api_key');
if (!apiKey) {
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
socket.destroy();
return;
}
const result = await db.verifyApiKey(apiKey);
if (!result) {
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
socket.destroy();
return;
}
wss.handleUpgrade(request, socket, head, (ws) => {
wss.emit('connection', ws, request, result);
});
} else {
socket.destroy();
}
});
wss.on('connection', (ws, request, apiKeyInfo) => {
manager.connect(ws, apiKeyInfo.id);
ws.on('message', (data) => {
try {
const msg = JSON.parse(data.toString());
if (msg.type === 'ping') {
ws.send(JSON.stringify({ type: 'pong' }));
}
} catch (error) {
}
});
ws.on('close', () => {
manager.disconnect(ws);
});
ws.on('error', () => {
manager.disconnect(ws);
});
});
async function startServer() {
console.log('🚀 启动Minecraft WebSocket API服务器...');
console.log('='.repeat(50));
await db.init();
const adminKeyInfo = await db.ensureInitialAdminKey();
const recoveryTokenInfo = await db.ensureAdminRecoveryToken();
if (adminKeyInfo) {
console.log('='.repeat(60));
console.log('重要: 已生成新的Admin Key!');
console.log(` 名称: ${adminKeyInfo.name}`);
console.log(` 密钥: ${adminKeyInfo.key}`);
console.log('请复制并安全保存此密钥。');
console.log('您需要使用它来管理API密钥。');
console.log('如果丢失此密钥且没有其他Admin Key,您可能失去管理员访问权限。');
console.log('='.repeat(60));
} else {
console.log('信息: 已找到现有Admin Key或Admin Key检查已执行。');
}
if (recoveryTokenInfo) {
console.log('='.repeat(60));
console.log('重要: 已生成 Admin 恢复令牌。');
console.log(` 令牌: ${recoveryTokenInfo.token}`);
console.log('请安全存储此令牌。它仅显示一次。');
console.log('='.repeat(60));
}
server.listen(PORT, HOST, () => {
const displayHost = HOST === '0.0.0.0' ? 'localhost' : HOST;
console.log(`服务器地址: http://${displayHost}:${PORT}/dashboard`);
console.log(`WebSocket端点: ws://${displayHost}:${PORT}/ws`);
console.log(`健康检查: http://${displayHost}:${PORT}/health`);
console.log('='.repeat(50));
console.log();
console.log('💡 首次使用提示:');
console.log('1. 使用CLI工具创建API密钥:');
console.log(' node cli/cli.js create-key "MyServer"');
console.log();
console.log('2. 生成Minecraft插件配置文件:');
console.log(' node cli/cli.js generate-config');
console.log();
console.log('3. 将API密钥配置到Minecraft插件中');
console.log('='.repeat(50));
});
}
if (require.main === module) {
startServer().catch(error => {
console.error('❌ 启动失败:', error);
process.exit(1);
});
}
module.exports = { app, server, db, wss, startServer };
|