UNPKG

qq-official-bot

Version:
200 lines (199 loc) 7.23 kB
"use strict"; /** * 消息发送器 - 专门负责消息的发送逻辑 */ Object.defineProperty(exports, "__esModule", { value: true }); exports.MessageSender = void 0; const builder_1 = require("./builder"); const file_processor_1 = require("./file-processor"); /** * 消息发送器 * 专门负责消息的发送、审核处理和结果返回 */ class MessageSender { constructor(bot, endpointPath, source) { this.bot = bot; this.endpointPath = endpointPath; this.source = source; this.apiBaseUrl = bot.config.sandbox ? 'https://sandbox.api.sgroup.qq.com' : 'https://api.sgroup.qq.com'; this.messageBuilder = new builder_1.MessageBuilder(bot.config.appid, this.apiBaseUrl, source); this.fileProcessor = new file_processor_1.FileProcessor(bot); } /** * 发送消息 */ async send(message, options = {}) { try { // 构建消息 const buildResult = await this.messageBuilder.build(message); // 记录发送日志 this.bot.logger.info(`[SENDER] 发送消息到 ${this.endpointPath}: ${buildResult.brief}`); // 处理文件发送 if (buildResult.isFile) { return await this.sendFile(buildResult); } // 发送普通消息 return await this.sendMessage(buildResult, options); } catch (error) { this.bot.logger.error(`[SENDER] 消息发送失败:`, error); throw error; } } /** * 发送文件消息 */ async sendFile(buildResult) { try { const { data: result } = await this.bot.request.post(this.endpointPath + '/files', buildResult.filePayload); return { id: result.file_uuid || '', timestamp: Date.now() / 1000, ...result }; } catch (error) { this.bot.logger.error("[SENDER] 文件发送失败:", error); throw new Error(`文件发送失败: ${error}`); } } /** * 发送普通消息 */ async sendMessage(buildResult, options) { try { const { data: result } = await this.bot.request.post(this.endpointPath + '/messages', buildResult.messagePayload, { headers: { 'Content-Type': buildResult.contentType }, timeout: options.timeout || 10000 }); // 检查是否需要审核 if (this.isAuditResult(result)) { this.bot.logger.info(`[SENDER] 消息需要审核: ${result.message_audit.audit_id}`); return await this.waitForAudit(result.message_audit.audit_id); } // 处理正常发送结果 const messageResult = result; return { id: messageResult.id, timestamp: new Date(messageResult.timestamp).getTime() / 1000, ...messageResult }; } catch (error) { this.bot.logger.error("[SENDER] 消息发送失败:", error); throw new Error(`消息发送失败: ${error}`); } } /** * 等待审核结果 */ async waitForAudit(auditId) { return new Promise((resolve, reject) => { const timeout = setTimeout(() => { this.bot.off('message_audit.pass', onPass); this.bot.off('message_audit.reject', onReject); reject(new Error('审核超时')); }, 30000); // 30秒超时 const onPass = (event) => { if (event.audit_id === auditId) { clearTimeout(timeout); this.bot.off('message_audit.pass', onPass); this.bot.off('message_audit.reject', onReject); resolve({ id: event.message_id || '', timestamp: Date.now() / 1000, audit_id: auditId, audit_status: 'passed' }); } }; const onReject = (event) => { if (event.audit_id === auditId) { clearTimeout(timeout); this.bot.off('message_audit.pass', onPass); this.bot.off('message_audit.reject', onReject); reject(new Error(`消息审核被拒绝: ${event.audit_time}`)); } }; this.bot.on('message_audit.pass', onPass); this.bot.on('message_audit.reject', onReject); }); } /** * 检查是否为审核结果 */ isAuditResult(result) { return result && typeof result === 'object' && 'message_audit' in result; } /** * 发送带引用的消息 */ async sendWithQuote(message, quote, options = {}) { if (quote) { // 创建新的MessageBuilder实例以包含引用信息 const quotedBuilder = new builder_1.MessageBuilder(this.bot.config.appid, this.apiBaseUrl, quote); const buildResult = await quotedBuilder.build(message); if (buildResult.isFile) { return await this.sendFile(buildResult); } return await this.sendMessage(buildResult, options); } return await this.send(message, options); } /** * 批量发送消息 */ async sendBatch(messages, options = {}) { const results = []; for (const message of messages) { try { const result = await this.send(message, options); results.push(result); // 添加发送间隔以避免频率限制 await this.delay(100); } catch (error) { this.bot.logger.error(`[SENDER] 批量发送中的消息失败:`, error); // 可以选择继续发送其他消息或停止 throw error; } } return results; } /** * 重试发送消息 */ async sendWithRetry(message, maxRetries = 3, options = {}) { let lastError; for (let attempt = 1; attempt <= maxRetries; attempt++) { try { return await this.send(message, options); } catch (error) { lastError = error; this.bot.logger.warn(`[SENDER] 发送失败,尝试重试 (${attempt}/${maxRetries}):`, error); if (attempt < maxRetries) { // 指数退避策略 await this.delay(Math.pow(2, attempt) * 1000); } } } throw new Error(`消息发送失败,已重试 ${maxRetries} 次: ${lastError.message}`); } /** * 获取发送摘要信息 */ async getBrief(message) { const buildResult = await this.messageBuilder.build(message); return buildResult.brief; } /** * 工具方法:延迟 */ delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } } exports.MessageSender = MessageSender;