ircbot 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/README +43 -21
  2. data/Rakefile +9 -6
  3. data/bin/ircbot +3 -27
  4. data/lib/ircbot.rb +12 -15
  5. data/lib/ircbot/client.rb +32 -0
  6. data/lib/ircbot/client/commands.rb +34 -0
  7. data/lib/ircbot/client/config.rb +55 -0
  8. data/lib/ircbot/client/config/channels.rb +40 -0
  9. data/lib/ircbot/client/config/plugins.rb +16 -0
  10. data/lib/ircbot/client/encoding.rb +17 -0
  11. data/lib/ircbot/client/plugins.rb +64 -0
  12. data/lib/ircbot/core_ext/delegation.rb +135 -0
  13. data/lib/ircbot/core_ext/extending.rb +80 -0
  14. data/lib/ircbot/core_ext/message.rb +18 -0
  15. data/lib/ircbot/framework.rb +22 -40
  16. data/lib/ircbot/plugin.rb +63 -0
  17. data/lib/ircbot/plugins.rb +141 -0
  18. data/lib/ircbot/version.rb +4 -0
  19. data/plugins/echo.rb +14 -0
  20. data/plugins/irc.rb +19 -0
  21. data/plugins/plugins.rb +59 -0
  22. data/spec/config_spec.rb +83 -0
  23. data/spec/fixtures/sama-zu.yml +8 -0
  24. data/spec/framework_spec.rb +18 -0
  25. data/spec/its_helper.rb +15 -0
  26. data/spec/plugin_spec.rb +70 -0
  27. data/spec/plugins_spec.rb +30 -0
  28. data/spec/provide_helper.rb +36 -0
  29. data/spec/spec_helper.rb +16 -0
  30. metadata +40 -19
  31. data/lib/irc/agent.rb +0 -177
  32. data/lib/irc/client.rb +0 -476
  33. data/lib/irc/const.rb +0 -242
  34. data/lib/irc/irc.rb +0 -324
  35. data/lib/irc/localize.rb +0 -260
  36. data/lib/ircbot/agent_manager.rb +0 -89
  37. data/lib/ircbot/config_client.rb +0 -369
  38. data/lib/ircbot/core_ext/digest.rb +0 -14
  39. data/lib/ircbot/core_ext/irc.rb +0 -61
  40. data/lib/ircbot/core_ext/rand-polimorphism.rb +0 -23
  41. data/lib/ircbot/core_ext/writefile.rb +0 -45
  42. data/lib/ircbot/ordered_hash.rb +0 -91
  43. data/lib/ircbot/reply_client.rb +0 -328
