初次提交

main
落雨楓 5 years ago
commit ac42f0fbdd

3
.gitignore vendored

@ -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,37 @@
var fs = require('fs');
var path = require('path');
var Yaml = require('yaml');
var Channel = require('./Channel');
var BroadcastChannel = require('./BroadcastChannel');
class ChannelManager {
constructor(app, configPath){
this.app = app;
this.configPath = configPath;
this.channels = {};
this.initChannels();
}
initChannels(){
let files = fs.readdirSync(this.configPath);
files.forEach((file) => {
if(!file.match(/\.yml$/)){
return;
}
let name = file.replace(/\.yml$/, '');
let content = fs.readFileSync(this.configPath + '/' + file, {encoding: 'utf-8'});
let config = Yaml.parse(content);
let channel = new Channel(this.app, config);
this.channels[name] = channel;
console.log('已加载Channel配置: ' + name + '对应channel: ' + config.channel);
});
this.channels['broadcast'] = new BroadcastChannel(this.app);
}
}
module.exports = ChannelManager;

@ -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,4 @@
# Pusher2CoolQ
将Pusher的推送消息转换为酷Q消息发送通过CoolQ Http
方便配合服务器可用性监测系统,提供比邮件更加实时的提示功能
仅支持单向推送

@ -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…
Cancel
Save