UNPKG

qq-official-bot

Version:
271 lines (270 loc) 8.58 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MiddlewareReceiver = exports.MiddlewareReceiverConfig = void 0; exports.createMiddlewareReceiver = createMiddlewareReceiver; const base_1 = require("./base"); const constants_1 = require("../constants"); const ed25519_1 = require("../ed25519"); /** * Middleware接收器配置 */ class MiddlewareReceiverConfig extends base_1.BaseReceiverConfig { constructor(options) { super(base_1.ReceiverMode.MIDDLEWARE); this.platform = options.platform; this.timeout = options.timeout || 30000; } validate() { return ['koa', 'express'].includes(this.platform) && this.timeout > 0; } toJson() { return { mode: this.mode, platform: this.platform, timeout: this.timeout }; } } exports.MiddlewareReceiverConfig = MiddlewareReceiverConfig; /** * Middleware接收器实现 */ class MiddlewareReceiver extends base_1.BaseReceiver { constructor(config) { const middleware = MiddlewareReceiver.createMiddleware(config.platform); super({ middleware: () => middleware }); this.session = null; this.config = config; this.setupMiddlewareEventHandlers(); } /** * 创建对应平台的中间件 */ static createMiddleware(platform) { switch (platform) { case 'koa': return (async function (ctx, next) { if (next) await next(); return this.handleWebhookRequest(ctx.req, ctx.res, this.handler.ed25519, ctx.request.body); }); case 'express': return (async function (req, res) { return this.handleWebhookRequest(req, res, this.handler.ed25519); }); default: throw new Error(`Unsupported platform: ${platform}`); } } /** * 设置Middleware特定的事件处理器 */ setupMiddlewareEventHandlers() { this.on('start', this.handleStart.bind(this)); this.on('stop', this.handleStop.bind(this)); } /** * 启动Middleware接收器 */ async start(session) { this.session = session; this._isStarted = true; // 初始化Ed25519签名验证 this.handler.ed25519 = new ed25519_1.Ed25519(session.getBot().config.secret); // 绑定中间件的this上下文 const originalMiddleware = this.handler.middleware; this.handler.middleware = () => { const middleware = originalMiddleware(); return middleware.bind(this); }; this.emitReady(); } /** * 停止Middleware接收器 */ async stop(session) { this._isStarted = false; this.handler.ed25519 = undefined; this.emitClose(); } /** * 处理启动事件 */ async handleStart(session) { await this.start(session); } /** * 处理停止事件 */ async handleStop() { await this.stop(); } /** * 获取中间件函数 */ getMiddleware() { return this.handler.middleware(); } /** * 处理Webhook请求 */ async handleWebhookRequest(req, res, ed25519, fallbackData) { if (!this.session || !ed25519) { this.handleError(res, 'Server not ready', 500); return; } try { const bodyData = await this.resolveBodyData(req, JSON.stringify(fallbackData)); // 验证签名 const signature = req.headers['x-signature-ed25519']?.toString(); const timestamp = req.headers['x-signature-timestamp']?.toString(); if (!signature) { this.session.getBot().logger.warn('[MiddlewareReceiver] 缺少签名头'); this.handleError(res, 'Missing signature', 400); return; } if (!ed25519.verify(signature, timestamp + bodyData)) { this.session.getBot().logger.warn('[MiddlewareReceiver] 签名验证失败'); this.handleError(res, 'Invalid signature', 401); return; } // 解析数据包 let packet; try { packet = JSON.parse(bodyData); } catch (error) { this.session.getBot().logger.error('[MiddlewareReceiver] 数据包解析失败:', error); this.handleError(res, 'Invalid JSON', 400); return; } // 处理不同类型的操作 switch (packet.op) { case constants_1.OpCode.SIGN_VERIFY: await this.handleSignVerify(packet, res, ed25519); break; case constants_1.OpCode.DISPATCH: await this.handleDispatch(packet, res); break; default: this.session.getBot().logger.warn(`[MiddlewareReceiver] 未知的操作码: ${packet.op}`); this.handleError(res, 'Unknown operation', 400); } } catch (error) { this.handleRequestError(res, error); } } /** * 处理签名验证 */ async handleSignVerify(packet, res, ed25519) { if (!this.session) return; const { plain_token, event_ts } = packet.d; const signed = ed25519.sign(event_ts + plain_token); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ plain_token, signature: signed })); this.session.getBot().logger.debug('[MiddlewareReceiver] 处理签名验证完成'); } /** * 处理事件分发 */ async handleDispatch(packet, res) { if (!this.session) return; this.session.getBot().logger.debug('[MiddlewareReceiver] 收到事件:', packet.t); // 发送packet事件 this.emitPacket(packet); // 返回成功响应 res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ code: 0, message: 'success' })); } /** * 解析请求体数据 */ async resolveBodyData(req, fallbackData) { return new Promise((resolve) => { if (fallbackData) { resolve(fallbackData); return; } const dataArr = []; req.on('data', (data) => { dataArr.push(data); }); req.on('end', () => { resolve(Buffer.concat(dataArr).toString()); }); }); } /** * 处理错误响应 */ handleError(res, message, statusCode) { if (!res.headersSent) { res.writeHead(statusCode, { 'Content-Type': 'text/plain' }); res.end(message); } } /** * 处理请求错误 */ handleRequestError(res, error) { if (this.session) { this.session.getBot().logger.error('[MiddlewareReceiver] 请求处理错误:', error); } this.emitError(error); if (!res.headersSent) { res.writeHead(500, { 'Content-Type': 'text/plain' }); res.end('Internal Server Error'); } } /** * 处理数据包(基类抽象方法实现) */ handlePacket(packet) { // Middleware接收器的数据包处理在handleWebhookRequest中进行 // 这里不需要额外处理 } /** * 获取接收器类型 */ getType() { return base_1.ReceiverMode.MIDDLEWARE; } /** * 获取接收器配置 */ getConfig() { return this.config.toJson(); } /** * 健康检查 */ healthCheck() { const baseHealth = super.healthCheck(); return { ...baseHealth, details: { ...baseHealth.details, platform: this.config.platform, hasEd25519: !!this.handler.ed25519, hasMiddleware: typeof this.handler.middleware === 'function' } }; } } exports.MiddlewareReceiver = MiddlewareReceiver; /** * 创建Middleware接收器的工厂函数(向后兼容) */ function createMiddlewareReceiver(platform) { const config = new MiddlewareReceiverConfig({ platform }); return new MiddlewareReceiver(config); }