#!/usr/bin/env ruby require "ircinch" require "sinatra" require "yaml" require "json" require "net/http" config_file = ARGV.shift || "config.yml" if not File.exists? config_file puts "Can't find config file #{config_file}" puts "Either create it or specify another config file with: #{File.basename $0} [filename]" exit end $config = YAML.load_file config_file $secret = $config["env"]["secret"] $bot = Cinch::Bot.new do configure do |c| c.nick = $config["irc"]["nick"] c.user = "Scummette" c.realname = "Razor" c.server = $config["irc"]["server"] c.port = $config["irc"]["port"] c.password = $config["irc"]["password"] c.channels = $config["irc"]["channels"] c.ping_interval = 120 c.timeouts.read = 480 end end Thread.new do $bot.start end def verify_signature(payload_body, github_signature) signature = 'sha1=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), $secret, payload_body) github_signature = "" if github_signature.nil? return halt 500, "Signatures didn't match!" unless Rack::Utils.secure_compare(signature, github_signature) end def say(repo,msg) $config["irc"]["channels"].each do |chan| unless $config["filters"].include? chan and not $config["filters"][chan].include? repo $bot.Channel(chan).send msg end end end def join() $config["irc"]["channels"].each do |chan| unless $config["filters"].include? chan and not $config["filters"][chan].include? repo $bot.join(chan) end end end def part() $config["irc"]["channels"].each do |chan| unless $config["filters"].include? chan and not $config["filters"][chan].include? repo $bot.part(chan) end end end configure do set :bind, $config["http"]["host"] set :port, $config["http"]["port"] set :host_authorization, { permitted_hosts: [] } set :logging, false set :lock, true end get "/" do "GitBot lives here. Direct your hooks to /github." end post "/github" do request.body.rewind payload_body = request.body.read verify_signature(payload_body, request.env['HTTP_X_HUB_SIGNATURE']) $bot.nick = $config["irc"]["nick"] eventType = request.env['HTTP_X_GITHUB_EVENT'] push = JSON.parse(params[:payload]) repo = push["repository"]["name"] sender = push["sender"]["login"] case eventType when "pull_request" return halt 200 unless ["opened", "closed", "reopened"].include?(push["action"]) res = Net::HTTP.post_form(URI('https://is.gd/create.php'), { 'format' => 'simple', 'url' => push["pull_request"]["html_url"] }) case res when Net::HTTPSuccess, Net::HTTPRedirection url = res.body say repo, "[%s] %s %s pull request #%s: %s (%s) %s" % [ $bot.Format(:purple, repo), sender, $bot.Format(:bold, push["action"]), $bot.Format(:bold, push["number"].to_s), push["pull_request"]["title"], $bot.Format(:purple, "%s...%s" % [ push["pull_request"]["base"]["ref"], push["pull_request"]["head"]["ref"] ]), $bot.Format(:aqua, $bot.Format(:underline, url)) ] else # Post Failed i.e. 502 # FIXME: do say with error message? i.e. res.value end when "push" res = Net::HTTP.post_form(URI('https://is.gd/create.php'), { 'format' => 'simple', 'url' => push["compare"] }) case res when Net::HTTPSuccess, Net::HTTPRedirection url = res.body branch = push["ref"].gsub(/^refs\/heads\//,"") numberOfCommits = push["commits"].length forced = push["forced"] say repo, "[%s] %s %s %s new commits to %s: %s" % [ $bot.Format(:purple, repo), sender, forced ? "force pushed" : "pushed", $bot.Format(:bold, numberOfCommits.to_s), $bot.Format(:purple, branch), $bot.Format(:aqua, $bot.Format(:underline, url)) ] push["commits"][0..2].each do |c| say repo, "%s/%s %s %s: %s" % [ $bot.Format(:purple, repo), $bot.Format(:purple, branch), $bot.Format(:grey, c["id"].slice(0..6)), c["author"]["username"], c["message"].split("\n")[0] ] end else # Post Failed i.e. 502 # FIXME: do say with error message? i.e. res.value end end push.inspect end