初次提交
commit
ac42f0fbdd
@ -0,0 +1,3 @@
|
|||||||
|
config.yml
|
||||||
|
node_modules/
|
||||||
|
package-lock.json
|
@ -0,0 +1,31 @@
|
|||||||
|
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;
|
@ -0,0 +1,101 @@
|
|||||||
|
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;
|
@ -0,0 +1,67 @@
|
|||||||
|
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;
|
@ -0,0 +1,17 @@
|
|||||||
|
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;
|
@ -0,0 +1,8 @@
|
|||||||
|
channel: "debug"
|
||||||
|
templates:
|
||||||
|
message: "{{data.message}}"
|
||||||
|
receiver:
|
||||||
|
group:
|
||||||
|
- 11111111111
|
||||||
|
user:
|
||||||
|
- 11111111111
|
@ -0,0 +1,12 @@
|
|||||||
|
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,10 @@
|
|||||||
|
channel: "server_status"
|
||||||
|
templates:
|
||||||
|
disconnect: "{{data.srcName}} 与 {{data.dstName}} 的连接已断开"
|
||||||
|
connect: "{{data.srcName}} 与 {{data.dstName}} 的连接已恢复"
|
||||||
|
receiver:
|
||||||
|
group:
|
||||||
|
- 111111111
|
||||||
|
- 111111111
|
||||||
|
user:
|
||||||
|
- 111111111
|
@ -0,0 +1,9 @@
|
|||||||
|
robot:
|
||||||
|
host: "192.168.0.14:5700"
|
||||||
|
pusher:
|
||||||
|
app_id: ""
|
||||||
|
key: ""
|
||||||
|
secret: ""
|
||||||
|
cluster: "ap1"
|
||||||
|
channel_config_path: "./channels"
|
||||||
|
debug: false
|
@ -0,0 +1,37 @@
|
|||||||
|
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();
|
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "isekai-pusher2coolq",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"run": "node index.js"
|
||||||
|
},
|
||||||
|
"author": "hyperzlib",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"pusher": "^3.0.1",
|
||||||
|
"pusher-js": "^5.1.1",
|
||||||
|
"request": "^2.88.2",
|
||||||
|
"request-promise": "^4.2.5",
|
||||||
|
"yaml": "^1.8.3"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
var Pusher = require('pusher');
|
||||||
|
|
||||||
|
var pusher = new Pusher({
|
||||||
|
appId: '',
|
||||||
|
key: '',
|
||||||
|
secret: '',
|
||||||
|
cluster: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
pusher.trigger('debug', 'message', {"message": "Isekai Puser远端推送测试 (二周目)"});
|
Loading…
Reference in New Issue