xinc
Version:
基于napcat,node-napcat-ts的bot框架
318 lines • 15.6 kB
JavaScript
"use strict";
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _NCWebsocketBase_instances, _NCWebsocketBase_debug, _NCWebsocketBase_baseUrl, _NCWebsocketBase_accessToken, _NCWebsocketBase_throwPromise, _NCWebsocketBase_reconnection, _NCWebsocketBase_socket, _NCWebsocketBase_eventBus, _NCWebsocketBase_echoMap, _NCWebsocketBase_message;
Object.defineProperty(exports, "__esModule", { value: true });
exports.NCWebsocketBase = void 0;
const ws_1 = __importDefault(require("ws"));
const nanoid_1 = require("nanoid");
const NCEventBus_1 = require("./NCEventBus");
const Utils_1 = require("./Utils");
class NCWebsocketBase {
constructor(NCWebsocketOptions, debug = false) {
_NCWebsocketBase_instances.add(this);
_NCWebsocketBase_debug.set(this, void 0);
_NCWebsocketBase_baseUrl.set(this, void 0);
_NCWebsocketBase_accessToken.set(this, void 0);
_NCWebsocketBase_throwPromise.set(this, void 0);
_NCWebsocketBase_reconnection.set(this, void 0);
_NCWebsocketBase_socket.set(this, void 0);
_NCWebsocketBase_eventBus.set(this, void 0);
_NCWebsocketBase_echoMap.set(this, void 0);
__classPrivateFieldSet(this, _NCWebsocketBase_accessToken, NCWebsocketOptions.accessToken ?? '', "f");
__classPrivateFieldSet(this, _NCWebsocketBase_throwPromise, NCWebsocketOptions.throwPromise ?? false, "f");
if ('baseUrl' in NCWebsocketOptions) {
__classPrivateFieldSet(this, _NCWebsocketBase_baseUrl, NCWebsocketOptions.baseUrl, "f");
}
else if ('protocol' in NCWebsocketOptions && 'host' in NCWebsocketOptions && 'port' in NCWebsocketOptions) {
const { protocol, host, port } = NCWebsocketOptions;
__classPrivateFieldSet(this, _NCWebsocketBase_baseUrl, protocol + '://' + host + ':' + port, "f");
}
else {
throw new Error('NCWebsocketOptions must contain either "protocol && host && port" or "baseUrl"');
}
// 整理重连参数
const { enable = true, attempts = 10, delay = 5000 } = NCWebsocketOptions.reconnection ?? {};
__classPrivateFieldSet(this, _NCWebsocketBase_reconnection, { enable, attempts, delay, nowAttempts: 1 }, "f");
__classPrivateFieldSet(this, _NCWebsocketBase_debug, debug, "f");
__classPrivateFieldSet(this, _NCWebsocketBase_eventBus, new NCEventBus_1.NCEventBus(this), "f");
__classPrivateFieldSet(this, _NCWebsocketBase_echoMap, new Map(), "f");
}
// ==================WebSocket操作=============================
/**
* await connect() 等待 ws 连接
*/
async connect() {
return new Promise((resolve, reject) => {
__classPrivateFieldGet(this, _NCWebsocketBase_eventBus, "f").emit('socket.connecting', { reconnection: __classPrivateFieldGet(this, _NCWebsocketBase_reconnection, "f") });
const socket = new ws_1.default(`${__classPrivateFieldGet(this, _NCWebsocketBase_baseUrl, "f")}?access_token=${__classPrivateFieldGet(this, _NCWebsocketBase_accessToken, "f")}`);
socket.onopen = () => {
__classPrivateFieldGet(this, _NCWebsocketBase_eventBus, "f").emit('socket.open', { reconnection: __classPrivateFieldGet(this, _NCWebsocketBase_reconnection, "f") });
__classPrivateFieldGet(this, _NCWebsocketBase_reconnection, "f").nowAttempts = 1;
resolve();
};
socket.onclose = async (event) => {
__classPrivateFieldGet(this, _NCWebsocketBase_eventBus, "f").emit('socket.close', {
code: event.code,
reason: event.reason,
reconnection: __classPrivateFieldGet(this, _NCWebsocketBase_reconnection, "f"),
});
if (__classPrivateFieldGet(this, _NCWebsocketBase_reconnection, "f").enable && __classPrivateFieldGet(this, _NCWebsocketBase_reconnection, "f").nowAttempts < __classPrivateFieldGet(this, _NCWebsocketBase_reconnection, "f").attempts) {
__classPrivateFieldGet(this, _NCWebsocketBase_reconnection, "f").nowAttempts++;
setTimeout(async () => {
try {
await this.reconnect();
}
catch (error) {
reject(error);
}
}, __classPrivateFieldGet(this, _NCWebsocketBase_reconnection, "f").delay);
}
};
socket.onmessage = (event) => __classPrivateFieldGet(this, _NCWebsocketBase_instances, "m", _NCWebsocketBase_message).call(this, event.data);
socket.onerror = (event) => {
__classPrivateFieldGet(this, _NCWebsocketBase_eventBus, "f").emit('socket.error', {
reconnection: __classPrivateFieldGet(this, _NCWebsocketBase_reconnection, "f"),
error_type: 'connect_error',
errors: event?.error?.errors ?? [event?.error ?? null],
});
if (__classPrivateFieldGet(this, _NCWebsocketBase_throwPromise, "f")) {
if (__classPrivateFieldGet(this, _NCWebsocketBase_reconnection, "f").enable && __classPrivateFieldGet(this, _NCWebsocketBase_reconnection, "f").nowAttempts < __classPrivateFieldGet(this, _NCWebsocketBase_reconnection, "f").attempts) {
// 重连未到最后一次,等待继续重连,不抛出错误
return;
}
reject({
reconnection: __classPrivateFieldGet(this, _NCWebsocketBase_reconnection, "f"),
error_type: 'connect_error',
errors: event?.error?.errors ?? [event?.error ?? null],
});
}
};
__classPrivateFieldSet(this, _NCWebsocketBase_socket, socket, "f");
});
}
disconnect() {
if (__classPrivateFieldGet(this, _NCWebsocketBase_socket, "f")) {
__classPrivateFieldGet(this, _NCWebsocketBase_socket, "f").close(1000);
__classPrivateFieldSet(this, _NCWebsocketBase_socket, undefined, "f");
}
}
async reconnect() {
this.disconnect();
await this.connect();
}
// ==================事件绑定=============================
/**
* 发送API请求
* @param method API 端点
* @param params 请求参数
*/
send(method, params) {
const echo = (0, nanoid_1.nanoid)();
const message = {
action: method,
params: params,
echo,
};
if (__classPrivateFieldGet(this, _NCWebsocketBase_debug, "f")) {
Utils_1.logger.debug('[node-open-napcat] send request');
Utils_1.logger.dir(message);
}
return new Promise((resolve, reject) => {
const onSuccess = (response) => {
__classPrivateFieldGet(this, _NCWebsocketBase_echoMap, "f").delete(echo);
return resolve(response.data);
};
const onFailure = (reason) => {
__classPrivateFieldGet(this, _NCWebsocketBase_echoMap, "f").delete(echo);
return reject(reason);
};
__classPrivateFieldGet(this, _NCWebsocketBase_echoMap, "f").set(echo, {
message,
onSuccess,
onFailure,
});
__classPrivateFieldGet(this, _NCWebsocketBase_eventBus, "f").emit('api.preSend', message);
if (__classPrivateFieldGet(this, _NCWebsocketBase_socket, "f") === undefined) {
reject({
status: 'failed',
retcode: -1,
data: null,
message: 'api socket is not connected',
echo: '',
});
}
else if (__classPrivateFieldGet(this, _NCWebsocketBase_socket, "f").readyState === ws_1.default.CLOSING) {
reject({
status: 'failed',
retcode: -1,
data: null,
message: 'api socket is closed',
echo: '',
});
}
else {
__classPrivateFieldGet(this, _NCWebsocketBase_socket, "f").send(JSON.stringify(message));
}
});
}
/**
* 发送API请求并返回完整响应
* @param method API 端点
* @param params 请求参数
*/
call(method, params) {
const echo = (0, nanoid_1.nanoid)();
const message = {
action: method,
params: params,
echo,
};
if (__classPrivateFieldGet(this, _NCWebsocketBase_debug, "f")) {
Utils_1.logger.debug('[node-open-napcat] send request');
Utils_1.logger.dir(message);
}
return new Promise((resolve, reject) => {
const onSuccess = (response) => {
__classPrivateFieldGet(this, _NCWebsocketBase_echoMap, "f").delete(echo);
return resolve(response); // 返回完整响应
};
const onFailure = (reason) => {
__classPrivateFieldGet(this, _NCWebsocketBase_echoMap, "f").delete(echo);
return resolve(reason); // 失败时也返回响应而不是reject
};
__classPrivateFieldGet(this, _NCWebsocketBase_echoMap, "f").set(echo, {
message,
onSuccess,
onFailure,
});
__classPrivateFieldGet(this, _NCWebsocketBase_eventBus, "f").emit('api.preSend', message);
if (__classPrivateFieldGet(this, _NCWebsocketBase_socket, "f") === undefined) {
reject({
status: 'failed',
retcode: -1,
data: null,
message: 'api socket is not connected',
echo: '',
});
}
else if (__classPrivateFieldGet(this, _NCWebsocketBase_socket, "f").readyState === ws_1.default.CLOSING) {
reject({
status: 'failed',
retcode: -1,
data: null,
message: 'api socket is closed',
echo: '',
});
}
else {
__classPrivateFieldGet(this, _NCWebsocketBase_socket, "f").send(JSON.stringify(message));
}
});
}
/**
* 注册监听方法
* @param event
* @param handle
*/
on(event, handle) {
__classPrivateFieldGet(this, _NCWebsocketBase_eventBus, "f").on(event, handle);
return this;
}
/**
* 只执行一次
* @param event
* @param handle
*/
once(event, handle) {
__classPrivateFieldGet(this, _NCWebsocketBase_eventBus, "f").once(event, handle);
return this;
}
/**
* 解除监听方法
* @param event
* @param handle
*/
off(event, handle) {
__classPrivateFieldGet(this, _NCWebsocketBase_eventBus, "f").off(event, handle);
return this;
}
/**
* 手动模拟触发某个事件
* @param type
* @param context
*/
emit(type, context) {
__classPrivateFieldGet(this, _NCWebsocketBase_eventBus, "f").emit(type, context);
return this;
}
}
exports.NCWebsocketBase = NCWebsocketBase;
_NCWebsocketBase_debug = new WeakMap(), _NCWebsocketBase_baseUrl = new WeakMap(), _NCWebsocketBase_accessToken = new WeakMap(), _NCWebsocketBase_throwPromise = new WeakMap(), _NCWebsocketBase_reconnection = new WeakMap(), _NCWebsocketBase_socket = new WeakMap(), _NCWebsocketBase_eventBus = new WeakMap(), _NCWebsocketBase_echoMap = new WeakMap(), _NCWebsocketBase_instances = new WeakSet(), _NCWebsocketBase_message = function _NCWebsocketBase_message(data) {
let json;
try {
json = JSON.parse(data.toString());
if (json.post_type === 'message' || json.post_type === 'message_sent') {
if (json.message_format === 'string') {
json = JSON.parse((0, Utils_1.CQCodeDecode)(json));
json.message = (0, Utils_1.convertCQCodeToJSON)(json.message);
json.message_format = 'array';
}
json.raw_message = (0, Utils_1.CQCodeDecode)(json.raw_message);
}
}
catch (error) {
Utils_1.logger.warn('[node-napcat-ts]', '[socket]', 'failed to parse JSON');
Utils_1.logger.dir(error);
return;
}
if (__classPrivateFieldGet(this, _NCWebsocketBase_debug, "f")) {
Utils_1.logger.debug('[node-napcat-ts]', '[socket]', 'receive data');
Utils_1.logger.dir(json);
}
if (json.echo) {
const handler = __classPrivateFieldGet(this, _NCWebsocketBase_echoMap, "f").get(json.echo);
if (handler) {
if (json.retcode === 0) {
__classPrivateFieldGet(this, _NCWebsocketBase_eventBus, "f").emit('api.response.success', json);
handler.onSuccess(json);
}
else {
__classPrivateFieldGet(this, _NCWebsocketBase_eventBus, "f").emit('api.response.failure', json);
handler.onFailure(json);
}
}
}
else {
if (json?.status === 'failed' && json?.echo === null) {
__classPrivateFieldGet(this, _NCWebsocketBase_reconnection, "f").enable = false;
__classPrivateFieldGet(this, _NCWebsocketBase_eventBus, "f").emit('socket.error', {
reconnection: __classPrivateFieldGet(this, _NCWebsocketBase_reconnection, "f"),
error_type: 'response_error',
info: {
url: __classPrivateFieldGet(this, _NCWebsocketBase_baseUrl, "f"),
errno: json.retcode,
message: json.message,
},
});
if (__classPrivateFieldGet(this, _NCWebsocketBase_throwPromise, "f"))
throw new Error(json.message);
this.disconnect();
return;
}
__classPrivateFieldGet(this, _NCWebsocketBase_eventBus, "f").parseMessage(json);
}
};
//# sourceMappingURL=NCWebsocketBase.js.map