Skip to content

Instantly share code, notes, and snippets.

@kimoto
Created March 6, 2012 01:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kimoto/1982811 to your computer and use it in GitHub Desktop.
Save kimoto/1982811 to your computer and use it in GitHub Desktop.
gig2.rb (Nokogiri+retry-handler+open-uri)
#!/usr/bin/env ruby
# vim:encoding=UTF-8:
=begin
# gig.rb
Github IRC Gateway
=end
require "logger"
require "ostruct"
require 'time'
require 'open-uri'
require 'net/irc/mala'
require 'nokogiri'
require 'retry-handler'
class Net::IRC::Github < Net::IRC::Server::Session
EVENTS = {
'DownloadEvent' => '6',
'GistEvent' => '10',
'WatchEvent' => '15',
'FollowEvent' => '15',
'CreateEvent' => '13',
'ForkEvent' => '3',
'PushEvent' => '14'
}
def server_name
"github"
end
def server_version
"0.0.0"
end
def main_channel
@opts.main_channel || "#github"
end
def initialize(*args)
super
@last_retrieved = Time.now
@wait_time = 30
@retry_wait_time = 10
@retry_max = 3
end
def on_disconnected
@retrieve_thread.kill rescue nil
end
def on_user(m)
super
parse_real_name_field
post @nick, JOIN, main_channel
@retrieve_thread = Thread.start do
loop do
retrieve_from_github
end
end
end
private
def parse_real_name_field
@real, *@opts = real.split(/\s+/)
@opts = OpenStruct.new @opts.inject({}) {|r, i|
key, value = i.split("=", 2)
value2 = case value
when nil then true
when /\A\d+\z/ then value.to_i
when /\A(?:\d+\.\d*|\.\d+)\z/ then value.to_f
else value
end
r.update key => value2
}
end
def parse_github_rss(feed_data)
ns = {"a" => "http://www.w3.org/2005/Atom"}
Nokogiri::XML(feed_data).xpath("//a:feed/a:entry", ns).map do |entry|
{
:datetime => Time.parse(entry.xpath('string(a:published)', ns)),
:id => entry.xpath('string(a:id)', ns),
:title => entry.xpath('string(a:title)', ns),
:author => entry.xpath('string(a:author/a:name)', ns),
:link => entry.xpath('string(a:link/@href)', ns),
}
end
end
def retrieve_from_github
begin
@log.info 'retrieveing feed...'
uri = "https://github.com/#{@real}.private.atom"
feed_data = open(uri.to_s, :http_basic_authentication => [@real, @pass]).read
entries = parse_github_rss(feed_data)
entries.reverse_each do |entry|
next if entry[:datetime] <= @last_retrieved
type = entry[:id][%r|tag:github.com,2008:(.+?)/\d+|, 1]
post entry[:author], PRIVMSG, main_channel,
"\003#{EVENTS[type] || '5'}#{entry[:title]}\017 \00314#{entry[:link]}\017"
end
@last_retrieved = entries.first[:datetime]
GC.start
@log.info "sleep: #{@wait_time} seconds"
sleep @wait_time
end.retry(:max => @retry_max, :wait => @retry_wait_time, :accept_exception => Exception, :logger => @log)
end
end
if __FILE__ == $0
Net::IRC::CLI.run(Net::IRC::Github, ARGV)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment