lib/net/irc.rb in net-irc-0.0.1 vs lib/net/irc.rb in net-irc-0.0.2
- old
+ new
@@ -2,15 +2,16 @@
require "ostruct"
require "socket"
require "thread"
require "logger"
+require "monitor"
module Net; end
module Net::IRC
- VERSION = "0.0.1"
+ VERSION = "0.0.2"
class IRCException < StandardError; end
module PATTERN # :nodoc:
# letter = %x41-5A / %x61-7A ; A-Z / a-z
# digit = %x30-39 ; 0-9
@@ -307,11 +308,11 @@
extract[2]
end
# Extract prefix string to [nick, user, host] Array.
def extract
- _, *ret = *self.match(/^([^\s!]+)!([^\s@]+)@(\S+)$/)
+ _, *ret = *self.match(/^([^\s!]+)(?:!([^\s@]+)@(\S+))?$/)
ret
end
end
# Encoding to CTCP message. Prefix and postfix \x01.
@@ -447,10 +448,11 @@
# "#channel" => {
# :modes => [],
# :users => [],
# }
}
+ @channels.extend(MonitorMixin)
end
# Connect to server and start loop.
def start
@socket = TCPSocket.open(@host, @port)
@@ -493,138 +495,152 @@
end
# Default RPL_WELCOME callback.
# This sets @prefix from the message.
def on_rpl_welcome(m)
- @prefix = Prefix.new(m[1][/\S+!\S+@\S+/])
+ @prefix = Prefix.new(m[1][/\S+$/])
end
# Default PING callback. Response PONG.
def on_ping(m)
- post PONG, @nick
+ post PONG, @prefix ? @prefix.nick : ""
end
# For managing channel
def on_rpl_namreply(m)
type = m[1]
channel = m[2]
init_channel(channel)
- m[3].split(/\s+/).each do |u|
- _, mode, nick = *u.match(/^([@+]?)(.+)/)
+ @channels.synchronize do
+ m[3].split(/\s+/).each do |u|
+ _, mode, nick = *u.match(/^([@+]?)(.+)/)
- @channels[channel][:users] << nick
- @channels[channel][:users].uniq!
+ @channels[channel][:users] << nick
+ @channels[channel][:users].uniq!
- case mode
- when "@" # channel operator
- @channels[channel][:modes] << ["o", nick]
- when "+" # voiced (under moderating mode)
- @channels[channel][:modes] << ["v", nick]
+ case mode
+ when "@" # channel operator
+ @channels[channel][:modes] << ["o", nick]
+ when "+" # voiced (under moderating mode)
+ @channels[channel][:modes] << ["v", nick]
+ end
end
- end
- case type
- when "@" # secret
- @channels[channel][:modes] << ["s", nil]
- when "*" # private
- @channels[channel][:modes] << ["p", nil]
- when "=" # public
- end
+ case type
+ when "@" # secret
+ @channels[channel][:modes] << ["s", nil]
+ when "*" # private
+ @channels[channel][:modes] << ["p", nil]
+ when "=" # public
+ end
- @channels[channel][:modes].uniq!
+ @channels[channel][:modes].uniq!
+ end
end
# For managing channel
def on_part(m)
nick = m.prefix.nick
channel = m[0]
init_channel(channel)
- info = @channels[channel]
- if info
- info[:users].delete(nick)
- info[:modes].delete_if {|u|
- u[1] == nick
- }
+ @channels.synchronize do
+ info = @channels[channel]
+ if info
+ info[:users].delete(nick)
+ info[:modes].delete_if {|u|
+ u[1] == nick
+ }
+ end
end
end
# For managing channel
def on_quit(m)
nick = m.prefix.nick
- @channels.each do |channel, info|
- info[:users].delete(nick)
- info[:modes].delete_if {|u|
- u[1] == nick
- }
+ @channels.synchronize do
+ @channels.each do |channel, info|
+ info[:users].delete(nick)
+ info[:modes].delete_if {|u|
+ u[1] == nick
+ }
+ end
end
end
# For managing channel
def on_kick(m)
users = m[1].split(/,/)
- m[0].split(/,/).each do |chan|
- init_channel(chan)
- info = @channels[chan]
- if info
- users.each do |nick|
- info[:users].delete(nick)
- info[:modes].delete_if {|u|
- u[1] == nick
- }
+
+ @channels.synchronize do
+ m[0].split(/,/).each do |chan|
+ init_channel(chan)
+ info = @channels[chan]
+ if info
+ users.each do |nick|
+ info[:users].delete(nick)
+ info[:modes].delete_if {|u|
+ u[1] == nick
+ }
+ end
end
end
end
end
# For managing channel
def on_join(m)
nick = m.prefix.nick
channel = m[0]
- init_channel(channel)
- @channels[channel][:users] << nick
- @channels[channel][:users].uniq!
+ @channels.synchronize do
+ init_channel(channel)
+
+ @channels[channel][:users] << nick
+ @channels[channel][:users].uniq!
+ end
end
# For managing channel
def on_mode(m)
channel = m[0]
- init_channel(channel)
+ @channels.synchronize do
+ init_channel(channel)
- positive_mode = []
- negative_mode = []
+ positive_mode = []
+ negative_mode = []
- mode = positive_mode
- arg_pos = 0
- m[1].each_byte do |c|
- case c
- when ?+
- mode = positive_mode
- when ?-
- mode = negative_mode
- when ?o, ?v, ?k, ?l, ?b, ?e, ?I
- mode << [c.chr, m[arg_pos + 2]]
- arg_pos += 1
- else
- mode << [c.chr, nil]
+ mode = positive_mode
+ arg_pos = 0
+ m[1].each_byte do |c|
+ case c
+ when ?+
+ mode = positive_mode
+ when ?-
+ mode = negative_mode
+ when ?o, ?v, ?k, ?l, ?b, ?e, ?I
+ mode << [c.chr, m[arg_pos + 2]]
+ arg_pos += 1
+ else
+ mode << [c.chr, nil]
+ end
end
- end
- mode = nil
+ mode = nil
- negative_mode.each do |m|
- @channels[channel][:modes].delete(m)
- end
+ negative_mode.each do |m|
+ @channels[channel][:modes].delete(m)
+ end
- positive_mode.each do |m|
- @channels[channel][:modes] << m
- end
+ positive_mode.each do |m|
+ @channels[channel][:modes] << m
+ end
- @channels[channel][:modes].uniq!
- [negative_mode, positive_mode]
+ @channels[channel][:modes].uniq!
+ [negative_mode, positive_mode]
+ end
end
# For managing channel
def init_channel(channel)
@channels[channel] ||= {
@@ -717,11 +733,11 @@
attr_reader :prefix, :nick, :real, :host
# Override subclass.
def server_name
- "Net::IRC::Server::Session"
+ "net-irc"
end
# Override subclass.
def server_version
"0.0.0"
@@ -828,17 +844,19 @@
m = Message.new(prefix, command, params.map {|s|
s.gsub(/[\r\n]/, " ")
})
@log.debug "SEND: #{m.to_s.chomp}"
@socket << m
+ rescue IOError
+ finish
end
# Call when client connected.
# Send RPL_WELCOME sequence. If you want to customize, override this method at subclass.
def inital_message
- post nil, RPL_WELCOME, @nick, "Welcome to the Internet Relay Network #{@prefix}"
- post nil, RPL_YOURHOST, @nick, "Your host is #{server_name}, running version #{server_version}"
- post nil, RPL_CREATED, @nick, "This server was created #{Time.now}"
- post nil, RPL_MYINFO, @nick, "#{server_name} #{server_version} #{avaiable_user_modes} #{avaiable_channel_modes}"
+ post server_name, RPL_WELCOME, @nick, "Welcome to the Internet Relay Network #{@prefix}"
+ post server_name, RPL_YOURHOST, @nick, "Your host is #{server_name}, running version #{server_version}"
+ post server_name, RPL_CREATED, @nick, "This server was created #{Time.now}"
+ post server_name, RPL_MYINFO, @nick, "#{server_name} #{server_version} #{avaiable_user_modes} #{avaiable_channel_modes}"
end
end
end # Server