ircbot 0.0.2 → 0.1.0

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