syndi 0.0.1 → 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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +12 -0
  3. data/CHANGELOG.md +0 -0
  4. data/Gemfile +8 -0
  5. data/INSTALL.md +86 -0
  6. data/LICENSE +28 -0
  7. data/README.md +104 -0
  8. data/Rakefile +26 -0
  9. data/WINDOWS.md +64 -0
  10. data/bin/syndi +102 -0
  11. data/bin/syndi-conf +47 -0
  12. data/conf/example.yml +101 -0
  13. data/docs/Events.md +103 -0
  14. data/docs/Upgrade.md +16 -0
  15. data/ext/csyndi/events.c +50 -0
  16. data/ext/csyndi/extconf.rb +20 -0
  17. data/ext/csyndi/integer.c +53 -0
  18. data/ext/csyndi/libauto.c +37 -0
  19. data/ext/csyndi/logger.c +228 -0
  20. data/include/syndi/csyndi.h +38 -0
  21. data/include/syndi/events.h +19 -0
  22. data/include/syndi/integer.h +17 -0
  23. data/include/syndi/logger.h +57 -0
  24. data/include/syndi.h +22 -0
  25. data/lib/syndi/actress.rb +12 -0
  26. data/lib/syndi/api/events.rb +170 -0
  27. data/lib/syndi/api/object.rb +29 -0
  28. data/lib/syndi/api/plugin.rb +155 -0
  29. data/lib/syndi/api.rb +7 -0
  30. data/lib/syndi/bot.rb +270 -0
  31. data/lib/syndi/config.rb +113 -0
  32. data/lib/syndi/configure/cli.rb +23 -0
  33. data/lib/syndi/configure/generator.rb +410 -0
  34. data/lib/syndi/configure.rb +19 -0
  35. data/lib/syndi/dsl/base.rb +74 -0
  36. data/lib/syndi/dsl/irc.rb +13 -0
  37. data/lib/syndi/events.rb +114 -0
  38. data/lib/syndi/irc/common.rb +63 -0
  39. data/lib/syndi/irc/library.rb +89 -0
  40. data/lib/syndi/irc/object/channel.rb +21 -0
  41. data/lib/syndi/irc/object/entity.rb +90 -0
  42. data/lib/syndi/irc/object/message.rb +99 -0
  43. data/lib/syndi/irc/object/user.rb +139 -0
  44. data/lib/syndi/irc/protocol/numerics.rb +60 -0
  45. data/lib/syndi/irc/protocol.rb +164 -0
  46. data/lib/syndi/irc/sasl/diffie_hellman.rb +36 -0
  47. data/lib/syndi/irc/sasl/mech/dh_blowfish.rb +83 -0
  48. data/lib/syndi/irc/sasl/mech/plain.rb +39 -0
  49. data/lib/syndi/irc/sasl/mech.rb +15 -0
  50. data/lib/syndi/irc/server.rb +301 -0
  51. data/lib/syndi/irc/state/channel_manager.rb +6 -0
  52. data/lib/syndi/irc/state/support.rb +142 -0
  53. data/lib/syndi/irc/state/user_manager.rb +6 -0
  54. data/lib/syndi/irc/std/commands.rb +99 -0
  55. data/lib/syndi/irc/std/numerics.rb +216 -0
  56. data/lib/syndi/irc.rb +8 -0
  57. data/lib/syndi/jewel/specification.rb +121 -0
  58. data/lib/syndi/jewel/util.rb +27 -0
  59. data/lib/syndi/jewel.rb +5 -0
  60. data/lib/syndi/rubyext/string.rb +10 -0
  61. data/lib/syndi/verbosity.rb +10 -0
  62. data/lib/syndi/version.rb +38 -0
  63. data/lib/syndi.rb +129 -0
  64. data/spec/helper.rb +32 -0
  65. data/spec/syndi/events_spec.rb +43 -0
  66. data/tasks/compile.rake +15 -0
  67. data/tasks/install.rake +10 -0
  68. data/tasks/package.rake +13 -0
  69. data/tasks/spec.rake +12 -0
  70. metadata +101 -13
@@ -0,0 +1,170 @@
1
+ # Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
2
+ # This free software is distributed under the FreeBSD license (see LICENSE).
3
+
4
+ require 'thread'
5
+ require 'syndi/verbosity'
6
+ require 'syndi/api/object'
7
+
8
+ # Entering namespace: Syndi
9
+ module Syndi
10
+
11
+ # Entering namespace: API
12
+ module API
13
+
14
+ # A class which provides the the fundamental event system, upon which
15
+ # much of the API is based, and which follows a simple model of broadcasting
16
+ # and hooking onto such broadcasts.
17
+ #
18
+ # Plugin writers may be rather interested in {Syndi::DSL::Base}, since that
19
+ # provides a simpler interface to Syndi's instances of this class.
20
+ #
21
+ # @api Syndi
22
+ # @since 4.0.0
23
+ # @author noxgirl
24
+ #
25
+ # @see Syndi::DSL::Base
26
+ #
27
+ # @!attribute [r] threads
28
+ # @return [Array] An array of threads used by {#call}.
29
+ class Events < Syndi::API::Object
30
+
31
+ attr_reader :events, :threads
32
+
33
+ # Create a new instance of Syndi::API::Events.
34
+ def initialize
35
+ @events = {}
36
+ @threads = []
37
+ end
38
+
39
+ # Listen for (hook onto) an event.
40
+ #
41
+ # @param [Symbol] event The name of the event for which to listen.
42
+ # @param [Integer] priority The priority of the event from 1-5, 1 being utmost priority.
43
+ #
44
+ # @yield [...] The arguments that will be yielded to the block vary by event.
45
+ # Please consult with the {file:docs/Events.md events specification} for details by event.
46
+ #
47
+ # @return [Array(Symbol, Integer, String)] Identification data including a unique string. Keep
48
+ # this if you need to destroy the hook later.
49
+ #
50
+ # @example
51
+ # events.on :disconnect do |irc|
52
+ # puts "I'm dying!"
53
+ # end
54
+ #
55
+ # @see Syndi::DSL::Base#on
56
+ # @see file:docs/Events.md
57
+ def on(event, priority=3, &cb)
58
+
59
+ # Priority must be in the range of 1-5.
60
+ unless (1..5).include? priority
61
+ return 0
62
+ end
63
+
64
+ # If the event does not exist, create it.
65
+ @events[event] ||= {1 => {}, 2 => {}, 3 => {}, 4 => {}, 5 => {}}
66
+
67
+ # Generate a unique pseudorandom ID for this hook.
68
+ id = ''
69
+ 10.times { id += get_rand_char }
70
+ while @events[event][priority].has_key? id
71
+ id = ''
72
+ 10.times { id += get_rand_char }
73
+ end
74
+
75
+ # Create the hook in memory.
76
+ @events[event][priority][id] = cb
77
+
78
+ [event, priority, id]
79
+
80
+ end
81
+
82
+ # Broadcast an event and associated arguments.
83
+ #
84
+ # The arguments are globbed into an array from the list passed to the
85
+ # method, so be sure to format your call correctly.
86
+ #
87
+ # If a hook returns +false+, all subsequent hook executions will be
88
+ # forestalled from occurring.
89
+ #
90
+ # @param [Symbol] event The event being broadcasted.
91
+ # @param [Array] args A list of arguments which should be passed to
92
+ # the listeners. (splat)
93
+ #
94
+ # @example
95
+ # events.call(:cow_moo, "the cows", "go moo", [1, 3, 5])
96
+ #
97
+ # @see Syndi::DSL::Base#emit
98
+ def call(event, *args)
99
+ # Check if any hooks exist for this event.
100
+ if @events.include? event
101
+
102
+ $m.verbose("A thread is spawning for an event broadcast (:#{event}).", VNOISY) do
103
+ @threads << Thread.new(event) do |evnt|
104
+
105
+ status = nil
106
+
107
+ begin # catch exceptions
108
+ # Iterate through the hooks.
109
+ @events[evnt].each_key do |priority|
110
+ @events[evnt][priority].each_value do |prc|
111
+ status = prc.call(*args) unless status == false
112
+ end # each hook
113
+ end # each priority
114
+ rescue => e
115
+ $m.error "An exception occurred within the thread of :#{event}: #{e}", false, e.backtrace
116
+ end # begin
117
+
118
+ end # thread
119
+ end # verbose
120
+
121
+ end # whether this event exists
122
+ end
123
+
124
+ # Delete a hook or listener.
125
+ #
126
+ # @param [Array(Symbol, Integer, String)] id The identification data of the hook,
127
+ # as provided by #on.
128
+ #
129
+ # @see Syndi::DSL::Base#undo_on
130
+ def del(id)
131
+ event, priority, hook = id
132
+
133
+ if @events.has_key? event
134
+ if @events[event][priority].has_key? hook
135
+ @events[event][priority].delete(hook)
136
+ end
137
+ end
138
+
139
+ tidy
140
+ end
141
+
142
+ # Terminate all active threads.
143
+ def die
144
+ @threads.each { |thr| thr.kill }
145
+ end
146
+
147
+ #######
148
+ private
149
+ #######
150
+
151
+ # Tidy up.
152
+ def tidy
153
+ @events.each do |name, lists|
154
+ empty = true
155
+ empty = lists.each_value { |v| break false if not v.empty? }
156
+ if empty
157
+ # Drop the event.
158
+ @events.delete name
159
+ next
160
+ end
161
+ end
162
+ end
163
+
164
+ end # class Events
165
+
166
+ end # module API
167
+
168
+ end # module Syndi
169
+
170
+ # vim: set ts=4 sts=2 sw=2 et:
@@ -0,0 +1,29 @@
1
+ # Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
2
+ # This free software is distributed under the FreeBSD license (see LICENSE).
3
+
4
+ # Namespace: Syndi
5
+ module Syndi
6
+
7
+ # Namespace: API
8
+ module API
9
+
10
+ # A superclass for {Syndi::API::Timers} and {Syndi::API::Events}.
11
+ class Object
12
+
13
+ private
14
+
15
+ # Get a random character.
16
+ #
17
+ # @return [String] A random character.
18
+ def get_rand_char
19
+ chrs = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".split(//)
20
+ chrs[rand(chrs.length)]
21
+ end
22
+
23
+ end # class Object
24
+
25
+ end # module API
26
+
27
+ end # module Syndi
28
+
29
+ # vim: set ts=4 sts=2 sw=2 et:
@@ -0,0 +1,155 @@
1
+ # Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
2
+ # This free software is distributed under the FreeBSD license (see LICENSE).
3
+
4
+ require 'ostruct'
5
+ require 'libsyndi'
6
+ require 'syndi/bot'
7
+
8
+ module Syndi
9
+
10
+ module API
11
+
12
+ # A basic superclass for plugins.
13
+ #
14
+ # @api Syndi
15
+ # @since 4.0.0
16
+ # @author noxgirl
17
+ # @author swarley
18
+ #
19
+ # @!attribute [r] name
20
+ # @return [String] Name of the plugin.
21
+ #
22
+ # @!attribute [r] summary
23
+ # @return [String] Summary of the plugin.
24
+ #
25
+ # @!attribute [r] version
26
+ # @return [String] Version of the plugin.
27
+ #
28
+ # @!attribute [r] library
29
+ # @return [String] The library upon which the plugin is based.
30
+ #
31
+ # @!attribute [r] author
32
+ # @return [String] Author of the plugin.
33
+ #
34
+ # @!attribute [r] syndi
35
+ # @return [String] Version of Syndi required by the plugin.
36
+ class Plugin
37
+
38
+ attr_reader :name, :summary, :version, :library, :author, :syndi
39
+
40
+ # Configure the plugin.
41
+ #
42
+ # @yieldparam [OpenStruct] conf Configuration structure.
43
+ #
44
+ # - +conf.name+: Name of the plugin (String).
45
+ # - +conf.summary+: Summary of the plugin (String).
46
+ # - +conf.version+: Version of the plugin (String).
47
+ # - +conf.library+: Library upon which the plugin is based. (String).
48
+ # - +conf.author+: Author of the plugin (String).
49
+ # - +conf.syndi+: Required version of Syndi (String). Should be in the format of
50
+ # +'~> version'+ or +'>= version'+. +~>+ means at least +version+ but no later
51
+ # than the minor version (e.g. +'~> 4.0'+ will allow +4.0.2+ but not +4.1.0+).
52
+ # +>=+ means at at least +version+.
53
+ #
54
+ # Additionally, it should be noted that +conf.library+ should be either of the
55
+ # core libraries, *or* 'multi' if it uses multiple libraries.
56
+ #
57
+ # @example
58
+ # configure do |c|
59
+ # c.name = 'MagicPlugin'
60
+ # c.summary = 'A magical extension.'
61
+ # c.version = '1.00'
62
+ # c.library = 'irc'
63
+ # c.author = 'noxgirl'
64
+ # c.syndi = '~> 4.0'
65
+ # end
66
+ def configure
67
+
68
+ # Prepare an open structure.
69
+ conf = OpenStruct.new
70
+
71
+ # Yield it to the configuration block.
72
+ yield conf if block_given?
73
+
74
+ # Check for sufficient configuration.
75
+ [:name,:summary,:version,:library,:author,:syndi].each do |s|
76
+ if conf.send(s).nil?
77
+ raise PluginError, "Plugin #{self.inspect} provided insufficient configuration (#{s} is nil)."
78
+ end
79
+ end
80
+
81
+ @name = conf.name
82
+ @summary = conf.summary
83
+ @version = conf.version
84
+ @library = conf.library
85
+ @author = conf.author
86
+
87
+ # Check for compatibility.
88
+ if conf.syndi =~ /^(~>\s*)((?:[\dabcr])(?:\.[\dabcr]))+$/ # ~>
89
+
90
+ ver = $2
91
+ if Gem::Version.new(ver.dup) >= Gem::Version.new(Syndi::VERSION.dup) # must be later than or equal to current
92
+
93
+ # Split current version and plugin-demanded version by '.'.
94
+ verarr = Syndi::VERSION.split(/\./)
95
+ pverarr = ver.split(/\./)
96
+
97
+ # Must be no later than the current minor version
98
+ unless verarr[1] <= pverarr[1]
99
+ raise PluginError, "Plugin #@name v#@version demands Syndi #{conf.syndi}; current version is #{Syndi::VERSION}. Incompatible! Aborting load!"
100
+ end
101
+
102
+ @syndi = conf.syndi
103
+
104
+ else
105
+ raise PluginError, "Plugin #@name v#@version demands Syndi #{conf.syndi}; current version is #{Syndi::VERSION}. Incompatible! Aborting load!"
106
+ end # if ver >=
107
+
108
+ elsif conf.syndi =~ /^(>=\s*)((?:[\dabcr])(?:\.[\dabcr]))+$/ # >=
109
+
110
+ ver = $2
111
+ unless ver >= Syndi::VERSION # must be later than or equal to current
112
+ raise PluginError, "Plugin #@name v#@version demands Syndi #{conf.syndi}; current version is #{Syndi::VERSION}. Incompatible! Aborting load!"
113
+ end
114
+
115
+ @syndi = conf.syndi
116
+
117
+ else
118
+ raise PluginError, "Plugin #@name v#@version cannot be checked for compatibility. Aborting load!"
119
+ end # compat check
120
+
121
+ # If we've made it this far, it's sufficiently compatible with the API.
122
+ # Now, we need to extend this plugin with our domain-specific language (DSL).
123
+ self.extend Syndi::DSL::Base # this is the base
124
+ case @library
125
+
126
+ when 'irc'
127
+ self.extend Syndi::DSL::IRC
128
+ when 'multi'
129
+ # the specifications for multilib DSL functionality are yet undecided
130
+ else
131
+ # If it's a library we don't comprehend, exception time, it is.
132
+ raise PluginError, "Plugin #@name v#@version demands '#{@library}' library, which I do not understand. Aborting load!"
133
+
134
+ end
135
+
136
+ end # def configure
137
+
138
+ #########
139
+ protected
140
+ #########
141
+
142
+ # Inheritance event.
143
+ #
144
+ # @param [Class] subklass The subclass which has inherited {self}.
145
+ def self.inherited(subklass)
146
+ $m.debug("[plugin] Syndi::API::Plugin inherited by #{subklass}")
147
+ end
148
+
149
+ end # class Plugin
150
+
151
+ end # module API
152
+
153
+ end # module Syndi
154
+
155
+ # vim: set ts=4 sts=2 sw=2 et:
data/lib/syndi/api.rb ADDED
@@ -0,0 +1,7 @@
1
+ # Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
2
+ # This free software is distributed under the FreeBSD license (see LICENSE).
3
+
4
+ require 'syndi/api/events'
5
+ require 'syndi/api/timers'
6
+
7
+ # vim: set ts=4 sts=2 sw=2 et:
data/lib/syndi/bot.rb ADDED
@@ -0,0 +1,270 @@
1
+ # Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
2
+ # This free software is distributed under the FreeBSD license (see LICENSE).
3
+
4
+ syndiload :Redis, 'redis'
5
+ syndiload :FileKV, 'filekv'
6
+
7
+ require 'syndi/config'
8
+ require 'syndi/api'
9
+
10
+ # Namespace: Syndi
11
+ module Syndi
12
+
13
+ # This is the central class of Syndi, providing all core functionality.
14
+ #
15
+ # It should be additionally noted that for each loaded core library, a readable
16
+ # instance attribute of the library's name will exist, typically pointing to
17
+ # an instance of its respective Library class. (e.g. @irc = <Syndi::IRC::Library>)
18
+ #
19
+ # @!attribute [r] opts
20
+ # @return [Slop] The options object.
21
+ #
22
+ #
23
+ # @!attribute [r] log
24
+ # @return [Syndi::Logger] The logging instance.
25
+ #
26
+ # @!attribute [r] conf
27
+ # @return [Syndi::Config] The configuration instance.
28
+ #
29
+ # @!attribute [r] events
30
+ # @return [Syndi::API::Events] The event system instance.
31
+ #
32
+ # @!attribute [r] clock
33
+ # @return [Syndi::API::Timers] The timer system instance.
34
+ #
35
+ # @!attribute [r] db
36
+ # @return [Redis] The Redis database.
37
+ #
38
+ # @!attribute [r] libs
39
+ # @return [Array<String>] List of loaded core libraries.
40
+ #
41
+ # @!attribute [r] netloop
42
+ # @return [Thread] The thread in which #main_loop is running.
43
+ #
44
+ # @!attribute [r] sockets
45
+ # @return [Array<Object>] A list of socket objects.
46
+ class Bot
47
+
48
+ attr_reader :opts, :log, :conf, :events, :clock, :db, :libs,
49
+ :netloop, :sockets
50
+
51
+ # Create a new instance of Syndi.
52
+ #
53
+ # @param [Hash{String => Object}] opts A hash of options.
54
+ def initialize opts
55
+ # Save options.
56
+ @opts = opts
57
+ end
58
+
59
+ # Initialize this instance.
60
+ def init
61
+
62
+ # Load configuration
63
+ load_config
64
+
65
+ # Initialize the central event system
66
+ @events = Syndi::API::Events.new
67
+
68
+ # Start the timer system.
69
+ @clock = Syndi::API::Timers.new
70
+
71
+ # Prepare for sockets.
72
+ @sockets = []
73
+
74
+ # Initialize the database
75
+ @db = load_database
76
+
77
+ # Load core libraries.
78
+ load_libraries
79
+
80
+ true
81
+ end
82
+
83
+ # Start the bot.
84
+ def start
85
+
86
+ # Call the start event.
87
+ @events.call :start
88
+
89
+ # Throw the program into the main loop.
90
+ @events.threads.each { |thr| thr.join } # block until we're ready to go
91
+ $log.verbose("Producing a thread and entering the main loop...", VUSEFUL) do
92
+ @netloop = Thread.new { main_loop }
93
+ @netloop.join
94
+ end
95
+
96
+ end
97
+
98
+ # Daemonize the bot.
99
+ def daemonize
100
+ $log.info "Forking into the background. . . ."
101
+
102
+ # Direct all incoming data on STDIN and outgoing data on STDOUT/STDERR to /dev/null.
103
+ $stdin = File.open '/dev/null'
104
+ $stdout = $stderr = File.open '/dev/null', 'w'
105
+
106
+ # Fork and retrieve the PID.
107
+ pid = fork
108
+
109
+ # Save it to syndi.pid.
110
+ unless pid.nil?
111
+ File.open('syndi.pid', 'w') { |io| io.puts pid }
112
+ exit 0
113
+ end
114
+ end
115
+
116
+ # Main loop.
117
+ def main_loop
118
+ loop do
119
+ # Build a list of sockets.
120
+ sockets = []
121
+ assoc_objects = {}
122
+ @sockets.each do |o|
123
+ unless o.socket.nil? or o.socket.closed?
124
+ sockets << o.socket
125
+ assoc_objects[o.socket] = o
126
+ end
127
+ end
128
+ next if sockets.empty?
129
+
130
+ # Call #select.
131
+ ready_read, _, _ = IO.select(sockets, [], [], nil)
132
+
133
+ # Iterate through sockets ready for reading.
134
+ ready_read.each do |socket|
135
+ @events.call :net_receive, assoc_objects[socket]
136
+ end
137
+ end
138
+ end
139
+
140
+ # Terminate the bot.
141
+ #
142
+ # @param [String] reason The reason for termination.
143
+ def terminate reason = 'Terminating'
144
+ info "Syndi is terminating owing to thus: #{reason}"
145
+
146
+ # Call :die
147
+ @events.call :die, reason
148
+
149
+ # Close the database.
150
+ @db.disconnect
151
+
152
+ # When dying, allow about three seconds for hooks to execute before
153
+ # fully terminating.
154
+ sleep 3
155
+
156
+ # Delete syndi.pid
157
+ File.delete 'syndi.pid' unless @opts.foreground?
158
+
159
+ exit 0
160
+ end
161
+
162
+ #######
163
+ private
164
+ #######
165
+
166
+ # Load the configuration.
167
+ def load_config
168
+
169
+ # Try to find the file
170
+ # if we're a gem, we'll try ~/.syndi/syndi.yml
171
+ # else we'll try ./conf/syndi.yml
172
+ confpath = nil
173
+ if Syndi.gem?
174
+ confpath = File.join(SYNDI_DIR, 'syndi.yml')
175
+ else
176
+ confpath = File.join('conf', 'syndi.yml')
177
+ end
178
+ confpath = @opts[:conf] if @opts.conf? # --conf=FILE has supreme precedence
179
+
180
+ $log.info "Reading the configuration file #{confpath}..."
181
+ @conf = Syndi::Config.new File.expand_path(confpath)
182
+
183
+ end
184
+
185
+ # Load Syndi libraries.
186
+ def load_libraries
187
+
188
+ $log.info 'Loading core libraries...'
189
+ @libs = []
190
+
191
+ # Iterate through each configured library.
192
+ @conf['libraries'].each do |lib|
193
+ lib.dc!
194
+
195
+ if @libs.include? lib
196
+ # Don't load a library more than once!
197
+ $log.error "Cannot load library twice (#{lib})! Please fix your configuration."
198
+ next
199
+ end
200
+
201
+ begin
202
+ load_library lib
203
+ @libs.push lib
204
+ rescue => e
205
+ $log.error_bt "Failed to load core library '#{lib}': #{e}", e.backtrace
206
+ end
207
+
208
+ end
209
+
210
+ end
211
+
212
+ # Load a core library.
213
+ def load_library lib
214
+ # here is where magic occurs to load a library
215
+ require "syndi/#{lib}"
216
+ instance_variable_set "@#{lib}".to_sym, Object.const_get("LIBRARY_#{lib.uc}")
217
+ define_singleton_method(lib.to_sym) { self.instance_variable_get("@#{__method__}".to_sym) }
218
+ end
219
+
220
+ # Load the Redis database.
221
+ def load_database
222
+
223
+ driver = @conf['database']['driver'] || 'redis'
224
+
225
+ case driver
226
+ when 'redis'
227
+ load_db_redis
228
+ when 'flatfile'
229
+ load_db_flatfile
230
+ end
231
+
232
+ end
233
+
234
+ # Initializes Redis.
235
+ def load_db_redis
236
+
237
+ config = Hash.new
238
+ if host = @conf['database']['address']
239
+ config[:host] = host
240
+ end
241
+ if port = @conf['database']['port']
242
+ config[:port] = port
243
+ end
244
+ if path = @conf['database']['path']
245
+ config[:path] = path
246
+ end
247
+
248
+ redis = Redis.new config
249
+
250
+ if passwd = @conf['database']['password']
251
+ redis.auth passwd
252
+ end
253
+ if id = @conf['database']['number']
254
+ redis.select id
255
+ end
256
+
257
+ redis
258
+
259
+ end
260
+
261
+ # Initializes Flatfile.
262
+ def load_db_flatfile
263
+ FileKV.new 'syndi.db'
264
+ end
265
+
266
+ end # class Bot
267
+
268
+ end # module Syndi
269
+
270
+ # vim: set ts=4 sts=2 sw=2 et: