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 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,4 @@
1
+ silent: false
2
+ loud: false
3
+ output-dir: /tmp/logs
4
+ master: Nerdmaster
@@ -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 IRCBot for a basic bot base class example.
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 /^:((.+?)(?:!.+?)?) PRIVMSG (\S+?) :?\001ACTION (.+?)\001$/i
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(*new_args)
506
+ result = handler.call(*arguments)
499
507
  break if result == true
500
508
  end
501
509
  end
@@ -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>:channel</tt>: Channel name to join
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
- @channel = options[:channel]
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 a single channel upon successful registration
108
+ # Basic handler for joining our channels upon successful registration
93
109
  def welcome(text, args)
94
- @irc.join(@channel)
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
@@ -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.0.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
- test_files: []
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
- extra_rdoc_files:
46
- - README
47
- - CHANGELOG
48
- executables: []
49
-
50
- extensions: []
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
- dependencies: []
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