diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..418703b
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,13 @@
+{
+ "env": {
+ "commonjs": true,
+ "es2021": true,
+ "node": true
+ },
+ "extends": "eslint:recommended",
+ "parserOptions": {
+ "ecmaVersion": 12
+ },
+ "rules": {
+ }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c2658d7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+node_modules/
diff --git a/.vscode/httpRequest.code-snippets b/.vscode/httpRequest.code-snippets
new file mode 100644
index 0000000..cc58b93
--- /dev/null
+++ b/.vscode/httpRequest.code-snippets
@@ -0,0 +1,123 @@
+{
+ "HttpRequest-get": {
+ "scope": "javascript,typescript",
+ "prefix": "hrget",
+ "body": [
+ "HttpRequest({",
+ " method: 'GET',",
+ " url: '$1',",
+ " query: {",
+ " $2",
+ " },",
+ " headers: {",
+ " accept: 'application/json, text/plain, */*',",
+ " cookie: '$3',",
+ " },",
+ " success: res => {",
+ " $4",
+ " },",
+ " failure: err => {",
+ " $5",
+ " }",
+ "})$6"
+ ],
+ "description": "简化http-get请求"
+ },
+ "HttpRequest-post": {
+ "scope": "javascript,typescript",
+ "prefix": "hrpost",
+ "body": [
+ "HttpRequest({",
+ " method: 'POST',",
+ " url: '$1',",
+ " contents: {",
+ " $2",
+ " },",
+ " headers: {",
+ " accept: 'application/json, text/plain, */*',",
+ " 'content-type': 'application/x-www-form-urlencoded; charset=utf-8',",
+ " cookie: '$3',",
+ " },",
+ " success: res => {",
+ " $4",
+ " },",
+ " failure: err => {",
+ " $5",
+ " }",
+ "})$6"
+ ],
+ "description": "简化http-post请求"
+ },
+ "CORSajax-get": {
+ "scope": "javascript,typescript",
+ "prefix": "corsget",
+ "body": [
+ "CORSajax.get({",
+ " proxy_link: '$1',",
+ " proxy_querystring: {",
+ " $2",
+ " },",
+ " proxy_headers: {",
+ " Cookie: '$3'",
+ " },",
+ "},chunk => {",
+ " $4",
+ "})$5"
+ ],
+ "description": "简化跨域Ajax本地nodejsのget代理"
+ },
+ "CORSajax-post": {
+ "scope": "javascript,typescript",
+ "prefix": "corspost",
+ "body": [
+ "CORSajax.post({",
+ " proxy_link: '$1',",
+ " proxy_headers: {",
+ " 'content-type': 'application/x-www-form-urlencoded; charset=utf-8',",
+ " cookie: '$2'",
+ " },",
+ " proxy_body: {",
+ " $3",
+ " },",
+ "},chunk => {",
+ " $4",
+ "})$5"
+ ],
+ "description": "简化跨域Ajax本地nodejsのpost代理"
+ },
+ "Ajax-get": {
+ "scope": "javascript,typescript",
+ "prefix": "myget",
+ "body": [
+ "Ajax.get({",
+ " url: '$1',",
+ " queryStringsObj: {",
+ " $2",
+ " },",
+ " hasCookies: true,",
+ " success: responseText => {",
+ " $3",
+ " }",
+ "})",
+ ],
+ "description": "简化AjaxのGet请求"
+ },
+ "Ajax-post": {
+ "scope": "javascript,typescript",
+ "prefix": "mypost",
+ "body": [
+ "Ajax.post({",
+ " url: '$1',",
+ " hasCookies: true,",
+ " dataType: 'application/x-www-form-urlencoded',",
+ " data: {",
+ " $2",
+ " },",
+ " success: responseText => {",
+ " $3",
+ " }",
+ "})",
+ ],
+ "description": "简化Ajaxのpost请求"
+ },
+}
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d6cae26
--- /dev/null
+++ b/README.md
@@ -0,0 +1,84 @@
+# BiliBili 直播间弹幕
+包括全区礼物广播, 投喂信息, 入场信息, 人气值等
+
+直播间`WebSocket`传输数据格式
+```
+Packet Header Format
+
+ 0 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| PL |HL |PV | Op |Seq ID |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| |
+| Data |
+| |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+PL: 4 bits
+
+ Packet Length
+
+HL: 2 bits
+
+ Header Length
+
+ 16 - HEADER_TOTAL_LENGTH
+
+PV: 2 bits
+
+ Protocol Version
+
+ 1 - HEADER_DEFAULT_VERSION
+ 0 - BODY_PROTOCOL_VERSION_NORMAL
+ 2 - BODY_PROTOCOL_VERSION_DEFLATE
+
+
+Op: 4 bits
+
+ Operation
+
+ 1 - HEADER_DEFAULT_OPERATION
+ 2 - OP_HEARTBEAT
+ 3 - OP_HEARTBEAT_REPLY
+ 5 - OP_MESSAGE
+ 7 - OP_USER_AUTHENTICATION
+ 8 - OP_CONNECT_SUCCESS
+
+
+Seq ID: 4 bits
+
+ Sequence Id
+
+ 1 - HEADER_DEFAULT_SEQUENCE
+
+
+Data: ANY bits
+
+ if PV = 0 then Data is UTF-8 Code JSON Format
+ if PV = 2 then Data is Gzip
+ Unzip: Data -> Header0 + Data0 + Header1 + Data1 + ...
+ And Data(n) is also UTF-8 Code JSON Format
+
+```
+
+## 初始化
+`GET` [https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo](https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo)
+
+获取所需的`HostList` `key`
+
+
+
+
+ HostList |
+ WebSocket主机列表 |
+
+
+ key |
+ 身份识别 |
+
+
+
+
+连接至WebSocket服务器
\ No newline at end of file
diff --git a/lib/Base.js b/lib/Base.js
new file mode 100644
index 0000000..199acce
--- /dev/null
+++ b/lib/Base.js
@@ -0,0 +1,26 @@
+/**
+ * mergeArrayBuffer
+ * @param {ArrayBuffer[]} arrays
+ * @returns {ArrayBuffer}
+ */
+function mergeArrayBuffer(...arrays) {
+ let totalLen = 0
+ for (let i = 0; i < arrays.length; i++) {
+ arrays[i] = new Uint8Array(arrays[i])
+ totalLen += arrays[i].length
+ }
+
+ let res = new Uint8Array(totalLen)
+
+ let offset = 0
+ for(let arr of arrays) {
+ res.set(arr, offset)
+ offset += arr.length
+ }
+
+ return res.buffer
+}
+
+module.exports = {
+ mergeArrayBuffer
+}
\ No newline at end of file
diff --git a/lib/Convert.js b/lib/Convert.js
new file mode 100644
index 0000000..670eca3
--- /dev/null
+++ b/lib/Convert.js
@@ -0,0 +1,153 @@
+const { mergeArrayBuffer } = require("./Base");
+const { inflateSync } = require('zlib');
+const WS = {
+ OP_HEARTBEAT: 2,
+ OP_USER_AUTHENTICATION: 7,
+ OP_HEARTBEAT_REPLY: 3,
+ OP_MESSAGE: 5,
+ OP_CONNECT_SUCCESS: 8,
+
+ PACKAGE_HEADER_TOTAL_LENGTH: 16,
+
+ PACKAGE_OFFSET: 0,
+ HEADER_OFFSET: 4,
+ VERSION_OFFSET: 6,
+ OPERATION_OFFSET: 8,
+ SEQUENCE_OFFSET: 12,
+
+ BODY_PROTOCOL_VERSION_NORMAL: 0,
+ BODY_PROTOCOL_VERSION_DEFLATE: 2,
+
+ HEADER_DEFAULT_VERSION: 1,
+ HEADER_DEFAULT_OPERATION: 1,
+ HEADER_DEFAULT_SEQUENCE: 1,
+
+ AUTH_OK: 0,
+ AUTH_TOKEN_ERROR: -101,
+
+ BinaryHeaderList: [
+ {
+ "name": "Header Length",
+ "key": "headerLen",
+ "bytes": 2,
+ "offset": 4,
+ "value": 16
+ },
+ {
+ "name": "Protocol Version",
+ "key": "ver",
+ "bytes": 2,
+ "offset": 6,
+ "value": 1
+ },
+ {
+ "name": "Operation",
+ "key": "op",
+ "bytes": 4,
+ "offset": 8,
+ "value": 2
+ },
+ {
+ "name": "Sequence Id",
+ "key": "seq",
+ "bytes": 4,
+ "offset": 12,
+ "value": 1
+ }
+ ]
+}
+
+/**
+ * 去掉头部信息
+ * 原始数据转为object
+ * @param {ArrayBuffer} raw_data
+ * @returns
+ */
+function toObject(raw_data) {
+ if (!raw_data) return {}
+
+ const decoder = new TextDecoder();
+
+ let raw_data_view = new DataView(raw_data),
+ ret = {
+ body: [],
+ totalLen: raw_data.byteLength
+ };
+
+ WS.BinaryHeaderList.forEach((header) => {
+ const { bytes, offset, key } = header;
+ if (bytes === 4) {
+ ret[key] = raw_data_view.getInt32(offset)
+ } else if (bytes === 2) {
+ ret[key] = raw_data_view.getInt16(offset)
+ }
+ })
+
+ if (ret.op !== WS.OP_HEARTBEAT_REPLY) {
+
+ for (let wpo = WS.PACKAGE_OFFSET, pl = 0, hl = 0, body = null; wpo < ret.totalLen; wpo += pl) {
+
+ pl = raw_data_view.getInt32(wpo);
+ hl = raw_data_view.getInt16(wpo + WS.HEADER_OFFSET);
+
+ try {
+
+ if (ret.ver === WS.BODY_PROTOCOL_VERSION_DEFLATE) {
+ const _raw_data = raw_data.slice(wpo + hl, wpo + pl);
+ const unzip_data = inflateSync(_raw_data);
+ ({ body } = toObject(unzip_data.buffer.slice(unzip_data.byteOffset, unzip_data.byteOffset + unzip_data.byteLength)));
+ } else {
+ const msg_str = decoder.decode(
+ raw_data.slice(wpo + hl, wpo + pl)
+ );
+ if (msg_str) body = JSON.parse(msg_str);
+ }
+
+ if (body instanceof Array) {
+ ret.body.push(...body)
+ } else {
+ body && ret.body.push(body);
+ }
+
+ } catch (error) { console.log('decode body error:', error) }
+ }
+
+ } else {
+
+ ret.popular_count = raw_data_view.getInt32(WS.PACKAGE_HEADER_TOTAL_LENGTH);
+
+ }
+
+ return ret
+}
+
+/**
+ * 加上头部信息
+ * 字符串转为ArrayBuffer
+ * @param {string} raw_str
+ * @param {number} op
+ * @returns {ArrayBuffer}
+ */
+function toArrayBuffer(raw_str, op) {
+ const encoder = new TextEncoder()
+ , body = encoder.encode(raw_str);
+
+ let header = new ArrayBuffer(WS.PACKAGE_HEADER_TOTAL_LENGTH),
+ header_view = new DataView(header, WS.PACKAGE_OFFSET);
+
+ header_view.setInt32(WS.PACKAGE_OFFSET, WS.PACKAGE_HEADER_TOTAL_LENGTH + body.byteLength);
+ WS.BinaryHeaderList[2].value = op;
+ WS.BinaryHeaderList.forEach(((header) => {
+ const { bytes, offset, value } = header;
+ if (bytes === 4) {
+ header_view.setInt32(offset, value)
+ } else if (bytes === 2) {
+ header_view.setInt16(offset, value)
+ }
+ }))
+
+ return mergeArrayBuffer(header, body.buffer);
+}
+
+
+module.exports = { WS, toObject, toArrayBuffer };
\ No newline at end of file
diff --git a/lib/HttpRequest.js b/lib/HttpRequest.js
new file mode 100644
index 0000000..005afba
--- /dev/null
+++ b/lib/HttpRequest.js
@@ -0,0 +1,193 @@
+//@ts-check
+/**
+ * @typedef {import("http").IncomingHttpHeaders} HttpHeaders 头部信息
+ *
+ * @typedef {object} Respond 返回的响应
+ * @property {HttpHeaders} headers 响应头
+ * @property {string} [body] UTF8编码响应
+ * @property {import("http").IncomingMessage} [resStream] 可读流式响应体
+ *
+ * @callback SuccessCb 成功回调
+ * @param {Respond} res
+ * @returns {void}
+ * @callback FailureCb 失败回调
+ * @param {string} err
+ * @returns {void}
+ *
+ * @typedef Proxy
+ * @property {string} hostname
+ * @property {string} [host]
+ * @property {number} port
+ *
+ * @typedef RequestConfig
+ * @property {number} [timeout] 超时
+ * @property {number} [wait] 错误等待
+ * @property {boolean} [retry] 是否重传
+ * @property {boolean} [redirect] 是否重定向
+ * @property {number} [retry_times] 重试次数
+ *
+ * @typedef {object} RequestOptions Http请求选项
+ * @property {string} method 请求方法
+ * @property {string} url 完整链接
+ * @property {boolean} [stream] 是否流式数据
+ * @property {RequestConfig} [config] 设置
+ * @property {Proxy} [proxy] 代理
+ * @property {Object.} [query] 查询选项
+ * @property {Object. | string} [contents] 内容
+ * @property {HttpHeaders} [headers] 请求头
+ * @property {SuccessCb} success 成功回调
+ * @property {FailureCb} failure 失败回调
+ */
+
+const { request: http_request } = require('http');
+const { request: https_request } = require('https');
+const { stringify } = require('querystring');
+
+/**默认编码 */
+const DEFAULT_DECODE = 'utf8';
+/**超时时间 */
+const DEFAULT_TIMEOUT = 20000;
+/**出错等待时间 */
+const DEFAULT_WAIT = 10000;
+/**默认重传 */
+const DEFAULT_RETRY = true;
+/**默认不重定向 */
+const DEFAULT_REDIRECT = false;
+/**错误尝试次数 */
+const DEFAULT_RETRY_TIMES = 6;
+/**Google Chrome */
+const DEFAULT_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36';
+/**默认url编码 */
+const DEFAULT_CONTENT_TYPE = 'application/x-www-form-urlencoded; charset=UTF-8';
+/**
+ * @description 简化HTTP请求
+ * @param {RequestOptions} detail
+ * @returns {void}
+ */
+function HttpRequest(detail) {
+ detail = setDefault(detail);
+ const { method, url, stream, config, proxy, query, contents, headers, success, failure } = detail;
+ const { timeout, wait, retry, redirect, retry_times } = config;
+ const thisURL = new URL(url)
+ , content = formatContents(headers["content-type"], contents)
+ , request = thisURL.protocol === 'https:' ? https_request : http_request;
+ let options = {
+ timeout,
+ method: method.toUpperCase(),
+ host: thisURL.host,
+ path: thisURL.pathname + thisURL.search + thisURL.hash,
+ headers,
+ };
+ if (!headers["user-agent"]) options.headers["user-agent"] = DEFAULT_UA;
+ if (query) options.path += (thisURL.search ? '&' : '?') + stringify(query);
+ if (content) {
+ if (!headers["content-type"]) options.headers["content-type"] = DEFAULT_CONTENT_TYPE;
+ options.headers['content-length'] = Buffer.byteLength(content, 'utf-8').toString();
+ }
+ if (proxy) {
+ options.headers.host = thisURL.host;
+ [options.hostname, options.port] = proxy.host ?
+ proxy.host.split(':') : [proxy.hostname, proxy.port]
+ options.path = thisURL.href;
+ }
+ const req = request(options, res => {
+ let protodata = '';
+ const { statusCode, headers } = res;
+ if (redirect && ~~(statusCode / 100) === 3) {
+ try {
+ detail.url = new URL(headers.location).href
+ } catch (error) {
+ detail.url = new URL(thisURL.origin + headers.location).href
+ }
+ console.log(`[重定向]状态码:${statusCode} location:${detail.url}`);
+ HttpRequest(detail)
+ return
+ }
+ if (stream) {
+ success({ headers: headers, resStream: res })
+ } else {
+ res.setEncoding(DEFAULT_DECODE)
+ .on('data', chunk => { protodata += chunk })
+ .on('error', async err => {
+ if (retry && retry_times) {
+ console.log(`[不期待响应]原因:${err.message} 尝试重新请求中...`);
+ await delay(wait);
+ detail.config.retry_times = retry_times - 1;
+ HttpRequest(detail);
+ } else {
+ failure(`[响应错误]${err.message} 响应数据:\n${protodata}`)
+ }
+ })
+ .on('end', () => {
+ if (statusCode < 400) {
+ success({ headers: headers, body: protodata })
+ } else {
+ res.emit('error', new Error(`HTTP状态码: ${statusCode}`))
+ }
+ })
+ }
+ })
+ req.on('error', async err => {
+ if (retry && retry_times) {
+ console.log(`[请求失败]原因:${err.message} 尝试重新连接中...`);
+ await delay(wait);
+ detail.config.retry_times = retry_times - 1;
+ HttpRequest(detail);
+ } else {
+ failure(`[请求失败]: ${err.message}`);
+ }
+ })
+ req.on('timeout', () => { req.destroy(new Error('请求超时')) })
+ req.end(content)
+}
+
+/**
+ * 处理请求体
+ * 默认url编码字符串
+ * @private
+ * @param {string} type 请求的内容格式
+ * @param {object} contents 请求体
+ * @returns {string} 格式化字符串
+ */
+function formatContents(type, contents) {
+ if (/application\/json/i.test(type)) return JSON.stringify(contents);
+ if (typeof contents === 'object') return stringify(contents);
+ return contents;
+}
+
+/**
+ * 设置默认
+ * @param {RequestOptions} detail
+ */
+function setDefault(detail) {
+ detail = {
+ stream: false,
+ headers: {},
+ ...detail
+ }
+ detail.config = {
+ timeout: DEFAULT_TIMEOUT,
+ wait: DEFAULT_WAIT,
+ retry: DEFAULT_RETRY,
+ redirect: DEFAULT_REDIRECT,
+ retry_times: DEFAULT_RETRY_TIMES,
+ ...detail.config
+ }
+ return detail;
+}
+
+/**
+ * 延时函数
+ * @param {number} time ms
+ * @returns {Promise}
+ */
+function delay(time) {
+ return new Promise(resolve => {
+ setTimeout(() => {
+ resolve();
+ }, time);
+ });
+}
+
+
+module.exports = { HttpRequest }
\ No newline at end of file
diff --git a/lib/LiveAPI.js b/lib/LiveAPI.js
new file mode 100644
index 0000000..0ea8e08
--- /dev/null
+++ b/lib/LiveAPI.js
@@ -0,0 +1,46 @@
+const { HttpRequest } = require("./HttpRequest");
+
+const LiveAPI = {
+ HOST: 'https://api.live.bilibili.com',
+ /**
+ * DanmuServer
+ * @typedef Host
+ * @property {string} host
+ * @property {string} wss_port
+ *
+ * @typedef ServerHost
+ * @property {string} token
+ * @property {Array} host_list
+ *
+ * @param {number} roomid
+ * @returns {Promise}
+ */
+ DanmuServer(roomid) {
+ return new Promise((resolve, reject) => {
+ HttpRequest({
+ method: 'GET',
+ url: this.HOST + '/xlive/web-room/v1/index/getDanmuInfo',
+ query: {
+ id: roomid,
+ type: 0
+ },
+ headers: {
+ accept: 'application/json, text/plain, */*',
+ },
+ success: res => {
+ try {
+ const res_jsonify = JSON.parse(res.body);
+ if (res_jsonify.code !== 0) throw Error(res.body);
+ resolve(res_jsonify.data)
+ } catch (error) {
+ reject(error)
+ }
+ },
+ failure: reject
+ })
+ });
+ }
+}
+
+
+module.exports = LiveAPI;
\ No newline at end of file
diff --git a/lib/LiveChat.js b/lib/LiveChat.js
new file mode 100644
index 0000000..8f44185
--- /dev/null
+++ b/lib/LiveChat.js
@@ -0,0 +1,156 @@
+const WebSocket = require("ws");
+const convert = require("./Convert");
+const LiveAPI = require("./LiveAPI");
+
+class ServerInfo {
+ constructor() {
+ this.roomid = 0;
+ this.uid = 0;
+ this.wss_url = '';
+ this._hostList = [];
+ this.userAuthentication = {
+ uid: 0,
+ roomid: 0,
+ protover: convert.WS.BODY_PROTOCOL_VERSION_DEFLATE,
+ platform: "web",
+ clientver: "2.6.42",
+ type: 2,
+ key: ''
+ };
+ }
+
+ setRoomId(rid) {
+ this.roomid = rid;
+ return this
+ }
+
+ setUid(uid) {
+ this.uid = uid;
+ return this
+ }
+
+ setWssURL(wss_url) {
+ this.wss_url = wss_url;
+ }
+
+ *hostListIter() {
+ for (const host of this._hostList) {
+ yield host
+ }
+ }
+
+ async initInfo() {
+ let result = true;
+ try {
+ const DanmuInfo = await LiveAPI.DanmuServer(this.roomid);
+ this.userAuthentication.key = DanmuInfo.token;
+ this.userAuthentication.roomid = this.roomid;
+ this.userAuthentication.uid = this.uid;
+ this._hostList = DanmuInfo.host_list.map(it => {
+ return 'wss://' + it.host + ':' + it.wss_port + '/sub'
+ })
+ } catch (error) {
+ console.error(error);
+ result = false;
+ }
+ return result
+ }
+}
+
+class LiveChat extends ServerInfo {
+ constructor() {
+ super();
+ this.heartBeat = 0;
+ this.HostList = null;
+ this.option = {
+ retryTimeOut: 1 * 1000,
+ heartBeatInterval: 30 * 1000,
+ msgState: false
+ }
+ this.messageHandle = () => {};
+ }
+
+ setMessageHandle(cb) {
+ this.messageHandle = cb;
+ return this;
+ }
+
+ async run() {
+ if (this.roomid && this.uid && await this.initInfo()) {
+ console.log('chat_client -> initialize success');
+ this.HostList = this.hostListIter();
+ this._wsConnect()
+ } else {
+ console.log('chat_client -> initialize failed');
+ }
+ }
+
+ _wsConnect() {
+ const { value, done } = this.HostList.next();
+ if (!done) {
+ this.setWssURL(value);
+ this.ws = new WebSocket(this.wss_url);
+ this.ws.onopen = this.onOpen.bind(this);
+ this.ws.onmessage = this.onMessage.bind(this);
+ this.ws.onerror = this.onError.bind(this);
+ this.ws.onclose = this.onClose.bind(this);
+ }
+ }
+
+ close() {
+ this.ws.close()
+ }
+
+ _heartBeat() {
+ return setInterval(() => {
+ console.log('chat_client -> heartBeat');
+ this.ws.send(
+ convert.toArrayBuffer(
+ {}.toString(),
+ convert.WS.OP_HEARTBEAT
+ )
+ )
+ }, this.option.heartBeatInterval);
+ }
+
+ onOpen() {
+ console.log('chat_client -> connent to ' + this.wss_url);
+ this.ws.send(
+ convert.toArrayBuffer(
+ JSON.stringify(this.userAuthentication),
+ convert.WS.OP_USER_AUTHENTICATION
+ )
+ );
+ this.heartBeat = this._heartBeat();
+ }
+
+ onMessage(raw_msg) {
+ this.option.msgState = true;
+ let raw_data_toArrayBuffer = null;
+ const raw_data = raw_msg.data;
+ if (raw_data instanceof Buffer) {
+ raw_data_toArrayBuffer = raw_data.buffer.slice(raw_data.byteOffset, raw_data.byteOffset + raw_data.byteLength)
+ } else if (raw_data instanceof ArrayBuffer) {
+ raw_data_toArrayBuffer = raw_data
+ }
+ const raw_data_obj = convert.toObject(raw_data_toArrayBuffer);
+ this.messageHandle(raw_data_obj);
+ }
+
+ onError(err) {
+ console.log(err.message);
+ }
+
+ onClose() {
+ clearInterval(this.heartBeat);
+ if (this.option.msgState) {
+ console.log('chat_client -> close');
+ } else {
+ console.log('chat_client -> change host');
+ setTimeout(this._wsConnect.bind(this), this.option.retryTimeOut)
+ }
+ }
+}
+
+
+module.exports = LiveChat;
\ No newline at end of file
diff --git a/main.js b/main.js
new file mode 100644
index 0000000..60b8e45
--- /dev/null
+++ b/main.js
@@ -0,0 +1,12 @@
+const LiveChat = require("./lib/LiveChat");
+
+(function () {
+ const LiveChatCLient = new LiveChat();
+ LiveChatCLient
+ .setRoomId(1)
+ .setUid(1)
+ .setMessageHandle((msg) => {
+ console.log(msg);
+ })
+ .run();
+})()
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..59ea5d8
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,1051 @@
+{
+ "name": "comment",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.12.11",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
+ "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.12.11",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
+ "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.13.10",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz",
+ "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.12.11",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ }
+ }
+ },
+ "@eslint/eslintrc": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz",
+ "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.12.4",
+ "debug": "^4.1.1",
+ "espree": "^7.3.0",
+ "globals": "^12.1.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^3.13.1",
+ "minimatch": "^3.0.4",
+ "strip-json-comments": "^3.1.1"
+ },
+ "dependencies": {
+ "globals": {
+ "version": "12.4.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
+ "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.8.1"
+ }
+ }
+ }
+ },
+ "acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "dev": true
+ },
+ "acorn-jsx": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
+ "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
+ "dev": true
+ },
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ }
+ },
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+ "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "debug": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+ "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "deep-is": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+ "dev": true
+ },
+ "doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "enquirer": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+ "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "^4.1.1"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "eslint": {
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.23.0.tgz",
+ "integrity": "sha512-kqvNVbdkjzpFy0XOszNwjkKzZ+6TcwCQ/h+ozlcIWwaimBBuhlQ4nN6kbiM2L+OjDcznkTJxzYfRFH92sx4a0Q==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "7.12.11",
+ "@eslint/eslintrc": "^0.4.0",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.0.1",
+ "doctrine": "^3.0.0",
+ "enquirer": "^2.3.5",
+ "eslint-scope": "^5.1.1",
+ "eslint-utils": "^2.1.0",
+ "eslint-visitor-keys": "^2.0.0",
+ "espree": "^7.3.1",
+ "esquery": "^1.4.0",
+ "esutils": "^2.0.2",
+ "file-entry-cache": "^6.0.1",
+ "functional-red-black-tree": "^1.0.1",
+ "glob-parent": "^5.0.0",
+ "globals": "^13.6.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "js-yaml": "^3.13.1",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash": "^4.17.21",
+ "minimatch": "^3.0.4",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "progress": "^2.0.0",
+ "regexpp": "^3.1.0",
+ "semver": "^7.2.1",
+ "strip-ansi": "^6.0.0",
+ "strip-json-comments": "^3.1.0",
+ "table": "^6.0.4",
+ "text-table": "^0.2.0",
+ "v8-compile-cache": "^2.0.3"
+ }
+ },
+ "eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "eslint-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+ "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz",
+ "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==",
+ "dev": true
+ },
+ "espree": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
+ "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==",
+ "dev": true,
+ "requires": {
+ "acorn": "^7.4.0",
+ "acorn-jsx": "^5.3.1",
+ "eslint-visitor-keys": "^1.3.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "dev": true
+ }
+ }
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true
+ },
+ "esquery": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+ "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.1.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+ "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+ "dev": true
+ }
+ }
+ },
+ "esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.2.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+ "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+ "dev": true
+ }
+ }
+ },
+ "estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
+ "file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "requires": {
+ "flat-cache": "^3.0.4"
+ }
+ },
+ "flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "requires": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "flatted": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz",
+ "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==",
+ "dev": true
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+ "dev": true
+ },
+ "get-intrinsic": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
+ "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1"
+ }
+ },
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "globals": {
+ "version": "13.7.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.7.0.tgz",
+ "integrity": "sha512-Aipsz6ZKRxa/xQkZhNg0qIWXT6x6rD46f6x/PCnBomlttdIyAPak4YD9jTmKpZ72uROSMU87qJtcgpgHaVchiA==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.20.2"
+ },
+ "dependencies": {
+ "type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true
+ }
+ }
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "has-symbols": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
+ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
+ "dev": true
+ },
+ "ignore": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "dev": true
+ },
+ "import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "is-boolean-object": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz",
+ "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.0"
+ }
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number-object": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz",
+ "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==",
+ "dev": true
+ },
+ "is-string": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
+ "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+ "dev": true
+ },
+ "levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
+ "lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
+ "dev": true
+ },
+ "lodash.flatten": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+ "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=",
+ "dev": true
+ },
+ "lodash.truncate": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
+ "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "requires": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.3"
+ }
+ },
+ "parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "requires": {
+ "callsites": "^3.0.0"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true
+ },
+ "progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "dev": true
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ },
+ "regexpp": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
+ "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
+ "dev": true
+ },
+ "require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true
+ },
+ "resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ }
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
+ "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.0"
+ }
+ },
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "table": {
+ "version": "6.0.9",
+ "resolved": "https://registry.npmjs.org/table/-/table-6.0.9.tgz",
+ "integrity": "sha512-F3cLs9a3hL1Z7N4+EkSscsel3z55XT950AvB05bwayrNg5T1/gykXtigioTAjbltvbMSJvvhFCbnf6mX+ntnJQ==",
+ "dev": true,
+ "requires": {
+ "ajv": "^8.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "lodash.clonedeep": "^4.5.0",
+ "lodash.flatten": "^4.4.0",
+ "lodash.truncate": "^4.4.2",
+ "slice-ansi": "^4.0.0",
+ "string-width": "^4.2.0"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "8.0.5",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.0.5.tgz",
+ "integrity": "sha512-RkiLa/AeJx7+9OvniQ/qeWu0w74A8DiPPBclQ6ji3ZQkv5KamO+QGpqmi7O4JIw3rHGUXZ6CoP9tsAkn3gyazg==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true
+ }
+ }
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+ "dev": true
+ },
+ "type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1"
+ }
+ },
+ "type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true
+ },
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "v8-compile-cache": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
+ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
+ "dev": true
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "ws": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz",
+ "integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw=="
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..453f9a2
--- /dev/null
+++ b/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "bili-live-comment-ws",
+ "version": "1.0.0",
+ "description": "",
+ "main": "main.js",
+ "scripts": {
+ "start": "node main.js"
+ },
+ "author": "shanmite",
+ "license": "ISC",
+ "dependencies": {
+ "ws": "^7.4.4"
+ },
+ "devDependencies": {
+ "eslint": "^7.23.0"
+ }
+}