Created
June 13, 2012 14:34
-
-
Save smiler/2924436 to your computer and use it in GitHub Desktop.
This file contains 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
require "socket" | |
require "net/http" | |
require "plugin" | |
require "channel" | |
# The irc class, which talks to the server and holds the main event loop | |
class IRC | |
attr_reader :channels, :nick | |
def initialize(server, port, nick, user, realname, channels) | |
@server = server | |
@port = port | |
@nick = nick | |
@user = user | |
@realname = realname | |
@plugin_handler = Plugin_Handler.new | |
@channels = [] | |
channels.each { |channel| | |
@channels << Channel.new(channel) | |
} | |
# Used to store names while joining a channel | |
@names = Hash.new | |
end | |
# Sends message to the nick specified by target | |
def putnick(target, message) | |
putserv "PRIVMSG #{target} :#{message}" | |
end | |
# Sends message to the channel specified by target | |
def putchan(target, message) | |
putserv "PRIVMSG #{target} :#{message}" | |
end | |
# Sets mode on channel with optional args | |
def putmode(channel, mode, args) | |
putserv "MODE #{channel} #{mode} #{args}" | |
end | |
# Sends a string in its raw form to the server | |
def putserv(s) | |
# Send a message to the irc server and print it to the screen | |
puts "--> #{s}" | |
@irc.send "#{s}\n", 0 | |
end | |
# Tires to kick a user from a channel | |
def putkick(nick, channel, message) | |
putserv "KICK #{channel} #{user} :#{message}" | |
end | |
# Connects, registers and join channels | |
def connect() | |
@irc = TCPSocket.open(@server, @port) | |
putserv "NICK #{@nick}" | |
putserv "USER #{@user} 8 * :#{@realname}" | |
@channels.each { |chan| | |
putserv "JOIN #{chan.name}" | |
} | |
end | |
# Matches server input and delegates control to the plugin event handler | |
# server PING PONG is handled locally here. | |
def handle_server_input(s) | |
case s.strip | |
# Server PING | |
when /^PING :(.+)$/i | |
puts "[ Server ping ]" | |
putserv "PONG :#{$1}" | |
# CTCP PING | |
when /^:(.+?)!(.+?)@(.+?)\sPRIVMSG\s.+\s:[\001]PING (.+)[\001]$/i | |
@plugin_handler.event(:on_ctcp_ping, :nick => $1, :user => $2, | |
:host => $3, :message => $4) | |
# CTCP VERSION | |
when /^:(.+?)!(.+?)@(.+?)\sPRIVMSG\s.+\s:[\001]VERSION[\001]$/i | |
@plugin_handler.event(:on_ctcp_version, :nick => $1, :user => $2, | |
:host => $3) | |
# PRIVMSG | |
when /^:(.+?)!(.+?)@(.+?)\sPRIVMSG\s(.+?)\s:(.+)$/i | |
if $1 == $4 | |
@plugin_handler.event(:on_privmsg, :nick => $1, :user => $2, | |
:host => $3, :message => $5) | |
else | |
@plugin_handler.event(:on_msg, :nick => $1, :user => $2, | |
:host => $3, :channel => $4, :message => $5) | |
end | |
# NOTICE | |
when /^:(.+?)!(.+?)@(.+?)\sNOTICE\s(.+?)\s:(.+)$/i | |
@plugin_handler.event(:on_notice, :nick => $1, :user => $2, | |
:host => $3, :target => $4, :message => $5) | |
# JOIN | |
when /^:(.+?)!(.+?)@(.+?)\sJOIN\s:(.+)/i | |
channel = $4 | |
nick = $1 | |
if nick == @nick | |
@channels << Channel.new(channel) | |
end | |
# Create channel if it dosen't exist | |
chan = @channels.select { |c| c.name == channel.downcase }[0] | |
if chan == nil | |
chan = Channel.new(channel) | |
@channels << chan | |
end | |
# Add user to our channel db | |
chan.adduser(nick, "") | |
# Handle plugins | |
@plugin_handler.event(:on_join, :nick => $1, :user => $2, :host => $3, | |
:channel => $4) | |
# PART | |
when /^:(.+?)!(.+?)@(.+?)\sPART\s(\S+)(\s:(.+))?/ | |
channel = $4 | |
nick = $1 | |
# Remove channel if it's us that are leaving otherwise remove | |
# user from channel db | |
chan = @channels.select { |c| c.name == channel.downcase }[0] | |
if nick == @nick | |
@channels.delete(chan) | |
else | |
chan.deluser(nick) | |
end | |
# Handle plugins | |
@plugin_handler.event(:on_part, :nick => $1, :user => $2, :host => $3, | |
:channel => $4, :message => $6) | |
# KICK | |
when /^:(.+?)!(.+?)@(.+?)\sKICK\s(\S+)\s(\S+)(\s:(.+))?/ | |
channel = $4 | |
knick = $5 | |
# Remove channel if it's us that are being kicked otherwise remove | |
# user from channel db | |
chan = @channels.select { |c| c.name == channel.downcase }[0] | |
if knick == @nick | |
@channels.delete(chan) | |
else | |
chan.deluser(knick) | |
end | |
# Handle plugins | |
@plugin_handler.event(:on_kick, :nick => $1, :user => $2, :host => $3, | |
:knick => $4, | |
:channel => $5, :message => $7) | |
# QUIT | |
when /^:(.+?)!(.+?)@(.+?)\sQUIT\s:(.+)$/ | |
nick = $1 | |
return if nick == @nick # TODO: Shall we do this? | |
# Remove user from all channels | |
@channels.each { |c| c.deluser(nick) } | |
# Handle plugins | |
@plugin_handler.event(:on_quit, :nick => $1, :user => $2, :host => $3, | |
:message => $4) | |
# MODE | |
when /^:(.+?)!(.+?)@(.+?)\sMODE\s(\S*)\s(\S*)(\s(.*))?/ | |
# Set mode in our channel db | |
chan = @channels.select { |c| c.name == $4.downcase }[0] | |
chan.setmode($5, $7) | |
# Handle plugins | |
@plugin_handler.event(:on_mode, :nick => $1, :user => $2, :host => $3, | |
:channel => $4, :mode => $5, :args => $7) | |
# SMODE | |
when /^:(.+)\sMODE\s(.+)\s(.+)(\s(.+))?/ | |
server = $1 | |
channel = $2 | |
mode = $3 | |
args = $4 | |
# Set mode in our channel db | |
chan = @channels.select { |c| c.name == channel.downcase }[0] | |
chan.setmode(mode, args) | |
# Handle plugins | |
@plugin_handler.event(:on_smode, :server => server, :channel => | |
channel, :mode => mode, :args => args) | |
# NAMES reply | |
when /^:(.+)\s353\s(.+)\s([\*=@])\s(.+)\s:(.+)/ | |
channel = $4.downcase | |
users = $5.split | |
puts "[ NAMES #{channel}: #{users.join(', ')} ]" | |
# Store users for later usage in NAMES end event | |
if @names[channel] == nil | |
@names[channel] = Array.new users | |
else | |
@names[channel].concat users | |
end | |
# NAMES end | |
when /^:(.+)366\s(.+)\s(.*)\s:(.+)/ | |
channel = $3.downcase | |
message = $4 | |
puts "[ NAMES #{channel}: #{message} ]" | |
# Add all stored users to our channel db | |
@names[channel].each { |user| | |
modes = user.chars.take_while { |c| "@%+".chars.to_a.include? c }.join | |
user = user.chars.drop_while { |c| "@%+".chars.to_a.include? c }.join | |
chan = @channels.select { |c| c.name == channel }[0] | |
chan.adduser(user, modes) | |
} | |
@names[channel] = nil | |
# Name already in use | |
when /^:(.+)\s433\s(.*)\s(.*)\s(.*)/ | |
nick = $4 | |
# TODO: handle this in a better way | |
putserv "NICK #{$altnick}" | |
putserv "USER #{@user} 8 * :#{@realname}" | |
@channels.each { |chan| | |
putserv "JOIN #{chan.name}" | |
} | |
else | |
@plugin_handler.event(:unknown, s) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment