完成重构,完成基本推送功能
parent
ac42f0fbdd
commit
de258bff73
@ -1,3 +1,4 @@
|
||||
config.yml
|
||||
subscribe.yml
|
||||
node_modules/
|
||||
package-lock.json
|
||||
dist/
|
||||
|
@ -1,31 +0,0 @@
|
||||
var Channel = require('./Channel');
|
||||
|
||||
class BroadcastChannel extends Channel {
|
||||
constructor(app){
|
||||
super(app, {});
|
||||
}
|
||||
|
||||
initialize(){
|
||||
this.channelName = 'broadcast';
|
||||
this.baseTemplate = '{{data.message}}';
|
||||
this.parseTemplate = this.buildTemplateCallback(this.baseTemplate);
|
||||
|
||||
this.initPush();
|
||||
}
|
||||
|
||||
onMessage(data){
|
||||
try {
|
||||
let finalMessage = this.parseMessage(data);
|
||||
if(data.target.group){
|
||||
this.app.robot.sendToGroup(data.target.group, finalMessage);
|
||||
}
|
||||
if(data.target.user){
|
||||
this.app.robot.sendToUser(data.target.group, finalMessage);
|
||||
}
|
||||
} catch(ex){
|
||||
console.log(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BroadcastChannel;
|
@ -1,101 +0,0 @@
|
||||
var utils = require('./Utils');
|
||||
|
||||
class Channel {
|
||||
constructor(app, data){
|
||||
this.app = app;
|
||||
|
||||
this.initialize(data);
|
||||
}
|
||||
|
||||
initialize(data){
|
||||
this.config = data;
|
||||
|
||||
this.channelName = data.channel;
|
||||
this.baseTemplates = data.templates;
|
||||
this.prepareFileList = data.files;
|
||||
this.receiver = data.receiver;
|
||||
|
||||
this.initPush();
|
||||
this.initTemplates();
|
||||
}
|
||||
|
||||
initPush(){
|
||||
this.channel = this.app.pusher.subscribe(this.channelName);
|
||||
this.channel.bind_global(this.onPush.bind(this));
|
||||
}
|
||||
|
||||
initTemplates(){
|
||||
this.template = {};
|
||||
for(let key in this.baseTemplates){
|
||||
let one = this.baseTemplates[key];
|
||||
this.template[key] = this.buildTemplateCallback(one);
|
||||
}
|
||||
}
|
||||
|
||||
initPrepareFileList(){
|
||||
this.prepareFileCallback = {};
|
||||
for(let key in this.prepareFileList){
|
||||
let one = this.prepareFileList[key];
|
||||
this.prepareFileCallback[key] = this.buildPrepareFileCallback(one);
|
||||
}
|
||||
}
|
||||
|
||||
destory(){
|
||||
this.app.pusher.unsubscribe(this.channelName);
|
||||
this.channel.unbind();
|
||||
}
|
||||
|
||||
parseTemplate(template){
|
||||
template = template.replace(/\\/g, "\\\\").replace(/\r\n/g, "\n").replace(/\n/g, "\\n").replace(/'/g, "\\'");
|
||||
if(template.indexOf('{{') == 0){ //开头是{{
|
||||
template = template.substr(2);
|
||||
} else {
|
||||
template = "'" + template;
|
||||
}
|
||||
|
||||
if(template.indexOf('}}') == template.length - 2){ //结尾是}}
|
||||
template = template.substr(0, template.length - 2);
|
||||
} else {
|
||||
template = template + "'";
|
||||
}
|
||||
|
||||
template = template.replace(/\{\{/g, "' + ").replace(/\}\}/g, " + '");
|
||||
return template;
|
||||
}
|
||||
|
||||
buildTemplateCallback(template){
|
||||
return eval('(function(data){ return ' + this.parseTemplate(template) + '; })').bind(this);
|
||||
}
|
||||
|
||||
buildPrepareFileCallback(cond){
|
||||
return eval('(function(data){ return ' + cond + '; })').bind(this);
|
||||
}
|
||||
|
||||
parseMessage(data){
|
||||
try {
|
||||
return this.parseTemplate(data);
|
||||
} catch(ex){
|
||||
return this.baseTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
onPush(channel, data){
|
||||
try {
|
||||
if(channel.indexOf('pusher:') == 0 || !this.template[channel]){
|
||||
return;
|
||||
}
|
||||
|
||||
let finalMessage = this.template[channel](data);
|
||||
if(this.receiver.group){
|
||||
this.app.robot.sendToGroup(this.receiver.group, finalMessage);
|
||||
}
|
||||
if(this.receiver.user){
|
||||
this.app.robot.sendToUser(this.receiver.user, finalMessage);
|
||||
}
|
||||
} catch(ex){
|
||||
console.log(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Channel;
|
@ -1,67 +0,0 @@
|
||||
const request = require('request-promise');
|
||||
|
||||
class QQRobot {
|
||||
constructor(config){
|
||||
this.endpoint = 'http://' + config.host;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送私聊消息
|
||||
* @param {int|int[]} user - QQ号
|
||||
* @param {string} message - 消息
|
||||
* @returns {Promise<void>} 回调
|
||||
*/
|
||||
sendToUser(user, message){
|
||||
if(Array.isArray(user)){ //发送给多个用户的处理
|
||||
let queue = [];
|
||||
user.forEach((one) => {
|
||||
queue.push(this.sendToUser(one, message));
|
||||
});
|
||||
return Promise.all(queue);
|
||||
}
|
||||
|
||||
return this.doApiRequest('send_private_msg', {
|
||||
user_id: user,
|
||||
message: message,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送群消息
|
||||
* @param {int|int[]} group - 群号
|
||||
* @param {string} message - 消息
|
||||
* @returns {Promise<void>} 回调
|
||||
*/
|
||||
sendToGroup(group, message){
|
||||
if(Array.isArray(group)){ //发送给多个用户的处理
|
||||
let queue = [];
|
||||
group.forEach((one) => {
|
||||
queue.push(this.sendToGroup(one, message));
|
||||
});
|
||||
return Promise.all(queue);
|
||||
}
|
||||
|
||||
return this.doApiRequest('send_group_msg', {
|
||||
group_id: group,
|
||||
message: message,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行酷Q的API调用
|
||||
* @param {string} method - 方法名
|
||||
* @param {any} data - 数据
|
||||
* @returns {Promise<void>} 回调
|
||||
*/
|
||||
doApiRequest(method, data){
|
||||
let opt = {
|
||||
method: 'POST',
|
||||
uri: this.endpoint + '/' + method,
|
||||
body: data,
|
||||
json: true,
|
||||
}
|
||||
return request(opt);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = QQRobot;
|
@ -1,17 +0,0 @@
|
||||
class Utils {
|
||||
static dictJoin(dict, d1 = ": ", d2 = "\n"){
|
||||
let lines = [];
|
||||
for(var key in dict){
|
||||
let value = dict[key];
|
||||
lines.push(key + d1 + value);
|
||||
}
|
||||
return lines.join(d2);
|
||||
}
|
||||
|
||||
static getCurrentDate(){
|
||||
let date = new Date();
|
||||
return date.getFullYear() + '年' + date.getMonth() + '月' + date.getDate() + '日';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Utils;
|
@ -1,8 +0,0 @@
|
||||
channel: "debug"
|
||||
templates:
|
||||
message: "{{data.message}}"
|
||||
receiver:
|
||||
group:
|
||||
- 11111111111
|
||||
user:
|
||||
- 11111111111
|
@ -1,12 +0,0 @@
|
||||
channel: "feed"
|
||||
files:
|
||||
thumb: "data.image"
|
||||
templates:
|
||||
thumb: "[CQ:image,file={{data.image}}]"
|
||||
feed: "{{utils.getCurrentDate()}}的异世界百科摘要:\n{{utils.dictJoin(data.feedList)}}"
|
||||
receiver:
|
||||
group:
|
||||
- 111111111
|
||||
- 111111111
|
||||
user:
|
||||
- 111111111
|
@ -0,0 +1 @@
|
||||
name: "异世界百科"
|
@ -0,0 +1 @@
|
||||
name: "管理信息"
|
@ -0,0 +1,11 @@
|
||||
name: 自动审核通过
|
||||
provider: pusher
|
||||
source:
|
||||
service: pusher
|
||||
channel: isekaiwiki
|
||||
type: autoReview
|
||||
tpl:
|
||||
default: |-
|
||||
{{data.author}} 更新了新页面: {{data.title}}
|
||||
{{data.summary}}
|
||||
{{data.result}}
|
@ -0,0 +1,11 @@
|
||||
name: 修改页面
|
||||
provider: pusher
|
||||
source:
|
||||
service: pusher
|
||||
channel: isekaiwiki
|
||||
type: edit
|
||||
tpl:
|
||||
default: |-
|
||||
{{data.author}} 更新了页面: {{data.title}}
|
||||
{{data.summary}}
|
||||
{{data.url}}
|
@ -0,0 +1,11 @@
|
||||
name: 新页面
|
||||
provider: pusher
|
||||
source:
|
||||
service: pusher
|
||||
channel: isekaiwiki
|
||||
type: new
|
||||
tpl:
|
||||
default: |-
|
||||
{{data.author}} 创建了新页面: {{data.title}}
|
||||
{{data.summary}}
|
||||
{{data.url}}
|
@ -1,10 +0,0 @@
|
||||
channel: "server_status"
|
||||
templates:
|
||||
disconnect: "{{data.srcName}} 与 {{data.dstName}} 的连接已断开"
|
||||
connect: "{{data.srcName}} 与 {{data.dstName}} 的连接已恢复"
|
||||
receiver:
|
||||
group:
|
||||
- 111111111
|
||||
- 111111111
|
||||
user:
|
||||
- 111111111
|
@ -1,37 +1,2 @@
|
||||
var fs = require('fs');
|
||||
|
||||
var Yaml = require('yaml');
|
||||
var QQRobot = require('./QQRobot');
|
||||
var ChannelManager = require('./ChannelManager');
|
||||
var Pusher = require('pusher-js');
|
||||
|
||||
class App {
|
||||
constructor(){
|
||||
this.config = Yaml.parse(fs.readFileSync('./config.yml', {encoding: 'utf-8'}));
|
||||
|
||||
this.initRobot();
|
||||
this.initPusher();
|
||||
this.initChannelManager();
|
||||
console.log('加载完成,正在接收消息');
|
||||
}
|
||||
|
||||
initRobot(){
|
||||
this.robot = new QQRobot(this.config.robot);
|
||||
}
|
||||
|
||||
initPusher(){
|
||||
this.pusher = new Pusher(this.config.pusher.key, {
|
||||
cluster: this.config.pusher.cluster,
|
||||
forceTLS: true,
|
||||
});
|
||||
if(this.config.debug){
|
||||
Pusher.logToConsole = true;
|
||||
}
|
||||
}
|
||||
|
||||
initChannelManager(){
|
||||
this.channels = new ChannelManager(this, this.config.channel_config_path);
|
||||
}
|
||||
}
|
||||
|
||||
new App();
|
||||
var App = require('./dist/App').default;
|
||||
new App(__dirname + "/config.yml");
|
@ -0,0 +1,909 @@
|
||||
{
|
||||
"name": "isekai-feedbot",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz",
|
||||
"integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
},
|
||||
"@cspotcode/source-map-consumer": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
|
||||
"integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==",
|
||||
"dev": true
|
||||
},
|
||||
"@cspotcode/source-map-support": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz",
|
||||
"integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@cspotcode/source-map-consumer": "0.8.0"
|
||||
}
|
||||
},
|
||||
"@tsconfig/node10": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz",
|
||||
"integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==",
|
||||
"dev": true
|
||||
},
|
||||
"@tsconfig/node12": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz",
|
||||
"integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==",
|
||||
"dev": true
|
||||
},
|
||||
"@tsconfig/node14": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz",
|
||||
"integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==",
|
||||
"dev": true
|
||||
},
|
||||
"@tsconfig/node16": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz",
|
||||
"integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/bluebird": {
|
||||
"version": "3.5.36",
|
||||
"resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.36.tgz",
|
||||
"integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/braces": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/braces/-/braces-3.0.1.tgz",
|
||||
"integrity": "sha512-+euflG6ygo4bn0JHtn4pYqcXwRtLvElQ7/nnjDu7iYG56H0+OhCd7d6Ug0IE3WcFpZozBKW2+80FUbv5QGk5AQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/caseless": {
|
||||
"version": "0.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz",
|
||||
"integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w=="
|
||||
},
|
||||
"@types/micromatch": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/micromatch/-/micromatch-4.0.2.tgz",
|
||||
"integrity": "sha512-oqXqVb0ci19GtH0vOA/U2TmHTcRY9kuZl4mqUxe0QmJAlIW13kzhuK5pi1i9+ngav8FjpSb9FVS/GE00GLX1VA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/braces": "*"
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "17.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.8.tgz",
|
||||
"integrity": "sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg=="
|
||||
},
|
||||
"@types/request": {
|
||||
"version": "2.48.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.4.tgz",
|
||||
"integrity": "sha512-W1t1MTKYR8PxICH+A4HgEIPuAC3sbljoEVfyZbeFJJDbr30guDspJri2XOaM2E+Un7ZjrihaDi7cf6fPa2tbgw==",
|
||||
"requires": {
|
||||
"@types/caseless": "*",
|
||||
"@types/node": "*",
|
||||
"@types/tough-cookie": "*",
|
||||
"form-data": "^2.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"form-data": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
|
||||
"integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/request-promise": {
|
||||
"version": "4.1.48",
|
||||
"resolved": "https://registry.npmjs.org/@types/request-promise/-/request-promise-4.1.48.tgz",
|
||||
"integrity": "sha512-sLsfxfwP5G3E3U64QXxKwA6ctsxZ7uKyl4I28pMj3JvV+ztWECRns73GL71KMOOJME5u1A5Vs5dkBqyiR1Zcnw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/bluebird": "*",
|
||||
"@types/request": "*"
|
||||
}
|
||||
},
|
||||
"@types/throttle-debounce": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/@types/throttle-debounce/download/@types/throttle-debounce-2.1.0.tgz",
|
||||
"integrity": "sha1-HD32JL/Eti+ZLTASuExW1B6rN3Y=",
|
||||
"dev": true
|
||||
},
|
||||
"@types/tough-cookie": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.0.tgz",
|
||||
"integrity": "sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A=="
|
||||
},
|
||||
"@types/yaml": {
|
||||
"version": "1.9.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz",
|
||||
"integrity": "sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"yaml": "*"
|
||||
}
|
||||
},
|
||||
"acorn": {
|
||||
"version": "8.7.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
|
||||
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
|
||||
"dev": true
|
||||
},
|
||||
"acorn-walk": {
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
|
||||
"integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
|
||||
"dev": true
|
||||
},
|
||||
"ajv": {
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz",
|
||||
"integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"anymatch": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npm.taobao.org/anymatch/download/anymatch-3.1.1.tgz",
|
||||
"integrity": "sha1-xV7PAhheJGklk5kxDBc84xIzsUI=",
|
||||
"requires": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
}
|
||||
},
|
||||
"arg": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
|
||||
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
|
||||
"dev": true
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
|
||||
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
|
||||
"requires": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz",
|
||||
"integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug=="
|
||||
},
|
||||
"bcrypt-pbkdf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
|
||||
"requires": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
},
|
||||
"binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npm.taobao.org/binary-extensions/download/binary-extensions-2.2.0.tgz?cache=0&sync_timestamp=1610299293319&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbinary-extensions%2Fdownload%2Fbinary-extensions-2.2.0.tgz",
|
||||
"integrity": "sha1-dfUC7q+f/eQvyYgpZFvk6na9ni0="
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
|
||||
},
|
||||
"braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npm.taobao.org/braces/download/braces-3.0.2.tgz",
|
||||
"integrity": "sha1-NFThpGLujVmeI23zNs2epPiv4Qc=",
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"call-bind": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.nlark.com/call-bind/download/call-bind-1.0.2.tgz",
|
||||
"integrity": "sha1-sdTonmiBGcPJqQOtMKuy9qkZvjw=",
|
||||
"requires": {
|
||||
"function-bind": "^1.1.1",
|
||||
"get-intrinsic": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
|
||||
},
|
||||
"chokidar": {
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npm.taobao.org/chokidar/download/chokidar-3.5.1.tgz?cache=0&sync_timestamp=1610719440699&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchokidar%2Fdownload%2Fchokidar-3.5.1.tgz",
|
||||
"integrity": "sha1-7pznu+vSt59J8wR5nVRo4x4U5oo=",
|
||||
"requires": {
|
||||
"anymatch": "~3.1.1",
|
||||
"braces": "~3.0.2",
|
||||
"fsevents": "~2.3.1",
|
||||
"glob-parent": "~5.1.0",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.5.0"
|
||||
}
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"create-require": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
||||
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"cron-parser": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.nlark.com/cron-parser/download/cron-parser-3.5.0.tgz",
|
||||
"integrity": "sha1-sanalRTAMQqn75nC8/HQ+MI1JXw=",
|
||||
"requires": {
|
||||
"is-nan": "^1.3.2",
|
||||
"luxon": "^1.26.0"
|
||||
}
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"debrief": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.nlark.com/debrief/download/debrief-1.5.0.tgz",
|
||||
"integrity": "sha1-nuMcTKumUc6Hw6KGxFXfJPmAP0k="
|
||||
},
|
||||
"decoders": {
|
||||
"version": "1.25.3",
|
||||
"resolved": "https://registry.nlark.com/decoders/download/decoders-1.25.3.tgz",
|
||||
"integrity": "sha1-amTZm8BdIlCk1AFOi2ikcpVpMeY=",
|
||||
"requires": {
|
||||
"debrief": "^1.5.0",
|
||||
"lemons": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"define-properties": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.nlark.com/define-properties/download/define-properties-1.1.3.tgz?cache=0&sync_timestamp=1618847174317&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdefine-properties%2Fdownload%2Fdefine-properties-1.1.3.tgz",
|
||||
"integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=",
|
||||
"requires": {
|
||||
"object-keys": "^1.0.12"
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
},
|
||||
"diff": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
|
||||
"dev": true
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
|
||||
"requires": {
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
|
||||
"integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA=="
|
||||
},
|
||||
"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=="
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npm.taobao.org/fill-range/download/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha1-GRmmp8df44ssfHflGYU12prN2kA=",
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-2.3.2.tgz?cache=0&sync_timestamp=1612537044236&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffsevents%2Fdownload%2Ffsevents-2.3.2.tgz",
|
||||
"integrity": "sha1-ilJveLj99GI7cJ4Ll1xSwkwC/Ro=",
|
||||
"optional": true
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.nlark.com/function-bind/download/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0="
|
||||
},
|
||||
"get-intrinsic": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.nlark.com/get-intrinsic/download/get-intrinsic-1.1.1.tgz",
|
||||
"integrity": "sha1-FfWfN2+FXERpY5SPDSTNNje0q8Y=",
|
||||
"requires": {
|
||||
"function-bind": "^1.1.1",
|
||||
"has": "^1.0.3",
|
||||
"has-symbols": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
|
||||
"requires": {
|
||||
"assert-plus": "^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==",
|
||||
"requires": {
|
||||
"is-glob": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.1.3",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
|
||||
"integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
|
||||
"requires": {
|
||||
"ajv": "^6.5.5",
|
||||
"har-schema": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.nlark.com/has/download/has-1.0.3.tgz",
|
||||
"integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=",
|
||||
"requires": {
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"has-symbols": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.nlark.com/has-symbols/download/has-symbols-1.0.2.tgz",
|
||||
"integrity": "sha1-Fl0wcMADCXUqEjakeTMeOsVvFCM="
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"jsprim": "^1.2.2",
|
||||
"sshpk": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"is-base64": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-base64/-/is-base64-1.1.0.tgz",
|
||||
"integrity": "sha512-Nlhg7Z2dVC4/PTvIFkgVVNvPHSO2eR/Yd0XzhGiXCXEvWnptXlXa/clQ8aePPiMuxEGcWfzWbGw2Fe3d+Y3v1g=="
|
||||
},
|
||||
"is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npm.taobao.org/is-binary-path/download/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha1-6h9/O4DwZCNug0cPhsCcJU+0Wwk=",
|
||||
"requires": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npm.taobao.org/is-extglob/download/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
|
||||
},
|
||||
"is-glob": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-4.0.1.tgz",
|
||||
"integrity": "sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw=",
|
||||
"requires": {
|
||||
"is-extglob": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"is-nan": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.nlark.com/is-nan/download/is-nan-1.3.2.tgz",
|
||||
"integrity": "sha1-BDpUreoxdItVts1OCara+mm9nh0=",
|
||||
"requires": {
|
||||
"call-bind": "^1.0.0",
|
||||
"define-properties": "^1.1.3"
|
||||
}
|
||||
},
|
||||
"is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npm.taobao.org/is-number/download/is-number-7.0.0.tgz",
|
||||
"integrity": "sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss="
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
|
||||
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
|
||||
},
|
||||
"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=="
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
|
||||
},
|
||||
"jsprim": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
|
||||
"integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"extsprintf": "1.3.0",
|
||||
"json-schema": "0.4.0",
|
||||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"lemons": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.nlark.com/lemons/download/lemons-1.6.0.tgz",
|
||||
"integrity": "sha1-ScGH4I+WdaHvPg8He0GSgFUx0b8="
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"long-timeout": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npm.taobao.org/long-timeout/download/long-timeout-0.1.1.tgz",
|
||||
"integrity": "sha1-lyHXiLR+C8taJMLivuGg2lXatRQ="
|
||||
},
|
||||
"lua-runner": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/lua-runner/download/lua-runner-2.0.3.tgz",
|
||||
"integrity": "sha1-GV+PYVhMioURjgHVE75k5THXCFk="
|
||||
},
|
||||
"luxon": {
|
||||
"version": "1.28.0",
|
||||
"resolved": "https://registry.nlark.com/luxon/download/luxon-1.28.0.tgz",
|
||||
"integrity": "sha1-5/ltqtOTjAamLeD7AnEV0lElH78="
|
||||
},
|
||||
"make-error": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
|
||||
"dev": true
|
||||
},
|
||||
"micromatch": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.nlark.com/micromatch/download/micromatch-4.0.4.tgz",
|
||||
"integrity": "sha1-iW1Rnf6dsl/OlM63pQCRm/iB6/k=",
|
||||
"requires": {
|
||||
"braces": "^3.0.1",
|
||||
"picomatch": "^2.2.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/picomatch/download/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.43.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
|
||||
"integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.26",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
|
||||
"integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
|
||||
"requires": {
|
||||
"mime-db": "1.43.0"
|
||||
}
|
||||
},
|
||||
"node-schedule": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npm.taobao.org/node-schedule/download/node-schedule-2.0.0.tgz",
|
||||
"integrity": "sha1-c6tJV9BWxjcIQJzB+rZ24OFJwZE=",
|
||||
"requires": {
|
||||
"cron-parser": "^3.1.0",
|
||||
"long-timeout": "0.1.1",
|
||||
"sorted-array-functions": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU="
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
|
||||
},
|
||||
"object-keys": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.nlark.com/object-keys/download/object-keys-1.1.1.tgz",
|
||||
"integrity": "sha1-HEfyct8nfzsdrwYWd9nILiMixg4="
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
},
|
||||
"picomatch": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npm.taobao.org/picomatch/download/picomatch-2.2.2.tgz",
|
||||
"integrity": "sha1-IfMz6ba46v8CRo9RRupAbTRfTa0="
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
|
||||
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
|
||||
},
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
},
|
||||
"pusher": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pusher/-/pusher-3.0.1.tgz",
|
||||
"integrity": "sha512-jrI4N33paSh1vsYvEJx7QmXbf/zeeHIeoEAREqj4i2jJdK5I2FxhS96DsRl8+iwBJcsnk6TMMbfIrDniAFs5AA==",
|
||||
"requires": {
|
||||
"@types/request": "^2.47.1",
|
||||
"is-base64": "^1.1.0",
|
||||
"request": "2.88.0",
|
||||
"tweetnacl": "^1.0.0",
|
||||
"tweetnacl-util": "^0.15.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"punycode": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
|
||||
},
|
||||
"request": {
|
||||
"version": "2.88.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
|
||||
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
|
||||
"requires": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.8.0",
|
||||
"caseless": "~0.12.0",
|
||||
"combined-stream": "~1.0.6",
|
||||
"extend": "~3.0.2",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~2.3.2",
|
||||
"har-validator": "~5.1.0",
|
||||
"http-signature": "~1.2.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.19",
|
||||
"oauth-sign": "~0.9.0",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.5.2",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"tough-cookie": "~2.4.3",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.3.2"
|
||||
}
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
|
||||
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
|
||||
"requires": {
|
||||
"psl": "^1.1.24",
|
||||
"punycode": "^1.4.1"
|
||||
}
|
||||
},
|
||||
"tweetnacl": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
|
||||
"integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"pusher-js": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/pusher-js/-/pusher-js-5.1.1.tgz",
|
||||
"integrity": "sha512-f2tdoA7NvJQkU8Y/iCH25ZSNGxnwCXrVbwos38isX6gnjsSZ1aksWvyZddm2N0sHJWyl+oPBz/MzU5cevVDyEQ=="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||
},
|
||||
"readdirp": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npm.taobao.org/readdirp/download/readdirp-3.5.0.tgz",
|
||||
"integrity": "sha1-m6dMAZsV02UnjS6Ru4xI17TULJ4=",
|
||||
"requires": {
|
||||
"picomatch": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.5",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
|
||||
"integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA=="
|
||||
},
|
||||
"request": {
|
||||
"version": "2.88.2",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
|
||||
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
|
||||
"requires": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.8.0",
|
||||
"caseless": "~0.12.0",
|
||||
"combined-stream": "~1.0.6",
|
||||
"extend": "~3.0.2",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~2.3.2",
|
||||
"har-validator": "~5.1.3",
|
||||
"http-signature": "~1.2.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.19",
|
||||
"oauth-sign": "~0.9.0",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.5.2",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"tough-cookie": "~2.5.0",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.3.2"
|
||||
}
|
||||
},
|
||||
"request-promise": {
|
||||
"version": "4.2.5",
|
||||
"resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.5.tgz",
|
||||
"integrity": "sha512-ZgnepCykFdmpq86fKGwqntyTiUrHycALuGggpyCZwMvGaZWgxW6yagT0FHkgo5LzYvOaCNvxYwWYIjevSH1EDg==",
|
||||
"requires": {
|
||||
"bluebird": "^3.5.0",
|
||||
"request-promise-core": "1.1.3",
|
||||
"stealthy-require": "^1.1.1",
|
||||
"tough-cookie": "^2.3.3"
|
||||
}
|
||||
},
|
||||
"request-promise-core": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz",
|
||||
"integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==",
|
||||
"requires": {
|
||||
"lodash": "^4.17.15"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
|
||||
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"sorted-array-functions": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npm.taobao.org/sorted-array-functions/download/sorted-array-functions-1.3.0.tgz",
|
||||
"integrity": "sha1-hgVpVWMpTf+yyXltYCvYRZ96DdU="
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
||||
"integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
|
||||
"requires": {
|
||||
"asn1": "~0.2.3",
|
||||
"assert-plus": "^1.0.0",
|
||||
"bcrypt-pbkdf": "^1.0.0",
|
||||
"dashdash": "^1.12.0",
|
||||
"ecc-jsbn": "~0.1.1",
|
||||
"getpass": "^0.1.1",
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.0.2",
|
||||
"tweetnacl": "~0.14.0"
|
||||
}
|
||||
},
|
||||
"stealthy-require": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
|
||||
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="
|
||||
},
|
||||
"throttle-debounce": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.nlark.com/throttle-debounce/download/throttle-debounce-3.0.1.tgz",
|
||||
"integrity": "sha1-MvlNhN+olPeGyaHykOemRbahmrs="
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ=",
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
|
||||
"requires": {
|
||||
"psl": "^1.1.28",
|
||||
"punycode": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"ts-node": {
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz",
|
||||
"integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@cspotcode/source-map-support": "0.7.0",
|
||||
"@tsconfig/node10": "^1.0.7",
|
||||
"@tsconfig/node12": "^1.0.7",
|
||||
"@tsconfig/node14": "^1.0.0",
|
||||
"@tsconfig/node16": "^1.0.2",
|
||||
"acorn": "^8.4.1",
|
||||
"acorn-walk": "^8.1.1",
|
||||
"arg": "^4.1.0",
|
||||
"create-require": "^1.1.0",
|
||||
"diff": "^4.0.1",
|
||||
"make-error": "^1.1.1",
|
||||
"yn": "3.1.1"
|
||||
}
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
|
||||
"requires": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
|
||||
},
|
||||
"tweetnacl-util": {
|
||||
"version": "0.15.1",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz",
|
||||
"integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw=="
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz",
|
||||
"integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==",
|
||||
"dev": true
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
|
||||
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
|
||||
"requires": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"yaml": {
|
||||
"version": "1.8.3",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.8.3.tgz",
|
||||
"integrity": "sha512-X/v7VDnK+sxbQ2Imq4Jt2PRUsRsP7UcpSl3Llg6+NRRqWLIvxkMFYtH1FmvwNGYRKKPa+EPA4qDBlI9WVG1UKw==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.8.7"
|
||||
}
|
||||
},
|
||||
"yn": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
|
||||
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
@ -1,18 +1,35 @@
|
||||
{
|
||||
"name": "isekai-pusher2coolq",
|
||||
"name": "isekai-feedbot",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"run": "node index.js"
|
||||
"start": "node index.js",
|
||||
"start-dev": "tsc && node index.js",
|
||||
"build": "tsc"
|
||||
},
|
||||
"author": "hyperzlib",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chokidar": "^3.5.1",
|
||||
"decoders": "^1.25.3",
|
||||
"lua-runner": "^2.0.3",
|
||||
"micromatch": "^4.0.4",
|
||||
"node-schedule": "^2.0.0",
|
||||
"pusher": "^3.0.1",
|
||||
"pusher-js": "^5.1.1",
|
||||
"request": "^2.88.2",
|
||||
"request-promise": "^4.2.5",
|
||||
"throttle-debounce": "^3.0.1",
|
||||
"yaml": "^1.8.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/micromatch": "^4.0.2",
|
||||
"@types/node": "^17.0.8",
|
||||
"@types/request-promise": "^4.1.48",
|
||||
"@types/throttle-debounce": "^2.1.0",
|
||||
"@types/yaml": "^1.9.7",
|
||||
"ts-node": "^10.4.0",
|
||||
"typescript": "^4.5.4"
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,19 @@
|
||||
var fs = require('fs');
|
||||
var Yaml = require('yaml');
|
||||
var Pusher = require('pusher');
|
||||
|
||||
var config = Yaml.parse(fs.readFileSync('../config.yml', {encoding: 'utf-8'}));
|
||||
|
||||
var pusher = new Pusher({
|
||||
appId: '',
|
||||
key: '',
|
||||
secret: '',
|
||||
cluster: ''
|
||||
appId: config.service.pusher.app_id,
|
||||
key: config.service.pusher.key,
|
||||
secret: config.service.pusher.secret,
|
||||
cluster: config.service.pusher.cluster
|
||||
});
|
||||
|
||||
pusher.trigger('debug', 'message', {"message": "Isekai Puser远端推送测试 (二周目)"});
|
||||
pusher.trigger('isekai', 'newPage', {
|
||||
author: "Hyperzlib",
|
||||
title: "沙盒",
|
||||
summary: "机器人应该可以用了",
|
||||
url: "https://www.isekai.cn/ShaHe"
|
||||
});
|
||||
|
@ -0,0 +1,105 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import Yaml from 'yaml';
|
||||
import { BaseProvider, MultipleMessage } from './base/provider/BaseProvider';
|
||||
|
||||
import { ChannelManager } from './ChannelManager';
|
||||
import { ChannelConfig, Config } from './Config';
|
||||
import { ProviderManager } from './ProviderManager';
|
||||
import { RobotManager } from './RobotManager';
|
||||
import { Service, ServiceManager } from './ServiceManager';
|
||||
import { SubscribeManager, Target } from './SubscribeManager';
|
||||
|
||||
export default class App {
|
||||
public config: Config;
|
||||
public srcPath: string = __dirname;
|
||||
|
||||
public robot!: RobotManager;
|
||||
public provider!: ProviderManager;
|
||||
public service!: ServiceManager;
|
||||
public subscribe!: SubscribeManager;
|
||||
public channel!: ChannelManager;
|
||||
|
||||
constructor(configFile: string) {
|
||||
this.config = Yaml.parse(fs.readFileSync(configFile, { encoding: 'utf-8' }));
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
await this.initRobot();
|
||||
await this.initProviderManager();
|
||||
await this.initServiceManager();
|
||||
await this.initSubscribeManager();
|
||||
await this.initChannelManager();
|
||||
console.log('初始化完成,正在接收消息');
|
||||
}
|
||||
|
||||
async initRobot() {
|
||||
this.robot = new RobotManager(this, this.config.robot);
|
||||
await this.robot.initialize();
|
||||
}
|
||||
|
||||
async initProviderManager() {
|
||||
this.provider = new ProviderManager(this);
|
||||
await this.provider.initialize();
|
||||
}
|
||||
|
||||
async initServiceManager() {
|
||||
this.service = new ServiceManager(this, this.config.service);
|
||||
await this.service.initialize();
|
||||
}
|
||||
|
||||
async initSubscribeManager() {
|
||||
this.subscribe = new SubscribeManager(this, this.config.subscribe_config);
|
||||
await this.subscribe.initialize();
|
||||
}
|
||||
|
||||
async initCommandManager() {
|
||||
|
||||
}
|
||||
|
||||
async initChannelManager() {
|
||||
this.channel = new ChannelManager(this, this.config.channel_config_path);
|
||||
|
||||
this.channel.on('add', (channelId) => {
|
||||
this.subscribe.addChannel(channelId);
|
||||
});
|
||||
this.channel.on('remove', (channelId) => {
|
||||
this.subscribe.removeChannel(channelId);
|
||||
});
|
||||
|
||||
await this.channel.initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务
|
||||
* @param serviceName
|
||||
* @returns
|
||||
*/
|
||||
getService<T extends Service>(serviceName: string): T {
|
||||
return this.service.get<T>(serviceName);
|
||||
}
|
||||
|
||||
createChannel(provider: string, channelId: string, config: ChannelConfig): BaseProvider | null {
|
||||
return this.provider.create(provider, channelId, config);
|
||||
}
|
||||
|
||||
getSubscriber(channelId: string, robotId: string): Target[] | null {
|
||||
return this.subscribe.getSubscriber(channelId, robotId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
* @param channelId Channel ID
|
||||
* @param messages 消息内容
|
||||
* @returns
|
||||
*/
|
||||
async sendMessage(channelId: string, messages: MultipleMessage): Promise<void> {
|
||||
console.log(`[${channelId}] 消息: `, messages);
|
||||
this.robot.sendMessage(channelId, messages);
|
||||
}
|
||||
|
||||
require(file: string): any {
|
||||
return require(path.join(this.srcPath, file));
|
||||
}
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import Yaml from 'yaml';
|
||||
import chokidar from 'chokidar';
|
||||
import { debounce } from 'throttle-debounce';
|
||||
import EventEmitter from 'events';
|
||||
|
||||
import App from './App';
|
||||
import { BaseProvider } from './base/provider/BaseProvider';
|
||||
import { ChannelConfig } from './Config';
|
||||
|
||||
export class ChannelManager extends EventEmitter {
|
||||
private app: App;
|
||||
private channelPath: string;
|
||||
private loadChannelCallback: (file: string) => any;
|
||||
private removeChannelCallback: (file: string) => any;
|
||||
private setLoading?: debounce<Function>;
|
||||
private watcher!: chokidar.FSWatcher;
|
||||
|
||||
public channels: { [key: string]: BaseProvider };
|
||||
public channelName: { [key: string]: string };
|
||||
|
||||
constructor(app: App, channelPath: string) {
|
||||
super();
|
||||
|
||||
this.app = app;
|
||||
this.channelPath = channelPath;
|
||||
this.channels = {};
|
||||
this.channelName = {};
|
||||
|
||||
this.loadChannelCallback = this.loadChannel.bind(this);
|
||||
this.removeChannelCallback = this.removeChannel.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载所有Channel
|
||||
*/
|
||||
async initialize() {
|
||||
this.watcher = chokidar.watch(this.channelPath, {
|
||||
ignored: '*.bak',
|
||||
ignorePermissionErrors: true,
|
||||
persistent: true
|
||||
});
|
||||
|
||||
this.watcher.on('add', this.loadChannelCallback);
|
||||
this.watcher.on('change', this.loadChannelCallback);
|
||||
this.watcher.on('unlink', this.removeChannelCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Channel ID
|
||||
* @param {string} file - channel config file
|
||||
* @returns
|
||||
*/
|
||||
getChannelId(file: string): string {
|
||||
let channelPath = path.relative(this.channelPath, file).replace(/\\/g, "/").replace(/\..*?$/, "");
|
||||
return channelPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Channel的全名
|
||||
* @param {string} channelId - channel ID
|
||||
*/
|
||||
getChannelFullName(channelId: string): string {
|
||||
// 从最顶层开始查找
|
||||
let pathList = channelId.split("/");
|
||||
let nameList: string[] = [];
|
||||
for (let i = 0; i < pathList.length; i++) {
|
||||
let currentPath = pathList.slice(0, i + 1).join("/");
|
||||
console.log(currentPath);
|
||||
let findedName = this.channelName[currentPath];
|
||||
if (findedName) {
|
||||
nameList.push(findedName);
|
||||
} else {
|
||||
nameList.push(pathList[i]);
|
||||
}
|
||||
}
|
||||
return nameList.join("/");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Provider名
|
||||
* @param config
|
||||
* @returns
|
||||
*/
|
||||
getProviderName(config: ChannelConfig): string {
|
||||
return config.provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取或更新Channel配置文件
|
||||
* @param {string} file
|
||||
*/
|
||||
async loadChannel(file: string) {
|
||||
try {
|
||||
let content = await fs.readFile(file, { encoding: 'utf-8' });
|
||||
let config = Yaml.parse(content);
|
||||
let channelId = this.getChannelId(file);
|
||||
if (path.basename(channelId) === "_group") {
|
||||
// 只是group标记
|
||||
channelId = path.dirname(channelId);
|
||||
this.channelName[channelId] = config?.name;
|
||||
} else {
|
||||
if (BaseProvider.checkConfig(config)) {
|
||||
// console.log(`正在加载Channel: ${channelId}`);
|
||||
// 处理channel
|
||||
let providerName = this.getProviderName(config);
|
||||
let isReload = false;
|
||||
if (channelId in this.channels) {
|
||||
// 重载配置
|
||||
isReload = true;
|
||||
await this.channels[channelId].destory();
|
||||
}
|
||||
// 读取配置
|
||||
let channel = this.app.createChannel(providerName, channelId, config);
|
||||
if (channel) {
|
||||
await channel.initialize();
|
||||
// 更新列表
|
||||
this.channels[channelId] = channel;
|
||||
this.channelName[channelId] = config?.name;
|
||||
if (isReload) {
|
||||
this.emit('reload', channelId);
|
||||
console.log(`已重载Channel: ${channelId}`);
|
||||
} else {
|
||||
this.emit('add', channelId);
|
||||
console.log(`已加载Channel: ${channelId}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.error(`配置文件: ${file} 格式错误`);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除Channel
|
||||
* @param {string} file
|
||||
*/
|
||||
async removeChannel(file: string) {
|
||||
let channelId = this.getChannelId(file);
|
||||
if (path.basename(channelId) === "_group") {
|
||||
// 仅删除组名
|
||||
channelId = path.basename(channelId);
|
||||
delete this.channelName[channelId];
|
||||
} else {
|
||||
let channel = this.channels[channelId];
|
||||
if (channel) {
|
||||
await channel.destory();
|
||||
delete this.channels[channelId];
|
||||
delete this.channelName[channelId];
|
||||
this.emit('remove', channelId);
|
||||
console.log("已移除Channel: ", this.getChannelFullName(channelId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onLoad() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { JsonFilterConfig } from "./generator/JsonFilter";
|
||||
import { RegexFilterConfig } from "./generator/RegexFilter";
|
||||
|
||||
export type Config = {
|
||||
channel_config_path: string;
|
||||
subscribe_config: string;
|
||||
debug: boolean;
|
||||
robot: { [key: string]: RobotConfig };
|
||||
service: { [key: string]: ServiceConfig };
|
||||
};
|
||||
|
||||
export type RobotConfig = {
|
||||
type: string;
|
||||
baseId: string;
|
||||
};
|
||||
|
||||
export type ServiceConfig = { [name: string]: any };
|
||||
|
||||
export type ChannelConfig = any;
|
||||
|
||||
export type GeneratorConfig = {
|
||||
json: JsonFilterConfig;
|
||||
match: RegexFilterConfig;
|
||||
tpl: any;
|
||||
};
|
@ -0,0 +1,52 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import App from './App';
|
||||
import { BaseProvider } from './base/provider/BaseProvider';
|
||||
import { ChannelConfig } from './Config';
|
||||
|
||||
const PROVIDER_PATH = __dirname + "/provider";
|
||||
|
||||
export class ProviderManager {
|
||||
private app: App;
|
||||
private providerClasses: { [key: string]: any }
|
||||
|
||||
constructor(app: App) {
|
||||
this.app = app;
|
||||
this.providerClasses = {};
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
for (let file of fs.readdirSync(PROVIDER_PATH)) {
|
||||
let providerFile = `${PROVIDER_PATH}/${file}`;
|
||||
if (providerFile.match(/\.(js|mjs)$/)) {
|
||||
// 加载js文件
|
||||
let providerName = path.basename(providerFile).replace(/Provider\.(js|mjs)$/gi, "").toLocaleLowerCase();
|
||||
try {
|
||||
let provider = require(providerFile)?.default;
|
||||
if (!provider) {
|
||||
throw new Error("provider is empty");
|
||||
}
|
||||
this.providerClasses[providerName] = provider;
|
||||
console.log(`已加载Provider: ${providerName}`);
|
||||
} catch(err) {
|
||||
console.log(`无法加载Provider: ${providerName}`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Provider
|
||||
* @param {string} providerName
|
||||
* @param {any} config
|
||||
*/
|
||||
create(providerName: string, channelId: string, config: ChannelConfig): BaseProvider | null {
|
||||
providerName = providerName.toLocaleLowerCase();
|
||||
if (providerName in this.providerClasses) {
|
||||
let CurrentProvider: any = this.providerClasses[providerName];
|
||||
return new CurrentProvider(this.app, channelId, config);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
import App from "./App";
|
||||
import { MultipleMessage } from "./base/provider/BaseProvider";
|
||||
import { RobotConfig } from "./Config";
|
||||
import { Target } from "./SubscribeManager";
|
||||
|
||||
const ROBOT_PATH = __dirname + "/robot";
|
||||
|
||||
export interface Robot {
|
||||
initialize(): Promise<void>;
|
||||
sendMessage(targets: Target[], message: string): Promise<void>;
|
||||
baseId?: string;
|
||||
}
|
||||
|
||||
export class RobotManager {
|
||||
private app: App;
|
||||
private config: { [key: string]: RobotConfig };
|
||||
|
||||
private robotClasses: { [key: string]: any };
|
||||
private robots: { [key: string]: Robot };
|
||||
|
||||
constructor(app: App, config: { [key: string]: RobotConfig }) {
|
||||
this.app = app;
|
||||
this.config = config;
|
||||
|
||||
this.robotClasses = {};
|
||||
this.robots = {};
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
for (let file of fs.readdirSync(ROBOT_PATH)) {
|
||||
let robotFile = `${ROBOT_PATH}/${file}`;
|
||||
if (robotFile.match(/\.(js|mjs)$/)) {
|
||||
// 加载js文件
|
||||
let robotName = path.basename(robotFile).replace(/Robot\.(js|mjs)$/gi, "").toLocaleLowerCase();
|
||||
try {
|
||||
let robotClass = require(robotFile)?.default;
|
||||
if (!robotClass) {
|
||||
throw new Error("robot api is empty");
|
||||
}
|
||||
this.robotClasses[robotName] = robotClass;
|
||||
} catch(err) {
|
||||
console.log(`无法加载Robot API: ${robotName}`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let robotId in this.config) {
|
||||
let robotConfig = this.config[robotId];
|
||||
let robotType: string = robotConfig.type;
|
||||
if (!robotType) {
|
||||
console.error("无法加载 " + robotId + " Robot: 配置文件中未定义 'type'");
|
||||
continue;
|
||||
}
|
||||
robotType = robotType.toLocaleLowerCase();
|
||||
if (robotType in this.robotClasses) {
|
||||
let robotClass = this.robotClasses[robotType];
|
||||
try {
|
||||
let robotObject: Robot = new robotClass(this.app, robotId, robotConfig);
|
||||
await robotObject.initialize();
|
||||
this.robots[robotId] = robotObject;
|
||||
console.log(`已加载Robot: ${robotId}`);
|
||||
} catch(err) {
|
||||
console.error(`无法加载 ${robotId} Robot: `, err);
|
||||
}
|
||||
} else {
|
||||
console.error(`无法加载 ${robotId} Robot: Robot不存在`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async sendMessage(channelId: string, messages: MultipleMessage) {
|
||||
for (let robotId in this.robots) {
|
||||
let robot = this.robots[robotId];
|
||||
let baseId = robot.baseId;
|
||||
let currentMsg: string | null = null;
|
||||
if (robotId in messages) {
|
||||
currentMsg = messages[robotId];
|
||||
} else if (baseId && baseId in messages) {
|
||||
currentMsg = messages[baseId];
|
||||
} else if ("base" in messages) {
|
||||
currentMsg = messages["base"];
|
||||
}
|
||||
if (!currentMsg) { // 未找到消息
|
||||
continue;
|
||||
}
|
||||
|
||||
let targets = this.app.getSubscriber(channelId, robotId);
|
||||
if (!targets) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
robot.sendMessage(targets, currentMsg);
|
||||
} catch(err) {
|
||||
console.error(`[${channelId}] 无法发送消息到 ${robotId} : `, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
import App from './App';
|
||||
import { ServiceConfig } from './Config';
|
||||
|
||||
const SERVICE_PATH = __dirname + "/service";
|
||||
|
||||
export interface Service {
|
||||
initialize(): Promise<void>;
|
||||
destory(): Promise<void>;
|
||||
}
|
||||
|
||||
export class ServiceNotExistsError extends Error {
|
||||
public serviceName: string;
|
||||
|
||||
constructor(message: string, serviceName: string) {
|
||||
super(message);
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
}
|
||||
|
||||
export class ServiceManager {
|
||||
private app: App;
|
||||
private config: ServiceConfig;
|
||||
|
||||
public serviceClasses: { [key: string]: any };
|
||||
public services: { [key: string]: Service };
|
||||
|
||||
constructor(app: App, config: ServiceConfig) {
|
||||
this.app = app;
|
||||
this.config = config;
|
||||
|
||||
this.serviceClasses = {};
|
||||
this.services = {};
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
for (let file of fs.readdirSync(SERVICE_PATH)) {
|
||||
let serviceFile = `${SERVICE_PATH}/${file}`;
|
||||
if (serviceFile.match(/\.(js|mjs)$/)) {
|
||||
// 加载js文件
|
||||
let serviceName = path.basename(serviceFile).replace(/Service\.(js|mjs)$/gi, "").toLocaleLowerCase();
|
||||
try {
|
||||
let serviceClass = require(serviceFile)?.default;
|
||||
if (!serviceClass) {
|
||||
throw new Error("service is empty");
|
||||
}
|
||||
this.serviceClasses[serviceName] = serviceClass;
|
||||
} catch(err) {
|
||||
console.log(`无法加载Service: ${serviceName}`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let serviceName in this.config) {
|
||||
let serviceConfig = this.config[serviceName];
|
||||
let serviceType: string = serviceConfig.type;
|
||||
if (!serviceType) {
|
||||
console.error(`无法加载 ${serviceName} Service: 配置文件中未定义 'type'`);
|
||||
continue;
|
||||
}
|
||||
serviceType = serviceType.toLocaleLowerCase();
|
||||
if (serviceType in this.serviceClasses) {
|
||||
let serviceClass = this.serviceClasses[serviceType];
|
||||
try {
|
||||
let serviceObject: Service = new serviceClass(this.app, serviceConfig);
|
||||
await serviceObject.initialize();
|
||||
this.services[serviceName] = serviceObject;
|
||||
console.log(`已加载Service: ${serviceName}`);
|
||||
} catch(err) {
|
||||
console.error(`无法加载 ${serviceName} Service: `, err);
|
||||
}
|
||||
} else {
|
||||
console.error(`无法加载 ${serviceName} Service: Service 不存在`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get<T extends Service>(name: string): T {
|
||||
if (name in this.services) {
|
||||
return this.services[name] as T;
|
||||
} else {
|
||||
throw new ServiceNotExistsError(`Service ${name} not exists`, name);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
import fs from "fs";
|
||||
import Yaml from "yaml";
|
||||
import micromatch from "micromatch";
|
||||
import chokidar from 'chokidar';
|
||||
|
||||
import App from "./App";
|
||||
|
||||
export interface Target {
|
||||
type: string;
|
||||
identity: string;
|
||||
}
|
||||
|
||||
export class SubscribeManager {
|
||||
private app: App;
|
||||
private subscribeFile: string;
|
||||
private watcher!: chokidar.FSWatcher;
|
||||
private subscribeList: {
|
||||
[channelId: string]: {
|
||||
[robotId: string]: Target[]
|
||||
}
|
||||
};
|
||||
|
||||
private subscribeConfig: {
|
||||
[robotId: string]: {
|
||||
[targetType: string]: {
|
||||
[targetIdentity: string]: string[]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
constructor(app: App, subscribeFile: string) {
|
||||
this.app = app;
|
||||
this.subscribeFile = subscribeFile;
|
||||
this.subscribeList = {};
|
||||
this.subscribeConfig = {};
|
||||
|
||||
this.loadSubscribeFile();
|
||||
}
|
||||
|
||||
public async initialize() {
|
||||
this.watcher = chokidar.watch(this.subscribeFile, {
|
||||
ignorePermissionErrors: true,
|
||||
persistent: true
|
||||
});
|
||||
|
||||
this.watcher.on('change', () => {
|
||||
this.reloadSubscribeFile();
|
||||
});
|
||||
}
|
||||
|
||||
private loadSubscribeFile() {
|
||||
this.subscribeConfig = Yaml.parse(fs.readFileSync(this.subscribeFile, { encoding: 'utf-8' }));
|
||||
}
|
||||
|
||||
private reloadSubscribeFile() {
|
||||
this.loadSubscribeFile();
|
||||
this.subscribeList = {};
|
||||
for (let channelId in this.app.channel.channels) {
|
||||
this.addChannel(channelId);
|
||||
}
|
||||
console.log('已重载Subscribe');
|
||||
}
|
||||
|
||||
public addChannel(channelId: string) {
|
||||
this.subscribeList[channelId] = {};
|
||||
for (let robotId in this.subscribeConfig) {
|
||||
let targetConf = this.subscribeConfig[robotId];
|
||||
let matchedTargetList: Target[] = [];
|
||||
for (let targetType in targetConf) {
|
||||
let targetList = targetConf[targetType];
|
||||
for (let targetIdentity in targetList) {
|
||||
let matchList = targetList[targetIdentity];
|
||||
if (micromatch.isMatch(channelId, matchList)) {
|
||||
matchedTargetList.push({
|
||||
type: targetType,
|
||||
identity: targetIdentity
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
this.subscribeList[channelId][robotId] = matchedTargetList;
|
||||
}
|
||||
}
|
||||
|
||||
public removeChannel(channelId: string) {
|
||||
delete this.subscribeList[channelId];
|
||||
}
|
||||
|
||||
public getSubscriber(channelId: string, robotId: string): Target[] | null {
|
||||
if (channelId in this.subscribeList && robotId in this.subscribeList[channelId]) {
|
||||
return this.subscribeList[channelId][robotId];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
export class Utils {
|
||||
static dictJoin(dict: { [key: string]: any }, d1: string = ": ", d2: string = "\n"): string {
|
||||
let lines: string[] = [];
|
||||
for(var key in dict){
|
||||
let value = dict[key];
|
||||
lines.push(key + d1 + value);
|
||||
}
|
||||
return lines.join(d2);
|
||||
}
|
||||
|
||||
static getCurrentDate(): string {
|
||||
let date = new Date();
|
||||
return date.getFullYear() + '年' + date.getMonth() + '月' + date.getDate() + '日';
|
||||
}
|
||||
|
||||
static count(dict: { [key: string]: any }): number {
|
||||
try {
|
||||
return Object.keys(dict).length;
|
||||
} catch(e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static sleep(time: number): Promise<void> {
|
||||
return new Promise((resolve) => {
|
||||
let tid = setTimeout(() => {
|
||||
resolve();
|
||||
clearTimeout(tid);
|
||||
}, time);
|
||||
});
|
||||
}
|
||||
|
||||
static excerpt(text: string, maxLength: number, ellipsis: string = '……'): string {
|
||||
if (text.length > maxLength) {
|
||||
return text.substring(0, maxLength) + ellipsis;
|
||||
} else {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
export class BaseRobot {
|
||||
|
||||
}
|
@ -0,0 +1 @@
|
||||
export class ConfigCheckError extends Error { }
|
@ -0,0 +1,75 @@
|
||||
import App from "../App";
|
||||
import { MultipleMessage } from "../base/provider/BaseProvider";
|
||||
import { GeneratorConfig } from "../Config";
|
||||
import { JsonFilter } from "./JsonFilter";
|
||||
import { RegexFilter } from "./RegexFilter";
|
||||
import { TemplateFilter } from "./TemplateFilter";
|
||||
|
||||
export interface MessageFilter {
|
||||
initialize(): Promise<void>;
|
||||
destory(): Promise<void>;
|
||||
parse(data: any): Promise<MultipleMessage | null>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于给推送生成文本内容
|
||||
*/
|
||||
export class Generator {
|
||||
private app: App;
|
||||
private config: GeneratorConfig;
|
||||
private filters: MessageFilter[];
|
||||
|
||||
constructor(app: App, config: GeneratorConfig) {
|
||||
this.app = app;
|
||||
this.config = config;
|
||||
this.filters = [];
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
let filter: MessageFilter;
|
||||
// 解析下载的json
|
||||
if ('json' in this.config && this.config.json) {
|
||||
filter = new JsonFilter(this.app, this.config.json);
|
||||
await filter.initialize();
|
||||
this.filters.push(filter);
|
||||
}
|
||||
// 正则匹配内容,用于提取字符串内容
|
||||
if ('match' in this.config) {
|
||||
filter = new RegexFilter(this.app, this.config.match);
|
||||
await filter.initialize();
|
||||
this.filters.push(filter);
|
||||
}
|
||||
// 通过模板生成最终文本
|
||||
if ('tpl' in this.config) {
|
||||
filter = new TemplateFilter(this.app, this.config.tpl);
|
||||
await filter.initialize();
|
||||
this.filters.push(filter);
|
||||
}
|
||||
}
|
||||
|
||||
async destory() {
|
||||
for (let i = 0; i < this.filters.length; i ++) {
|
||||
let filter = this.filters[i];
|
||||
try {
|
||||
await filter.destory();
|
||||
delete this.filters[i];
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成模板
|
||||
*/
|
||||
async generate(data: any): Promise<MultipleMessage> {
|
||||
let retData = data;
|
||||
for (let filter of this.filters) {
|
||||
let newData = await filter.parse(retData);
|
||||
if (newData) {
|
||||
retData = newData;
|
||||
}
|
||||
}
|
||||
return retData;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
import App from "../App";
|
||||
import { MultipleMessage } from "../base/provider/BaseProvider";
|
||||
import { MessageFilter } from "./Generator";
|
||||
|
||||
export type JsonFilterConfig = string[];
|
||||
|
||||
export class JsonFilter implements MessageFilter {
|
||||
private app: App;
|
||||
private config: JsonFilterConfig;
|
||||
private keys!: string[];
|
||||
|
||||
constructor(app: App, config: JsonFilterConfig) {
|
||||
/** @type {App} */
|
||||
this.app = app;
|
||||
|
||||
/** @type {string[]} */
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
this.keys = this.config;
|
||||
}
|
||||
|
||||
async destory() {
|
||||
|
||||
}
|
||||
|
||||
async parse(data: any): Promise<MultipleMessage> {
|
||||
for (let key of this.keys) {
|
||||
if (key in data && typeof data[key] === "string"){
|
||||
data[key] = JSON.parse(data[key]);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
import App from "../App";
|
||||
import { MultipleMessage } from "../base/provider/BaseProvider";
|
||||
import { MessageFilter } from "./Generator";
|
||||
|
||||
export type LuaFilterConfig = {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用Lua过滤信息
|
||||
*/
|
||||
export class LuaFilter implements MessageFilter {
|
||||
private app: App;
|
||||
private config: LuaFilterConfig;
|
||||
|
||||
constructor(app: App, config: LuaFilterConfig) {
|
||||
this.app = app;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
|
||||
}
|
||||
|
||||
async destory() {
|
||||
|
||||
}
|
||||
|
||||
async parse(data: any): Promise<MultipleMessage | null> {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
import App from "../App";
|
||||
import { MultipleMessage } from "../base/provider/BaseProvider";
|
||||
import { MessageFilter } from "./Generator";
|
||||
|
||||
export type RegexFilterConfig = { [key: string]: string | string[] };
|
||||
|
||||
export class RegexFilter implements MessageFilter {
|
||||
private app: App;
|
||||
private config: RegexFilterConfig;
|
||||
private regexList: { [key: string]: RegExp[] };
|
||||
|
||||
constructor(app: App, config: RegexFilterConfig) {
|
||||
this.app = app;
|
||||
this.config = config;
|
||||
this.regexList = {};
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
for (let key in this.config) {
|
||||
let patternList = this.config[key];
|
||||
if (typeof patternList === "string") {
|
||||
patternList = [patternList];
|
||||
}
|
||||
let regexList: RegExp[] = [];
|
||||
patternList.forEach((one) => {
|
||||
regexList.push(new RegExp(one));
|
||||
});
|
||||
this.regexList[key] = regexList;
|
||||
}
|
||||
}
|
||||
|
||||
async destory() {
|
||||
|
||||
}
|
||||
|
||||
async parse(data: any): Promise<MultipleMessage> {
|
||||
for (let key in this.regexList) {
|
||||
if (typeof data[key] !== "string") continue;
|
||||
let str: string = data[key];
|
||||
let matchedGroup: { [key: string]: string } = {};
|
||||
let regexList = this.regexList[key];
|
||||
for (let regex of regexList) {
|
||||
let matches = str.match(regex);
|
||||
if (matches?.groups) {
|
||||
matchedGroup = { ...matchedGroup, ...matches.groups };
|
||||
}
|
||||
}
|
||||
data[key] = matchedGroup;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
import App from "../App";
|
||||
import { MultipleMessage } from "../base/provider/BaseProvider";
|
||||
import { ConfigCheckError } from "../error/ConfigCheckError";
|
||||
|
||||
// 请勿删除这些没有使用的导入,模板中会用到
|
||||
const { Utils } = require('../Utils');
|
||||
|
||||
export type TemplateFilterConfig = { [key: string]: string };
|
||||
export type TemplateRenderFunction = (data: any) => string;
|
||||
|
||||
export class TemplateFilter {
|
||||
private app: App;
|
||||
private config: TemplateFilterConfig;
|
||||
private renderFunctionList: { [target: string]: TemplateRenderFunction };
|
||||
|
||||
constructor(app: App, config: TemplateFilterConfig) {
|
||||
this.app = app;
|
||||
this.config = config;
|
||||
this.renderFunctionList = {};
|
||||
|
||||
this.checkConfig();
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
for (let key in this.config) {
|
||||
let template = this.config[key];
|
||||
if (key === "default") {
|
||||
key = "base";
|
||||
}
|
||||
if (typeof template === "string") {
|
||||
this.renderFunctionList[key] = this.buildTemplateCallback(template);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async destory() {
|
||||
for (let key in this.renderFunctionList){
|
||||
delete this.renderFunctionList[key];
|
||||
}
|
||||
}
|
||||
|
||||
checkConfig() {
|
||||
if (!('base' in this.config) && !('default' in this.config)) {
|
||||
throw new ConfigCheckError('Unset template.base or template.default');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析模板
|
||||
*/
|
||||
parseTemplate(template: string): string {
|
||||
template = template.replace(/\\/g, "\\\\").replace(/\r\n/g, "\n").replace(/\n/g, "\\n").replace(/'/g, "\\'");
|
||||
template = template.replace(/\{\{(.*?)\}\}/g, (str, token) => {
|
||||
if (token) {
|
||||
return "' + (" + (token.replace(/\\'/g, "'")) + ") + '";
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
});
|
||||
|
||||
if(template.indexOf("' + (") == 0){ //开头是{{
|
||||
template = template.substr(4);
|
||||
} else {
|
||||
template = "'" + template;
|
||||
}
|
||||
|
||||
if(template.lastIndexOf(") + '") == template.length - 5){ //结尾是}}
|
||||
template = template.substr(0, template.length - 4);
|
||||
} else {
|
||||
template = template + "'";
|
||||
}
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建callback
|
||||
* @param {string} template
|
||||
* @returns {Function}
|
||||
*/
|
||||
buildTemplateCallback(template: string): TemplateRenderFunction {
|
||||
const renderTpl = eval('(function(){ return ' + this.parseTemplate(template) + '; })')
|
||||
return (data: any): string => {
|
||||
let overridedKeys: string[] = [];
|
||||
for (let key in data) {
|
||||
if (!(key in global)) {
|
||||
overridedKeys.push(key);
|
||||
(global as any)[key] = data[key];
|
||||
}
|
||||
}
|
||||
let result = renderTpl();
|
||||
for (let key of overridedKeys) {
|
||||
delete (global as any)[key];
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
async parse(data: any): Promise<MultipleMessage | null> {
|
||||
let result: MultipleMessage = {};
|
||||
for (let target in this.renderFunctionList) {
|
||||
let renderFunction = this.renderFunctionList[target];
|
||||
result[target] = renderFunction(data);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
declare module 'yaml';
|
@ -0,0 +1,82 @@
|
||||
import App from "../App";
|
||||
import { BaseProvider, MultipleMessage } from "../base/provider/BaseProvider";
|
||||
import { ChannelConfig } from "../Config";
|
||||
import { ConfigCheckError } from "../error/ConfigCheckError";
|
||||
import PusherService from "../service/PusherService";
|
||||
|
||||
const { string, optional, object, guard } = require("decoders");
|
||||
|
||||
export type PusherProviderConfig = {
|
||||
source: {
|
||||
service: string;
|
||||
channel: string;
|
||||
type: string;
|
||||
}
|
||||
}
|
||||
|
||||
export default class PusherProvider extends BaseProvider {
|
||||
static providerName = "pusher";
|
||||
static defaultConfig = {
|
||||
source: {
|
||||
service: "pusher"
|
||||
}
|
||||
};
|
||||
|
||||
protected config: PusherProviderConfig;
|
||||
|
||||
private service: PusherService;
|
||||
|
||||
/**
|
||||
* @param {App} app
|
||||
* @param {any} config
|
||||
*/
|
||||
constructor(app: App, channelId: string, config: ChannelConfig) {
|
||||
super(app, channelId, config);
|
||||
this.config = config;
|
||||
|
||||
if (!this.checkConfig()) {
|
||||
throw new ConfigCheckError("配置文件错误");
|
||||
}
|
||||
|
||||
let service = app.getService<PusherService>(config.source.service);
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
checkConfig() {
|
||||
let checkType = guard(
|
||||
object({
|
||||
source: object({
|
||||
service: optional(string),
|
||||
channel: string,
|
||||
type: string,
|
||||
})
|
||||
})
|
||||
);
|
||||
|
||||
return checkType(this.config);
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
await super.initialize();
|
||||
|
||||
// 绑定事件
|
||||
let srcConf = this.config.source;
|
||||
this.service.on(srcConf.channel, srcConf.type, this.onData.bind(this));
|
||||
}
|
||||
|
||||
async destory() {
|
||||
let srcConf = this.config.source;
|
||||
this.service.off(srcConf.channel, srcConf.type);
|
||||
await super.destory();
|
||||
}
|
||||
|
||||
async onData(data: any) {
|
||||
let messages: MultipleMessage = {};
|
||||
try {
|
||||
messages = await this.generator.generate(data);
|
||||
this.sendMessage(messages);
|
||||
} catch(err: any) {
|
||||
this.error('无法解析数据', err);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
import App from "../App";
|
||||
import { Robot } from "../RobotManager";
|
||||
import { Target } from "../SubscribeManager";
|
||||
import request from "request-promise";
|
||||
import { Utils } from "../Utils";
|
||||
|
||||
export type QQRobotConfig = {
|
||||
user: string;
|
||||
host: string;
|
||||
baseId?: string;
|
||||
}
|
||||
|
||||
export default class QQRobot implements Robot {
|
||||
private robotId: string;
|
||||
private endpoint: string;
|
||||
private botQQ: number;
|
||||
|
||||
public baseId?: string;
|
||||
|
||||
constructor(app: App, robotId: string, config: QQRobotConfig) {
|
||||
this.robotId = robotId;
|
||||
this.endpoint = 'http://' + config.host;
|
||||
this.botQQ = parseInt(config.user);
|
||||
|
||||
this.baseId = config.baseId;
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送私聊消息
|
||||
* @param {int|int[]} user - QQ号
|
||||
* @param {string} message - 消息
|
||||
* @returns {Promise<void>} 回调
|
||||
*/
|
||||
async sendToUser(user: number|number[], message: string) {
|
||||
if(Array.isArray(user)){ //发送给多个用户的处理
|
||||
for (let one of user) {
|
||||
await this.sendToUser(one, message);
|
||||
await Utils.sleep(100);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return await this.doApiRequest('send_msg', {
|
||||
bot: this.botQQ,
|
||||
type: 1,
|
||||
qq: user,
|
||||
msg: message,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送群消息
|
||||
*/
|
||||
async sendToGroup(group: number|number[], message: string) {
|
||||
if(Array.isArray(group)){ //发送给多个群组的处理
|
||||
for (let one of group) {
|
||||
await this.sendToGroup(one, message);
|
||||
await Utils.sleep(100);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return await this.doApiRequest('send_msg', {
|
||||
bot: this.botQQ,
|
||||
type: 2,
|
||||
group: group,
|
||||
msg: message,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
*/
|
||||
async sendMessage(targets: Target[], message: string) {
|
||||
let groupList: number[] = [];
|
||||
let userList: number[] = [];
|
||||
for (let target of targets) {
|
||||
if (target.type === "group") {
|
||||
groupList.push(parseInt(target.identity));
|
||||
} else if (target.type === "user") {
|
||||
userList.push(parseInt(target.identity));
|
||||
}
|
||||
}
|
||||
|
||||
if (groupList.length > 0) {
|
||||
await this.sendToGroup(groupList, message);
|
||||
}
|
||||
if (userList.length > 0) {
|
||||
await this.sendToUser(userList, message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行API调用
|
||||
*/
|
||||
async doApiRequest(method: string, data: any): Promise<any> {
|
||||
return await request({
|
||||
method: 'POST',
|
||||
uri: this.endpoint + '/' + method,
|
||||
body: data,
|
||||
json: true,
|
||||
timeout: 10000
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
class Cron {
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
class HttpQueue {
|
||||
|
||||
}
|
||||
|
||||
module.exports = HttpQueue;
|
@ -0,0 +1,93 @@
|
||||
import App from "../App";
|
||||
import { Service } from "../ServiceManager";
|
||||
import Pusher, { Channel } from 'pusher-js';
|
||||
import { Utils } from "../Utils";
|
||||
|
||||
export type PusherServiceConfig = {
|
||||
app_id: string;
|
||||
key: string;
|
||||
secret: string;
|
||||
cluster: string;
|
||||
};
|
||||
|
||||
export default class PusherService implements Service {
|
||||
private app: App;
|
||||
private config: PusherServiceConfig;
|
||||
private channelList: { [name: string]: Channel };
|
||||
private callbackList: { [name: string]: { [type: string]: Function } }
|
||||
|
||||
public pusher!: Pusher;
|
||||
|
||||
constructor(app: App, config: PusherServiceConfig) {
|
||||
this.app = app;
|
||||
this.config = config;
|
||||
|
||||
this.channelList = {};
|
||||
this.callbackList = {};
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
this.pusher = new Pusher(this.config.key, {
|
||||
cluster: this.config.cluster,
|
||||
forceTLS: true,
|
||||
});
|
||||
if(this.app.config.debug){
|
||||
Pusher.logToConsole = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 好像不需要
|
||||
async destory() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取channel
|
||||
*/
|
||||
getChannel(channelName: string): Channel {
|
||||
if (!(channelName in this.channelList)) {
|
||||
this.channelList[channelName] = this.pusher.subscribe(channelName);
|
||||
this.callbackList[channelName] = {};
|
||||
}
|
||||
return this.channelList[channelName];
|
||||
}
|
||||
|
||||
/**
|
||||
* 解除订阅channel
|
||||
*/
|
||||
public unsubscribeChannel(channelName: string) {
|
||||
this.pusher.unsubscribe(channelName);
|
||||
if (channelName in this.channelList) {
|
||||
delete this.channelList[channelName];
|
||||
delete this.callbackList[channelName];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定事件
|
||||
*/
|
||||
public on(channelName: string, eventName: string, callback: Function) {
|
||||
// 先解除绑定之前的
|
||||
this.off(channelName, eventName);
|
||||
|
||||
let channel = this.getChannel(channelName);
|
||||
channel.bind(eventName, callback);
|
||||
this.callbackList[channelName][eventName] = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解除绑定事件
|
||||
*/
|
||||
public off(channelName: string, eventName: string) {
|
||||
if (!(channelName in this.channelList)) return;
|
||||
let channel = this.channelList[channelName];
|
||||
let callback = this.callbackList[channelName][eventName];
|
||||
if (callback) {
|
||||
channel.unbind(eventName);
|
||||
delete this.callbackList[channelName][eventName];
|
||||
}
|
||||
if (Utils.count(this.callbackList[channelName]) === 0) {
|
||||
this.unsubscribeChannel(channelName);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
qq:
|
||||
user:
|
||||
1234567890:
|
||||
- some_channel_group/*
|
||||
- some_channel_group2/some_channel
|
||||
group:
|
||||
1234567890:
|
||||
- some_channel_group/*
|
||||
- some_channel_group2/some_channel
|
@ -0,0 +1,101 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
||||
|
||||
/* Projects */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
|
||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
|
||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
|
||||
/* Language and Environment */
|
||||
"target": "es2017", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
|
||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
|
||||
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
|
||||
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||
|
||||
/* Modules */
|
||||
"module": "commonjs", /* Specify what module code is generated. */
|
||||
"rootDir": "./src", /* Specify the root folder within your source files. */
|
||||
// "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
|
||||
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
// "resolveJsonModule": true, /* Enable importing .json files */
|
||||
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
|
||||
|
||||
/* JavaScript Support */
|
||||
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
|
||||
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
|
||||
|
||||
/* Emit */
|
||||
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||
"sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
|
||||
"outDir": "./dist", /* Specify an output folder for all emitted files. */
|
||||
// "removeComments": true, /* Disable emitting comments. */
|
||||
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
|
||||
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
|
||||
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
|
||||
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
|
||||
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||
|
||||
/* Interop Constraints */
|
||||
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
|
||||
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
|
||||
|
||||
/* Type Checking */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
|
||||
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
|
||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
|
||||
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
|
||||
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
|
||||
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
|
||||
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
|
||||
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
|
||||
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||
|
||||
/* Completeness */
|
||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue