Created
March 16, 2012 10:35
-
-
Save rkh/2049493 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding: binary | |
# IRC <-> Campfire bridge, set IRC password to SUBDOMAIN:TOKEN and connect to localhost:6667 | |
# Remove special chars/spaces from channel names (ie "Foo Bar" becomes #FooBar). Only tested with LimeChat. | |
# gem install excon && gem install yajl-ruby -v "< 2.0" | |
%w[socket thread uri excon yajl yajl/http_stream].each { |lib| require lib } | |
Thread.abort_on_exception = true | |
[:INT, :TERM].each { |sig| trap(sig) { exit } } | |
server = TCPServer.new('127.0.0.1', 6667) | |
loop do | |
Thread.new(server.accept) do |irc| | |
out = Queue.new | |
writer = Thread.new { loop { irc << out.pop.to_s << "\r\n" } } | |
token = subdomain = url = nick = nil | |
rooms, users, streams = {}, {}, {} | |
add_user = proc { |data| data['name'].split(' ').first.tap { |n| users[n] = data['id'] } } | |
http = proc { |v,r,a={}| Yajl.load Excon.public_send(v, "https://#{token}:x@#{subdomain}.campfirenow.com/#{r}.json", a).body } | |
get, post = http.curry[:get], http.curry[:post] | |
until irc.closed? or irc.eof? | |
rest, last = irc.gets.chop.split(":", 2) | |
command, *args = rest.split(" ") | |
args << last | |
case command | |
when "USER", "PONG" | |
when "PASS" | |
subdomain, token = args | |
get['rooms']['rooms'].each { |d| rooms["##{d['name'].gsub(/\W/, '')}"] = d['id'] } | |
nick = add_user[get['users/me']['user']] | |
out << ":localhost 001 #{nick} :Welcome to the #{subdomain} IRC Network #{nick}\r\n:localhost 002 #{nick} :Your host is localhost" | |
out << ":localhost 003 #{nick} :This server was created #{Time.now}\r\n:localhost 004 #{nick} :CampIRC 0.0.1 hello fake" | |
when "NICK" | |
out << ":#{args.first} NICK #{nick}" | |
when "PRIVMSG" | |
room_id, body = rooms[args[0]], Yajl.dump('message' => {'body' => args[1].gsub(/\x01(ACTION)?/, '')}) | |
post["room/#{room_id}/speak", :body => body, :headers => {"Content-Type" => "application/json"}] if room_id | |
when "JOIN" | |
channel = args.first | |
if room_id = rooms[channel] | |
post["room/#{room_id}/join"] | |
data = get["room/#{room_id}"]['room'] | |
nicks = data['users'].map { |u| add_user[u] } | |
out << ":#{nick} JOIN #{channel}\r\n:localhost 332 #{nick} #{channel} :#{data['topic']}\r\n:localhost 333 #{nick} #{channel} #{nick} #{Time.now.to_i}" | |
out << ":localhost 353 #{nick} @ #{channel} :#{nicks.join " "}\r\n:localhost 366 #{nick} @ #{channel} :End of /NAMES list" | |
streams[channel] = Thread.new do | |
Yajl::HttpStream.get URI.parse("http://#{token}:[email protected]//room/#{room_id}/live.json") do |msg| | |
next unless channel = rooms.key(msg['room_id']) | |
user = users.key(msg['user_id']) || add_user[get["users/#{msg['user_id']}"]] if msg['user_id'] | |
case msg['type'].downcase | |
when 'timestampmessage' | |
when 'textmessage', 'pastemessage', 'tweetmessage', 'uploadmessage' then out << ":#{user} #{user == nick ? "NOTICE" : "PRIVMSG"} #{channel} :#{msg['body']}" | |
when 'kickmessage', 'leavemessage' then out << ":#{user} PART #{channel} :#{msg['type']}" | |
when 'entermessage' then out << ":#{user} JOIN #{channel}" | |
when "topicchangemessage" then out << ":#{user} TOPIC #{channel} :#{msg['body']}" | |
when "soundmessage" then out << ":#{user} PRIVMSG #{channel} :\x01ACTION plays #{msg['body']}\x01" | |
else puts "unsupported message: #{msg.inspect}" | |
end | |
end | |
end | |
else | |
out << ":localhost 403 #{channel} :No such channel" | |
end | |
when "QUIT" | |
writer.kill | |
streams.each_value(&:kill) | |
irc.close | |
else | |
puts "unkown command #{command}" | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment