254 lines
7.7 KiB
JavaScript
254 lines
7.7 KiB
JavaScript
var irc = require('irc');
|
|
var express = require('express');
|
|
var bodyParser = require('body-parser');
|
|
var request = require('request');
|
|
var cheerio = require('cheerio');
|
|
|
|
var config = require('./config');
|
|
|
|
// Bind recipients to notifications.
|
|
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);
|
|
}
|
|
}
|
|
|
|
// Sanitize projectUrl
|
|
if (typeof config.projectUrl !== 'undefined') {
|
|
var url = '' + config.projectUrl;
|
|
if (url[url.length - 1] !== '/') {
|
|
url += '/';
|
|
}
|
|
config.projectUrl = url;
|
|
}
|
|
|
|
var client = new irc.Client(config.server, config.nick, {
|
|
debug: config.debug || false,
|
|
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: ",
|
|
res ? "(status: " + res.statusCode + ")" : "(no response)",
|
|
'\nerror:', err,
|
|
'\nfailure reason:', body.msg);
|
|
callback(url);
|
|
} 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[0];
|
|
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;
|
|
|
|
if (typeof mergeRequests[id] === 'undefined') {
|
|
mergeRequests[id] = {
|
|
state: state
|
|
};
|
|
|
|
// Stay silent if the merge request state is open and we didn't
|
|
// know it before.
|
|
if (state === "opened") {
|
|
return;
|
|
}
|
|
} else {
|
|
var formerState = mergeRequests[id].state;
|
|
mergeRequests[id].state = state;
|
|
|
|
// Abort if the state hasn't changed.
|
|
if (state === formerState) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
shortenURL(url, function(shortUrl) {
|
|
var msg = projectName + ': MR# ' + id + ' (' + from + '->' + to + ': ' + title + ') ' +
|
|
' has been ' + 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 (!whom.length) {
|
|
return;
|
|
}
|
|
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.');
|
|
|
|
var issueRegexp = /#(\d+)/g;
|
|
var mergeRequestRegexp = /!(\d+)/g;
|
|
client.on('message', function(from, chan, message) {
|
|
var matches = null;
|
|
while ((matches = issueRegexp.exec(message)) !== null) {
|
|
var issueId = matches[1];
|
|
var url = config.projectUrl + 'issues/' + issueId;
|
|
request(url, function(err, res, body) {
|
|
if (res && res.statusCode === '200') {
|
|
var title = cheerio.load(body)('head title').text();
|
|
if (title.length) {
|
|
client.say(chan, title);
|
|
} else {
|
|
client.say(chan, "Issue #" + issueId + ": " + url);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
while ((matches = mergeRequestRegexp.exec(message)) !== null) {
|
|
var mrId = matches[1];
|
|
var url = config.projectUrl + 'merge_requests/' + mrId;
|
|
request(url, function(err, res, body) {
|
|
if (res && res.statusCode === '200') {
|
|
var title = cheerio.load(body)('head title').text();
|
|
if (title.length) {
|
|
client.say(chan, title);
|
|
} else {
|
|
client.say(chan, "Merge request !" + mrId + ": " + url);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
});
|