From 83ced8b38fe07d425df7fa9b9fadee98a4cba19e Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Tue, 1 Aug 2006 13:42:27 +0000 Subject: New Irc framework: fix channel modes handling --- lib/rbot/irc.rb | 114 ++++++++++++++++++++++++---------------------------- lib/rbot/ircbot.rb | 12 +++--- lib/rbot/rfc2812.rb | 9 +++-- 3 files changed, 64 insertions(+), 71 deletions(-) (limited to 'lib') diff --git a/lib/rbot/irc.rb b/lib/rbot/irc.rb index 6877af65..f9f3bc21 100644 --- a/lib/rbot/irc.rb +++ b/lib/rbot/irc.rb @@ -170,7 +170,7 @@ class ArrayOf < Array def internal_will_accept?(raising, *els) els.each { |el| unless el.class <= @element_class - raise TypeError if raising + raise TypeError, "#{el.inspect} is not of class #{@element_class}" if raising return false end } @@ -485,34 +485,49 @@ module Irc @set_by = set_by @set_on = Time.new end + + # Replace a ChannelTopic with another one + def replace(topic) + raise TypeError, "#{topic.inspect} is not an Irc::ChannelTopic" unless topic.class <= ChannelTopic + @text = topic.text.dup + @set_by = topic.set_by.dup + @set_on = topic.set_on.dup + end end # Mode on a channel class ChannelMode + def initialize(ch) + @channel = ch + end end # Channel modes of type A manipulate lists # class ChannelModeTypeA < ChannelMode - def initialize + def initialize(ch) + super @list = NetmaskList.new end def set(val) - @list << val unless @list.include?(val) + nm = @channel.server.new_netmask(val) + @list << nm unless @list.include?(nm) end def reset(val) - @list.delete(val) + nm = @channel.server.new_netmask(val) + @list.delete(nm) end end # Channel modes of type B need an argument # class ChannelModeTypeB < ChannelMode - def initialize + def initialize(ch) + super @arg = nil end @@ -531,16 +546,19 @@ module Irc # modes of type A # class ChannelUserMode < ChannelModeTypeB - def initialize + def initialize(ch) + super @list = UserList.new end def set(val) - @list << val unless @list.include?(val) + u = @channel.server.user(val) + @list << u unless @list.include?(u) end def reset(val) - @list.delete(val) + u = @channel.server.user(val) + @list.delete(u) end end @@ -548,7 +566,8 @@ module Irc # but not when they get reset # class ChannelModeTypeC < ChannelMode - def initialize + def initialize(ch) + super @arg = false end @@ -562,8 +581,9 @@ module Irc end # Channel modes of type D are basically booleans - class ChannelModeTypeD - def initialize + class ChannelModeTypeD < ChannelMode + def initialize(ch) + super @set = false end @@ -587,13 +607,14 @@ module Irc # * a set of modes # class Channel - attr_reader :name, :topic, :casemap, :mode, :users + attr_reader :name, :topic, :mode, :users, :server alias :to_s :name # A String describing the Channel and (some of its) internals # def inspect str = "<#{self.class}:#{'0x%08x' % self.object_id}:" + str << " on server #{server}" str << " @name=#{@name.inspect} @topic=#{@topic.text.inspect}" str << " @users=<#{@users.join(', ')}>" str @@ -607,14 +628,15 @@ module Irc # # FIXME doesn't check if users have the same casemap as the channel yet # - def initialize(name, topic=nil, users=[], casemap=nil) - @casemap = casemap || 'rfc1459' - + def initialize(server, name, topic=nil, users=[]) + raise TypeError, "First parameter must be an Irc::Server" unless server.class <= Server raise ArgumentError, "Channel name cannot be empty" if name.to_s.empty? raise ArgumentError, "Unknown channel prefix #{name[0].chr}" if name !~ /^[&#+!]/ raise ArgumentError, "Invalid character in #{name.inspect}" if name =~ /[ \x07,]/ - @name = name.irc_downcase(@casemap) + @server = server + + @name = name.irc_downcase(casemap) @topic = topic || ChannelTopic.new @@ -631,6 +653,11 @@ module Irc @mode = {} end + # Returns the casemap of the originating server + def casemap + return @server.casemap + end + # Removes a user from the channel # def delete_user(user) @@ -673,7 +700,7 @@ module Irc # Create a new mode # def create_mode(sym, kl) - @mode[sym.to_sym] = kl.new + @mode[sym.to_sym] = kl.new(self) end end @@ -802,6 +829,7 @@ module Irc # See the RPL_ISUPPORT draft[http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt] # def parse_isupport(line) + debug "Parsing ISUPPORT #{line.inspect}" ar = line.split(' ') reparse = "" ar.each { |en| @@ -837,10 +865,10 @@ module Irc when :chanmodes noval_warn(key, val) { groups = val.split(',') - @supports[key][:typea] = groups[0].scan(/./) - @supports[key][:typeb] = groups[1].scan(/./) - @supports[key][:typec] = groups[2].scan(/./) - @supports[key][:typed] = groups[3].scan(/./) + @supports[key][:typea] = groups[0].scan(/./).map { |x| x.to_sym} + @supports[key][:typeb] = groups[1].scan(/./).map { |x| x.to_sym} + @supports[key][:typec] = groups[2].scan(/./).map { |x| x.to_sym} + @supports[key][:typed] = groups[3].scan(/./).map { |x| x.to_sym} } when :channellen, :kicklen, :modes, :topiclen if val @@ -863,8 +891,8 @@ module Irc when :prefix if val val.scan(/\((.*)\)(.*)/) { |m, p| - @supports[key][:modes] = m.scan(/./) - @supports[key][:prefixes] = p.scan(/./) + @supports[key][:modes] = m.scan(/./).map { |x| x.to_sym} + @supports[key][:prefixes] = p.scan(/./).map { |x| x.to_sym} } else @supports[key][:modes] = nil @@ -965,7 +993,7 @@ module Irc # So far, everything is fine. Now create the actual Channel # - chan = Channel.new(name, topic, users, self.casemap) + chan = Channel.new(self, name, topic, users) # We wade through +prefix+ and +chanmodes+ to create appropriate # lists and flags for this channel @@ -1126,41 +1154,3 @@ module Irc end end -# TODO test cases - -if __FILE__ == $0 - -include Irc - - # puts " -- irc_regexp tests" - # ["*", "a?b", "a*b", "a\\*b", "a\\?b", "a?\\*b", "*a*\\**b?"].each { |s| - # puts " --" - # puts s.inspect - # puts s.to_irc_regexp.inspect - # puts "aUb".match(s.to_irc_regexp)[0] if "aUb" =~ s.to_irc_regexp - # } - - # puts " -- Netmasks" - # masks = [] - # masks << Netmask.new("start") - # masks << masks[0].dup - # masks << Netmask.new(masks[0]) - # puts masks.join("\n") - - # puts " -- Changing 1" - # masks[1].nick = "me" - # puts masks.join("\n") - - # puts " -- Changing 2" - # masks[2].nick = "you" - # puts masks.join("\n") - - # puts " -- Channel example" - # ch = Channel.new("#prova") - # p ch - # puts " -- Methods" - # puts ch.methods.sort.join("\n") - # puts " -- Instance variables" - # puts ch.instance_variables.join("\n") - -end diff --git a/lib/rbot/ircbot.rb b/lib/rbot/ircbot.rb index a42d27ba..42f39b16 100644 --- a/lib/rbot/ircbot.rb +++ b/lib/rbot/ircbot.rb @@ -442,9 +442,11 @@ class IrcBot @plugins.delegate("nick", m) } @client[:quit] = proc {|data| - m = QuitMessage.new(self, @server, data[:source], data[:source], data[:message]) + source = data[:source] + message = data[:message] + m = QuitMessage.new(self, @server, source, source, message) data[:was_on].each { |ch| - irclog "@ Quit: #{data[:source].nick}: #{message}", ch + irclog "@ Quit: #{source}: #{message}", ch } @plugins.delegate("listen", m) @plugins.delegate("quit", m) @@ -1012,10 +1014,10 @@ class IrcBot end def irclogtopic(m) - if source == myself - irclog "@ I set topic \"#{topic}\"", channel + if m.source == myself + irclog "@ I set topic \"#{m.topic}\"", m.channel else - irclog "@ #{source} set topic \"#{topic}\"", channel + irclog "@ #{m.source} set topic \"#{m.topic}\"", m.channel end end diff --git a/lib/rbot/rfc2812.rb b/lib/rbot/rfc2812.rb index c8e2e410..19b39159 100644 --- a/lib/rbot/rfc2812.rb +++ b/lib/rbot/rfc2812.rb @@ -954,7 +954,7 @@ module Irc # PREFIX=(ov)@+ CASEMAPPING=ascii CAPAB IRCD=dancer :are available # on this server" # - @server.parse_isupport(params.split(' ', 2).last) + @server.parse_isupport(argv[1..-2].join(' ')) handle(:isupport, data) when ERR_NICKNAMEINUSE # "* :Nickname is already in use" @@ -1018,7 +1018,7 @@ module Irc u = @server.user(ar[0]) chan.users << u if ar[1] - m = @server.supports[:prefix][:prefixes].index(ar[1]) + m = @server.supports[:prefix][:prefixes].index(ar[1].to_sym) m = @server.supports[:prefix][:modes][m] chan.mode[m.to_sym].set(u) end @@ -1151,7 +1151,7 @@ module Irc when 'TOPIC' data[:channel] = @server.channel(argv[0]) data[:topic] = ChannelTopic.new(argv[1], data[:source], Time.new) - data[:channel].topic = data[:topic] + data[:channel].topic.replace(data[:topic]) handle(:changetopic, data) when 'INVITE' @@ -1195,7 +1195,8 @@ module Irc argv[1..-1].each { |arg| setting = arg[0].chr if "+-".include?(setting) - arg[1..-1].each_byte { |m| + arg[1..-1].each_byte { |b| + m = b.chr case m.to_sym when *@server.supports[:chanmodes][:typea] data[:modes] << [setting + m] -- cgit v1.2.3