File

mod_pubsub_github/mod_pubsub_github.lua @ 3519:ac623080324a

mod_pubsub_github: Only put first line of commit message in title, rest in content
author Kim Alvefur <zash@zash.se>
date Sun, 31 Mar 2019 18:16:49 +0200
parent 3518:95c1c3e057cf
child 3520:37e89a76c7d7
line wrap: on
line source

module:depends("http");

local st = require "util.stanza";
local json = require "util.json";
local hmac_sha1 = require "util.hashes".hmac_sha1;

local pubsub_service = module:depends("pubsub").service;
local default_node = module:get_option("github_node", "github");
local node_prefix = module:get_option_string("github_node_prefix", "github/");
local node_mapping = module:get_option_string("github_node_mapping");
local github_actor = module:get_option_string("github_actor") or true;
local secret = module:get_option("github_secret");

assert(secret, "Please set 'github_secret'");

local error_mapping = {
	["forbidden"] = 403;
	["item-not-found"] = 404;
	["internal-server-error"] = 500;
	["conflict"] = 409;
};

function handle_POST(event)
	local request, response = event.request, event.response;
	if ("sha1=" .. hmac_sha1(secret, request.body, true)) ~= request.headers.x_hub_signature then
		return 401;
	end
	local data = json.decode(request.body);
	if not data then
		response.status_code = 400;
		return "Invalid JSON. From you of all people...";
	end

	local github_event = request.headers.x_github_event
	if github_event == "push" then
		module:log("debug", "Handling 'push' event: \n%s\n", tostring(request.body));
	elseif github_event then
		module:log("debug", "Unsupported Github event %q", github_event);
		return 501;
	end -- else .. is this even github?

	local node = default_node;
	if node_mapping then
		node = node_prefix .. data.repository[node_mapping];
	end

	for _, commit in ipairs(data.commits) do
		local ok, err = pubsub_service:publish(node, github_actor, commit.id,
			st.stanza("item", { id = commit.id, xmlns = "http://jabber.org/protocol/pubsub" })
			:tag("entry", { xmlns = "http://www.w3.org/2005/Atom" })
				:tag("id"):text(commit.id):up()
				:tag("title"):text(commit.message:match("^[^\r\n]*")):up()
				:tag("content"):text(commit.message):up()
				:tag("link", { rel = "alternate", href = commit.url }):up()
				:tag("published"):text(commit.author.date):up()
				:tag("author")
					:tag("name"):text(commit.author.name):up()
					:tag("email"):text(commit.author.email):up()
					:up()
		);
		if not ok then
			return error_mapping[err] or 500;
		end
	end

	response.status_code = 202;
	return "Thank you Github!";
end

module:provides("http", {
	route = {
		POST = handle_POST;
	};
});

if not node_mapping then
	function module.load()
		if not pubsub_service.nodes[default_node] then
			local ok, err = pubsub_service:create(default_node, true);
			if not ok then
				module:log("error", "Error creating node: %s", err);
			else
				module:log("debug", "Node %q created", default_node);
			end
		end
	end
end