gitlab-to-irc/index.js

192 lines
5.7 KiB
JavaScript

var irc = require('irc');
var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var config = require('./config');
var channels = [];
var hookToChannel = {};
for (var who in config.reports) {
if (who.indexOf('#') === 0)
channels.push(who);
var hooks = config.reports[who];
for (var i = 0; i < hooks.length; i++) {
var hook = hooks[i];
(hookToChannel[hook] = hookToChannel[hook] || []).push(who);
}
}
var client = new irc.Client(config.server, config.nick, {
//debug: true,
channels: channels,
userName: config.userName,
realName: config.realName,
retryDelay: 120000
});
var mergeRequests = {};
var app = express();
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
var shortenURL = function(url, callback) { callback(url); };
if (config.lstu) {
if (config.lstu[config.lstu.length - 1] !== '/') {
config.lstu += '/';
}
shortenURL = function shortenURL(url, callback) {
request(config.lstu + 'a', { method: 'POST', form: { lsturl: url, format: 'json' } }, function (err, res, body) {
try {
body = JSON.parse(body);
} catch(err) {
body = {err: 'cant parse JSON'};
}
if (err || !body.success) {
console.error("Error when shortening link: (status: " + res.statusCode + ")", '\nerror:', err, '\nfailure reason:', body.msg);
} else {
callback(body.short);
}
});
};
}
var handlers = {
push: function(body, say) {
var user = body.user_name;
var projectName = body.project.name;
var commits = body.commits;
var numCommits = body.total_commits_count;
var branchName = body.ref.replace('refs/heads/', '');
var msg = null;
if (!numCommits) {
// Special case: a branch was created or deleted.
var action = 'created';
if (body.after === '0000000000000000000000000000000000000000')
action = 'deleted';
msg = projectName + ': ' + user + ' ' + action + ' branch ' + branchName;
say(msg);
} else {
var maybeS = numCommits === 1 ? '' : 's';
var lastCommit = commits[commits.length - 1];
var lastCommitMessage = lastCommit.message.trim().split('\n')[0].trim();
shortenURL(lastCommit.url, function(shortUrl) {
msg = 'push on ' + projectName + '@' + branchName + ' (by ' + user + '): ' +
commits.length + ' commit' + maybeS + ' (last: ' + lastCommitMessage + ') ' + shortUrl;
say(msg);
});
}
},
issue: function(body, say) {
var user = body.user.name;
var projectName = body.project.name;
var issue = body.object_attributes;
var issueNumber = issue.iid;
var issueTitle = issue.title.trim();
var issueState = issue.state;
var url = issue.url;
// Don't trigger the hook on issue's update;
if (issue.action === 'update')
return;
shortenURL(url, function(shortUrl) {
var msg = projectName + ': issue #' + issueNumber + ' ("' + issueTitle + '") changed state ("' + issueState + '") ' + shortUrl;
say(msg);
});
},
merge_request: function(body, say) {
var user = body.user.name;
var request = body.object_attributes;
var projectName = request.target.name;
var from = request.source_branch;
var to = request.target_branch;
var id = request.iid;
var title = request.title.trim();
var url = request.url;
var state = request.state;
var assignee_id = request.assignee_id;
mergeRequests[id] = mergeRequests[id] || {};
var formerAssignee_id = mergeRequests[id].assignee_id;
mergeRequests[id].assignee_id = assignee_id;
// Abort if just the assignee changed;
if (typeof formerAssignee_id !== 'undefined' && assignee_id !== formerAssignee_id)
return;
shortenURL(url, function(shortUrl) {
var msg = projectName + ': merge request (' + from + '->' + to + ': ' + title + ') ' +
'#' + id + ' changed state ("' + state + '"): ' + shortUrl;
say(msg);
});
},
build: function(body, say) {
var id = body.build_id;
var status = body.build_status;
var isFinished = body.build_finished_at !== null;
var duration = body.build_duration;
var projectName = body.project_name;
var stage = body.build_stage;
var msg = projectName + ': build #' + id + ' (' + stage + ') changed status: ' + status;
if (isFinished)
msg += ' (finished in ' + duration + ' seconds.)';
say(msg);
}
};
function makeSay(body) {
var whom = hookToChannel[body.object_kind] || [];
return function say(msgs) {
if (msgs) {
if (msgs instanceof Array) {
for (var i = 0; i < msgs.length; i++)
client.say(whom, msgs[i]);
} else {
client.say(whom, msgs);
}
}
};
}
app.post('/', function(req, res) {
var body = req.body || {};
var msgs = null;
if (body.object_kind && handlers[body.object_kind])
handlers[body.object_kind](body, makeSay(body));
else
console.log("Unexpected object_kind:", body.object_kind);
res.sendStatus(200);
});
app.listen(config.port, config.hostname, function() {
console.log('gitlab-to-irc running.');
});