net-yail 1.0.1 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +18 -0
 - data/examples/logger/default.yml +4 -0
 - data/examples/logger/logger_bot.rb +125 -0
 - data/examples/logger/run.rb +40 -0
 - data/lib/net/yail.rb +18 -10
 - data/lib/net/yail/IRCBot.rb +23 -7
 - data/lib/net/yail/default_events.rb +6 -0
 - data/lib/net/yail/output_api.rb +63 -0
 - metadata +46 -36
 
    
        data/CHANGELOG
    CHANGED
    
    | 
         @@ -2,3 +2,21 @@ 
     | 
|
| 
       2 
2 
     | 
    
         
             
            * Fixed IRCBot to be part of the net/yail namespace so you can subclass
         
     | 
| 
       3 
3 
     | 
    
         
             
              without copying the file into your own project
         
     | 
| 
       4 
4 
     | 
    
         
             
            * Fixed IRCBot to actually be usable (fixed require)
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            2008-07-02:
         
     | 
| 
      
 7 
     | 
    
         
            +
            * Minor documentation fixes
         
     | 
| 
      
 8 
     | 
    
         
            +
            * Args aren't automatically duped for all handlers anymore, as that caused
         
     | 
| 
      
 9 
     | 
    
         
            +
              output handling to break (args come in, go to handler, get duped, get
         
     | 
| 
      
 10 
     | 
    
         
            +
              filtered, handler chain ends, required YAIL output methods finish with the
         
     | 
| 
      
 11 
     | 
    
         
            +
              original, unfiltered args)
         
     | 
| 
      
 12 
     | 
    
         
            +
            * All output APIs now dup the args at the top level to deal with above issue
         
     | 
| 
      
 13 
     | 
    
         
            +
            * Added more details to Rakefile - homepage and rubyforge project
         
     | 
| 
      
 14 
     | 
    
         
            +
            * Bumped to version 1.0.2 - will release gem only after a little testing,
         
     | 
| 
      
 15 
     | 
    
         
            +
              though
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            2008-07-03:
         
     | 
| 
      
 18 
     | 
    
         
            +
            * IRCBot can now auto-join multiple channels, and has a built-in uptime
         
     | 
| 
      
 19 
     | 
    
         
            +
              system.
         
     | 
| 
      
 20 
     | 
    
         
            +
            * Net::YAIL now has handling for INVITE messages
         
     | 
| 
      
 21 
     | 
    
         
            +
            * Added fully working logger bot for a solid example
         
     | 
| 
      
 22 
     | 
    
         
            +
            * Since changes are more extensive then a minor release, bumping to 1.1.1
         
     | 
| 
         @@ -0,0 +1,125 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'net/yail/IRCBot'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'date'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            class LoggerBot < IRCBot
         
     | 
| 
      
 8 
     | 
    
         
            +
              BOTNAME = 'Logger'
         
     | 
| 
      
 9 
     | 
    
         
            +
              BOTVERSION = 'v0.1.0'
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              public
         
     | 
| 
      
 12 
     | 
    
         
            +
              # Starts a new instance
         
     | 
| 
      
 13 
     | 
    
         
            +
              #
         
     | 
| 
      
 14 
     | 
    
         
            +
              # Options:
         
     | 
| 
      
 15 
     | 
    
         
            +
              # * <tt>:irc_network</tt>: IP/name of server
         
     | 
| 
      
 16 
     | 
    
         
            +
              # * <tt>:port</tt>: ...
         
     | 
| 
      
 17 
     | 
    
         
            +
              # * <tt>:loud</tt>: Overly-verbose logging
         
     | 
| 
      
 18 
     | 
    
         
            +
              # * <tt>:silent</tt>: Very little logging
         
     | 
| 
      
 19 
     | 
    
         
            +
              # * <tt>:master</tt>: User who can order quits
         
     | 
| 
      
 20 
     | 
    
         
            +
              # * <tt>:output_dir</tt>: Where to store log files
         
     | 
| 
      
 21 
     | 
    
         
            +
              def initialize(options = {})
         
     | 
| 
      
 22 
     | 
    
         
            +
                @master       = options.delete(:master)
         
     | 
| 
      
 23 
     | 
    
         
            +
                @output_dir   = options.delete(:output_dir) || File.dirname(__FILE__)
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                # Log files per channel - logs rotate every so often, so we have to store
         
     | 
| 
      
 26 
     | 
    
         
            +
                # filenames on a per-channel basis
         
     | 
| 
      
 27 
     | 
    
         
            +
                @current_log  = {}
         
     | 
| 
      
 28 
     | 
    
         
            +
                @log_date     = {}
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                options[:username] = BOTNAME
         
     | 
| 
      
 31 
     | 
    
         
            +
                options[:realname] = BOTNAME
         
     | 
| 
      
 32 
     | 
    
         
            +
                options[:nicknames] = ['LoggerBot', 'Logger_Bot', 'logger_bot', '_LoggerBot', 'LoggerBot_']
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                # Set up IRCBot, our loving parent, and begin
         
     | 
| 
      
 35 
     | 
    
         
            +
                super(options)
         
     | 
| 
      
 36 
     | 
    
         
            +
                self.connect_socket
         
     | 
| 
      
 37 
     | 
    
         
            +
                self.start_listening
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              # Add hooks on startup (base class's start method calls add_custom_handlers)
         
     | 
| 
      
 41 
     | 
    
         
            +
              def add_custom_handlers
         
     | 
| 
      
 42 
     | 
    
         
            +
                # Set up hooks
         
     | 
| 
      
 43 
     | 
    
         
            +
                @irc.prepend_handler(:incoming_msg,             self.method(:_in_msg))
         
     | 
| 
      
 44 
     | 
    
         
            +
                @irc.prepend_handler(:incoming_act,             self.method(:_in_act))
         
     | 
| 
      
 45 
     | 
    
         
            +
                @irc.prepend_handler(:incoming_invite,          self.method(:_in_invited))
         
     | 
| 
      
 46 
     | 
    
         
            +
                @irc.prepend_handler(:incoming_kick,            self.method(:_in_kick))
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
              private
         
     | 
| 
      
 50 
     | 
    
         
            +
              # Incoming message handler
         
     | 
| 
      
 51 
     | 
    
         
            +
              def _in_msg(fullactor, user, channel, text)
         
     | 
