From 6e0297efd99e34609d6895089e730ce9177c8655 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Sat, 6 Jan 2007 21:29:44 +0000 Subject: Irc framework: fix errors in filling up the user lists for channels --- lib/rbot/irc.rb | 59 +++++++++++++++++++++++++++++++++++++++++++++-------- lib/rbot/rfc2812.rb | 24 +++++++++++++--------- 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/lib/rbot/irc.rb b/lib/rbot/irc.rb index f2425d6a..31c14802 100644 --- a/lib/rbot/irc.rb +++ b/lib/rbot/irc.rb @@ -4,6 +4,8 @@ # Channels is the User on (of those the client is on too)? # We may want this so that when a User leaves all Channels and he hasn't # sent us privmsgs, we know remove him from the Server @users list +# * Maybe ChannelList and UserList should be HashesOf instead of ArrayOf? +# See items marked as TODO Ho #++ # :title: IRC module # @@ -851,6 +853,8 @@ module Irc # Channel modes of type A manipulate lists # + # Example: b (banlist) + # class ModeTypeA < Mode def initialize(ch) super @@ -872,6 +876,8 @@ module Irc # Channel modes of type B need an argument # + # Example: k (key) + # class ModeTypeB < Mode def initialize(ch) super @@ -916,6 +922,8 @@ module Irc # Channel modes of type C need an argument when set, # but not when they get reset # + # Example: l (limit) + # class ModeTypeC < Mode def initialize(ch) super @@ -939,6 +947,8 @@ module Irc # Channel modes of type D are basically booleans # + # Example: m (moderate) + # class ModeTypeD < Mode def initialize(ch) super @@ -1024,7 +1034,7 @@ module Irc str = "<#{self.class}:#{'0x%x' % self.object_id}:" str << " on server #{server}" if server str << " @name=#{@name.inspect} @topic=#{@topic.text.inspect}" - str << " @users=[#{@users.sort.join(', ')}]" + str << " @users=[#{user_nicks.sort.join(', ')}]" str << ">" end @@ -1034,6 +1044,35 @@ module Irc self end + # TODO Ho + def user_nicks + @users.map { |u| u.downcase } + end + + # Checks if the receiver already has a user with the given _nick_ + # + def has_user?(nick) + user_nicks.index(nick.irc_downcase(casemap)) + end + + # Returns the user with nick _nick_, if available + # + def get_user(nick) + idx = has_user?(nick) + @users[idx] if idx + end + + # Adds a user to the channel + # + def add_user(user, opts={}) + silent = opts.fetch(:silent, false) + if has_user?(user) && !silent + warn "Trying to add user #{user} to channel #{self} again" + else + @users << user.to_irc_user(server_and_casemap) + end + end + # Creates a new channel with the given name, optionally setting the topic # and an initial users list. # @@ -1054,7 +1093,7 @@ module Irc @users = UserList.new users.each { |u| - @users << u.to_irc_user(server_and_casemap) + add_user(u) } # Flags @@ -1079,25 +1118,25 @@ module Irc # A channel is local to a server if it has the '&' prefix # def local? - name[0] = 0x26 + name[0] == 0x26 end # A channel is modeless if it has the '+' prefix # def modeless? - name[0] = 0x2b + name[0] == 0x2b end # A channel is safe if it has the '!' prefix # def safe? - name[0] = 0x21 + name[0] == 0x21 end # A channel is normal if it has the '#' prefix # def normal? - name[0] = 0x23 + name[0] == 0x23 end # Create a new mode @@ -1150,10 +1189,12 @@ module Irc attr_reader :channels, :users + # TODO Ho def channel_names @channels.map { |ch| ch.downcase } end + # TODO Ho def user_nicks @users.map { |u| u.downcase } end @@ -1396,7 +1437,7 @@ module Irc # Checks if the receiver already has a channel with the given _name_ # def has_channel?(name) - channel_names.index(name.downcase) + channel_names.index(name.irc_downcase(casemap)) end alias :has_chan? :has_channel? @@ -1500,7 +1541,7 @@ module Irc # Checks if the receiver already has a user with the given _nick_ # def has_user?(nick) - user_nicks.index(nick.downcase) + user_nicks.index(nick.irc_downcase(casemap)) end # Returns the user with nick _nick_, if available @@ -1582,7 +1623,7 @@ module Irc @users.inject(UserList.new) { |list, user| if user.user == "*" or user.host == "*" - list << user if user.nick.downcase =~ nm.nick.downcase.to_irc_regexp + list << user if user.nick.irc_downcase(casemap) =~ nm.nick.irc_downcase(casemap).to_irc_regexp else list << user if user.matches?(nm) end diff --git a/lib/rbot/rfc2812.rb b/lib/rbot/rfc2812.rb index 26549539..900c750d 100644 --- a/lib/rbot/rfc2812.rb +++ b/lib/rbot/rfc2812.rb @@ -1009,7 +1009,7 @@ module Irc users = [] argv[3].scan(/\S+/).each { |u| # FIXME beware of servers that allow multiple prefixes - if(u =~ /^(#{@server.supports[:prefix][:prefixes].join})?(.*)$/) + if(u =~ /^([#{@server.supports[:prefix][:prefixes].join}])?(.*)$/) umode = $1 user = $2 users << [user, umode] @@ -1018,11 +1018,13 @@ module Irc users.each { |ar| u = @server.user(ar[0]) - chan.users << u unless chan.users.include?(u) + chan.add_user(u, :silent => true) + debug "Adding user #{u}" if 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) + ms = @server.supports[:prefix][:modes][m] + debug "\twith mode #{ar[1]} (#{ms})" + chan.mode[ms].set(u) end } @tmpusers += users @@ -1155,8 +1157,8 @@ module Irc when 'QUIT' data[:message] = argv[0] data[:was_on] = @server.channels.inject(ChannelList.new) { |list, ch| - list << ch if ch.users.include?(data[:source]) - list + list << ch if ch.has_user?(data[:source]) + list } @server.delete_user(data[:source]) @@ -1164,7 +1166,7 @@ module Irc handle(:quit, data) when 'JOIN' data[:channel] = @server.channel(argv[0]) - data[:channel].users << data[:source] + data[:channel].add_user(data[:source]) handle(:join, data) when 'TOPIC' @@ -1180,7 +1182,7 @@ module Irc handle(:invite, data) when 'NICK' data[:is_on] = @server.channels.inject(ChannelList.new) { |list, ch| - list << ch if ch.users.include?(data[:source]) + list << ch if ch.has_user?(data[:source]) list } @@ -1203,6 +1205,7 @@ module Irc case data[:channel] when User # TODO + warn "Unhandled user mode message '#{serverstring}'" else # data[:modes] is an array where each element # is either a flag which doesn't need parameters @@ -1238,13 +1241,13 @@ module Irc data[:modes] << [setting + m] who_wants_params << data[:modes].length - 1 else - warn "Unknown mode #{m} in #{serverstring}" + warn "Unknown mode #{m} in #{serverstring.inspect}" end } else idx = who_wants_params.shift if idx.nil? - warn "Oops, problems parsing #{serverstring}" + warn "Oops, problems parsing #{serverstring.inspect}" break end data[:modes][idx] << arg @@ -1268,6 +1271,7 @@ module Irc handle(:mode, data) else + warn "Unknown message #{serverstring.inspect}" handle(:unknown, data) end end -- cgit v1.2.3