zmb 0.1.1
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/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.markdown +39 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/bin/zmb +188 -0
- data/lib/zmb.rb +296 -0
- data/lib/zmb/commands.rb +63 -0
- data/lib/zmb/event.rb +15 -0
- data/lib/zmb/plugin.rb +110 -0
- data/lib/zmb/settings.rb +48 -0
- data/lib/zmb/timer.rb +28 -0
- data/plugins/bank.rb +101 -0
- data/plugins/commands.rb +119 -0
- data/plugins/irc.rb +230 -0
- data/plugins/quote.rb +100 -0
- data/plugins/relay.rb +70 -0
- data/plugins/users.rb +280 -0
- data/test/helper.rb +10 -0
- data/test/test_zmb.rb +7 -0
- data/zmb.gemspec +71 -0
- metadata +97 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 kylef
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
## zmb messenger bot
|
2
|
+
|
3
|
+
zmb is a complete messenger bot supporting irc, and command line interface.
|
4
|
+
|
5
|
+
### Install
|
6
|
+
gem install zmb
|
7
|
+
|
8
|
+
### Uninstall
|
9
|
+
gem uninstall zmb
|
10
|
+
rm -rf ~/.zmb # If you used the default settings location
|
11
|
+
|
12
|
+
### Creating a bot
|
13
|
+
|
14
|
+
This command will use the default settings location of ~/.zmb, you can pass `-s <PATH>` to change this.
|
15
|
+
|
16
|
+
zmb --create
|
17
|
+
|
18
|
+
### Launching the bot
|
19
|
+
zmb --daemon
|
20
|
+
|
21
|
+
### Using the bot in command shell mode
|
22
|
+
|
23
|
+
You can run zmb in a shell mode to test plugins without even connecting to any irc servers. It will create a shell where you can enter commands.
|
24
|
+
|
25
|
+
zmb --shell
|
26
|
+
|
27
|
+
### Included plugins
|
28
|
+
|
29
|
+
- IRC
|
30
|
+
- Quote
|
31
|
+
- Relay - Relay between servers and/or channels
|
32
|
+
- Users - User management
|
33
|
+
- Bank - Points system
|
34
|
+
|
35
|
+
### Support
|
36
|
+
|
37
|
+
You can find support at #zmb @ efnet.
|
38
|
+
|
39
|
+
For complete documentation please visit [Documentation](http://kylefuller.co.uk/projects/zmb/)
|
data/Rakefile
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "zmb"
|
8
|
+
gem.summary = %Q{ZMB, messenger bot}
|
9
|
+
gem.description = %Q{ZMB, messenger bot}
|
10
|
+
gem.email = "inbox@kylefuller.co.uk"
|
11
|
+
gem.homepage = "http://github.com/kylef/zmb"
|
12
|
+
gem.authors = ["kylef"]
|
13
|
+
gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
|
14
|
+
gem.add_dependency "json", ">= 1.0.0"
|
15
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'rake/testtask'
|
23
|
+
Rake::TestTask.new(:test) do |test|
|
24
|
+
test.libs << 'lib' << 'test'
|
25
|
+
test.pattern = 'test/**/test_*.rb'
|
26
|
+
test.verbose = true
|
27
|
+
end
|
28
|
+
|
29
|
+
begin
|
30
|
+
require 'rcov/rcovtask'
|
31
|
+
Rcov::RcovTask.new do |test|
|
32
|
+
test.libs << 'test'
|
33
|
+
test.pattern = 'test/**/test_*.rb'
|
34
|
+
test.verbose = true
|
35
|
+
end
|
36
|
+
rescue LoadError
|
37
|
+
task :rcov do
|
38
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
task :test => :check_dependencies
|
43
|
+
|
44
|
+
task :default => :test
|
45
|
+
|
46
|
+
require 'rake/rdoctask'
|
47
|
+
Rake::RDocTask.new do |rdoc|
|
48
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
49
|
+
|
50
|
+
rdoc.rdoc_dir = 'rdoc'
|
51
|
+
rdoc.title = "zmb #{version}"
|
52
|
+
rdoc.rdoc_files.include('README*')
|
53
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
54
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
data/bin/zmb
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
4
|
+
|
5
|
+
require 'zmb'
|
6
|
+
require 'optparse'
|
7
|
+
|
8
|
+
class AdminUser
|
9
|
+
attr_accessor :username, :userhosts
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@username = 'admin'
|
13
|
+
@userhosts = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def admin?
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def permission?(perm)
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
def authenticated?
|
25
|
+
true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Event
|
30
|
+
attr_accessor :message
|
31
|
+
|
32
|
+
def initialize(message)
|
33
|
+
@message = message
|
34
|
+
end
|
35
|
+
|
36
|
+
def message?
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def private?
|
41
|
+
true
|
42
|
+
end
|
43
|
+
|
44
|
+
def user
|
45
|
+
AdminUser.new
|
46
|
+
end
|
47
|
+
|
48
|
+
def reply(msg)
|
49
|
+
puts "> #{msg}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def ask(question)
|
54
|
+
puts "#{question} (yes/no)"
|
55
|
+
answer = gets.chomp
|
56
|
+
answer == 'yes' or answer == 'y'
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_value(question)
|
60
|
+
puts question
|
61
|
+
answer = gets.chomp
|
62
|
+
|
63
|
+
return nil if answer == ''
|
64
|
+
answer
|
65
|
+
end
|
66
|
+
|
67
|
+
def wizard(zmb, plugin)
|
68
|
+
STDOUT.flush
|
69
|
+
|
70
|
+
if ask("Would you like to add the #{plugin.name} plugin? #{plugin.description}") then
|
71
|
+
if plugin.multi_instances? then
|
72
|
+
instance = get_value("What would you like to name this instance of #{plugin.name}?")
|
73
|
+
else
|
74
|
+
instance = plugin.name
|
75
|
+
end
|
76
|
+
|
77
|
+
if not instance then
|
78
|
+
puts "Must supply instance name, if this plugin should only be loaded once such as commands or users then you can call it that."
|
79
|
+
return wizard zmb, plugin
|
80
|
+
end
|
81
|
+
|
82
|
+
zmb.setup(plugin.name, instance)
|
83
|
+
obj = zmb.plugin_manager.plugin plugin.name
|
84
|
+
if obj.respond_to?('wizard') then
|
85
|
+
settings = zmb.settings.setting(instance)
|
86
|
+
settings['plugin'] = plugin.name
|
87
|
+
|
88
|
+
obj.wizard.each do |key, value|
|
89
|
+
if value.has_key?('help') then
|
90
|
+
set = get_value("#{value['help']} (default=#{value['default']})")
|
91
|
+
settings[key] = set if set
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
zmb.settings.save(instance, settings)
|
96
|
+
end
|
97
|
+
zmb.load instance
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
options = {}
|
102
|
+
|
103
|
+
optparse = OptionParser.new do |opts|
|
104
|
+
opts.banner = "Usage: zmb [options]"
|
105
|
+
|
106
|
+
options[:settings] = nil
|
107
|
+
opts.on('-s', '--settings SETTING', 'Use a settings folder') do |settings|
|
108
|
+
options[:settings] = settings
|
109
|
+
end
|
110
|
+
|
111
|
+
options[:daemon] = false
|
112
|
+
opts.on('-d', '--daemon', 'Run ZMB') do
|
113
|
+
options[:daemon] = true
|
114
|
+
end
|
115
|
+
|
116
|
+
options[:create] = false
|
117
|
+
opts.on('-c', '--create', 'Create a new ZMB settings file') do
|
118
|
+
options[:create] = true
|
119
|
+
end
|
120
|
+
|
121
|
+
options[:shell] = false
|
122
|
+
opts.on('-b', '--shell', 'Create a commands shell') do
|
123
|
+
options[:shell] = true
|
124
|
+
end
|
125
|
+
|
126
|
+
options[:command] = false
|
127
|
+
opts.on('-l', '--line LINE', 'Execute a command') do |line|
|
128
|
+
options[:command] = line
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
optparse.parse!
|
133
|
+
|
134
|
+
if not options[:settings] then
|
135
|
+
options[:settings] = File.expand_path('~/.zmb')
|
136
|
+
puts "No settings file specified, will use #{options[:settings]}"
|
137
|
+
end
|
138
|
+
|
139
|
+
zmb = Zmb.new(options[:settings])
|
140
|
+
|
141
|
+
if options[:create] then
|
142
|
+
STDOUT.flush
|
143
|
+
|
144
|
+
zmb.save
|
145
|
+
|
146
|
+
while ask('Would you like to add additional plugin sources?')
|
147
|
+
source = get_value('Which path?')
|
148
|
+
if source and File.exists?(source) then
|
149
|
+
zmb.plugin_manager.add_plugin_source source
|
150
|
+
puts 'Source added'
|
151
|
+
zmb.save
|
152
|
+
else
|
153
|
+
puts 'Invalid source'
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
zmb.plugin_manager.plugins.reject{ |plugin| zmb.instances.has_key? plugin.name }.each{ |plugin| wizard(zmb, plugin) }
|
158
|
+
|
159
|
+
if zmb.instances.has_key?('users') and ask('Would you like to add a admin user?') then
|
160
|
+
username = get_value('Username:')
|
161
|
+
password = get_value('Password:')
|
162
|
+
userhost = get_value('Userhost: (Leave blank for none)')
|
163
|
+
zmb.instances['users'].create_user(username, password, userhost).permit('admin')
|
164
|
+
end
|
165
|
+
|
166
|
+
zmb.save
|
167
|
+
end
|
168
|
+
|
169
|
+
if options[:command] then
|
170
|
+
zmb.event(nil, Event.new(options[:command]))
|
171
|
+
zmb.save
|
172
|
+
end
|
173
|
+
|
174
|
+
if options[:shell] then
|
175
|
+
STDOUT.flush
|
176
|
+
|
177
|
+
begin
|
178
|
+
while 1
|
179
|
+
zmb.event(nil, Event.new(gets.chomp))
|
180
|
+
end
|
181
|
+
rescue Interrupt
|
182
|
+
zmb.save
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
if options[:daemon] then
|
187
|
+
zmb.run
|
188
|
+
end
|
data/lib/zmb.rb
ADDED
@@ -0,0 +1,296 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'json'
|
5
|
+
rescue LoadError
|
6
|
+
require 'rubygems'
|
7
|
+
gem 'json'
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'zmb/plugin'
|
11
|
+
require 'zmb/settings'
|
12
|
+
require 'zmb/event'
|
13
|
+
require 'zmb/commands'
|
14
|
+
require 'zmb/timer'
|
15
|
+
|
16
|
+
class Zmb
|
17
|
+
attr_accessor :instances, :plugin_manager, :settings
|
18
|
+
|
19
|
+
def initialize(config_dir)
|
20
|
+
@plugin_manager = PluginManager.new
|
21
|
+
@settings = Settings.new(config_dir)
|
22
|
+
|
23
|
+
@instances = {'core/zmb' => self}
|
24
|
+
@sockets = Hash.new
|
25
|
+
|
26
|
+
@minimum_timeout = 0.5 # Half a second
|
27
|
+
@maximum_timeout = 60.0 # Sixty seconds
|
28
|
+
@timers = Array.new
|
29
|
+
timer_add(Timer.new(self, :save, 120.0, true)) # Save every 2 minutes
|
30
|
+
|
31
|
+
@settings.get('core/zmb', 'plugin_sources', []).each{|source| @plugin_manager.add_plugin_source source}
|
32
|
+
|
33
|
+
if @plugin_manager.plugin_sources.empty? then
|
34
|
+
@plugin_manager.add_plugin_source File.join(File.expand_path(File.dirname(File.dirname(__FILE__))), 'plugins')
|
35
|
+
end
|
36
|
+
|
37
|
+
@settings.get('core/zmb', 'plugin_instances', []).each{|instance| load instance}
|
38
|
+
|
39
|
+
@running = false
|
40
|
+
end
|
41
|
+
|
42
|
+
def running?
|
43
|
+
@running
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_json(*a)
|
47
|
+
{
|
48
|
+
'plugin_sources' => @plugin_manager.plugin_sources,
|
49
|
+
'plugin_instances' => @instances.keys,
|
50
|
+
}.to_json(*a)
|
51
|
+
end
|
52
|
+
|
53
|
+
def save
|
54
|
+
@instances.each{ |k,v| @settings.save(k, v) }
|
55
|
+
end
|
56
|
+
|
57
|
+
def load(key)
|
58
|
+
return true if @instances.has_key?(key)
|
59
|
+
|
60
|
+
if p = @settings.get(key, 'plugin') then
|
61
|
+
object = @plugin_manager.plugin(p)
|
62
|
+
return false if not object
|
63
|
+
@instances[key] = object.new(self, @settings.setting(key))
|
64
|
+
post! :plugin_loaded, key, @instances[key]
|
65
|
+
true
|
66
|
+
else
|
67
|
+
false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def unload(key, tell=true)
|
72
|
+
return false if not @instances.has_key?(key)
|
73
|
+
instance = @instances.delete(key)
|
74
|
+
@settings.save key, instance
|
75
|
+
socket_delete instance
|
76
|
+
timer_delete instance
|
77
|
+
instance.unloaded if instance.respond_to?('unloaded') and tell
|
78
|
+
post! :plugin_unloaded, key, instance
|
79
|
+
end
|
80
|
+
|
81
|
+
def run
|
82
|
+
post! :running, self
|
83
|
+
|
84
|
+
@running = true
|
85
|
+
begin
|
86
|
+
while @running
|
87
|
+
socket_run(timeout)
|
88
|
+
timer_run
|
89
|
+
end
|
90
|
+
rescue Interrupt
|
91
|
+
save
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def timeout
|
96
|
+
if timer_timeout > @maximum_timeout
|
97
|
+
if @sockets.count < 1 then
|
98
|
+
5
|
99
|
+
else
|
100
|
+
@maximum_timeout
|
101
|
+
end
|
102
|
+
elsif timer_timeout > @minimum_timeout
|
103
|
+
timer_timeout
|
104
|
+
else
|
105
|
+
@minimum_timeout
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def socket_add(delegate, socket)
|
110
|
+
@sockets[socket] = delegate
|
111
|
+
end
|
112
|
+
|
113
|
+
def socket_delete(item)
|
114
|
+
if @sockets.has_value?(item) then
|
115
|
+
@sockets.select{ |sock, delegate| delegate == item }.each{ |sock, delegate| @sockets.delete(sock) }
|
116
|
+
end
|
117
|
+
|
118
|
+
if @sockets.has_key?(item) then
|
119
|
+
@sockets.delete(item)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def socket_run(timeout)
|
124
|
+
result = select(@sockets.keys, nil, nil, timeout)
|
125
|
+
|
126
|
+
if result != nil then
|
127
|
+
result[0].select{|sock| @sockets.has_key?(sock)}.each do |sock|
|
128
|
+
if sock.eof? then
|
129
|
+
@sockets[sock].disconnected(self, sock) if @sockets[sock].respond_to?('disconnected')
|
130
|
+
socket_delete sock
|
131
|
+
else
|
132
|
+
@sockets[sock].received(self, sock, sock.gets()) if @sockets[sock].respond_to?('received')
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def timer_add(timer)
|
139
|
+
@timers << timer
|
140
|
+
end
|
141
|
+
|
142
|
+
def timer_delete(search)
|
143
|
+
@timers.each{ |timer| @timers.delete(timer) if timer.delegate == search }
|
144
|
+
@timers.delete(search)
|
145
|
+
end
|
146
|
+
|
147
|
+
def timer_timeout # When will the next timer run?
|
148
|
+
@timers.map{|timer| timer.timeout}.sort.fetch(0, @maximum_timeout)
|
149
|
+
end
|
150
|
+
|
151
|
+
def timer_run
|
152
|
+
@timers.select{|timer| timer.timeout <= 0.0 and timer.respond_to?("fire") }.each{|timer| timer.fire(self)}
|
153
|
+
end
|
154
|
+
|
155
|
+
def post(signal, *args)
|
156
|
+
results = Array.new
|
157
|
+
|
158
|
+
@instances.select{|name, instance| instance.respond_to?(signal)}.each do |name, instance|
|
159
|
+
results << instance.send(signal, *args) rescue nil
|
160
|
+
end
|
161
|
+
|
162
|
+
results
|
163
|
+
end
|
164
|
+
|
165
|
+
def post!(signal, *args) # This will exclude the plugin manager
|
166
|
+
@instances.select{|name, instance| instance.respond_to?(signal) and instance != self}.each do |name, instance|
|
167
|
+
instance.send(signal, *args) rescue nil
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def setup(plugin, instance)
|
172
|
+
object = @plugin_manager.plugin plugin
|
173
|
+
return false if not object
|
174
|
+
|
175
|
+
settings = Hash.new
|
176
|
+
settings['plugin'] = plugin
|
177
|
+
|
178
|
+
if object.respond_to? 'wizard' then
|
179
|
+
d = object.wizard
|
180
|
+
d.each{ |k,v| settings[k] = v['default'] if v.has_key?('default') and v['default'] }
|
181
|
+
end
|
182
|
+
|
183
|
+
@settings.save instance, settings
|
184
|
+
|
185
|
+
true
|
186
|
+
end
|
187
|
+
|
188
|
+
def event(sender, e)
|
189
|
+
post! :pre_event, sender, e
|
190
|
+
post! :event, sender, e
|
191
|
+
end
|
192
|
+
|
193
|
+
def commands
|
194
|
+
{
|
195
|
+
'reload' => PermCommand.new('admin', self, :reload_command),
|
196
|
+
'unload' => PermCommand.new('admin', self, :unload_command),
|
197
|
+
'load' => PermCommand.new('admin', self, :load_command),
|
198
|
+
'save' => PermCommand.new('admin', self, :save_command, 0),
|
199
|
+
'loaded' => PermCommand.new('admin', self, :loaded_command, 0),
|
200
|
+
'setup' => PermCommand.new('admin', self, :setup_command, 2),
|
201
|
+
'set' => PermCommand.new('admin', self, :set_command, 3),
|
202
|
+
'get' => PermCommand.new('admin', self, :get_command, 2),
|
203
|
+
'clone' => PermCommand.new('admin', self, :clone_command, 2),
|
204
|
+
'reset' => PermCommand.new('admin', self, :reset_command),
|
205
|
+
'addsource' => PermCommand.new('admin', self, :addsource_command),
|
206
|
+
}
|
207
|
+
end
|
208
|
+
|
209
|
+
def reload_command(e, instance)
|
210
|
+
if @instances.has_key?(instance) then
|
211
|
+
sockets = Array.new
|
212
|
+
@sockets.each{ |sock,delegate| sockets << sock if delegate == @instances[instance] }
|
213
|
+
unload(instance, false)
|
214
|
+
reloaded = @plugin_manager.reload_plugin(@settings.get(instance, 'plugin'))
|
215
|
+
load(instance)
|
216
|
+
|
217
|
+
sockets.each{ |socket| @sockets[socket] = @instances[instance] }
|
218
|
+
@instances[instance].socket = sockets[0] if sockets.size == 1 and @instances[instance].respond_to?('socket=')
|
219
|
+
|
220
|
+
reloaded ? "#{instance} reloaded" : "#{instance} refreshed"
|
221
|
+
else
|
222
|
+
"No such instance #{instance}"
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def unload_command(e, instance)
|
227
|
+
if @instances.has_key?(instance) then
|
228
|
+
unload(instance)
|
229
|
+
"#{instance} unloaded"
|
230
|
+
else
|
231
|
+
"No such instance #{instance}"
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def load_command(e, instance)
|
236
|
+
if not @instances.has_key?(instance) then
|
237
|
+
load(instance) ? "#{instance} loaded" : "#{instance} did not load correctly"
|
238
|
+
else
|
239
|
+
"Instance already #{instance}"
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def save_command(e)
|
244
|
+
save
|
245
|
+
'settings saved'
|
246
|
+
end
|
247
|
+
|
248
|
+
def loaded_command(e)
|
249
|
+
@instances.keys.join(', ')
|
250
|
+
end
|
251
|
+
|
252
|
+
def setup_command(e, plugin, instance)
|
253
|
+
if setup(plugin, instance) then
|
254
|
+
object = @plugin_manager.plugin plugin
|
255
|
+
result = ["Instance saved, please use the set command to override the default configuration for this instance."]
|
256
|
+
result += d.map{ |k,v| "#{k} - #{v['help']} (default=#{v['default']})" } if object.respond_to? 'wizard'
|
257
|
+
result.join("\n")
|
258
|
+
else
|
259
|
+
"plugin not found"
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def set_command(e, instance, key, value)
|
264
|
+
settings = @settings.setting(instance)
|
265
|
+
settings[key] = value
|
266
|
+
@settings.save(instance, settings)
|
267
|
+
"#{key} set to #{value} for #{instance}"
|
268
|
+
end
|
269
|
+
|
270
|
+
def get_command(e, instance, key)
|
271
|
+
if value = @settings.get(instance, key) then
|
272
|
+
"#{key} is #{value} for #{instance}"
|
273
|
+
else
|
274
|
+
"#{instance} or #{instance}/#{key} not found."
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def clone_command(e, instance, new_instance)
|
279
|
+
if (settings = @settings.setting(instance)) != {} then
|
280
|
+
@settings.save(new_instance, settings)
|
281
|
+
"The settings for #{instance} were copied to #{new_instance}"
|
282
|
+
else
|
283
|
+
"No settings for #{instance}"
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
def reset_command(e, instance)
|
288
|
+
@settings.save(instance, {})
|
289
|
+
"Settings for #{instance} have been deleted."
|
290
|
+
end
|
291
|
+
|
292
|
+
def addsource_command(e, source)
|
293
|
+
@plugin_manager.add_plugin_source source
|
294
|
+
"#{source} added to plugin manager"
|
295
|
+
end
|
296
|
+
end
|