| 
      
 52 
     | 
    
         
            +
                # check if this is a /msg command, or normal channel talk
         
     | 
| 
      
 53 
     | 
    
         
            +
                incoming_private_message(user, text) if (channel =~ /#{bot_name}/)
         
     | 
| 
      
 54 
     | 
    
         
            +
                incoming_channel_message(user, channel, text)
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
              def _in_act(fullactor, user, channel, text)
         
     | 
| 
      
 58 
     | 
    
         
            +
                # check if this is a /msg command, or normal channel talk
         
     | 
| 
      
 59 
     | 
    
         
            +
                return if (channel =~ /#{bot_name}/)
         
     | 
| 
      
 60 
     | 
    
         
            +
                log_channel_message(user, channel, "#{user} #{text}")
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
              # TODO: recalls the most recent logs for a given channel by reading from
         
     | 
| 
      
 64 
     | 
    
         
            +
              # the file system or using a hash of log data.  Num maxes out at 100 for
         
     | 
| 
      
 65 
     | 
    
         
            +
              # general sanity
         
     | 
| 
      
 66 
     | 
    
         
            +
              def recent_logs(channel, num = 10)
         
     | 
| 
      
 67 
     | 
    
         
            +
                raise "Not implemented"
         
     | 
| 
      
 68 
     | 
    
         
            +
              end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
              def incoming_channel_message(user, channel, text)
         
     | 
| 
      
 71 
     | 
    
         
            +
                # check for special stuff before keywords
         
     | 
| 
      
 72 
     | 
    
         
            +
                # Nerdmaster is allowed to do special ordering
         
     | 
| 
      
 73 
     | 
    
         
            +
                if @master == user
         
     | 
| 
      
 74 
     | 
    
         
            +
                  if (text == "#{bot_name}: QUIT")
         
     | 
| 
      
 75 
     | 
    
         
            +
                    self.irc.quit("Ordered by my master")
         
     | 
| 
      
 76 
     | 
    
         
            +
                    sleep 1
         
     | 
| 
      
 77 
     | 
    
         
            +
                    exit
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                case text
         
     | 
| 
      
 82 
     | 
    
         
            +
                  when /^\s*#{bot_name}(:|)\s*uptime\s*$/i
         
     | 
| 
      
 83 
     | 
    
         
            +
                    msg(channel, get_uptime_string)
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  when /botcheck/i
         
     | 
| 
      
 86 
     | 
    
         
            +
                    msg(channel, "#{BOTNAME} #{BOTVERSION}")
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                  else
         
     | 
| 
      
 89 
     | 
    
         
            +
                    log_channel_message(user, channel, "<#{user}> #{text}")
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
              end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
              # Logs the message data to a flat text file.  Fun.
         
     | 
| 
      
 94 
     | 
    
         
            +
              def log_channel_message(user, channel, text)
         
     | 
| 
      
 95 
     | 
    
         
            +
                today = Date.today
         
     | 
| 
      
 96 
     | 
    
         
            +
                if @current_log[channel].nil? || @log_date[channel] != today
         
     | 
| 
      
 97 
     | 
    
         
            +
                  chan_dir = @output_dir + '/' + channel
         
     | 
| 
      
 98 
     | 
    
         
            +
                  Dir::mkdir(chan_dir) unless File.exists?(chan_dir)
         
     | 
| 
      
 99 
     | 
    
         
            +
                  filename = chan_dir + '/' + today.strftime('%Y%m%d') + '.log'
         
     | 
| 
      
 100 
     | 
    
         
            +
                  @current_log[channel] = filename
         
     | 
| 
      
 101 
     | 
    
         
            +
                  @log_date[channel] = today
         
     | 
| 
      
 102 
     | 
    
         
            +
                end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                time = Time.now.strftime '%H:%M:%S'
         
     | 
| 
      
 105 
     | 
    
         
            +
                File.open(@current_log[channel], 'a') do |f|
         
     | 
| 
      
 106 
     | 
    
         
            +
                  f.puts "[#{time}] #{text}"
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
              end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
              # Invited to a channel for logging purposes - simply auto-join for now.
         
     | 
| 
      
 111 
     | 
    
         
            +
              # Maybe allow only @master one day, or array of authorized users.
         
     | 
| 
      
 112 
     | 
    
         
            +
              def _in_invited(fullactor, actor, target)
         
     | 
| 
      
 113 
     | 
    
         
            +
                join target
         
     | 
| 
      
 114 
     | 
    
         
            +
              end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
              # If bot is kicked, he must rejoin!
         
     | 
| 
      
 117 
     | 
    
         
            +
              def _in_kick(fullactor, actor, target, object, text)
         
     | 
| 
      
 118 
     | 
    
         
            +
                if object == bot_name
         
     | 
| 
      
 119 
     | 
    
         
            +
                  # Rejoin almost immediately - logging is important.
         
     | 
| 
      
 120 
     | 
    
         
            +
                  join target
         
     | 
| 
      
 121 
     | 
    
         
            +
                end
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                return true
         
     | 
| 
      
 124 
     | 
    
         
            +
              end
         
     | 
| 
      
 125 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,40 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'logger_bot'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'getopt/long'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            # This code just launches our logger with certain parameters.
         
     | 
| 
      
 8 
     | 
    
         
            +
            #
         
     | 
| 
      
 9 
     | 
    
         
            +
            # If options are specified, they override the default yaml file.  If a
         
     | 
| 
      
 10 
     | 
    
         
            +
            # different yaml file is specified, its settings are read, then overridden
         
     | 
| 
      
 11 
     | 
    
         
            +
            # by options.
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            opt = Getopt::Long.getopts(
         
     | 
| 
      
 14 
     | 
    
         
            +
              ['--silent',      '-s', Getopt::BOOLEAN],
         
     | 
| 
      
 15 
     | 
    
         
            +
              ['--loud',        '-l', Getopt::BOOLEAN],
         
     | 
| 
      
 16 
     | 
    
         
            +
              ['--network',     '-n', Getopt::OPTIONAL],
         
     | 
| 
      
 17 
     | 
    
         
            +
              ['--output-dir',  '-o', Getopt::OPTIONAL],
         
     | 
| 
      
 18 
     | 
    
         
            +
              ['--master',      '-m', Getopt::OPTIONAL],
         
     | 
| 
      
 19 
     | 
    
         
            +
              ['--yaml',        '-y', Getopt::OPTIONAL]
         
     | 
| 
      
 20 
     | 
    
         
            +
            )
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            opt['yaml'] ||= File.dirname(__FILE__) + '/default.yml'
         
     | 
| 
      
 23 
     | 
    
         
            +
            if File.exists?(opt['yaml'])
         
     | 
| 
      
 24 
     | 
    
         
            +
              options = File.open(opt['yaml']) {|f| YAML::load(f)}
         
     | 
| 
      
 25 
     | 
    
         
            +
            else
         
     | 
| 
      
 26 
     | 
    
         
            +
              options = {}
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            for key in %w{silent loud network output-dir master}
         
     | 
| 
      
 30 
     | 
    
         
            +
              options[key] ||= opt[key]
         
     | 
| 
      
 31 
     | 
    
         
            +
            end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            @bot = LoggerBot.new(
         
     | 
| 
      
 34 
     | 
    
         
            +
              :silent       => options['silent'],
         
     | 
| 
      
 35 
     | 
    
         
            +
              :loud         => options['loud'],
         
     | 
| 
      
 36 
     | 
    
         
            +
              :irc_network  => options['network'],
         
     | 
| 
      
 37 
     | 
    
         
            +
              :output_dir   => options['output-dir'],
         
     | 
| 
      
 38 
     | 
    
         
            +
              :master       => options['master']
         
     | 
| 
      
 39 
     | 
    
         
            +
            )
         
     | 
| 
      
 40 
     | 
    
         
            +
            @bot.irc_loop
         
     | 
    
        data/lib/net/yail.rb
    CHANGED
    
    | 
         @@ -15,6 +15,14 @@ require 'net/yail/output_api' 
     | 
|
| 
       15 
15 
     | 
    
         
             
            # * Build a system to allow numeric events to get sent post-processed data
         
     | 
| 
       16 
16 
     | 
    
         
             
            #   if it makes sense (converting the text to specific parts instead of all
         
     | 
| 
       17 
17 
     | 
    
         
             
            #   handlers having to regex it themselves, for instance)
         
     | 
| 
      
 18 
     | 
    
         
            +
            # * To deal with the required post-handler logic in the output API, and
         
     | 
| 
      
 19 
     | 
    
         
            +
            #   "nicely" deal with filtering output, it may be better to have a separate
         
     | 
| 
      
 20 
     | 
    
         
            +
            #   hash of YAIL-required post-handlers.  This would allow all logic to be
         
     | 
| 
      
 21 
     | 
    
         
            +
            #   done as handlers (makes things more consistent) as well as getting rid of
         
     | 
| 
      
 22 
     | 
    
         
            +
            #   the funky arg duping on a per-API-method basis (putting the auto-dupe back
         
     | 
| 
      
 23 
     | 
    
         
            +
            #   in the handle method)
         
     | 
| 
      
 24 
     | 
    
         
            +
            # * Handle this:
         
     | 
| 
      
 25 
     | 
    
         
            +
            #   (14:45.25) +++INCOMING: :Nerdmaster!xxx@yyyy INVITE botname :#channel_name
         
     | 
| 
       18 
26 
     | 
    
         | 
| 
       19 
27 
     | 
    
         
             
            # If a thread crashes, I want the app to die.  My threads are persistent, not
         
     | 
| 
       20 
28 
     | 
    
         
             
            # temporary.
         
     | 
| 
         @@ -45,6 +53,7 @@ module Net 
     | 
|
| 
       45 
53 
     | 
    
         
             
            # Current list of incoming events and the parameters sent to the handler:
         
     | 
| 
       46 
54 
     | 
    
         
             
            # * :incoming_msg(fullactor, actor, target, text) - Normal message from actor to target
         
     | 
| 
       47 
55 
     | 
    
         
             
            # * :incoming_act(fullactor, actor, target, text) - CTCP "action" (emote) from actor to target
         
     | 
| 
      
 56 
     | 
    
         
            +
            # * :incoming_invite(fullactor, actor, target, text) - INVITE to target channel from actor
         
     | 
| 
       48 
57 
     | 
    
         
             
            # * :incoming_ctcp(fullactor, actor, target, text) - CTCP other than "action" from actor to target
         
     | 
| 
       49 
58 
     | 
    
         
             
            # * :incoming_ctcpreply(fullactor, actor, target, text) - CTCP NOTICE from actor to target
         
     | 
| 
       50 
59 
     | 
    
         
             
            # * :incoming_notice(fullactor, actor, target, text) - other NOTICE from actor to target
         
     | 
| 
         @@ -158,7 +167,7 @@ module Net 
     | 
|
| 
       158 
167 
     | 
    
         
             
            #     :nicknames  => ['bot1', 'bot2', 'bot3']
         
     | 
| 
       159 
168 
     | 
    
         
             
            #   )
         
     | 
| 
       160 
169 
     | 
    
         
             
            #
         
     | 
| 
       161 
     | 
    
         
            -
            #   irc.prepend_handler :incoming_welcome, proc {
         
     | 
| 
      
 170 
     | 
    
         
            +
            #   irc.prepend_handler :incoming_welcome, proc {|text, args|
         
     | 
| 
       162 
171 
     | 
    
         
             
            #     irc.join('#foo')
         
     | 
| 
       163 
172 
     | 
    
         
             
            #     return false
         
     | 
| 
       164 
173 
     | 
    
         
             
            #   }
         
     | 
| 
         @@ -178,7 +187,7 @@ module Net 
     | 
|
| 
       178 
187 
     | 
    
         
             
            #   require 'rubygems'
         
     | 
| 
       179 
188 
     | 
    
         
             
            #   require 'net/yail'
         
     | 
| 
       180 
189 
     | 
    
         
             
            #
         
     | 
| 
       181 
     | 
    
         
            -
            #   def welcome
         
     | 
| 
      
 190 
     | 
    
         
            +
            #   def welcome(text, args)
         
     | 
| 
       182 
191 
     | 
    
         
             
            #     @irc.join('#channel')
         
     | 
| 
       183 
192 
     | 
    
         
             
            #     return false
         
     | 
| 
       184 
193 
     | 
    
         
             
            #   end
         
     | 
| 
         @@ -199,7 +208,9 @@ module Net 
     | 
|
| 
       199 
208 
     | 
    
         
             
            #
         
     | 
| 
       200 
209 
     | 
    
         
             
            # =Better example
         
     | 
| 
       201 
210 
     | 
    
         
             
            #
         
     | 
| 
       202 
     | 
    
         
            -
            # See the included  
     | 
| 
      
 211 
     | 
    
         
            +
            # See the included logger bot (under the examples directory of this project)
         
     | 
| 
      
 212 
     | 
    
         
            +
            # for use of the IRCBot base class.  It's a fully working bot example with
         
     | 
| 
      
 213 
     | 
    
         
            +
            # real-world use.
         
     | 
| 
       203 
214 
     | 
    
         
             
            class YAIL 
         
     | 
| 
       204 
215 
     | 
    
         
             
              include Net::IRCEvents::Magic
         
     | 
| 
       205 
216 
     | 
    
         
             
              include Net::IRCEvents::Defaults
         
     | 
| 
         @@ -417,7 +428,9 @@ class YAIL 
     | 
|
| 
       417 
428 
     | 
    
         
             
              # Gets some input, sends stuff off to a handler.  Yay.
         
     | 
| 
       418 
429 
     | 
    
         
             
              def process_input(line)
         
     | 
| 
       419 
430 
     | 
    
         
             
                case line
         
     | 
| 
       420 
     | 
    
         
            -
                  when /^:((.+?)(?:!.+?)?)  
     | 
| 
      
 431 
     | 
    
         
            +
                  when /^:((.+?)(?:!.+?)?) INVITE \S+ :(\S+)/i
         
     | 
| 
      
 432 
     | 
    
         
            +
                    handle :incoming_invite, $1, $2, $3
         
     | 
| 
      
 433 
     | 
    
         
            +
                  when /^:((.+?)(?:!.+?)?) PRIVMSG (\S+) :?\001ACTION (.+?)\001$/i
         
     | 
| 
       421 
434 
     | 
    
         
             
                    handle :incoming_act, $1, $2, $3, $4
         
     | 
| 
       422 
435 
     | 
    
         
             
                  when /^:((.+?)(?:!.+?)?) PRIVMSG (\S+?) :?\001(.+?)\001$/i
         
     | 
| 
       423 
436 
     | 
    
         
             
                    handle :incoming_ctcp, $1, $2, $3, $4
         
     | 
| 
         @@ -483,11 +496,6 @@ class YAIL 
     | 
|
| 
       483 
496 
     | 
    
         | 
| 
       484 
497 
     | 
    
         
             
                report "+++EVENT HANDLER: Handling event #{event} via #{@handlers[event].inspect}:" if @loud
         
     | 
| 
       485 
498 
     | 
    
         | 
| 
       486 
     | 
    
         
            -
                # To allow others to modify args without messing up potentially important
         
     | 
| 
       487 
     | 
    
         
            -
                # internal data, dupe the array using a deep copy.  Hacky for sure, but
         
     | 
| 
       488 
     | 
    
         
            -
                # effective.
         
     | 
| 
       489 
     | 
    
         
            -
                new_args = Marshal.load(Marshal.dump(arguments))
         
     | 
| 
       490 
     | 
    
         
            -
             
     | 
| 
       491 
499 
     | 
    
         
             
                # Call all hooks in order until one breaks the chain.  For incoming
         
     | 
| 
       492 
500 
     | 
    
         
             
                # events, we want something to break the chain or else it'll likely
         
     | 
| 
       493 
501 
     | 
    
         
             
                # hit a reporter.  For outgoing events, we tend to report them anyway,
         
     | 
| 
         @@ -495,7 +503,7 @@ class YAIL 
     | 
|
| 
       495 
503 
     | 
    
         
             
                # to take full control over them.
         
     | 
| 
       496 
504 
     | 
    
         
             
                result = false
         
     | 
| 
       497 
505 
     | 
    
         
             
                for handler in @handlers[event]
         
     | 
| 
       498 
     | 
    
         
            -
                  result = handler.call(* 
     | 
| 
      
 506 
     | 
    
         
            +
                  result = handler.call(*arguments)
         
     | 
| 
       499 
507 
     | 
    
         
             
                  break if result == true
         
     | 
| 
       500 
508 
     | 
    
         
             
                end
         
     | 
| 
       501 
509 
     | 
    
         
             
              end
         
     | 
    
        data/lib/net/yail/IRCBot.rb
    CHANGED
    
    | 
         @@ -2,9 +2,6 @@ require 'rubygems' 
     | 
|
| 
       2 
2 
     | 
    
         
             
            require 'net/yail'
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            # My abstraction from adapter to a real bot.
         
     | 
| 
       5 
     | 
    
         
            -
            #
         
     | 
| 
       6 
     | 
    
         
            -
            # At the moment this only supports single-channel joining.  It's just a very
         
     | 
| 
       7 
     | 
    
         
            -
            # basic example, kids.  Deal with it.
         
     | 
| 
       8 
5 
     | 
    
         
             
            class IRCBot
         
     | 
| 
       9 
6 
     | 
    
         
             
              attr_reader :irc
         
     | 
| 
       10 
7 
     | 
    
         | 
| 
         @@ -16,7 +13,7 @@ class IRCBot 
     | 
|
| 
       16 
13 
     | 
    
         
             
              #
         
     | 
| 
       17 
14 
     | 
    
         
             
              # Options:
         
     | 
| 
       18 
15 
     | 
    
         
             
              # * <tt>:irc_network</tt>: Name/IP of the IRC server
         
     | 
| 
       19 
     | 
    
         
            -
              # * <tt>: 
     | 
| 
      
 16 
     | 
    
         
            +
              # * <tt>:channels</tt>: Channels to automatically join on connect
         
     | 
| 
       20 
17 
     | 
    
         
             
              # * <tt>:port</tt>: Port number, defaults to 6667
         
     | 
| 
       21 
18 
     | 
    
         
             
              # * <tt>:username</tt>: Username reported to server
         
     | 
| 
       22 
19 
     | 
    
         
             
              # * <tt>:realname</tt>: Real name reported to server
         
     | 
| 
         @@ -24,7 +21,9 @@ class IRCBot 
     | 
|
| 
       24 
21 
     | 
    
         
             
              # * <tt>:silent</tt>: Silence a lot of reports
         
     | 
| 
       25 
22 
     | 
    
         
             
              # * <tt>:loud</tt>: Lots more verbose reports
         
     | 
| 
       26 
23 
     | 
    
         
             
              def initialize(options = {})
         
     | 
| 
       27 
     | 
    
         
            -
                @ 
     | 
| 
      
 24 
     | 
    
         
            +
                @start_time = Time.now
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                @channels = options[:channels] || []
         
     | 
| 
       28 
27 
     | 
    
         
             
                @irc_network = options[:irc_network]
         
     | 
| 
       29 
28 
     | 
    
         
             
                @port = options[:port] || 6667
         
     | 
| 
       30 
29 
     | 
    
         
             
                @username = options[:username] || 'IRCBot'
         
     | 
| 
         @@ -34,6 +33,23 @@ class IRCBot 
     | 
|
| 
       34 
33 
     | 
    
         
             
                @loud = options[:loud] || false
         
     | 
| 
       35 
34 
     | 
    
         
             
              end
         
     | 
| 
       36 
35 
     | 
    
         | 
| 
      
 36 
     | 
    
         
            +
              # Returns a string representing uptime
         
     | 
| 
      
 37 
     | 
    
         
            +
              def get_uptime_string
         
     | 
| 
      
 38 
     | 
    
         
            +
                uptime = (Time.now - @start_time).to_i
         
     | 
| 
      
 39 
     | 
    
         
            +
                seconds = uptime % 60
         
     | 
| 
      
 40 
     | 
    
         
            +
                minutes = (uptime / 60) % 60
         
     | 
| 
      
 41 
     | 
    
         
            +
                hours = (uptime / 3600) % 24
         
     | 
| 
      
 42 
     | 
    
         
            +
                days = (uptime / 86400)
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                str = []
         
     | 
| 
      
 45 
     | 
    
         
            +
                str.push("#{days} day(s)") if days > 0
         
     | 
| 
      
 46 
     | 
    
         
            +
                str.push("#{hours} hour(s)") if hours > 0
         
     | 
| 
      
 47 
     | 
    
         
            +
                str.push("#{minutes} minute(s)") if minutes > 0
         
     | 
| 
      
 48 
     | 
    
         
            +
                str.push("#{seconds} second(s)") if seconds > 0
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                return str.join(', ')
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
       37 
53 
     | 
    
         
             
              # Creates the socket connection and registers the (very simple) default
         
     | 
| 
       38 
54 
     | 
    
         
             
              # welcome handler.  Subclasses should build their hooks in
         
     | 
| 
       39 
55 
     | 
    
         
             
              # add_custom_handlers to allow auto-creation in case of a restart.
         
     | 
| 
         @@ -89,9 +105,9 @@ class IRCBot 
     | 
|
| 
       89 
105 
     | 
    
         
             
              end
         
     | 
| 
       90 
106 
     | 
    
         | 
| 
       91 
107 
     | 
    
         
             
              private
         
     | 
| 
       92 
     | 
    
         
            -
              # Basic handler for joining  
     | 
| 
      
 108 
     | 
    
         
            +
              # Basic handler for joining our channels upon successful registration
         
     | 
| 
       93 
109 
     | 
    
         
             
              def welcome(text, args)
         
     | 
| 
       94 
     | 
    
         
            -
                @irc.join( 
     | 
| 
      
 110 
     | 
    
         
            +
                @channels.each {|channel| @irc.join(channel) }
         
     | 
| 
       95 
111 
     | 
    
         
             
                # Let the default welcome stuff still happen
         
     | 
| 
       96 
112 
     | 
    
         
             
                return false
         
     | 
| 
       97 
113 
     | 
    
         
             
              end
         
     | 
| 
         @@ -37,6 +37,7 @@ module Defaults 
     | 
|
| 
       37 
37 
     | 
    
         
             
                prepend_handler :incoming_motd,             self.method(:r_motd)
         
     | 
| 
       38 
38 
     | 
    
         
             
                prepend_handler :incoming_motdstart,        self.method(:r_motdstart)
         
     | 
| 
       39 
39 
     | 
    
         
             
                prepend_handler :incoming_endofmotd,        self.method(:r_endofmotd)
         
     | 
| 
      
 40 
     | 
    
         
            +
                prepend_handler :incoming_invite,           self.method(:r_invite)
         
     | 
| 
       40 
41 
     | 
    
         | 
| 
       41 
42 
     | 
    
         
             
                # Outgoing events
         
     | 
| 
       42 
43 
     | 
    
         
             
                prepend_handler :outgoing_begin_connection, self.method(:out_begin_connection)
         
     | 
| 
         @@ -186,6 +187,11 @@ module Defaults 
     | 
|
| 
       186 
187 
     | 
    
         
             
                nick @nicknames[0]
         
     | 
| 
       187 
188 
     | 
    
         
             
              end
         
     | 
| 
       188 
189 
     | 
    
         | 
| 
      
 190 
     | 
    
         
            +
              # Incoming invitation
         
     | 
| 
      
 191 
     | 
    
         
            +
              def r_invite(fullactor, actor, target)
         
     | 
| 
      
 192 
     | 
    
         
            +
                report "[#{actor}] INVITE to #{target}"
         
     | 
| 
      
 193 
     | 
    
         
            +
              end
         
     | 
| 
      
 194 
     | 
    
         
            +
             
     | 
| 
       189 
195 
     | 
    
         
             
            end
         
     | 
| 
       190 
196 
     | 
    
         | 
| 
       191 
197 
     | 
    
         
             
            end
         
     | 
    
        data/lib/net/yail/output_api.rb
    CHANGED
    
    | 
         @@ -3,6 +3,21 @@ module Net 
     | 
|
| 
       3 
3 
     | 
    
         
             
            # All output APIs live here.  In most cases, an outgoing handler will get a
         
     | 
| 
       4 
4 
     | 
    
         
             
            # call, but will not be able to stop the socket output since that's sorta
         
     | 
| 
       5 
5 
     | 
    
         
             
            # an essential part of this whole library.
         
     | 
| 
      
 6 
     | 
    
         
            +
            #
         
     | 
| 
      
 7 
     | 
    
         
            +
            # ==Argument Duping
         
     | 
| 
      
 8 
     | 
    
         
            +
            #
         
     | 
| 
      
 9 
     | 
    
         
            +
            # Output APIs dup incoming args before sending them off to handlers.  This
         
     | 
| 
      
 10 
     | 
    
         
            +
            # is a mechanism that I think could be done better, but I can't figure a good
         
     | 
| 
      
 11 
     | 
    
         
            +
            # way to do it at the moment.  The reason this is necessary is for a specific
         
     | 
| 
      
 12 
     | 
    
         
            +
            # situation where a bot has an array of response messages, and needs to filter
         
     | 
| 
      
 13 
     | 
    
         
            +
            # those messages.  A call to "msg(messages[rand(10)])" with a handler on :outgoing_msg
         
     | 
| 
      
 14 
     | 
    
         
            +
            # that does something like <code>text.gsub!('a', '@')</code> (like a leetspeek
         
     | 
| 
      
 15 
     | 
    
         
            +
            # filter) shouldn't destroy the original data in the messages array.
         
     | 
| 
      
 16 
     | 
    
         
            +
            #
         
     | 
| 
      
 17 
     | 
    
         
            +
            # This could be left up to the programmer, but it seems like something that
         
     | 
| 
      
 18 
     | 
    
         
            +
            # a library should own - protecting the programmer for having to remember that
         
     | 
| 
      
 19 
     | 
    
         
            +
            # sort of crap, especially if the app is calling msg, act, ctcp, etc. in
         
     | 
| 
      
 20 
     | 
    
         
            +
            # various ways from multiple points in the code....
         
     | 
| 
       6 
21 
     | 
    
         
             
            module IRCOutputAPI
         
     | 
| 
       7 
22 
     | 
    
         
             
              # Spits a raw string out to the server - in case a subclass wants to do
         
     | 
| 
       8 
23 
     | 
    
         
             
              # something special on *all* output, please make all output go through this
         
     | 
| 
         @@ -24,6 +39,10 @@ module IRCOutputAPI 
     | 
|
| 
       24 
39 
     | 
    
         
             
              # straight out to the channel.  The output thread has to deal with
         
     | 
| 
       25 
40 
     | 
    
         
             
              # sending these out.
         
     | 
| 
       26 
41 
     | 
    
         
             
              def privmsg(target, text, report_string)
         
     | 
| 
      
 42 
     | 
    
         
            +
                # Dup strings so handler can filter safely
         
     | 
| 
      
 43 
     | 
    
         
            +
                target = target.dup
         
     | 
| 
      
 44 
     | 
    
         
            +
                text = text.dup
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
       27 
46 
     | 
    
         
             
                handle(:outgoing_privmsg, target, text)
         
     | 
| 
       28 
47 
     | 
    
         | 
| 
       29 
48 
     | 
    
         
             
                @privmsg_buffer_mutex.synchronize do
         
     | 
| 
         @@ -37,6 +56,10 @@ module IRCOutputAPI 
     | 
|
| 
       37 
56 
     | 
    
         
             
              # shortcut methods for those types.  Target is a channel or username, text
         
     | 
| 
       38 
57 
     | 
    
         
             
              # is the message.
         
     | 
| 
       39 
58 
     | 
    
         
             
              def msg(target, text)
         
     | 
| 
      
 59 
     | 
    
         
            +
                # Dup strings so handler can filter safely
         
     | 
| 
      
 60 
     | 
    
         
            +
                target = target.dup
         
     | 
| 
      
 61 
     | 
    
         
            +
                text = text.dup
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
       40 
63 
     | 
    
         
             
                handle(:outgoing_msg, target, text)
         
     | 
| 
       41 
64 
     | 
    
         | 
| 
       42 
65 
     | 
    
         
             
                report_string = @silent ? '' : "{#{target}} <#{@me}> #{text}"
         
     | 
| 
         @@ -45,6 +68,10 @@ module IRCOutputAPI 
     | 
|
| 
       45 
68 
     | 
    
         | 
| 
       46 
69 
     | 
    
         
             
              # Calls :outgoing_ctcp handler, then sends CTCP to target channel or user
         
     | 
| 
       47 
70 
     | 
    
         
             
              def ctcp(target, text)
         
     | 
| 
      
 71 
     | 
    
         
            +
                # Dup strings so handler can filter safely
         
     | 
| 
      
 72 
     | 
    
         
            +
                target = target.dup
         
     | 
| 
      
 73 
     | 
    
         
            +
                text = text.dup
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
       48 
75 
     | 
    
         
             
                handle(:outgoing_ctcp, target, text)
         
     | 
| 
       49 
76 
     | 
    
         | 
| 
       50 
77 
     | 
    
         
             
                report_string = @silent ? '' :  "{#{target}}  [#{@me} #{text}]"
         
     | 
| 
         @@ -54,6 +81,10 @@ module IRCOutputAPI 
     | 
|
| 
       54 
81 
     | 
    
         
             
              # Calls :outgoing_act handler, then ctcp to send a CTCP ACTION (text) to
         
     | 
| 
       55 
82 
     | 
    
         
             
              # a given user or channel (target)
         
     | 
| 
       56 
83 
     | 
    
         
             
              def act(target, text)
         
     | 
| 
      
 84 
     | 
    
         
            +
                # Dup strings so handler can filter safely
         
     | 
| 
      
 85 
     | 
    
         
            +
                target = target.dup
         
     | 
| 
      
 86 
     | 
    
         
            +
                text = text.dup
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
       57 
88 
     | 
    
         
             
                handle(:outgoing_act, target, text)
         
     | 
| 
       58 
89 
     | 
    
         | 
| 
       59 
90 
     | 
    
         
             
                ctcp(target, "ACTION #{text}")
         
     | 
| 
         @@ -61,6 +92,10 @@ module IRCOutputAPI 
     | 
|
| 
       61 
92 
     | 
    
         | 
| 
       62 
93 
     | 
    
         
             
              # Calls :outgoing_notice handler, then outputs raw NOTICE message
         
     | 
| 
       63 
94 
     | 
    
         
             
              def notice(target, text)
         
     | 
| 
      
 95 
     | 
    
         
            +
                # Dup strings so handler can filter safely
         
     | 
| 
      
 96 
     | 
    
         
            +
                target = target.dup
         
     | 
| 
      
 97 
     | 
    
         
            +
                text = text.dup
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
       64 
99 
     | 
    
         
             
                handle(:outgoing_notice, target, text)
         
     | 
| 
       65 
100 
     | 
    
         | 
| 
       66 
101 
     | 
    
         
             
                report "{#{target}} -#{@me}- #{text}" unless @silent
         
     | 
| 
         @@ -70,6 +105,10 @@ module IRCOutputAPI 
     | 
|
| 
       70 
105 
     | 
    
         
             
              # Calls :outgoing_ctcpreply handler, then uses notice method to send the
         
     | 
| 
       71 
106 
     | 
    
         
             
              # CTCP text
         
     | 
| 
       72 
107 
     | 
    
         
             
              def ctcpreply(target, text)
         
     | 
| 
      
 108 
     | 
    
         
            +
                # Dup strings so handler can filter safely
         
     | 
| 
      
 109 
     | 
    
         
            +
                target = target.dup
         
     | 
| 
      
 110 
     | 
    
         
            +
                text = text.dup
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
       73 
112 
     | 
    
         
             
                handle(:outgoing_ctcpreply, target, text)
         
     | 
| 
       74 
113 
     | 
    
         | 
| 
       75 
114 
     | 
    
         
             
                report "{#{target}} [Reply: #{@me} #{text}]" unless @silent
         
     | 
| 
         @@ -80,6 +119,11 @@ module IRCOutputAPI 
     | 
|
| 
       80 
119 
     | 
    
         
             
              # and possibly specific users (objects).  If modes and objects are blank,
         
     | 
| 
       81 
120 
     | 
    
         
             
              # just sends a raw MODE query.
         
     | 
| 
       82 
121 
     | 
    
         
             
              def mode(target, modes = '', objects = '')
         
     | 
| 
      
 122 
     | 
    
         
            +
                # Dup strings so handler can filter safely
         
     | 
| 
      
 123 
     | 
    
         
            +
                target = target.dup
         
     | 
| 
      
 124 
     | 
    
         
            +
                modes = modes.dup
         
     | 
| 
      
 125 
     | 
    
         
            +
                objects = objects.dup
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
       83 
127 
     | 
    
         
             
                handle(:outgoing_mode, target, modes, objects)
         
     | 
| 
       84 
128 
     | 
    
         | 
| 
       85 
129 
     | 
    
         
             
                message = "MODE #{target}"
         
     | 
| 
         @@ -90,6 +134,9 @@ module IRCOutputAPI 
     | 
|
| 
       90 
134 
     | 
    
         | 
| 
       91 
135 
     | 
    
         
             
              # Calls :outgoing_join handler and then raw JOIN message for a given channel
         
     | 
| 
       92 
136 
     | 
    
         
             
              def join(target)
         
     | 
| 
      
 137 
     | 
    
         
            +
                # Dup strings so handler can filter safely
         
     | 
| 
      
 138 
     | 
    
         
            +
                target = target.dup
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
       93 
140 
     | 
    
         
             
                handle(:outgoing_join, target)
         
     | 
| 
       94 
141 
     | 
    
         | 
| 
       95 
142 
     | 
    
         
             
                raw "JOIN #{target}"
         
     | 
| 
         @@ -98,6 +145,10 @@ module IRCOutputAPI 
     | 
|
| 
       98 
145 
     | 
    
         
             
              # Calls :outgoing_part handler and then raw PART for leaving a given channel
         
     | 
| 
       99 
146 
     | 
    
         
             
              # (with an optional message)
         
     | 
| 
       100 
147 
     | 
    
         
             
              def part(target, text = '')
         
     | 
| 
      
 148 
     | 
    
         
            +
                # Dup strings so handler can filter safely
         
     | 
| 
      
 149 
     | 
    
         
            +
                target = target.dup
         
     | 
| 
      
 150 
     | 
    
         
            +
                text = text.dup
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
       101 
152 
     | 
    
         
             
                handle(:outgoing_part, target, text)
         
     | 
| 
       102 
153 
     | 
    
         | 
| 
       103 
154 
     | 
    
         
             
                request = "PART #{target}";
         
     | 
| 
         @@ -108,6 +159,9 @@ module IRCOutputAPI 
     | 
|
| 
       108 
159 
     | 
    
         
             
              # Calls :outgoing_quit handler and then raw QUIT message with an optional
         
     | 
| 
       109 
160 
     | 
    
         
             
              # reason
         
     | 
| 
       110 
161 
     | 
    
         
             
              def quit(text = '')
         
     | 
| 
      
 162 
     | 
    
         
            +
                # Dup strings so handler can filter safely
         
     | 
| 
      
 163 
     | 
    
         
            +
                text = text.dup
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
       111 
165 
     | 
    
         
             
                handle(:outgoing_quit, text)
         
     | 
| 
       112 
166 
     | 
    
         | 
| 
       113 
167 
     | 
    
         
             
                request = "QUIT";
         
     | 
| 
         @@ -118,12 +172,21 @@ module IRCOutputAPI 
     | 
|
| 
       118 
172 
     | 
    
         
             
              # Calls :outgoing_nick handler and then sends raw NICK message to change
         
     | 
| 
       119 
173 
     | 
    
         
             
              # nickname.
         
     | 
| 
       120 
174 
     | 
    
         
             
              def nick(new_nick)
         
     | 
| 
      
 175 
     | 
    
         
            +
                # Dup strings so handler can filter safely
         
     | 
| 
      
 176 
     | 
    
         
            +
                new_nick = new_nick.dup
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
       121 
178 
     | 
    
         
             
                handle(:outgoing_nick, new_nick)
         
     | 
| 
       122 
179 
     | 
    
         | 
| 
       123 
180 
     | 
    
         
             
                raw "NICK :#{new_nick}"
         
     | 
| 
       124 
181 
     | 
    
         
             
              end
         
     | 
| 
       125 
182 
     | 
    
         | 
| 
       126 
183 
     | 
    
         
             
              def user(username, myaddress, address, realname)
         
     | 
| 
      
 184 
     | 
    
         
            +
                # Dup strings so handler can filter safely
         
     | 
| 
      
 185 
     | 
    
         
            +
                username = username.dup
         
     | 
| 
      
 186 
     | 
    
         
            +
                myaddress = myaddress.dup
         
     | 
| 
      
 187 
     | 
    
         
            +
                address = address.dup
         
     | 
| 
      
 188 
     | 
    
         
            +
                realname = realname.dup
         
     | 
| 
      
 189 
     | 
    
         
            +
             
     | 
| 
       127 
190 
     | 
    
         
             
                handle(:outgoing_user, username, myaddress, address, realname)
         
     | 
| 
       128 
191 
     | 
    
         | 
| 
       129 
192 
     | 
    
         
             
                raw "USER #{username} #{myaddress} #{address} :#{realname}"
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,55 +1,65 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification 
         
     | 
| 
       2 
     | 
    
         
            -
            rubygems_version: 0.9.4
         
     | 
| 
       3 
     | 
    
         
            -
            specification_version: 1
         
     | 
| 
       4 
2 
     | 
    
         
             
            name: net-yail
         
     | 
| 
       5 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version 
         
     | 
| 
       6 
     | 
    
         
            -
              version: 1. 
     | 
| 
       7 
     | 
    
         
            -
            date: 2008-07-01 00:00:00 -04:00
         
     | 
| 
       8 
     | 
    
         
            -
            summary: "Yet Another IRC Library: wrapper for IRC communications in Ruby."
         
     | 
| 
       9 
     | 
    
         
            -
            require_paths: 
         
     | 
| 
       10 
     | 
    
         
            -
            - lib
         
     | 
| 
       11 
     | 
    
         
            -
            email: yail<at>nerdbucket dot com
         
     | 
| 
       12 
     | 
    
         
            -
            homepage: 
         
     | 
| 
       13 
     | 
    
         
            -
            rubyforge_project: 
         
     | 
| 
       14 
     | 
    
         
            -
            description: 
         
     | 
| 
       15 
     | 
    
         
            -
            autorequire: net/yail
         
     | 
| 
       16 
     | 
    
         
            -
            default_executable: 
         
     | 
| 
       17 
     | 
    
         
            -
            bindir: bin
         
     | 
| 
       18 
     | 
    
         
            -
            has_rdoc: true
         
     | 
| 
       19 
     | 
    
         
            -
            required_ruby_version: !ruby/object:Gem::Version::Requirement 
         
     | 
| 
       20 
     | 
    
         
            -
              requirements: 
         
     | 
| 
       21 
     | 
    
         
            -
              - - ">"
         
     | 
| 
       22 
     | 
    
         
            -
                - !ruby/object:Gem::Version 
         
     | 
| 
       23 
     | 
    
         
            -
                  version: 0.0.0
         
     | 
| 
       24 
     | 
    
         
            -
              version: 
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 1.1.1
         
     | 
| 
       25 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       26 
     | 
    
         
            -
            signing_key: 
         
     | 
| 
       27 
     | 
    
         
            -
            cert_chain: 
         
     | 
| 
       28 
     | 
    
         
            -
            post_install_message: 
         
     | 
| 
       29 
6 
     | 
    
         
             
            authors: 
         
     | 
| 
       30 
7 
     | 
    
         
             
            - Jeremy Echols
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire: net/yail
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2008-07-03 00:00:00 -07:00
         
     | 
| 
      
 13 
     | 
    
         
            +
            default_executable: 
         
     | 
| 
      
 14 
     | 
    
         
            +
            dependencies: []
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            description: 
         
     | 
| 
      
 17 
     | 
    
         
            +
            email: yail<at>nerdbucket dot com
         
     | 
| 
      
 18 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            extra_rdoc_files: 
         
     | 
| 
      
 23 
     | 
    
         
            +
            - README
         
     | 
| 
      
 24 
     | 
    
         
            +
            - CHANGELOG
         
     | 
| 
       31 
25 
     | 
    
         
             
            files: 
         
     | 
| 
      
 26 
     | 
    
         
            +
            - examples/logger/logger_bot.rb
         
     | 
| 
      
 27 
     | 
    
         
            +
            - examples/logger/run.rb
         
     | 
| 
      
 28 
     | 
    
         
            +
            - examples/logger/default.yml
         
     | 
| 
       32 
29 
     | 
    
         
             
            - lib/net/yail.rb
         
     | 
| 
       33 
30 
     | 
    
         
             
            - CHANGELOG
         
     | 
| 
      
 31 
     | 
    
         
            +
            - lib/net/yail/eventmap.yml
         
     | 
| 
      
 32 
     | 
    
         
            +
            - lib/net/yail/IRCBot.rb
         
     | 
| 
       34 
33 
     | 
    
         
             
            - lib/net/yail/magic_events.rb
         
     | 
| 
       35 
34 
     | 
    
         
             
            - lib/net/yail/default_events.rb
         
     | 
| 
       36 
35 
     | 
    
         
             
            - lib/net/yail/output_api.rb
         
     | 
| 
       37 
     | 
    
         
            -
            - lib/net/yail/eventmap.yml
         
     | 
| 
       38 
     | 
    
         
            -
            - lib/net/yail/IRCBot.rb
         
     | 
| 
       39 
36 
     | 
    
         
             
            - README
         
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
      
 37 
     | 
    
         
            +
            has_rdoc: true
         
     | 
| 
      
 38 
     | 
    
         
            +
            homepage: http://ruby-irc-yail.nerdbucket.com/
         
     | 
| 
      
 39 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
       42 
40 
     | 
    
         
             
            rdoc_options: 
         
     | 
| 
       43 
41 
     | 
    
         
             
            - --main
         
     | 
| 
       44 
42 
     | 
    
         
             
            - README
         
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
            -  
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
      
 43 
     | 
    
         
            +
            require_paths: 
         
     | 
| 
      
 44 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 45 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 46 
     | 
    
         
            +
              requirements: 
         
     | 
| 
      
 47 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 48 
     | 
    
         
            +
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 49 
     | 
    
         
            +
                  version: "0"
         
     | 
| 
      
 50 
     | 
    
         
            +
              version: 
         
     | 
| 
      
 51 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 52 
     | 
    
         
            +
              requirements: 
         
     | 
| 
      
 53 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 54 
     | 
    
         
            +
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 55 
     | 
    
         
            +
                  version: "0"
         
     | 
| 
      
 56 
     | 
    
         
            +
              version: 
         
     | 
| 
       52 
57 
     | 
    
         
             
            requirements: []
         
     | 
| 
       53 
58 
     | 
    
         | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
      
 59 
     | 
    
         
            +
            rubyforge_project: net-yail
         
     | 
| 
      
 60 
     | 
    
         
            +
            rubygems_version: 1.1.1
         
     | 
| 
      
 61 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 62 
     | 
    
         
            +
            specification_version: 2
         
     | 
| 
      
 63 
     | 
    
         
            +
            summary: "Yet Another IRC Library: wrapper for IRC communications in Ruby."
         
     | 
| 
      
 64 
     | 
    
         
            +
            test_files: []
         
     | 
| 
       55 
65 
     | 
    
         |