Created
September 29, 2017 01:15
-
-
Save leapar/0e5702dbffb791d46319a5e8c48446fc to your computer and use it in GitHub Desktop.
hubot代码分析
hubot-script-shellcmd
https://github.com/coderofsalvation/hubot-script-shellcmd/blob/master/src/shellcmd.coffee
http://coffeescript.org/#nodejs-usage
// Description:
// List/Execute shellcommands from a specified folder.
// Dependencies:
// None
// Configuration
// HUBOT_SHELLCMD="bash/handler" (cp the example 'bash'-directory to your root/runtime folder)
// where 'handler' is a shellscript like:
// Commands:
// Hubot shellcmd - list (bash)shell commands
// Hubot shellcmd <foo> - performs bashshell command
// Author:
// Leon van Kammen / Coderofsalvation
var fs;
fs = require("fs");
if (!process.env.HUBOT_SHELLCMD) {
process.env.HUBOT_SHELLCMD = "bash/handler";
}
if (!fs.existsSync(process.env.HUBOT_SHELLCMD)) {
console.log(process.env.HUBOT_SHELLCMD + " not found in hubot working dir..defaulting to example handler at " + __dirname + "/../bash/handler");
process.env.HUBOT_SHELLCMD = __dirname + "/../bash/handler";
}
if (!process.env.HUBOT_SHELLCMD_KEYWORD) {
process.env.HUBOT_SHELLCMD_KEYWORD = "shellcmd";
}
module.exports = function(robot) {
var run_cmd;
run_cmd = function(cmd, args, envs, cb) {
var child, opts, spawn;
console.log("spawn!");
spawn = require("child_process").spawn;
opts = {
env: envs
};
child = spawn(cmd, args, opts);
child.stdout.on("data", function(buffer) {
return cb(buffer.toString());
});
return child.stderr.on("data", function(buffer) {
return cb(buffer.toString());
});
};
//child.stdout.on "end", -> cb resp
robot.respond("/" + process.env.HUBOT_SHELLCMD_KEYWORD + "$/i", function(msg) {
var cmd, envs, key, ref, value;
cmd = process.env.HUBOT_SHELLCMD;
envs = {};
ref = msg.envelope.user;
for (key in ref) {
value = ref[key];
envs["HUBOT_USER_" + key.toUpperCase()] = value;
}
return run_cmd(cmd, [], envs, function(text) {
return msg.send(text);
});
});
return robot.respond("/" + process.env.HUBOT_SHELLCMD_KEYWORD + " (.*)/i", function(msg) {
var args, cmd, envs, key, ref, value;
msg.match[0] = msg.match[0].replace(/^[a-z0-9]+$/i);
msg.match.shift();
args = msg.match[0].split(" ");
cmd = process.env.HUBOT_SHELLCMD;
envs = {};
ref = msg.envelope.user;
for (key in ref) {
value = ref[key];
envs["HUBOT_USER_" + key.toUpperCase()] = value;
}
return run_cmd(cmd, args, envs, function(text) {
return msg.send(text.replace("\n", ""));
});
});
};
给hubot绑定两个规则:
- respond "/ shellcmd $/i"
- respond "/ shellcmd (.*)/i"
respond 绑定
hear (regex, options, callback) {
this.listeners.push(new Listener.TextListener(this, regex, options, callback))
}
respond (regex, options, callback) {
this.hear(this.respondPattern(regex), options, callback)
}
adapter 都会调用bot的receive函数
// Public: Dispatch a received message to the robot.
//
// Returns nothing.
receive (message) {
this.robot.receive(message)
}
receive (message, cb) {
// When everything is finished (down the middleware stack and back up),
// pass control back to the robot
this.middleware.receive.execute({ response: new Response(this, message) }, this.processListeners.bind(this), cb)
}
// Private: Passes the given message to any interested Listeners.
//
// message - A Message instance. Listeners can flag this message as 'done' to
// prevent further execution.
//
// done - Optional callback that is called when message processing is complete
//
// Returns nothing.
// Returns before executing callback
processListeners (context, done) {
// Try executing all registered Listeners in order of registration
// and return after message is done being processed
let anyListenersExecuted = false
async.detectSeries(this.listeners, (listener, done) => {
try {
listener.call(context.response.message, this.middleware.listener, function (listenerExecuted) {
anyListenersExecuted = anyListenersExecuted || listenerExecuted
// Defer to the event loop at least after every listener so the
// stack doesn't get too big
process.nextTick(() =>
// Stop processing when message.done == true
done(context.response.message.done)
)
})
} catch (err) {
this.emit('error', err, new this.Response(this, context.response.message, []))
// Continue to next listener when there is an error
done(false)
}
},
// Ignore the result ( == the listener that set message.done = true)
_ => {
// If no registered Listener matched the message
if (!(context.response.message instanceof Message.CatchAllMessage) && !anyListenersExecuted) {
this.logger.debug('No listeners executed; falling back to catch-all')
this.receive(new Message.CatchAllMessage(context.response.message), done)
} else {
if (done != null) {
process.nextTick(done)
}
}
})
}
最后当消息来,执行listeners里面的自定义处理函数。processListeners函数写的很有水平。
参考
- 理解 Node.js 里的 process.nextTick() http://www.oschina.net/translate/understanding-process-next-tick
- detectSeries(coll, iteratee, callbackopt) https://github.com/async-js/async#async.detectseries
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
安装
参考http://www.jevic.cn/2017/02/07/chatops/
doc
hubot自带express,监听8080,可以用export EXPRESS_PORT 进行设置端口。
配置
修改example.coffee文件,响应http 请求
设置channel
创建一个channel,取一个名字,然后查看该channel的id
post消息
查看响应