@@ -1,260 +0,0 @@
1
- =begin header
2
- localization extension
3
- IO supporting coding system conversion
4
-
5
- $Author: igarashi $
6
- $Date: 2001/01/02 00:21:18 $
7
-
8
- Copyright (C) 1998-2001 Hiroshi IGARASHI
9
- =end
10
-
11
- require 'kconv'
12
- #require 'uconv'
13
-
14
- $vsave, $VERBOSE = $VERBOSE, FALSE
15
-
16
- module Kernel
17
- private
18
-
19
- def println(*args)
20
- =begin
21
- print with ln
22
- =end
23
- STDOUT.println(*args)
24
- end
25
-
26
- def eprint(*args)
27
- =begin
28
- print to stderr
29
- =end
30
- STDERR.print(*args)
31
- end
32
-
33
- def eprintln(*args)
34
- =begin
35
- eprint with ln
36
- =end
37
- STDERR.println(*args)
38
- end
39
- end
40
-
41
- # IO class extension
42
- class IO
43
- def println(*args)
44
- =begin
45
- print with ln
46
- =end
47
- if args.length > 0
48
- print(*args)
49
- end
50
- print("\n")
51
- end
52
- public(:println)
53
- end
54
-
55
- class << ARGF
56
- def lineno
57
- $.
58
- end
59
- def path
60
- filename
61
- end
62
- end
63
-
64
- ## available only if kconv ext module imported
65
- if defined?(Kconv)
66
-
67
- module Kernel
68
- private
69
-
70
- # lreadline
71
- def lreadline(*arg)
72
- Kconv.tointern(readline(*arg))
73
- end
74
-
75
- # lgets
76
- def lgets(*arg)
77
- ret = gets(*arg)
78
- unless ret.nil?
79
- Kconv.tointern(ret)
80
- else
81
- nil
82
- end
83
- end
84
-
85
- def p(*args)
86
- args.each { |arg|
87
- println(Kconv.toextern(arg.inspect))
88
- }
89
- end
90
-
91
- # lprint
92
- def lprint(*args)
93
- STDOUT.lprint(*args)
94
- end
95
-
96
- # lprint with ln
97
- def lprintln(*args)
98
- STDOUT.lprintln(*args)
99
- end
100
-
101
- # leprint
102
- def leprint(*args)
103
- STDERR.lprint(*args)
104
- end
105
-
106
- def leprintln(*args)
107
- =begin
108
- leprint with ln
109
- =end
110
- STDERR.lprintln(*args)
111
- end
112
- end
113
-
114
- # Kconv module extension
115
- module Kconv
116
- ## local encoding
117
- case $KIOCODE
118
- ## EUC
119
- when 'EUC'
120
- alias_method(:toextern, :toeuc)
121
- ## JIS
122
- when 'JIS'
123
- alias_method(:toextern, :tojis)
124
- ## SJIS
125
- when 'SJIS'
126
- alias_method(:toextern, :tosjis)
127
- else
128
- case $KCODE
129
- ## EUC
130
- when 'EUC'
131
- alias_method(:toextern, :toeuc)
132
- ## JIS
133
- when 'JIS'
134
- alias_method(:toextern, :tojis)
135
- ## SJIS
136
- when 'SJIS'
137
- alias_method(:toextern, :tosjis)
138
- when 'NONE'
139
- def toextern(str)
140
- str
141
- end
142
- else
143
- raise "Unknown coding system(\"#{$KIOCODE}\")."
144
- end
145
- end
146
-
147
- case $KCODE
148
- ## EUC
149
- when 'EUC'
150
- alias_method(:tointern, :toeuc)
151
- ## SJIS
152
- when 'SJIS'
153
- alias_method(:tointern, :tosjis)
154
- when 'NONE'
155
- def tointern(str)
156
- str
157
- end
158
- else
159
- raise "Unknown coding system(\"#{$KCODE}\")."
160
- end
161
-
162
- alias_method(:tolocal, :toextern)
163
- module_function(:toextern, :tolocal, :tointern)
164
- end
165
- end
166
-
167
- class << ARGF
168
-
169
- if defined?(Kconv)
170
- # lreadline
171
- def lreadline(*arg)
172
- Kconv.tointern(readline(*arg))
173
- end
174
- # lgets
175
- def lgets(*arg)
176
- ret = gets(*arg)
177
- unless ret.nil?
178
- Kconv.tointern(ret)
179
- else
180
- nil
181
- end
182
- end
183
- end
184
-
185
- end
186
-
187
- class IO
188
-
189
- if defined?(Kconv)
190
-
191
- # lreadline
192
- def lreadline(*arg)
193
- Kconv.tointern(readline(*arg))
194
- end
195
-
196
- # lgets
197
- def lgets(*arg)
198
- ret = gets(*arg)
199
- unless ret.nil?
200
- Kconv.tointern(ret)
201
- else
202
- nil
203
- end
204
- end
205
-
206
- # convert to local encoding and print
207
- def lprint(*args)
208
- args.each { |arg|
209
- print(Kconv.toextern(arg.to_s))
210
- }
211
- end
212
- def jisprint(*args)
213
- args.each { |arg|
214
- print(Kconv.tojis(arg.to_s))
215
- }
216
- end
217
- def eucprint(*args)
218
- args.each { |arg|
219
- print(Kconv.toeuc(arg.to_s))
220
- }
221
- end
222
- def sjisprint(*args)
223
- args.each { |arg|
224
- print(Kconv.tosjis(arg.to_s))
225
- }
226
- end
227
-
228
- def lprintln(*args)
229
- lprint(*args)
230
- print("\n")
231
- end
232
-
233
- def set_codesys(codesys_name)
234
- case codesys_name
235
- ## JIS
236
- when 'JIS'
237
- class << self
238
- alias_method(:lprint, :jisprint)
239
- end
240
- ## EUC
241
- when 'EUC'
242
- class << self
243
- alias_method(:lprint, :eucprint)
244
- end
245
- ## SJIS
246
- when 'SJIS'
247
- class << self
248
- alias_method(:lprint, :sjisprint)
249
- end
250
- when 'NONE'
251
- alias_method(:lprint, :print)
252
- else
253
- raise "Unknown coding system(\"#{codesys_name}\")."
254
- end
255
- end
256
- public(:lreadline, :lprint, :lprintln)
257
- end
258
- end
259
-
260
- $VERBOSE = $vsave
@@ -1,89 +0,0 @@
1
- # -*- coding: euc-jp -*-
2
-
3
- module Ircbot
4
- ######################################################################
5
- ### agent ��������륯�饹
6
- ### (ľ�� agent �����Ѥ��ʤ��Τϡ�agent �δ�����ʻ���ƹԤ�����)
7
- ######################################################################
8
- class AgentManager
9
- attr :cpi, true
10
- attr :name
11
- attr :created
12
- attr :alive
13
-
14
- def initialize (name, obj, client, arg = nil)
15
- @name = name
16
- @cpi = obj
17
- @created = Time.now
18
- @alive = nil
19
- @client = client
20
- @arg = arg
21
-
22
- method = :do_construct
23
- if @cpi.respond_to?(method)
24
- @cpi.send(method, client)
25
- end
26
- end
27
-
28
- def notifyMessage (msg)
29
- # NOP
30
- end
31
-
32
- def start (arg = nil)
33
- @arg = arg if arg
34
-
35
- method = :do_start
36
- if @cpi.respond_to?(method)
37
- @cpi.send(method, @arg)
38
- end
39
-
40
- @alive = true
41
- end
42
-
43
- def stop
44
- method = :do_destruct
45
- if @cpi.respond_to?(method)
46
- @cpi.send(method, nil)
47
- end
48
- @alive = nil
49
- end
50
-
51
- def alive?
52
- @alive
53
- end
54
-
55
- def send (method, *args)
56
- if alive?
57
- return @cpi.send(method, *args)
58
- else
59
- return nil
60
- end
61
- end
62
-
63
- # ���ꤵ�줿�᥽�åɷ���缡�¹Ԥ���
64
- # 1�ļ¹Ԥ����齪λ���ɤΥ᥽�åɤ�������Ƥʤ����� nil ���֤���
65
- def apply_methods (msg, methods)
66
- methods = [methods] unless methods.is_a? Array
67
- methods.each do |method|
68
- next unless @cpi.respond_to?(method)
69
- begin
70
- if msg
71
- if (result = send(method, msg))
72
- return result
73
- end
74
- else
75
- if (result = send(method))
76
- return result
77
- end
78
- end
79
- rescue Exception => err
80
- error = "error: #{err} in #{self.name}"
81
- @client.syslog(error, :error)
82
- @client.syslog($@.join("\n"), :error)
83
- return error
84
- end
85
- end
86
- return nil
87
- end
88
- end
89
- end
@@ -1,369 +0,0 @@
1
- # -*- coding: euc-jp -*-
2
-
3
- require 'ircbot/agent_manager'
4
- require 'ircbot/ordered_hash'
5
-
6
- module Ircbot
7
- class ConfigClient < IRC::Client
8
- include ActiveSupport::Rescuable
9
-
10
- attr :config
11
- attr :messages
12
- attr :agents
13
-
14
- PARAM_STRING = %w( nick server username realname password port log syslog help pidfile )
15
- PARAM_ARRAY = %w( agents channels )
16
- PARAM_KEYS = PARAM_STRING + PARAM_ARRAY
17
-
18
- class << self
19
- ######################################################################
20
- ### config �ե����뤫�������ͤ��ɤ߹��ߡ�Client ���֥������Ȥ����
21
- ######################################################################
22
- def read_config(input, debug = nil)
23
- case input
24
- when IO # already IO (NOP)
25
- when String # maybe file
26
- begin
27
- input = File.open(input)
28
- rescue Exception
29
- $stderr.puts("cannot read config file. (#{input})")
30
- exit
31
- end
32
- else
33
- $stderr.puts("missing config file.")
34
- exit
35
- end
36
-
37
- params = {}
38
- param_regexp = self::PARAM_KEYS.join('|')
39
- while (line = input.gets)
40
- case line
41
- when /^#/ # ignore
42
- when /^(#{param_regexp})\s*=\s*/io
43
- key, val = $1.downcase, $'.chomp
44
- symbol = key.intern
45
- case key
46
- when *self::PARAM_STRING
47
- params[symbol] = val
48
- when *self::PARAM_ARRAY
49
- params[symbol] = val.split(/[,\s]+/)
50
- else # IGNORE...
51
- $stderr.puts "ignore: #{key} = #{params[symbol].inspect}(#{params[symbol].class})"
52
- end
53
- if debug
54
- $stderr.puts "debug: #{key} = #{params[symbol].inspect}(#{params[symbol].class})"
55
- end
56
- end
57
- end
58
- self.new(params)
59
- end
60
- end
61
-
62
- def initialize (hash = {})
63
- @config = hash
64
-
65
- # ɬ�ܹ���
66
- @nick = hash[:nick] || missing_error(:nick)
67
- @server = hash[:server] || missing_error(:server)
68
- @username = hash[:username] || @nick || missing_error(:username)
69
- @realname = hash[:realname] || @nick || missing_error(:realname)
70
- @channels = hash[:channels]
71
-
72
- @port = hash[:port] || 6667
73
- @password = hash[:password] || 'xxx'
74
- @log = hash[:log]
75
- @syslog = hash[:syslog]
76
- @help = hash[:help] || '�إ�פ�����ޤ���(config �� help �Ԥ򸫤ޤ�)'
77
- @agents = OrderedHash.new # String��Agent
78
-
79
- @agents_opt = {} # ����������Ȥε�ư�����Ѥ��륪�ץ����
80
-
81
- @mynames = [@nick, @realname].compact.sort.uniq
82
- @cachesize = (hash[:cachesize].to_i < 1) ? 100 : hash[:cachesize].to_i
83
- @last_message_id = 0
84
- @messages = []
85
-
86
- @last_ping_time = nil # �Ǹ�� CMD_PING �������ä�����
87
- end
88
-
89
- def each_agent
90
- @agents.each_pair do |name, agent|
91
- yield(agent)
92
- end
93
- end
94
-
95
- def missing_error (arg)
96
- syslog("#{arg}�����ꤵ��Ƥ��ޤ���", :fatal)
97
- end
98
-
99
- def syslog (message, level = :normal)
100
- line = Time.now.strftime("%Y-%m-%d %H:%M:%S #{message}")
101
- case level
102
- when :normal
103
- if @syslog
104
- File.open!(@syslog, "a+") {|file| file.puts line; file.flush}
105
- end
106
- when :error
107
- syslog(message, :normal)
108
- $stderr.puts line
109
- when :fatal
110
- syslog(message, :error)
111
- exit 1
112
- else
113
- syslog("syslog: wrong level(#{level}): mes=[#{message}]", :error)
114
- end
115
- end
116
-
117
- def write_pid_file
118
- # write pid information to a file
119
- filename = config[:pidfile]
120
- pid = Process::pid
121
- if filename
122
- if exist_process?
123
- raise "another process is running. (pid=#{pid})"
124
- end
125
- File::write!(pid.to_s, filename, 'w+')
126
- File::chmod(0664, filename)
127
- end
128
- end
129
-
130
- def exist_process?
131
- filename = config[:pidfile] or return nil
132
- File::exists?(filename) or return nil
133
- pid = File::open(filename).read or return nil
134
-
135
- begin
136
- Process::getpgid(pid.to_i)
137
- return pid.chomp
138
- rescue Errno::ESRCH
139
- return nil
140
- end
141
- end
142
-
143
- def do_log (message)
144
- begin
145
- case @log
146
- when NilClass
147
- return nil
148
- when /\/$/
149
- format = "#{@log}/%Y%m/%d.log"
150
- when String
151
- format = @log
152
- else
153
- syslog("do_log: unknown type #{@log.class}", :error)
154
- @log = nil
155
- return nil
156
- end
157
-
158
- now = Time.now
159
- path = now.strftime(format)
160
- from = message[:from]
161
- to = message[:to]
162
- str = message[:str]
163
-
164
- File.open!(path, "a+") {|file|
165
- file.puts now.strftime("%H:%M <#{to}:#{from}> #{str}")
166
- }
167
- return nil
168
- rescue
169
- syslog("do_log: #{$!}", :error)
170
- @log = nil
171
- end
172
- end
173
-
174
-
175
- ######################################################################
176
- ### IRC �Υ��ͥ������ط�
177
- ######################################################################
178
-
179
- def start
180
- write_pid_file
181
- syslog("#{self.class}: system starts.")
182
-
183
- create_message_thread
184
-
185
- # ����³�ΰ٤ˡ�initialize ��Ǥʤ������ǸƤӽФ���
186
-
187
- connect
188
- join
189
-
190
- # ����������Ȥ���Ͽ
191
- @config[:agents].each do |name|
192
- registerAgent(name)
193
- end
194
- each_agent {|agent| agent.start}
195
-
196
- startThreads
197
- @message_thread.join
198
- @log_thread.raise(Stop.new)
199
- @log_thread.join
200
-
201
- rescue Exception => e
202
- begin
203
- syslog("catch exception: #{e}(#{e.class})", :error)
204
- rescue_with_handler(e) or raise
205
- rescue Recover => recover
206
- irc.stop
207
- sleep recover.wait
208
- retry
209
- end
210
- end
211
-
212
- def ping_timeout
213
- stop
214
- exit
215
- end
216
-
217
- def startThreads
218
- super
219
- @ping_thread = Thread.start {
220
- eprintln("ping_thread started.") if $DEBUG
221
- #_putlog("debug", "ping_thread started.")
222
- sec = 3600 # �����ÿ� PING ���ʤ��� ping_timeout��Ƥ�
223
- while true
224
- sleep 60
225
- case @last_ping_time
226
- when Time
227
- if Time.now > @last_ping_time + sec
228
- ping_timeout
229
- end
230
- end
231
- end
232
- eprintln("ping_thread stopped.") if $DEBUG
233
- #_putlog("debug", "ping_thread stopped.")
234
- }
235
- eprintln("ping_thread created.") if $DEBUG
236
- end
237
-
238
- # derived from original ruby-irc::Client#stop
239
- def stop
240
- # Agent�����
241
- each_agent do |agent|
242
- agent.stop
243
- end
244
-
245
- disconnect
246
- @message_thread.raise(IRC::Stop.new)
247
- destroy_message_thread
248
- end
249
-
250
- # derived from original ruby-irc::Client's one.
251
- def connect
252
- @log_queue = Queue.new
253
- @connection = IRC::Connection::new(@log_queue)
254
-
255
- @connection.connect(@server, @port.to_s)
256
- @connection.sendPASS(@password)
257
- @connection.sendNICK(@nick)
258
- @connection.sendUSER(nil, @username, "hostname", "servername", @realname)
259
- end
260
-
261
- # derived from original ruby-irc::Client's one.
262
- def disconnect
263
- @connection.sendQUIT(@nick, nil)
264
- @connection.disconnect
265
- end
266
-
267
- def join
268
- channels = @channels.join(',')
269
- @connection.send(CMD_JOIN, nil, @nick, channels, '')
270
- end
271
-
272
- def names (channel = nil)
273
- @connection.sendNAMES(channel)
274
- end
275
-
276
- ######################################################################
277
- ### Message Handling
278
- ######################################################################
279
-
280
- def handlePING(msg)
281
- # p [:handlePING, Time.now]
282
- super
283
- @last_ping_time = Time.now
284
- end
285
-
286
- def add_message (msg)
287
- index = (@last_message_id += 1) % @cachesize
288
- @messages[index] = msg
289
-
290
- return index
291
- end
292
-
293
- def previous_message (msg)
294
- index = (@cachesize + msg[:id].to_i - 1) % @cachesize
295
- @messages[index]
296
- end
297
-
298
- def last_messages (size)
299
- mes = @messages[@last_message_id % @cachesize] or return []
300
- array = []
301
- i = 0
302
- j = 0
303
-
304
- while (size > 0)
305
- j += 1
306
- break if i > @cachesize # maybe looping. give up
307
- break if j > 100
308
- break unless mes
309
-
310
- i += 1
311
- # p [mes[:from],mes[:to],mes[:str], size, i, mes[:from] == mes[:to]]
312
- unless mes[:from] == mes[:to]
313
- array << mes
314
- size -= 1
315
- end
316
- mes = mes.previous
317
- end
318
- return array
319
- end
320
-
321
- # created by yu-yan@4th.to
322
- def create_message_thread
323
- @message_last = nil
324
- @message_timer = Time.now
325
- @message_queue = Queue.new
326
- @message_thread = Thread.new(@message_timer, @message_queue) { |message_timer, message_queue|
327
- loop {
328
- now = Time.now
329
- message_timer = [message_timer, now].max + 2
330
-
331
- if (message_timer - now) > 15
332
- sleep(3)
333
- else
334
- sleep(0.1)
335
- end
336
-
337
- # STDERR.print("timer:#{message_timer.strftime('%H:%M:%S')} - now:#{now.strftime('%H:%M:%S')} = #{message_timer - now}\n")
338
-
339
- message, to = message_queue.pop
340
- privmsg(message, to)
341
- # STDERR.print("MSG:", message, "\n")
342
- }
343
- }
344
- end
345
-
346
- def destroy_message_thread
347
- if @message_thread.is_a? Thread
348
- @message_thread.kill
349
- end
350
- end
351
-
352
- # derived from original ruby-irc::Client's one.
353
- def handleMessageLoop
354
- loop do
355
- msg = @connection.recv
356
- if msg.nil?
357
- syslog("handleMessageLoop: Abnormal terminated.", :error)
358
- abnormal_terminated
359
- end
360
- handleMessageInternal(msg)
361
- distributeMessage(msg)
362
- end
363
- end
364
-
365
- def abnormal_terminated
366
- raise IRC::AbnormalTerminated
367
- end
368
- end
369
- end