ircbot 0.0.2
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/MIT-LICENSE +20 -0
- data/README +47 -0
- data/Rakefile +56 -0
- data/bin/ircbot +50 -0
- data/lib/irc/agent.rb +177 -0
- data/lib/irc/client.rb +476 -0
- data/lib/irc/const.rb +242 -0
- data/lib/irc/irc.rb +324 -0
- data/lib/irc/localize.rb +260 -0
- data/lib/ircbot.rb +41 -0
- data/lib/ircbot/agent_manager.rb +89 -0
- data/lib/ircbot/config_client.rb +369 -0
- data/lib/ircbot/core_ext/digest.rb +14 -0
- data/lib/ircbot/core_ext/irc.rb +61 -0
- data/lib/ircbot/core_ext/rand-polimorphism.rb +23 -0
- data/lib/ircbot/core_ext/writefile.rb +45 -0
- data/lib/ircbot/framework.rb +50 -0
- data/lib/ircbot/ordered_hash.rb +91 -0
- data/lib/ircbot/reply_client.rb +328 -0
- metadata +82 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
# Extension to ruby-irc-lib
|
2
|
+
|
3
|
+
module IRC
|
4
|
+
class AbnormalTerminated < Exception; end
|
5
|
+
|
6
|
+
class Connection
|
7
|
+
def sendNAMES (channel = nil)
|
8
|
+
# p [:sendNAMES, Message(CMD_NAMES, nil, nil, channel)]
|
9
|
+
send(Message(CMD_NAMES, nil, nil, channel))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Message
|
14
|
+
def create_hash! (client)
|
15
|
+
unless @hash
|
16
|
+
@hash = {}
|
17
|
+
@hash[:client] = client
|
18
|
+
@hash[:type] = self.command
|
19
|
+
@hash[:prefix] = self.prefix
|
20
|
+
@hash[:from] = User::parse(self.prefix).nick
|
21
|
+
@hash[:str] = self .trailing
|
22
|
+
@hash[:string] = @hash[:str]
|
23
|
+
@hash[:to] = to = self .params[0]
|
24
|
+
@hash[:timestamp] = Time .now
|
25
|
+
|
26
|
+
unless to
|
27
|
+
case self .command
|
28
|
+
when CMD_JOIN, CMD_QUIT
|
29
|
+
@hash[:to] = to = @hash[:str]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
if to != nil and to == client .nick
|
34
|
+
@hash[:to] = @hash[:from]
|
35
|
+
end
|
36
|
+
if client .is_a? Client
|
37
|
+
@client = client
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def [] (key) # key must be a symbol
|
43
|
+
@hash[key]
|
44
|
+
end
|
45
|
+
|
46
|
+
def []= (key, val)
|
47
|
+
@hash[key] = val
|
48
|
+
end
|
49
|
+
|
50
|
+
def reply (string, to = nil)
|
51
|
+
self[:reply] = string
|
52
|
+
if @client and string
|
53
|
+
@client .speak(self, to)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def previous
|
58
|
+
@client && @client .previous_message(self)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
#
|
3
|
+
# rand-extension.rb
|
4
|
+
# Author:
|
5
|
+
# Created: Thu Nov 8 17:26:09 2001
|
6
|
+
|
7
|
+
|
8
|
+
# rand ��¿����
|
9
|
+
unless $__RAND_OVERRIDE__
|
10
|
+
$__RAND_OVERRIDE__ = true
|
11
|
+
alias :__rand__ :rand
|
12
|
+
def rand (obj)
|
13
|
+
case obj
|
14
|
+
when Array
|
15
|
+
index = __rand__(obj .size)
|
16
|
+
obj[index]
|
17
|
+
when Range
|
18
|
+
rand(obj .to_a)
|
19
|
+
else
|
20
|
+
__rand__(obj)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
#
|
3
|
+
# writefile.rb
|
4
|
+
# Author: maiha@wota.jp
|
5
|
+
# Created: 2002/05/10 14:16:13
|
6
|
+
# Changed: 2010/01/02 20:42:25
|
7
|
+
|
8
|
+
=begin
|
9
|
+
== usage
|
10
|
+
ensure directories of a path exist before open it.
|
11
|
+
|
12
|
+
=== syntacs
|
13
|
+
File::open!(path, ...)
|
14
|
+
|
15
|
+
== sample
|
16
|
+
Dir["/tmp/**/*"] # => []
|
17
|
+
File .open!("/tmp/foo/ora", "w+")
|
18
|
+
Dir["/tmp/**/*"] # => ["/tmp/foo", "/tmp/foo/ora"]
|
19
|
+
|
20
|
+
== changes
|
21
|
+
* 2002/06/11 19:45:32
|
22
|
+
change interface: open(...,'w!') => open!(...)
|
23
|
+
=end
|
24
|
+
|
25
|
+
def File.open! (path, *args, &block)
|
26
|
+
dirname = File.dirname(path) + '/'
|
27
|
+
unless File.directory?(dirname)
|
28
|
+
dirs = []
|
29
|
+
dirname.scan(/\//) {dirs << $`}
|
30
|
+
dirs.shift
|
31
|
+
dirs.each do |dir|
|
32
|
+
unless directory?(dir)
|
33
|
+
Dir.mkdir(dir)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
open(path, *args, &block)
|
38
|
+
end
|
39
|
+
|
40
|
+
if $0 == __FILE__
|
41
|
+
path = "/tmp/a/b/c.txt"
|
42
|
+
File.open!(path, "w+") {|f| f.puts "[OK] Wrote to #{path}"}
|
43
|
+
puts File.read(path){}
|
44
|
+
File.unlink(path)
|
45
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Ircbot
|
2
|
+
mattr_accessor :load_paths
|
3
|
+
self.load_paths = {}
|
4
|
+
|
5
|
+
class InvalidFilename < SecurityError; end
|
6
|
+
class FileNotFound < SecurityError; end
|
7
|
+
|
8
|
+
class Recover < RuntimeError
|
9
|
+
attr_reader :wait
|
10
|
+
|
11
|
+
def initialize(wait = 300)
|
12
|
+
@wait = wait
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def root
|
18
|
+
@root || File.expand_path(Dir.pwd)
|
19
|
+
end
|
20
|
+
|
21
|
+
def root=(value)
|
22
|
+
@root = value
|
23
|
+
end
|
24
|
+
|
25
|
+
def push_path(type, path, file_glob = "**/*.rb")
|
26
|
+
load_paths[type] = [Pathname(path), file_glob]
|
27
|
+
end
|
28
|
+
|
29
|
+
def dir_for(type)
|
30
|
+
load_paths[type][0] or
|
31
|
+
raise RuntimeError, "directory not found: #{type}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def glob_for(type)
|
35
|
+
load_paths[type][1]
|
36
|
+
end
|
37
|
+
|
38
|
+
def path_for(type, name)
|
39
|
+
name = name.to_s
|
40
|
+
raise InvalidFilename, name if name =~ %r{\.\.|~|/}
|
41
|
+
|
42
|
+
path = dir_for(type) + name
|
43
|
+
path.readable_real? or
|
44
|
+
raise FileNotFound, name
|
45
|
+
|
46
|
+
return path
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
@@ -0,0 +1,91 @@
|
|
1
|
+
## -*- coding: utf-8 -*-
|
2
|
+
# ordered_hash.rb
|
3
|
+
# Author:
|
4
|
+
# Created: Tue Jul 24 18:52:49 2001
|
5
|
+
|
6
|
+
class Ircbot::OrderedHash < Hash
|
7
|
+
def self.[] (*array)
|
8
|
+
size = array .size
|
9
|
+
if size % 2 == 0
|
10
|
+
hash = self .new
|
11
|
+
(size / 2) .times do |index|
|
12
|
+
key, value = array[index*2,2]
|
13
|
+
hash[key] = value
|
14
|
+
end
|
15
|
+
hash
|
16
|
+
else
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(*args)
|
22
|
+
super
|
23
|
+
@store_order = []
|
24
|
+
end
|
25
|
+
|
26
|
+
def []= (key, value)
|
27
|
+
unless self .has_key? key
|
28
|
+
@store_order << key
|
29
|
+
end
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
def keys
|
34
|
+
@store_order
|
35
|
+
end
|
36
|
+
|
37
|
+
def each
|
38
|
+
keys .each do |key|
|
39
|
+
yield(key, self[key])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
alias :each_pair :each
|
43
|
+
|
44
|
+
def delete (key)
|
45
|
+
@store_order .delete(key)
|
46
|
+
super
|
47
|
+
end
|
48
|
+
|
49
|
+
def each_value
|
50
|
+
keys .each do |key|
|
51
|
+
yield(self[key])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def collect
|
56
|
+
keys .collect do |key|
|
57
|
+
yield(key, self[key])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_a
|
62
|
+
keys .collect do |key|
|
63
|
+
[key, self[key]]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# $B@hF,$KDI2C$9$k!#(B
|
68
|
+
def unshift (key, val)
|
69
|
+
self[key] = val
|
70
|
+
@store_order .delete key
|
71
|
+
@store_order .unshift key
|
72
|
+
val
|
73
|
+
end
|
74
|
+
|
75
|
+
# $B;XDj$5$l$?%-!<$r;}$DMWAG$NE:;z$rJV$9!#(B(Array#index $BAjEv$N5!G=(B)
|
76
|
+
def index_of_key (value)
|
77
|
+
keys .index value
|
78
|
+
end
|
79
|
+
|
80
|
+
def position (value)
|
81
|
+
keys .each_with_index do |key, i|
|
82
|
+
return i if self[key] == value
|
83
|
+
end
|
84
|
+
return nil
|
85
|
+
end
|
86
|
+
|
87
|
+
def index_of_value (value)
|
88
|
+
position(value)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
@@ -0,0 +1,328 @@
|
|
1
|
+
# -*- coding: euc-jp -*-
|
2
|
+
|
3
|
+
require 'ircbot/config_client'
|
4
|
+
|
5
|
+
module Ircbot
|
6
|
+
class ReplyClient < ConfigClient
|
7
|
+
DIGEST_MAX_SIZE = 400
|
8
|
+
REGEXP_REDIRECT = ">|��"
|
9
|
+
|
10
|
+
def myname_regexp_string
|
11
|
+
names = @mynames.join('|')
|
12
|
+
"(#{ names })"
|
13
|
+
end
|
14
|
+
|
15
|
+
def speak0 (to, obj, save = nil)
|
16
|
+
Thread.critical = true
|
17
|
+
message =
|
18
|
+
case obj
|
19
|
+
when String ; obj
|
20
|
+
when Array
|
21
|
+
array = obj.collect {|item| item.inspect}.join(', ')
|
22
|
+
"(#{obj.size})[#{array}]"
|
23
|
+
when Regexp ; "/#{obj.source}/"
|
24
|
+
else ; obj.inspect
|
25
|
+
end
|
26
|
+
|
27
|
+
message.split(/\n+/).each do |line|
|
28
|
+
buffer = line.digest(DIGEST_MAX_SIZE)
|
29
|
+
unless buffer.empty?
|
30
|
+
# ����������������
|
31
|
+
@message_queue.push([buffer, to])
|
32
|
+
|
33
|
+
# ��å��������֥������Ȥ�������ơ�@messages �˻Ĥ�
|
34
|
+
if save
|
35
|
+
# :AnnaChan!~anna@219-106-253-19.cust.bit-drive.ne.jp PRIVMSG #bot :test\r\n"
|
36
|
+
str = ":#{@nick}!~bot@localhost PRIVMSG #{@channel} :#{buffer}\r\n"
|
37
|
+
msg = Message::parse(str)
|
38
|
+
msg.create_hash!(self)
|
39
|
+
msg[:id] = add_message(msg)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
Thread.critical = false
|
44
|
+
end
|
45
|
+
|
46
|
+
def speak (msg, to = nil, log = nil)
|
47
|
+
speak0(to || msg[:to], msg[:reply], log)
|
48
|
+
end
|
49
|
+
|
50
|
+
def newAgent (name)
|
51
|
+
script = Ircbot.path_for(:cpi, "#{name}.cpi").read{}
|
52
|
+
eval(script, TOPLEVEL_BINDING)
|
53
|
+
|
54
|
+
rescue SecurityError => e
|
55
|
+
err = "#{e.class}: #{e}"
|
56
|
+
syslog(err, :error)
|
57
|
+
return err
|
58
|
+
end
|
59
|
+
|
60
|
+
# xxxAgent: Agent �� xxx ����
|
61
|
+
# ����: String (Agent �μ��̻�)
|
62
|
+
# ����: String (������)
|
63
|
+
|
64
|
+
# ����������Ȥο�����Ͽ
|
65
|
+
def registerAgent (name0)
|
66
|
+
# ex) name0="daiben(12345)"
|
67
|
+
name, arg = name0.split(/\s|\(/, 2) # ex) name="daiben"
|
68
|
+
arg = arg.to_s.delete(")").strip # ex) arg="12345"
|
69
|
+
|
70
|
+
err = nil
|
71
|
+
this = "registerAgent"
|
72
|
+
agent = @agents[name]
|
73
|
+
@agents_opt[name] = arg
|
74
|
+
|
75
|
+
# p [:debug, :registerAgent, name0, name, arg]
|
76
|
+
|
77
|
+
agent = newAgent(name)
|
78
|
+
case agent
|
79
|
+
when NilClass
|
80
|
+
err = "Agent plugin script return nil (will not be registerd)."
|
81
|
+
when String
|
82
|
+
err = agent
|
83
|
+
else
|
84
|
+
@agents[name] = AgentManager.new(name, agent, self, arg)
|
85
|
+
end
|
86
|
+
|
87
|
+
status = "#{this}(#{name})... #{err || 'OK.'}"
|
88
|
+
syslog(status, err ? :error : :normal)
|
89
|
+
return status
|
90
|
+
end
|
91
|
+
|
92
|
+
def startAgent (name0)
|
93
|
+
# ex) name0="daiben(12345)"
|
94
|
+
name, arg = name0.split(/\s|\(/, 2) # ex) name="daiben"
|
95
|
+
arg = arg.to_s.delete(")").strip # ex) arg="12345"
|
96
|
+
|
97
|
+
err = nil
|
98
|
+
this = "startAgent"
|
99
|
+
agent = @agents[name]
|
100
|
+
arg = @agents_opt[name] if arg.empty?
|
101
|
+
|
102
|
+
case agent
|
103
|
+
when NilClass
|
104
|
+
err = "no such agent."
|
105
|
+
when AgentManager
|
106
|
+
agent.start(arg)
|
107
|
+
else
|
108
|
+
err = "unknown agent type(#{agent.class})."
|
109
|
+
end
|
110
|
+
|
111
|
+
status = "#{this}(#{name})... #{err || 'OK.'}"
|
112
|
+
syslog(status, err ? :error : :normal)
|
113
|
+
return status
|
114
|
+
end
|
115
|
+
|
116
|
+
def removeAgent (name)
|
117
|
+
err = nil
|
118
|
+
this = "removeAgent"
|
119
|
+
agent = @agents[name]
|
120
|
+
|
121
|
+
case agent
|
122
|
+
when NilClass
|
123
|
+
err = "no such agent."
|
124
|
+
when AgentManager
|
125
|
+
agent.stop
|
126
|
+
@agents.delete(name)
|
127
|
+
else
|
128
|
+
err = "unknown agent type(#{agent.class})."
|
129
|
+
end
|
130
|
+
|
131
|
+
status = "#{this}(#{name})... #{err || 'OK.'}"
|
132
|
+
syslog(status, err ? :error : :normal)
|
133
|
+
return status
|
134
|
+
end
|
135
|
+
|
136
|
+
# Agent �κƵ�ư
|
137
|
+
def restartAgent (name)
|
138
|
+
err = nil
|
139
|
+
this = "restartAgent"
|
140
|
+
agent = @agents[name]
|
141
|
+
|
142
|
+
case agent
|
143
|
+
when NilClass
|
144
|
+
err = "no such agent."
|
145
|
+
when AgentManager
|
146
|
+
agent.stop
|
147
|
+
obj = newAgent(name)
|
148
|
+
case obj
|
149
|
+
when NilClass
|
150
|
+
err = "Agent plugin script return nil (will not be registerd)."
|
151
|
+
when String
|
152
|
+
err = agent
|
153
|
+
else
|
154
|
+
arg = @agents_opt[name]
|
155
|
+
agent = AgentManager.new(name, obj, self, arg)
|
156
|
+
@agents[name] = agent
|
157
|
+
agent.start
|
158
|
+
end
|
159
|
+
else
|
160
|
+
err = "unknown agent type(#{agent.class})."
|
161
|
+
end
|
162
|
+
|
163
|
+
status = "#{this}(#{name})... #{err || 'OK.'}"
|
164
|
+
syslog(status, err ? :error : :normal)
|
165
|
+
return status
|
166
|
+
end
|
167
|
+
|
168
|
+
def stopAgent (name)
|
169
|
+
err = nil
|
170
|
+
this = "stopAgent"
|
171
|
+
agent = @agents[name]
|
172
|
+
|
173
|
+
case agent
|
174
|
+
when NilClass
|
175
|
+
err = "no such agent."
|
176
|
+
when AgentManager
|
177
|
+
agent.stop
|
178
|
+
else
|
179
|
+
err = "unknown agent type(#{agent.class})."
|
180
|
+
end
|
181
|
+
|
182
|
+
status = "#{this}(#{name})... #{err || 'OK.'}"
|
183
|
+
syslog(status, err ? :error : :normal)
|
184
|
+
return status
|
185
|
+
end
|
186
|
+
|
187
|
+
def do_help (msg)
|
188
|
+
target = msg[:arg].to_s.strip
|
189
|
+
if target.empty?
|
190
|
+
# �ܥåȤΥإ�ס�cpi�������֤�
|
191
|
+
alives = 0
|
192
|
+
names = @agents.collect {|name, agent|
|
193
|
+
if agent.alive?
|
194
|
+
alives += 1
|
195
|
+
name = "*#{name}"
|
196
|
+
end
|
197
|
+
name
|
198
|
+
}.join(', ')
|
199
|
+
msg[:reply] = "#{@help}\ncpi(#{alives}/#{@agents.size}): #{names}"
|
200
|
+
speak(msg)
|
201
|
+
|
202
|
+
else
|
203
|
+
# ���̤� cpi �Υإ�פ��֤���
|
204
|
+
target = target.delete('()[] ')
|
205
|
+
@agents.each_pair do |name, agent|
|
206
|
+
next unless target == name
|
207
|
+
next unless (result = agent.apply_methods(msg, :do_help))
|
208
|
+
msg[:reply] = result
|
209
|
+
speak(msg)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def parse_command (msg)
|
215
|
+
case msg[:type].to_s
|
216
|
+
when CMD_PRIVMSG
|
217
|
+
case msg[:str].to_s
|
218
|
+
when /^\s*#{myname_regexp_string}\s*(\.\s*[^\s\(]+)/o
|
219
|
+
msg[:called] = $1
|
220
|
+
msg[:command] = $2
|
221
|
+
msg[:arg] = $'.to_s.strip
|
222
|
+
msg[:command].gsub!(/^\./, '') if msg[:command]
|
223
|
+
when /(#{REGEXP_REDIRECT})\s*#{myname_regexp_string}\s*(\.\s*[^\s\(]+)?\s*$/o
|
224
|
+
msg[:arg] = $`.to_s.strip
|
225
|
+
msg[:called] = $2
|
226
|
+
msg[:command] = $3
|
227
|
+
msg[:command].gsub!(/^\./, '') if msg[:command]
|
228
|
+
end
|
229
|
+
end
|
230
|
+
return msg
|
231
|
+
end
|
232
|
+
|
233
|
+
def distributeMessage (msg)
|
234
|
+
# prepare accessors for dummy agents
|
235
|
+
msg.create_hash!(self)
|
236
|
+
msg[:id] = add_message(msg)
|
237
|
+
msg = parse_command(msg)
|
238
|
+
|
239
|
+
# p [msg[:type], msg[:from], msg[:from].to_s.empty?, msg[:str]]
|
240
|
+
|
241
|
+
# �ȸ������ʥ�å�����(PING��)��̵��
|
242
|
+
if msg[:from].to_s.empty?
|
243
|
+
return nil
|
244
|
+
end
|
245
|
+
|
246
|
+
begin
|
247
|
+
# reserved commands
|
248
|
+
name = msg[:arg].to_s.sub(/\A\s*\(?\s*/, '')
|
249
|
+
name = name.sub(/\s*\)?\s*\Z/, '') unless name.include?('(')
|
250
|
+
|
251
|
+
case msg[:command].to_s
|
252
|
+
when /^restart$/
|
253
|
+
names = name.split(/\s*,?\s+/)
|
254
|
+
names = @agents.keys if names.empty?
|
255
|
+
names.each do |name|
|
256
|
+
msg.reply(restartAgent(name))
|
257
|
+
end
|
258
|
+
return nil
|
259
|
+
when /^register$/ ; msg.reply(registerAgent(name)); return msg.reply(startAgent(name))
|
260
|
+
when /^remove$/ ; return msg.reply(removeAgent(name))
|
261
|
+
when /^start$/ ; return msg.reply(startAgent(name))
|
262
|
+
when /^stop$/ ; return msg.reply(stopAgent(name))
|
263
|
+
when /^help$/ ; return do_help(msg)
|
264
|
+
end
|
265
|
+
|
266
|
+
case msg[:type].to_s
|
267
|
+
when CMD_JOIN ; each_agent {|agent| agent.apply_methods(msg, :do_join)}
|
268
|
+
when CMD_PART ; each_agent {|agent| agent.apply_methods(msg, :do_part)}
|
269
|
+
when CMD_PING ; each_agent {|agent| agent.apply_methods(msg, :do_ping)}
|
270
|
+
when RPL_NAMREPLY
|
271
|
+
# p [:debug, :get_CMD_NAMES]
|
272
|
+
each_agent {|agent| agent.apply_methods(msg, :do_names)}
|
273
|
+
when CMD_PRIVMSG
|
274
|
+
|
275
|
+
# �����νФ�
|
276
|
+
if @log
|
277
|
+
do_log(msg)
|
278
|
+
end
|
279
|
+
|
280
|
+
# do_log �����˸ƤӽФ���(�����������Ѥ�����Τ���)
|
281
|
+
message = nil
|
282
|
+
catch(:reply) {
|
283
|
+
if msg[:called]
|
284
|
+
each_agent do |agent|
|
285
|
+
next unless (message = agent.apply_methods(msg, :do_command))
|
286
|
+
throw :reply
|
287
|
+
end
|
288
|
+
else
|
289
|
+
each_agent do |agent|
|
290
|
+
next unless (message = agent.apply_methods(msg, :do_reply))
|
291
|
+
throw :reply
|
292
|
+
end
|
293
|
+
end
|
294
|
+
}
|
295
|
+
|
296
|
+
# Agent#do_log �θƤӽФ�
|
297
|
+
each_agent do |agent|
|
298
|
+
msg.reply(agent.apply_methods(msg, :do_log))
|
299
|
+
end
|
300
|
+
|
301
|
+
# ��ʬ��ȯ���Ͽ
|
302
|
+
if message != nil then
|
303
|
+
dummy = {}
|
304
|
+
dummy[:str] = message
|
305
|
+
dummy[:from] = @nick
|
306
|
+
dummy[:to] = @channels
|
307
|
+
each_agent { |agent|
|
308
|
+
msg.reply(agent.apply_methods(dummy, :do_log))
|
309
|
+
}
|
310
|
+
end
|
311
|
+
|
312
|
+
return msg.reply(message)
|
313
|
+
end
|
314
|
+
rescue Exception
|
315
|
+
syslog("distributeMessage: #{$!}(#{$@[0]})", :error)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
|
322
|
+
if $0 == __FILE__
|
323
|
+
config = ARGV.shift or
|
324
|
+
raise "Specify your config file\nusage: #{$0} config/xxx.dat"
|
325
|
+
irc = IRC::ReplyClient.read_config(config)
|
326
|
+
irc.start
|
327
|
+
end
|
328
|
+
|