UNPKG

miraipie

Version:

the most powerful nodejs development kit for mirai-api-http

544 lines (543 loc) 24.9 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __values = (this && this.__values) || function(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spreadArray = (this && this.__spreadArray) || function (to, from) { for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) to[j] = from[i]; return to; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.makeAppConfig = exports.createApp = exports.Mirai = exports.FaceType = exports.ResponseCode = exports.MiraiPieApplication = void 0; var events_1 = __importDefault(require("events")); var log4js_1 = require("log4js"); var path_1 = __importDefault(require("path")); var chat_1 = require("./chat"); var config_1 = require("./config"); var message_1 = require("./message"); var utils_1 = require("./utils"); /** MiraiPie 应用程序 */ var MiraiPieApplication = /** @class */ (function (_super) { __extends(MiraiPieApplication, _super); function MiraiPieApplication(config, loggerOptions) { var e_1, _a, e_2, _b; var _this = _super.call(this) || this; _this.config = config; /** logger */ _this.logger = log4js_1.getLogger('miraipie'); MiraiPieApplication.instance = _this; // 注册全局模块 process.env.MIRAIPIE_MODULE = module.id; _this.qq = config.qq; // 初始化log4js log4js_1.configure(loggerOptions || { appenders: { console: { type: 'console' }, file: { type: 'dateFile', filename: config.logDirectory + '/miraipie.log' } }, categories: { default: { appenders: config.logDirectory ? ['console', 'file'] : ['console'], level: config.logLevel || 'debug' } } }); _this.setMaxListeners(0); _this.__apiAdapterMap = new Map(); _this.__piesMap = new Map(); _this.__piesEnabledMap = new Map(); // 加载内置 adapter var BuiltinApiAdapters = [ require('./builtin/HttpApiAdapter'), require('./builtin/WebsocketApiAdapter'), require('./builtin/MixedApiAdapter') ]; try { for (var BuiltinApiAdapters_1 = __values(BuiltinApiAdapters), BuiltinApiAdapters_1_1 = BuiltinApiAdapters_1.next(); !BuiltinApiAdapters_1_1.done; BuiltinApiAdapters_1_1 = BuiltinApiAdapters_1.next()) { var adapter = BuiltinApiAdapters_1_1.value; adapter.configs.qq = _this.qq; _this.adapter(adapter); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (BuiltinApiAdapters_1_1 && !BuiltinApiAdapters_1_1.done && (_a = BuiltinApiAdapters_1.return)) _a.call(BuiltinApiAdapters_1); } finally { if (e_1) throw e_1.error; } } // 加载配置文件中的各项拓展 var modules = new Set(__spreadArray(__spreadArray(__spreadArray([], __read(_this.config.extensions)), __read(Object.keys(_this.config.adapters).map(function (id) { return _this.config.adapters[id].module; }))), __read(Object.keys(_this.config.pies).map(function (id) { return _this.config.pies[id].module; })))); try { for (var modules_1 = __values(modules), modules_1_1 = modules_1.next(); !modules_1_1.done; modules_1_1 = modules_1.next()) { var module_1 = modules_1_1.value; if (module_1) { try { // 执行拓展文件 require(path_1.default.join(process.cwd(), module_1))(_this); } catch (err) { _this.logger.error("\u52A0\u8F7D\u62D3\u5C55\u6A21\u5757 '" + module_1 + "' \u65F6\u51FA\u9519:", err); } } } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (modules_1_1 && !modules_1_1.done && (_b = modules_1.return)) _b.call(modules_1); } finally { if (e_2) throw e_2.error; } } if (_this.config.verbose) { _this.on('message', function (chatMessage) { var displayString = chatMessage.messageChain.toDisplayString(); if (chatMessage.type === 'FriendMessage') { var sender = chatMessage.sender; _this.logger.info(sender.nickname + "(" + sender.id + ") -> " + displayString); } else if (chatMessage.type === 'GroupMessage') { var sender = chatMessage.sender; _this.logger.info("[" + sender.group.name + "(" + sender.group.id + ")] " + sender.memberName + "(" + sender.id + ") -> " + displayString); } else if (chatMessage.type === 'TempMessage') { var sender = chatMessage.sender; _this.logger.info(sender.memberName + "(" + sender.id + ") -> " + displayString); } }); _this.on('event', function (event) { _this.logger.info(event.type + ": " + JSON.stringify(event)); }); } // 选用默认 adapter _this.useAdapter(config.adapterInUse); // 捕获未处理的异常 process.on('uncaughtException', function (error) { _this.logger.debug('捕获到未处理的异常:', error); }); process.on('unhandledRejection', function (reason) { _this.logger.debug('捕获到未处理的rejection:', reason); }); // 捕捉Ctrl-C process.on('SIGINT', function () { _this.logger.info('已手动停止运行 (Ctrl-C)'); process.exit(); }); return _this; } /** * 创建 MiraiPie 应用程序实例 * @param appConfigs 应用程序配置 * @param loggerOptions log4js实例配置 */ MiraiPieApplication.createApp = function (appConfigs, loggerOptions) { return new MiraiPieApplication(appConfigs, loggerOptions); }; /** * 安装拓展 * @param extension 拓展对象, 可以为 adapter 和 pie */ MiraiPieApplication.prototype.install = function (extension) { if (extension.__isPie) this.pie(extension); else if (extension.__isApiAdapter) this.adapter(extension); else this.logger.error("\u672A\u77E5\u7684\u62D3\u5C55\u7C7B\u578B: " + extension); return this; }; /** * 安装 adapter * @param adapter adapter 对象 */ MiraiPieApplication.prototype.adapter = function (adapter) { var _this = this; if (!adapter.__isApiAdapter) { this.logger.error("\u5B89\u88C5 adapter \u5931\u8D25, " + adapter + " \u4E0D\u662F\u6709\u6548\u7684 adapter"); return this; } // 安装 adapter this.__apiAdapterMap.set(adapter.id, adapter); // 注册时事件 adapter.on('message', function (chatMessage) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: chatMessage.messageChain = message_1.MessageChain.from(chatMessage.messageChain); this.emit('message', chatMessage); this.emit(chatMessage.type, chatMessage); return [4 /*yield*/, this.__messageDispatcher(chatMessage)]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }); adapter.on('sync', function (syncMessage) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { syncMessage.messageChain = message_1.MessageChain.from(syncMessage.messageChain); this.emit('sync', syncMessage); this.emit(syncMessage.type, syncMessage); return [2 /*return*/]; }); }); }); adapter.on('event', function (event) { _this.emit('event', event); _this.emit(event.type, event); }); adapter.on('listen', function () { _this.emit('listen'); }); adapter.on('stop', function () { _this.emit('stop'); }); adapter.once('listen', function () { return __awaiter(_this, void 0, void 0, function () { var resp; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, adapter.getAbout()]; case 1: resp = _a.sent(); if (resp.data.version !== adapter.supportVersion) { this.logger.warn("\u5F53\u524D\u4F7F\u7528\u7684adapter: '" + adapter.id + "' \u652F\u6301 mirai-api-http V" + adapter.supportVersion + ", \u800C\u670D\u52A1\u7AEF\u8FD0\u884C\u7684\u7248\u672C\u4E3A V" + resp.data.version + ", \u4F7F\u7528\u4E2D\u53EF\u80FD\u4EA7\u751F\u517C\u5BB9\u6027\u95EE\u9898"); } return [2 /*return*/]; } }); }); }); // 配置 adapter if (adapter.id in this.config.adapters) { adapter.configs = Object.assign(adapter.configs, this.config.adapters[adapter.id].configs); config_1.checkUserConfig(adapter.configMeta, adapter.configs, adapter.logger); } this.logger.info("\u5DF2\u5B89\u88C5 adapter '" + adapter.id + "'"); adapter.emit('installed'); return this; }; /** * 切换服务 adapter * @param id adapter id */ MiraiPieApplication.prototype.useAdapter = function (id) { if (this.__apiAdapterMap.has(id)) { if (this.api) { this.api.emit('unused'); this.api.stop(); } this.api = this.__apiAdapterMap.get(id); this.__apiAdapterMap.get(id).emit('used'); } else { this.logger.error("\u4F7F\u7528 adapter \u5931\u8D25, \u6307\u5B9A\u7684 adapter '" + id + "' \u672A\u5B89\u88C5"); } return this; }; /** * 卸载 adapter * @param id adapter id */ MiraiPieApplication.prototype.uninstallAdapter = function (id) { if (this.api && this.api.id === id) { this.logger.error("\u5378\u8F7D adapter '" + id + "' \u5931\u8D25, \u5F53\u524D\u6B63\u5728\u4F7F\u7528"); } if (this.__apiAdapterMap.has(id)) { var adapter = this.__apiAdapterMap.get(id); this.__apiAdapterMap.delete(id); this.logger.info("\u5DF2\u5378\u8F7D adapter '" + id + "'"); return adapter; } else { this.logger.error("\u5378\u8F7D adapter \u5931\u8D25, \u6307\u5B9A\u7684 adapter '" + id + "' \u672A\u5B89\u88C5"); } }; /** * 安装 pie * @param pie pie 对象 */ MiraiPieApplication.prototype.pie = function (pie) { if (!pie.__isPie) { this.logger.error("\u5B89\u88C5 pie \u5931\u8D25, " + pie + " \u4E0D\u662F\u6709\u6548\u7684 pie"); return this; } // 安装 pie this.__piesMap.set(pie.id, pie); // 配置 pie if (pie.id in this.config.pies) { var pieConfig = this.config.pies[pie.id]; pie.configs = Object.assign(pie.configs, pieConfig.configs); config_1.checkUserConfig(pie.configMeta, pie.configs, pie.logger); // 是否启用 this.__piesEnabledMap.set(pie.id, pieConfig.enabled); } else { // 自动启用 this.__piesEnabledMap.set(pie.id, true); } this.logger.info("\u5DF2\u5B89\u88C5 pie '" + pie.id + "'"); pie.emit('installed'); if (this.__piesEnabledMap.get(pie.id)) this.enable(pie.id); return this; }; /** * 启用 pie * @param id pie id */ MiraiPieApplication.prototype.enable = function (id) { if (this.__piesMap.has(id)) { this.__piesEnabledMap.set(id, true); this.__piesMap.get(id).emit('enabled'); this.logger.info("\u5DF2\u542F\u7528 pie '" + id + "'"); } return this; }; /** * 禁用 pie * @param id pie id */ MiraiPieApplication.prototype.disable = function (id) { if (this.__piesMap.has(id)) { this.__piesEnabledMap.set(id, false); this.__piesMap.get(id).emit('disabled'); this.logger.info("\u5DF2\u7981\u7528 pie '" + id + "'"); } return this; }; /** * 卸载 pie * @param id pie id */ MiraiPieApplication.prototype.uninstallPie = function (id) { if (this.__piesMap.has(id)) { var pie = this.__piesMap.get(id); this.disable(id); this.__piesEnabledMap.delete(id); this.__piesMap.delete(id); pie.emit('uninstalled'); this.logger.info("\u5DF2\u5378\u8F7D pie '" + id + "'"); return pie; } else { this.logger.error("\u5378\u8F7D pie \u5931\u8D25, \u6307\u5B9A\u7684 pie '" + id + "' \u672A\u5B89\u88C5"); } }; /** 启动 adapter 的事件监听 */ MiraiPieApplication.prototype.listen = function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: if (!this.api) return [3 /*break*/, 3]; if (!!this.api.listening) return [3 /*break*/, 2]; return [4 /*yield*/, this.api.listen()]; case 1: _a.sent(); _a.label = 2; case 2: return [3 /*break*/, 4]; case 3: this.logger.error('未指定使用的 adapter, 无法启动监听'); _a.label = 4; case 4: return [2 /*return*/]; } }); }); }; /** 停止 adapter 的事件监听 */ MiraiPieApplication.prototype.stop = function () { if (this.api && this.api.listening) this.api.stop(); }; MiraiPieApplication.prototype.addListener = function (event, listener) { return _super.prototype.addListener.call(this, event, listener); }; MiraiPieApplication.prototype.on = function (event, listener) { return _super.prototype.on.call(this, event, listener); }; MiraiPieApplication.prototype.once = function (event, listener) { return _super.prototype.once.call(this, event, listener); }; MiraiPieApplication.prototype.listeners = function (event) { return _super.prototype.listeners.call(this, event); }; MiraiPieApplication.prototype.emit = function (event) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; } return _super.prototype.emit.apply(this, __spreadArray([event], __read(args))); }; MiraiPieApplication.prototype.prependListener = function (event, listener) { return _super.prototype.prependListener.call(this, event, listener); }; MiraiPieApplication.prototype.prependOnceListener = function (event, listener) { return _super.prototype.prependOnceListener.call(this, event, listener); }; /** 用于 pie 的消息分发器 */ MiraiPieApplication.prototype.__messageDispatcher = function (chatMessage) { return __awaiter(this, void 0, void 0, function () { var chat, chain, _loop_1, this_1, _a, _b, _c, id, enabled; var e_3, _d; return __generator(this, function (_e) { chat = null; if (chatMessage.type === 'FriendMessage') chat = new chat_1.FriendChat(chatMessage.sender); else if (chatMessage.type === 'GroupMessage') chat = new chat_1.GroupChat(chatMessage.sender); else if (chatMessage.type === 'TempMessage') chat = new chat_1.TempChat(chatMessage.sender); else return [2 /*return*/]; chat = utils_1.makeReadonly(chat); chain = utils_1.makeReadonly(message_1.MessageChain.from(chatMessage.messageChain)); _loop_1 = function (id, enabled) { if (enabled) { var pie_1 = this_1.__piesMap.get(id); if (pie_1.filters.map(function (filter) { return filter.handler(chat, chain, pie_1); }).some(function (v) { return !v; })) return "continue"; pie_1.emit('received', chat, chain); } }; this_1 = this; try { for (_a = __values(this.__piesEnabledMap.entries()), _b = _a.next(); !_b.done; _b = _a.next()) { _c = __read(_b.value, 2), id = _c[0], enabled = _c[1]; _loop_1(id, enabled); } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (_b && !_b.done && (_d = _a.return)) _d.call(_a); } finally { if (e_3) throw e_3.error; } } return [2 /*return*/]; }); }); }; /** 应用程序单例 */ MiraiPieApplication.instance = null; return MiraiPieApplication; }(events_1.default)); exports.MiraiPieApplication = MiraiPieApplication; var mirai_1 = require("./mirai"); Object.defineProperty(exports, "ResponseCode", { enumerable: true, get: function () { return mirai_1.ResponseCode; } }); Object.defineProperty(exports, "FaceType", { enumerable: true, get: function () { return mirai_1.FaceType; } }); exports.Mirai = __importStar(require("./mirai")); __exportStar(require("./adapter"), exports); __exportStar(require("./pie"), exports); __exportStar(require("./message"), exports); __exportStar(require("./chat"), exports); __exportStar(require("./config"), exports); exports.createApp = MiraiPieApplication.createApp; exports.makeAppConfig = config_1.ApplicationConfig.make; exports.default = exports.createApp; // 当存在全局 miraipie 应用程序时, 使用全局模块 if (process.env.MIRAIPIE_MODULE) { module.exports = require(process.env.MIRAIPIE_MODULE); }