nadoka 0.8.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 (54) hide show
  1. data/.gitignore +5 -0
  2. data/ChangeLog.old +1553 -0
  3. data/Gemfile +4 -0
  4. data/README.org +31 -0
  5. data/Rakefile +1 -0
  6. data/bin/nadoka +13 -0
  7. data/lib/rss_check.rb +206 -0
  8. data/lib/tagparts.rb +206 -0
  9. data/nadoka.gemspec +29 -0
  10. data/nadoka.rb +123 -0
  11. data/nadokarc +267 -0
  12. data/ndk/bot.rb +241 -0
  13. data/ndk/client.rb +288 -0
  14. data/ndk/config.rb +571 -0
  15. data/ndk/error.rb +61 -0
  16. data/ndk/logger.rb +311 -0
  17. data/ndk/server.rb +784 -0
  18. data/ndk/server_state.rb +324 -0
  19. data/ndk/version.rb +44 -0
  20. data/plugins/autoawaybot.nb +66 -0
  21. data/plugins/autodumpbot.nb +227 -0
  22. data/plugins/autoop.nb +56 -0
  23. data/plugins/backlogbot.nb +88 -0
  24. data/plugins/checkbot.nb +64 -0
  25. data/plugins/cronbot.nb +20 -0
  26. data/plugins/dictbot.nb +53 -0
  27. data/plugins/drbcl.rb +39 -0
  28. data/plugins/drbot.nb +93 -0
  29. data/plugins/evalbot.nb +49 -0
  30. data/plugins/gonzuibot.nb +41 -0
  31. data/plugins/googlebot.nb +345 -0
  32. data/plugins/identifynickserv.nb +43 -0
  33. data/plugins/mailcheckbot.nb +0 -0
  34. data/plugins/marldiabot.nb +99 -0
  35. data/plugins/messagebot.nb +96 -0
  36. data/plugins/modemanager.nb +150 -0
  37. data/plugins/opensearchbot.nb +156 -0
  38. data/plugins/opshop.nb +23 -0
  39. data/plugins/pastebot.nb +46 -0
  40. data/plugins/roulettebot.nb +33 -0
  41. data/plugins/rss_checkbot.nb +121 -0
  42. data/plugins/samplebot.nb +24 -0
  43. data/plugins/sendpingbot.nb +17 -0
  44. data/plugins/shellbot.nb +59 -0
  45. data/plugins/sixamobot.nb +77 -0
  46. data/plugins/tenkibot.nb +111 -0
  47. data/plugins/timestampbot.nb +62 -0
  48. data/plugins/titlebot.nb +226 -0
  49. data/plugins/translatebot.nb +301 -0
  50. data/plugins/twitterbot.nb +138 -0
  51. data/plugins/weba.nb +209 -0
  52. data/plugins/xibot.nb +113 -0
  53. data/rice/irc.rb +780 -0
  54. metadata +102 -0
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $LOAD_PATH.unshift File.dirname(__FILE__)
3
+ require 'ndk/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "nadoka"
7
+ s.version = Nadoka::VERSION
8
+ s.authors = ["Kazuhiro NISHIYAMA", "SASADA Koichi"]
9
+ s.email = ["kzhr.nsym\@gmail.com"]
10
+ s.homepage = "https://github.com/nadoka/nadoka"
11
+ s.summary = %q{IRC logger, monitor and proxy program ("bot")}
12
+ s.description = %q{
13
+ Nadoka is a tool for monitoring and logging IRC conversations and
14
+ responding to specially formatted requests. You define and customize
15
+ these responses in Ruby. Nadoka is conceptually similar to Madoka, an
16
+ older proxy written in Perl.
17
+ }.tr_s(" \n", " ").strip
18
+
19
+ s.rubyforge_project = "nadoka"
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
+ s.require_paths = ["lib"]
25
+
26
+ # specify any dependencies here; for example:
27
+ # s.add_development_dependency "rspec"
28
+ # s.add_runtime_dependency "rest-client"
29
+ end
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ ##
4
+ ## Nadoka:
5
+ ## Irc Client Server Program
6
+ ##
7
+ #
8
+ # Copyright (c) 2004-2005 SASADA Koichi <ko1 at atdot.net>
9
+ #
10
+ # This program is free software with ABSOLUTELY NO WARRANTY.
11
+ # You can re-distribute and/or modify this program under
12
+ # the same terms of the Ruby's license.
13
+ #
14
+ #
15
+ # $Id$
16
+ # Create : K.S. 03/07/10 20:29:07
17
+ #
18
+
19
+ unless "".respond_to?(:force_encoding)
20
+ class String
21
+ def force_encoding(enc)
22
+ self
23
+ end
24
+ end
25
+ end
26
+
27
+ $LOAD_PATH.unshift File.dirname(__FILE__)
28
+ require 'ndk/version'
29
+
30
+ if $0 == __FILE__
31
+
32
+ require 'optparse'
33
+
34
+ require 'ndk/server'
35
+ require 'ndk/bot'
36
+
37
+ $stdout.sync=true
38
+ $NDK_Debug = false
39
+
40
+ unless defined? Process.daemon
41
+ def Process.daemon(nochdir = nil, noclose = nil)
42
+ exit!(0) if fork
43
+ Process.setsid
44
+ exit!(0) if fork
45
+ Dir.chdir('/') unless nochdir
46
+ File.umask(0)
47
+ unless noclose
48
+ STDIN.reopen('/dev/null')
49
+ STDOUT.reopen('/dev/null', 'w')
50
+ STDERR.reopen('/dev/null', 'w')
51
+ end
52
+ end
53
+ end
54
+
55
+ rcfile = nil
56
+ daemon = false
57
+ optparse = OptionParser.new{|opts|
58
+ opts.banner = "Usage: ruby #{$0} [options]"
59
+
60
+ opts.separator ""
61
+ opts.separator "Require options:"
62
+
63
+ opts.on("-r", "--rc [RCFILE]",
64
+ "Specify rcfile(required)"){|f|
65
+ rcfile = f
66
+ }
67
+
68
+ opts.separator ""
69
+ opts.separator "Optional:"
70
+
71
+ opts.on("-d", "--debug",
72
+ "Debug Nadoka"){
73
+ $NDK_Debug = true
74
+ $DEBUG = true
75
+
76
+ puts 'Enter Nadoka Debug mode'
77
+ }
78
+ opts.on("--daemon", "run as daemon"){
79
+ daemon = true
80
+ }
81
+
82
+ opts.separator ""
83
+ opts.separator "Common options:"
84
+
85
+ opts.on_tail("-h", "--help", "Show this message"){
86
+ puts Nadoka.version
87
+ puts opts
88
+ exit
89
+ }
90
+ opts.on_tail("-v", "--version", "Show version"){
91
+ puts Nadoka.version
92
+ }
93
+ }
94
+ optparse.parse!(ARGV)
95
+
96
+ unless rcfile
97
+ puts Nadoka.version
98
+ puts optparse
99
+ exit
100
+ end
101
+
102
+ if daemon
103
+ Process.daemon
104
+ end
105
+
106
+ begin
107
+ GC.start
108
+ Nadoka::NDK_Server.new(rcfile).start
109
+ rescue Nadoka::NDK_QuitProgram
110
+ #
111
+ rescue Nadoka::NDK_RestartProgram
112
+ GC.start
113
+ ObjectSpace.each_object(Socket) {|sock| sock.close}
114
+ retry
115
+ rescue Exception => e
116
+ open('nadoka_fatal_error', 'w'){|f|
117
+ f.puts e
118
+ f.puts e.backtrace.join("\n")
119
+ }
120
+ end
121
+
122
+ end
123
+
@@ -0,0 +1,267 @@
1
+ ## -*-ruby-*- vim: set filetype=ruby :
2
+ ##
3
+ ## Nadoka Sample resource file
4
+ ## $Id$
5
+ #
6
+ # Copyright (c) 2004-2005 SASADA Koichi <ko1 at atdot.net>
7
+ #
8
+ # This program is free software with ABSOLUTELY NO WARRANTY.
9
+ # You can re-distribute and/or modify this program under
10
+ # the same terms of the Ruby's lisence.
11
+ #
12
+ #
13
+
14
+ class NADOKA_Config < Nadoka::NDK_ConfigBase
15
+
16
+ ###############################################
17
+ # System setting
18
+
19
+ # Setting_name = 'IRCNet'
20
+ # # If you don't specify Setting_name,
21
+ # # system use rc file name as setting name
22
+ # # if your rc file is "test.rc", setting name is "test"
23
+ # # (remove last .rc)
24
+ #
25
+
26
+ # 0: quiet
27
+ # 1: ch log only
28
+ # 2: normal
29
+ # 3: debug
30
+ Loglevel = 2
31
+
32
+
33
+ ###############################################
34
+ # client server setting
35
+ Client_server_port = 6667 # or nil (no listen)
36
+ Client_server_host = nil # You can specify binding host(interface)
37
+ Client_server_pass = 'NadokaPassWord'
38
+ Client_server_acl = nil
39
+
40
+ # ACL(Access Control List) example:
41
+ # Client_server_acl = %q{
42
+ # deny all
43
+ # allow 192.168.1.1
44
+ # allow 192.168.2.0/24
45
+ # } # ACL setting must be String
46
+ #
47
+ # or you can set acl directly like follows:
48
+ #
49
+ # ACL_Object = ::ACL.new(...)
50
+ #
51
+
52
+
53
+ ###############################################
54
+ # server setting
55
+
56
+ # IRCnet servers in Japan
57
+ Servers = [
58
+ { :host => 'irc.ircnet.ne.jp',
59
+ :port => 6667, # default: 6667
60
+ :pass => nil, # default: nil
61
+ },
62
+ { :host => 'irc.media.kyoto-u.ac.jp',
63
+ :port => (6660 .. 6669),
64
+ },
65
+ { :host => 'irc.huie.hokudai.ac.jp',
66
+ # without :port, use 6667 as default port
67
+ },
68
+ # IPv6 Sample
69
+ # {
70
+ # :host => 'irc6.ircnet.ne.jp',
71
+ # :port => 6667,
72
+ # },
73
+ # {
74
+ # :host => 'irc6.livedoor.ne.jp',
75
+ # :port => (6660 .. 6669),
76
+ # },
77
+ ]
78
+
79
+ #Servers = [
80
+ # SSL Sample
81
+ # {
82
+ # :host => 'ircs.example.net',
83
+ # :port => 6697,
84
+ # :ssl_params => { # with :ssl_params hash, use ssl
85
+ # # :ca_cert => "/etc/ssl/certs", # default: openssl's default certificates
86
+ # },
87
+ # },
88
+ #]
89
+
90
+
91
+ ###############################################
92
+ # userinfo
93
+ User = ENV['USER'] || ENV['USERNAME'] || 'nadokatest'
94
+ Nick = ENV['USER'] || ENV['USERNAME'] || 'ndk_nick'
95
+ Hostname = Socket.gethostname
96
+ Realname = 'nadoka user'
97
+ Mode = nil
98
+
99
+ Away_Message = 'away'
100
+
101
+ # If this item is String, your nick will
102
+ # be that when no clients are connected.
103
+ Away_Nick = nil
104
+
105
+ # Quit_Message = "Quit Nadoka"
106
+
107
+
108
+ ###############################################
109
+ # channel info
110
+
111
+ # log filename format
112
+ # ${setting_name} : Setting name
113
+ # ${channel_name} : Channel name
114
+ # %? : Time#strftime format(see ruby reference)
115
+ #
116
+
117
+
118
+ Default_log = {
119
+ :file => '${setting_name}-${channel_name}/%y%m%d.log',
120
+ :time_format => '%H:%M:%S',
121
+ :message_format => {
122
+ 'PRIVMSG' => '<{nick}> {msg}',
123
+ 'NOTICE' => '{{nick}} {msg}',
124
+ 'JOIN' => '+ {nick} ({prefix:user}@{prefix:host})',
125
+ 'NICK' => '* {nick} -> {newnick}',
126
+ 'QUIT' => '- {nick} (QUIT: {msg}) ({prefix:user}@{prefix:host})',
127
+ 'PART' => '- {nick} (PART: {msg}) ({prefix:user}@{prefix:host})',
128
+ 'KICK' => '- {nick} was kicked by {kicker} ({msg})',
129
+ 'MODE' => '* {nick} changed mode ({msg})',
130
+ 'TOPIC' => '* TOPIC: {msg} (by {nick})',
131
+ 'SYSTEM' => '[NDK] {orig}',
132
+ 'OTHER' => '{orig}',
133
+ 'SIMPLE' => '{orig}',
134
+ },
135
+ }
136
+
137
+ System_log = {
138
+ :file => '${setting_name}-system.log',
139
+ :time_format => '%y/%m/%d-%H:%M:%S',
140
+ :message_format => {
141
+ 'PRIVMSG' => '{ch} <{nick}> {msg}',
142
+ 'NOTICE' => '{ch} {{nick}} {msg}',
143
+ 'JOIN' => '{ch} + {nick} ({prefix:user}@{prefix:host})',
144
+ 'NICK' => '{ch} * {nick} -> {newnick}',
145
+ 'QUIT' => '{ch} - {nick} (QUIT: {msg}) ({prefix:user}@{prefix:host})',
146
+ 'PART' => '{ch} - {nick} (PART: {msg}) ({prefix:user}@{prefix:host})',
147
+ 'KICK' => '{ch} - {nick} was kicked by {kicker} ({msg})',
148
+ 'MODE' => '{ch} * {nick} changed mode ({msg})',
149
+ 'TOPIC' => '{ch} * TOPIC: {msg} (by {nick})',
150
+ 'SYSTEM' => '[NDK] {orig}',
151
+ 'OTHER' => nil,
152
+ 'SIMPLE' => nil,
153
+ },
154
+ }
155
+
156
+ Talk_log = {
157
+ :file => '${setting_name}-talk/%y%m%d.log',
158
+ :time_format => Default_log[:time_format],
159
+ :message_format => {
160
+ 'PRIVMSG' => '[{sender} => {receiver}] {msg}',
161
+ 'NOTICE' => '{{sender} => {receiver}} {msg}',
162
+ }
163
+ }
164
+
165
+ Channel_info = {
166
+ # nadoka talk (from Japanese server only)
167
+ '#nadoka' => {
168
+ # timing
169
+ # :startup / when nadoka start up <= default
170
+ # :login / when user login
171
+ # otherwise nadoka won't login automatically
172
+ :timing => :startup,
173
+ :log => '${setting_name}-nadoka-chan/%y%m%d.log',
174
+ # :part_message => "bye bye"
175
+ # :initial_mode => "+s"
176
+ },
177
+ '#nadoka:*.jp' => {
178
+ :timing => :startup,
179
+ :log => '${setting_name}-nadoka-chan-jp/%y%m%d.log',
180
+ },
181
+
182
+ # nadoka bot channel
183
+ '#nadoka_check' => {
184
+ :timing => :startup,
185
+ :log => '${setting_name}-nadoka-check/%y%m%d.log',
186
+ # you can specify store backlog lines
187
+ :backlog_lines => 5,
188
+ },
189
+
190
+ #
191
+ # '#log_setting_example' => {
192
+ # :log => {
193
+ # :file => 'logfilename', # log filename
194
+ # # :io => $stderr, # or IO object is supported
195
+ # :time_format => '%H:%M:%S',
196
+ # # :channel_name_in_file_name => 'hoge'
197
+ #
198
+ # :message_format => {
199
+ # 'PRIVMSG' => '<{nick}> {msg}',
200
+ # 'NOTICE' => '{{nick}} {msg}',
201
+ # 'JOIN' => '+ {nick} to {ch}',
202
+ # 'NICK' => '* {nick} -> {newnick}',
203
+ # 'QUIT' => '- {nick} ({msg})',
204
+ # 'PART' => '- {nick} from {ch} ({msg})',
205
+ # 'KICK' => '- {nick} kicked by {kicker} ({msg}) from {ch}',
206
+ # 'MODE' => '* {nick} changed mode ({msg})',
207
+ # 'TOPIC' => '<{ch} TOPIC> {msg}',
208
+ # 'SYSTEM' => '[NDK] {msg}',
209
+ # 'OTHER' => nil,
210
+ # 'SIMPLE' => nil,
211
+ #
212
+ # # for more complex log output:
213
+ # # :logwriterclass => your_log_writer_class,
214
+ # # :logwriter => your_log_writer_instance,
215
+ # # :other_logwriterclass_specific_setting => ...,
216
+ # },
217
+ # },
218
+ }
219
+
220
+ BackLog_Lines = 20
221
+
222
+ #
223
+ # FilenameEncoding = 'euc'
224
+ # FilenameEncoding = 'sjis'
225
+ # FilenameEncoding = 'utf8'
226
+ #
227
+ # If you not specify FilenameEncoding, nadoka infers
228
+ # suitable encoding (see ndk/config.rb).
229
+ #
230
+
231
+ ###############################################
232
+ # Directory
233
+ Log_dir = './log'
234
+
235
+ #Plugins_dir = './plugins'
236
+ Plugins_dir = Default_Plugins_dir
237
+ # You can set Plugins_dir as Enumerable object.
238
+ # ex: ['./dir1', './dir2', ...]
239
+
240
+
241
+ ###############################################
242
+ # Bots
243
+ BotConfig = [
244
+ # :BotName1,
245
+ # :BotName1,
246
+ # 'BotName1',
247
+ # :BotName2,
248
+ # { :name => :BotName3,
249
+ # :set1 => setting1,
250
+ # },
251
+ # { :name => :BotName3,
252
+ # :set1 => setting2,
253
+ # },
254
+ # { :name => :BotName4,
255
+ # :set1 => setting3,
256
+ # },
257
+
258
+ :BackLogBot, # strongly recommended
259
+ ]
260
+
261
+
262
+ ###############################################
263
+ # Misc
264
+
265
+ Privmsg_Filter = nil
266
+ Notice_Filter = nil
267
+ end
@@ -0,0 +1,241 @@
1
+ #
2
+ # Copyright (c) 2004-2005 SASADA Koichi <ko1 at atdot.net>
3
+ #
4
+ # This program is free software with ABSOLUTELY NO WARRANTY.
5
+ # You can re-distribute and/or modify this program under
6
+ # the same terms of the Ruby's licence.
7
+ #
8
+ #
9
+ # $Id$
10
+ # Create : K.S. 04/04/19 00:39:48
11
+ #
12
+ #
13
+ # To make bot for nadoka, see this code.
14
+ #
15
+
16
+ module Nadoka
17
+ class NDK_Bot
18
+ # To initialize bot instance, please override this.
19
+ def bot_initialize
20
+ # do something
21
+ end
22
+
23
+ # This method will be called when reload configuration.
24
+ def bot_destruct
25
+ # do something
26
+ end
27
+
28
+ # override me
29
+ def bot_state
30
+ info = "#<#{self.class}: #{@bot_config.inspect}>"
31
+ if info.length > 100
32
+ info[0..100] + '...'
33
+ else
34
+ info
35
+ end
36
+ end
37
+
38
+ # To access bot configuration, please use this.
39
+ #
40
+ # in configuration file,
41
+ # BotConfig = [
42
+ # :BotClassName1,
43
+ # :BotClassName2,
44
+ # {
45
+ # :name => :BotClassName3,
46
+ # :setX => X,
47
+ # :setY => Y,
48
+ # ...
49
+ # },
50
+ # ]
51
+ #
52
+ # You can access above setting via @bot_config
53
+ #
54
+
55
+ def bot_init_utils
56
+ bot_init_available_channel
57
+ bot_init_same_bot
58
+ end
59
+
60
+ def bot_init_available_channel
61
+ if @bot_config.key?(:channels)
62
+ channels = '\A(?:' + @bot_config[:channels].collect{|ch|
63
+ Regexp.quote(ch)
64
+ }.join('|') + ')\z'
65
+ @available_channel = Regexp.compile(channels)
66
+ else
67
+ @available_channel = @bot_config[:ch] || //
68
+ end
69
+ end
70
+
71
+ def bot_init_same_bot
72
+ @same_bot = @bot_config[:same_bot] || /(?!)/
73
+ end
74
+
75
+ def same_bot?(ch)
76
+ if @state.channel_users(ccn(ch)).find{|x| @same_bot =~ x }
77
+ true
78
+ else
79
+ false
80
+ end
81
+ end
82
+
83
+ def ccn2rcn ccn
84
+ chs = @manager.state.current_channels[ccn]
85
+ chs ? chs.name : ccn
86
+ end
87
+
88
+ # Mostly, you need this method.
89
+ def send_notice ch, msg
90
+ rch = ccn2rcn(ch)
91
+ msg = Cmd.notice(rch, msg)
92
+ @manager.send_to_server msg
93
+ @manager.send_to_clients_otherwise msg, nil
94
+ end
95
+
96
+ # Usually, you must not use this
97
+ def send_privmsg ch, msg
98
+ rch = ccn2rcn(ch)
99
+ msg = Cmd.privmsg(rch, msg)
100
+ @manager.send_to_server msg
101
+ @manager.send_to_clients_otherwise msg, nil
102
+ end
103
+
104
+ # Change user's mode as 'mode' on ch.
105
+ def change_mode ch, mode, user
106
+ rch = ccn2rcn(ch)
107
+ send_msg Cmd.mode(rch, mode, user)
108
+ end
109
+
110
+ # Change your nick to 'nick'.
111
+ def change_nick nick
112
+ send_msg Cmd.nick(nick)
113
+ end
114
+
115
+ # Send command or reply(?) to server.
116
+ def send_msg msg
117
+ @manager.send_to_server msg
118
+ end
119
+
120
+ # ccn or canonical_channel_name
121
+ def canonical_channel_name ch
122
+ @config.canonical_channel_name ch
123
+ end
124
+ alias ccn canonical_channel_name
125
+
126
+ =begin
127
+ # ...
128
+ # def on_[IRC Command or Reply(3 digits)] prefix(nick only), param1, param2, ...
129
+ #
130
+ # end
131
+ #
132
+
133
+ # like these
134
+ def on_privmsg prefix, ch, msg
135
+
136
+ end
137
+
138
+ def on_join prefix, ch
139
+
140
+ end
141
+
142
+ def on_part prefix, ch, msg=''
143
+
144
+ end
145
+
146
+ def on_quit prefix, msg=''
147
+
148
+ end
149
+
150
+ def on_xxx prefix, *params
151
+
152
+ end
153
+
154
+ In above methods, you can access nick, user, host information
155
+ via prefix argument variable like this.
156
+
157
+ - prefix.nick
158
+ - prefix.user
159
+ - prefix.host
160
+
161
+
162
+ ######
163
+ # special event
164
+
165
+ # This method will be called when received every message
166
+ def on_every_message prefix, command, *args
167
+ #
168
+ end
169
+
170
+ # if 'nick' user quit client and part ch, this event is called.
171
+ def on_quit_from_channel ch, nick, qmsg
172
+ # do something
173
+ end
174
+
175
+ # It's special event that will be called about a minute.
176
+ def on_timer timeobj
177
+ # do something
178
+ end
179
+
180
+ # It's special event that will be called when new client join.
181
+ def on_client_login client_count, client
182
+ # do something
183
+ end
184
+
185
+ # It's special event that will be called when a client part.
186
+ def on_client_logout client_count, client
187
+ # do something
188
+ end
189
+
190
+ # undocumented
191
+ def on_client_privmsg client, ch, msg
192
+ # do something
193
+ end
194
+ # undocumented
195
+ def on_nadoka_command client, command, *params
196
+ # do something
197
+ end
198
+
199
+ # undocumented
200
+ def on_server_connected
201
+ # do something
202
+ end
203
+
204
+ # on signal 'sigusr[12]' trapped
205
+ def on_sigusr[12] # no arguments
206
+ # do something
207
+ end
208
+
209
+ You can access your current state on IRC server via @state.
210
+ - @state.nick # your current nick
211
+ - @state.channels # channels which you are join ['ch1', 'ch2', ...]
212
+
213
+ # need canonicalized channel name
214
+ - @state.channel_users(ch) # channel users ['user1', ...]
215
+ - @state.channel_user_mode(ch, nick)
216
+
217
+ =end
218
+
219
+ Cmd = ::Nadoka::Cmd
220
+ Rpl = ::Nadoka::Rpl
221
+
222
+ def initialize manager, config, bot_config
223
+ @manager = manager
224
+ @config = config
225
+ @logger = config.logger
226
+ @state = manager.state
227
+ @bot_config = bot_config
228
+
229
+ bot_initialize
230
+ end
231
+
232
+ def config
233
+ @bot_config
234
+ end
235
+
236
+ def self.inherited klass
237
+ NDK_Config::BotClasses[klass.name.downcase.intern] = klass
238
+ end
239
+ end
240
+ end
241
+