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
|
|