Auto 4.0.0.alpha.1-x86-mingw32
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/.yardopts +7 -0
- data/Gemfile +19 -0
- data/LICENSE.md +31 -0
- data/README.md +109 -0
- data/Rakefile +41 -0
- data/bin/auto +110 -0
- data/bin/auto-conf +45 -0
- data/conf/example.json +100 -0
- data/conf/example.yml +125 -0
- data/docs/Contributing.md +77 -0
- data/docs/Events.md +103 -0
- data/docs/Todo.md +21 -0
- data/docs/Upgrade.md +16 -0
- data/ext/dsl_base.c +49 -0
- data/ext/libauto/auto.h +20 -0
- data/ext/libauto/extconf.rb +16 -0
- data/ext/libauto/libauto.c +29 -0
- data/ext/libauto/libauto.h +28 -0
- data/ext/libauto/logger.c +177 -0
- data/ext/libauto/logger.h +44 -0
- data/lib/auto.rb +43 -0
- data/lib/auto/api.rb +7 -0
- data/lib/auto/api/events.rb +166 -0
- data/lib/auto/api/object.rb +29 -0
- data/lib/auto/api/plugin.rb +155 -0
- data/lib/auto/api/timers.rb +93 -0
- data/lib/auto/bot.rb +338 -0
- data/lib/auto/config.rb +181 -0
- data/lib/auto/configure.rb +410 -0
- data/lib/auto/configure/shell.rb +154 -0
- data/lib/auto/dsl/base.rb +74 -0
- data/lib/auto/dsl/irc.rb +13 -0
- data/lib/auto/irc.rb +8 -0
- data/lib/auto/irc/common.rb +63 -0
- data/lib/auto/irc/library.rb +89 -0
- data/lib/auto/irc/object/channel.rb +21 -0
- data/lib/auto/irc/object/entity.rb +90 -0
- data/lib/auto/irc/object/message.rb +99 -0
- data/lib/auto/irc/object/user.rb +139 -0
- data/lib/auto/irc/protocol.rb +164 -0
- data/lib/auto/irc/protocol/numerics.rb +60 -0
- data/lib/auto/irc/sasl/diffie_hellman.rb +36 -0
- data/lib/auto/irc/sasl/mech.rb +15 -0
- data/lib/auto/irc/sasl/mech/dh_blowfish.rb +83 -0
- data/lib/auto/irc/sasl/mech/plain.rb +39 -0
- data/lib/auto/irc/server.rb +301 -0
- data/lib/auto/irc/state/channel_manager.rb +6 -0
- data/lib/auto/irc/state/support.rb +142 -0
- data/lib/auto/irc/state/user_manager.rb +6 -0
- data/lib/auto/irc/std/commands.rb +99 -0
- data/lib/auto/irc/std/numerics.rb +216 -0
- data/lib/auto/rubyext/integer.rb +25 -0
- data/lib/auto/rubyext/string.rb +10 -0
- data/lib/auto/version.rb +18 -0
- data/lib/libauto.so +0 -0
- data/spec/api_events_spec.rb +68 -0
- data/spec/config_json_spec.rb +116 -0
- data/spec/config_other_spec.rb +29 -0
- data/spec/config_yaml_spec.rb +136 -0
- data/spec/helper.rb +19 -0
- data/spec/irc_object_entity_spec.rb +51 -0
- data/spec/logger_spec.rb +30 -0
- data/spec/plugin_base_spec.rb +35 -0
- data/spec/timers_spec.rb +42 -0
- metadata +238 -0
data/lib/auto/config.rb
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
# Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
|
2
|
+
# This free software is distributed under the FreeBSD license (LICENSE.md).
|
3
|
+
autoload :JSON, 'json'
|
4
|
+
autoload :Psych, 'psych'
|
5
|
+
require 'libauto'
|
6
|
+
|
7
|
+
# Namespace: Auto
|
8
|
+
module Auto
|
9
|
+
|
10
|
+
# A class which provides a functional, simple configuration interface. It is
|
11
|
+
# very useful, as it supports both YAML and JSON for configuration. It
|
12
|
+
# determines which is appropriate by looking at file extensions.
|
13
|
+
#
|
14
|
+
# @api Auto
|
15
|
+
# @since 4.0.0
|
16
|
+
# @author noxgirl
|
17
|
+
# @author swarley
|
18
|
+
#
|
19
|
+
# @!attribute conf
|
20
|
+
# @return [Hash{}] This is the hash which contains the data parsed from
|
21
|
+
# the configuration file.
|
22
|
+
# @see #[]
|
23
|
+
#
|
24
|
+
# @!attribute type
|
25
|
+
# @return [Symbol] Type of configuration: +:yaml+ or +:json+.
|
26
|
+
class Config
|
27
|
+
|
28
|
+
attr_reader :conf, :type
|
29
|
+
|
30
|
+
# Produce a new instance, and attempt to parse.
|
31
|
+
#
|
32
|
+
# @param [String] filepath Path to configuration file.
|
33
|
+
#
|
34
|
+
# @raise [ConfigError] If the file extension is not recognized (should be +.yml+ or +.json+).
|
35
|
+
def initialize filepath
|
36
|
+
|
37
|
+
$m.debug("Trying to initialize configuration from '#{filepath}'...")
|
38
|
+
|
39
|
+
# Set path to file.
|
40
|
+
@path = filepath
|
41
|
+
|
42
|
+
# Determine the type: YAML or JSON.
|
43
|
+
case File.extname(filepath)
|
44
|
+
when ".yml"
|
45
|
+
@type = :yaml
|
46
|
+
when ".json"
|
47
|
+
@type = :json
|
48
|
+
else
|
49
|
+
raise ConfigError, "Unknown file type on #{filepath}."
|
50
|
+
end
|
51
|
+
|
52
|
+
# Process the configuration.
|
53
|
+
parse!
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
# Rehash the configuration.
|
58
|
+
#
|
59
|
+
# If an error occurs, it will revert the configuration to its prior state
|
60
|
+
# so that everything can continue to function.
|
61
|
+
def rehash!
|
62
|
+
|
63
|
+
$m.debug("Configuration file is rehashing.")
|
64
|
+
|
65
|
+
# Keep the old configuration in case of issues.
|
66
|
+
oldconf = @conf
|
67
|
+
@conf = {}
|
68
|
+
|
69
|
+
# Rehash
|
70
|
+
parse!
|
71
|
+
|
72
|
+
# Ensure it really succeeded.
|
73
|
+
if @conf.empty? or @conf.class != Hash
|
74
|
+
# Nope. Restore old configuration.
|
75
|
+
@conf = oldconf
|
76
|
+
$m.error("Failed to rehash the configuration file (parser produced empty config)! Reverting to old configuration.")
|
77
|
+
return 0
|
78
|
+
end
|
79
|
+
|
80
|
+
# bot:onRehash
|
81
|
+
$m.events.call('bot:onRehash')
|
82
|
+
|
83
|
+
# This rescue is applicable to anything that happens in here. Since if it is reached, there really was an error in general.
|
84
|
+
rescue => e
|
85
|
+
$m.error("Failed to rehash configuration file! Reverting to old configuration.", false, e.backtrace)
|
86
|
+
@conf = oldconf
|
87
|
+
return 0
|
88
|
+
end
|
89
|
+
|
90
|
+
# Return value of @conf[key].
|
91
|
+
#
|
92
|
+
# @return [Object] Value of @conf[key].
|
93
|
+
# @see @conf
|
94
|
+
def [] key
|
95
|
+
@conf[key]
|
96
|
+
end
|
97
|
+
|
98
|
+
#######
|
99
|
+
private
|
100
|
+
#######
|
101
|
+
|
102
|
+
# A constant for detecting comments and strings in JSON files
|
103
|
+
COMMENT_REGEXP = %r{(?:/\'(?:[^\'\\]|\\.)*\')|(?:\"(?:[^\"\\]|\\.)*\")|(?://.*\n)|(?:/\*(?m-ix:.)+?\*/)}
|
104
|
+
|
105
|
+
# Strip comments from JSON configuration text. This will not preserve
|
106
|
+
# the string passed to it.
|
107
|
+
#
|
108
|
+
# @argument [String] text The configuration data to strip.
|
109
|
+
#
|
110
|
+
# @return [String] The stripped configuration text.
|
111
|
+
def strip_js_comments! text
|
112
|
+
# Output string
|
113
|
+
out = ""
|
114
|
+
until (match_data = text.match(COMMENT_REGEXP)).nil?
|
115
|
+
off = match_data.offset(0)
|
116
|
+
# Check to see if it starts with /, if so then return up to the lower limit, otherwise to the upper.
|
117
|
+
out << text[0...off[(match_data.to_s[0] != '/') ? 1 : 0]]
|
118
|
+
# Delete the text that we were dealing with.
|
119
|
+
text[0...off[1]] = ''
|
120
|
+
end
|
121
|
+
# Append anything left
|
122
|
+
text = (out << text)
|
123
|
+
end
|
124
|
+
|
125
|
+
# The same as strip_js_comments! with original string preservation.
|
126
|
+
# @see strip_js_comments!
|
127
|
+
def strip_js_comments text
|
128
|
+
# Preserve
|
129
|
+
strip_js_comments!(text.clone)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Parse the configuration file, and output the data to {#x}.
|
133
|
+
#
|
134
|
+
# @raise [ConfigError] If the file does not exist.
|
135
|
+
# @raise [ConfigError] If the file cannot be processed.
|
136
|
+
def parse!
|
137
|
+
|
138
|
+
# Ensure foremost that the configuration file exists.
|
139
|
+
unless File.exists? @path
|
140
|
+
raise ConfigError, "Configuration file '#@path' does not exist!"
|
141
|
+
end
|
142
|
+
|
143
|
+
# Get the data from the file.
|
144
|
+
f = File.open(@path)
|
145
|
+
data = f.read
|
146
|
+
f.close
|
147
|
+
|
148
|
+
conf = {}
|
149
|
+
# JSON
|
150
|
+
if @type == :json
|
151
|
+
|
152
|
+
# Strip comments out of the data.
|
153
|
+
data = strip_js_comments!(data)
|
154
|
+
|
155
|
+
# Process the JSON.
|
156
|
+
begin
|
157
|
+
conf = JSON.parse(data)
|
158
|
+
rescue => e
|
159
|
+
raise ConfigError, "Failed to process the JSON in '#@path'", e.backtrace
|
160
|
+
end
|
161
|
+
|
162
|
+
else # Must be YAML
|
163
|
+
|
164
|
+
# Process the YAML.
|
165
|
+
begin
|
166
|
+
conf = Psych.load data
|
167
|
+
rescue => e
|
168
|
+
raise ConfigError, "Failed to process the YAML in '#@path'", e.backtrace
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
@conf = conf
|
174
|
+
|
175
|
+
end # def parse
|
176
|
+
|
177
|
+
end # class Config
|
178
|
+
|
179
|
+
end # module Auto
|
180
|
+
|
181
|
+
# vim: set ts=4 sts=2 sw=2 et:
|
@@ -0,0 +1,410 @@
|
|
1
|
+
# Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
|
2
|
+
# This free software is distributed under the FreeBSD license (LICENSE.md).
|
3
|
+
|
4
|
+
require 'colored'
|
5
|
+
require 'highline'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
$S = '>>>'.blue
|
9
|
+
|
10
|
+
|
11
|
+
# Check To make sure that we have a decent ruby version. There is no reason to support a
|
12
|
+
# version that has reached EOL.
|
13
|
+
if RUBY_VERSION < "1.9"
|
14
|
+
puts <<-EOM
|
15
|
+
The version of ruby that you are using is out dated. Please upgrade to a version of at least
|
16
|
+
1.9.1 to run auto. The ruby source code is located here http://ruby-lang.org/en/downloads
|
17
|
+
EOM
|
18
|
+
end
|
19
|
+
|
20
|
+
# namespace Auto
|
21
|
+
module Auto
|
22
|
+
|
23
|
+
# A library for configuration generation. It depends upon the highline gem.
|
24
|
+
#
|
25
|
+
# @version 1.02
|
26
|
+
# @author swarley
|
27
|
+
# @author noxgirl
|
28
|
+
#
|
29
|
+
# @!attribute hl
|
30
|
+
# @return [HighLine] HighLine instance.
|
31
|
+
#
|
32
|
+
# @!attribute conf
|
33
|
+
# @return [Hash{}] The configuration hash.
|
34
|
+
class Configure
|
35
|
+
|
36
|
+
autoload :Shell, 'auto/configure/shell'
|
37
|
+
# Load the shell.
|
38
|
+
def shell
|
39
|
+
Auto::Configure::Shell.new(@hl)
|
40
|
+
end
|
41
|
+
|
42
|
+
VERSION = '1.02'.freeze
|
43
|
+
AUTODIR = File.join(Dir.home, '.config', 'autobot')
|
44
|
+
|
45
|
+
attr_accessor :hl, :conf
|
46
|
+
|
47
|
+
# Produce a new instance of Auto::Configure.
|
48
|
+
def initialize
|
49
|
+
|
50
|
+
# Produce a new instance of HighLine.
|
51
|
+
@hl = HighLine.new
|
52
|
+
# Prepare for configuration.
|
53
|
+
@conf = Hash.new
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
# Initiate configuration.
|
58
|
+
def generate
|
59
|
+
|
60
|
+
greeting = <<-EOM
|
61
|
+
Greetings! ^.^
|
62
|
+
|
63
|
+
I am going to assist you in configuring your installation of Auto. :) I suggest
|
64
|
+
that, if you're not already reading it, you consult the installation guide:
|
65
|
+
https://github.com/Auto/Auto/wiki/Install-Guide
|
66
|
+
|
67
|
+
When specifying lists, separate elements by commas.
|
68
|
+
|
69
|
+
Remember, if you need additional help, you're free to use the mailing list at
|
70
|
+
https://groups.google.com/group/autobot-talk, or to join the official IRC
|
71
|
+
channel at #auto on irc.freenode.net. :)
|
72
|
+
|
73
|
+
Let us begin!
|
74
|
+
EOM
|
75
|
+
puts greeting.yellow.bold
|
76
|
+
|
77
|
+
conf_libraries
|
78
|
+
conf_database
|
79
|
+
|
80
|
+
dump
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
# Configure libraries.
|
85
|
+
def conf_libraries
|
86
|
+
puts ">>> Currently, the only available library is the IRC library. I will load this automatically.".cyan.bold
|
87
|
+
@conf['libraries'] = ['irc']
|
88
|
+
|
89
|
+
conf_irclib
|
90
|
+
end
|
91
|
+
|
92
|
+
# Configure the IRC library.
|
93
|
+
def conf_irclib
|
94
|
+
|
95
|
+
# Create the configuration hash.
|
96
|
+
@conf['irc'] = {}
|
97
|
+
|
98
|
+
# Add the first server.
|
99
|
+
conf_irc_add_server
|
100
|
+
|
101
|
+
# Add subsequent servers.
|
102
|
+
another = @hl.agree("#$S Would you like to add another IRC server? ") { |q| q.default = 'n' }
|
103
|
+
while another
|
104
|
+
conf_irc_add_server
|
105
|
+
another = @hl.agree("#$S Would you like to add another IRC server? ") { |q| q.default = 'n' }
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
# Add an IRC server.
|
111
|
+
def conf_irc_add_server
|
112
|
+
|
113
|
+
# We need a name.
|
114
|
+
name = @hl.ask("#$S What is the name of this IRC server? ")
|
115
|
+
while @conf['irc'].include? name
|
116
|
+
puts "You've already specified that server. Use a different name.".red.bold
|
117
|
+
name = @hl.ask("#$S What is the name of this IRC server?")
|
118
|
+
end
|
119
|
+
|
120
|
+
# We need an address.
|
121
|
+
address = @hl.ask("#$S What is the address of <%= color('#{name}', :blue, :bold) %>? ")
|
122
|
+
|
123
|
+
# And a port.
|
124
|
+
port = @hl.ask("#$S What is the port of <%= color('#{name}', :blue, :bold) %>? ", Integer) { |q| q.default = 6667 }
|
125
|
+
|
126
|
+
# Does it use SSL?
|
127
|
+
ssl = @hl.agree("#$S Does <%= color('#{address}:#{port}', :blue, :bold) %> use SSL? ") { |q| q.default = 'n' }
|
128
|
+
|
129
|
+
# What nickname(s) should we use?
|
130
|
+
nicks = @hl.ask("#$S What nicknames should I use on <%= color('#{name}', :blue, :bold) %> (list in descending priority)? ",
|
131
|
+
->(str) { str.split(/,\s*/) }) { |q| q.default = 'auto' }
|
132
|
+
nicksvalid = true
|
133
|
+
nicks.each { |n| nicksvalid = false unless n =~ /^[\w\d\[\]\{\}\^\-\_\`]+$/ }
|
134
|
+
until nicksvalid
|
135
|
+
puts "You entered an invalid nickname. Try again.".red.bold
|
136
|
+
nicks = @hl.ask("#$S What nicknames should I use on <%= color('#{name}', :blue, :bold) %> (list in descending priority)? ",
|
137
|
+
->(str) { str.split(/,\s*/) }) { |q| q.default = 'auto' }
|
138
|
+
nicksvalid = true
|
139
|
+
nicks.each { |n| nicksvalid = false unless n =~ /^[\w\d\[\]\{\}\^\-\_\`]+$/ }
|
140
|
+
end
|
141
|
+
|
142
|
+
# What username?
|
143
|
+
user = @hl.ask("#$S What username should I use on <%= color('#{name}', :blue, :bold) %>? ") { |q| q.default = 'auto' }
|
144
|
+
|
145
|
+
# What GECOS?
|
146
|
+
gecos = @hl.ask("#$S What real name or GECOS should I use on <%= color('#{name}', :blue, :bold) %>? ") { |q| q.default = 'Auto (http://auto.autoproj.org)' }
|
147
|
+
|
148
|
+
# Save the data.
|
149
|
+
@conf['irc'][name] = {
|
150
|
+
'address' => address,
|
151
|
+
'port' => port,
|
152
|
+
'useSSL' => ssl,
|
153
|
+
'nickname' => nicks,
|
154
|
+
'username' => user,
|
155
|
+
'realName' => gecos
|
156
|
+
}
|
157
|
+
|
158
|
+
# Should we use SASL?
|
159
|
+
sasl = @hl.agree("#$S Should I use SASL to authenticate with services on <%= color('#{name}', :blue, :bold) %>? ") { |q| q.default = 'n' }
|
160
|
+
|
161
|
+
if sasl
|
162
|
+
|
163
|
+
sasl_user = @hl.ask("#$S What username (i.e. accountname) should I use in SASL authentication? ")
|
164
|
+
sasl_pass = @hl.ask("#$S What is the password for <%= color('#{sasl_user}', :blue, :bold) %>? ") { |q| q.echo = false }
|
165
|
+
sasl_to = @hl.ask("#$S After how many seconds should SASL authentication time out? ", Integer) { |q| q.default = 15 }
|
166
|
+
|
167
|
+
@conf['irc'][name]['SASL'] = {
|
168
|
+
'username' => sasl_user,
|
169
|
+
'password' => sasl_pass,
|
170
|
+
'timeout' => sasl_to,
|
171
|
+
}
|
172
|
+
|
173
|
+
else
|
174
|
+
# Perhaps NickServ or some other service?
|
175
|
+
auth = @hl.agree("#$S OK. Should I identify with a service (e.g. NickServ)? ") { |q| q.default = 'n' }
|
176
|
+
|
177
|
+
if auth
|
178
|
+
|
179
|
+
service = @hl.ask("#$S What service should I message? ") { |q| q.default = 'NickServ' }
|
180
|
+
command = @hl.ask("#$S What command should I use to identify? ") { |q| q.default = 'IDENTIFY' }
|
181
|
+
password = @hl.ask("#$S What password should I use? ") { |q| q.echo = false }
|
182
|
+
|
183
|
+
@conf['irc'][name]['nickIdentify'] = {
|
184
|
+
'service' => service,
|
185
|
+
'command' => command,
|
186
|
+
'password' => password
|
187
|
+
}
|
188
|
+
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
# Setup autojoin.
|
194
|
+
conf_irc_autojoin name
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
# Configure autojoin.
|
199
|
+
#
|
200
|
+
# @param [String] name Name of IRC server.
|
201
|
+
def conf_irc_autojoin(name)
|
202
|
+
another = @hl.agree("#$S Should I automatically join a channel on <%= color('#{name}', :blue, :bold) %>? ") { |q| q.default = 'y' }
|
203
|
+
@conf['irc'][name]['autojoin'] = []
|
204
|
+
|
205
|
+
while another
|
206
|
+
@conf['irc'][name]['autojoin'] << conf_irc_add_channel
|
207
|
+
another = @hl.agree("#$S Should I automatically join another channel? ") { |q| q.default = 'n' }
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# Add an IRC channel.
|
212
|
+
#
|
213
|
+
# @param [String] server The name of the IRC server.
|
214
|
+
def conf_irc_add_channel
|
215
|
+
|
216
|
+
# What's it called?
|
217
|
+
name = @hl.ask("#$S What is the name of the channel? ") { |q| q.default = '#auto' }
|
218
|
+
|
219
|
+
# Does it use a key?
|
220
|
+
usekey = @hl.agree("#$S Does <%= color('#{name}', :blue, :bold) %> use a key (+k)? ") { |q| q.default = 'n' }
|
221
|
+
key = nil
|
222
|
+
|
223
|
+
if usekey
|
224
|
+
key = @hl.ask("#$S What is the key? ")
|
225
|
+
end
|
226
|
+
|
227
|
+
{'name' => name, 'key' => key}
|
228
|
+
end
|
229
|
+
|
230
|
+
# Configure the database.
|
231
|
+
def conf_database
|
232
|
+
@conf['database'] = Hash.new
|
233
|
+
|
234
|
+
msg = <<-eom
|
235
|
+
>> Auto supports three database management systems: SQLite 3, MySQL, and Postgres.
|
236
|
+
>> If you use SQLite 3, you need the 'sqlite3' gem.
|
237
|
+
>> If you use MySQL, you need the 'mysqlplus' gem.
|
238
|
+
>> If you use Postgres, you need the 'pg' gem.
|
239
|
+
>> See https://github.com/Auto/Auto/wiki/Install-Guide for more information.
|
240
|
+
eom
|
241
|
+
puts msg.cyan
|
242
|
+
|
243
|
+
type = @hl.ask("#$S What database management system should I use? (sqlite, mysql, or postgres) ") do |q|
|
244
|
+
q.default = 'sqlite'
|
245
|
+
q.validate = /^(sqlite|mysql|postgres)$/
|
246
|
+
end
|
247
|
+
@conf['database']['type'] = type
|
248
|
+
|
249
|
+
if type == 'sqlite'
|
250
|
+
|
251
|
+
file = @hl.ask("#$S What should be the filename of the database? (relative to <%= color('#{AUTODIR}', :blue, :bold) %>) ") do |q|
|
252
|
+
q.default = File.join AUTODIR, 'auto.db'
|
253
|
+
end
|
254
|
+
|
255
|
+
unless Dir.exists File.dirname(file)
|
256
|
+
puts "Warning: Directory #{File.dirname(file)} does not exist.".red.bold
|
257
|
+
end
|
258
|
+
|
259
|
+
@conf['database']['name'] = file
|
260
|
+
|
261
|
+
else # mysql and pg
|
262
|
+
|
263
|
+
address = @hl.ask("#$S What is the host address of the <%= color('#{type}', :blue, :bold) %> server? ") { |q| q.default = 'localhost' }
|
264
|
+
name = @hl.ask("#$S What is the database name on the <%= color('#{type}', :blue, :bold) %> server? ") { |q| q.default = 'auto' }
|
265
|
+
username = @hl.ask("#$S What username should I use to connect to <%= color('#{type}', :blue, :bold) %> server? ") { |q| q.default = 'auto' }
|
266
|
+
password = @hl.ask("#$S What is the password for <%= color('#{username}', :blue, :bold) %>? ") { |q| q.echo = false }
|
267
|
+
|
268
|
+
@conf['database'].merge!({
|
269
|
+
'address' => address,
|
270
|
+
'name' => name,
|
271
|
+
'username' => username,
|
272
|
+
'password' => password
|
273
|
+
})
|
274
|
+
|
275
|
+
end
|
276
|
+
|
277
|
+
end
|
278
|
+
|
279
|
+
# Dump configuration.
|
280
|
+
def dump
|
281
|
+
|
282
|
+
# A sanity check.
|
283
|
+
if @conf.empty?
|
284
|
+
puts "Configuration is inexplicably empty: aborting.".red.bold
|
285
|
+
exit 1
|
286
|
+
end
|
287
|
+
|
288
|
+
# Produce file.
|
289
|
+
data = <<-EOD
|
290
|
+
# Configuration file generated by auto-conf
|
291
|
+
# version #{Auto::Configure::VERSION}
|
292
|
+
# at #{Time.now}
|
293
|
+
|
294
|
+
#{YAML.dump(@conf)}
|
295
|
+
EOD
|
296
|
+
|
297
|
+
# Produce message.
|
298
|
+
final = <<-EOM
|
299
|
+
OK! Your configuration file is ready! :D
|
300
|
+
|
301
|
+
I just need to know one last thing: where to write this fabulous configuration.
|
302
|
+
|
303
|
+
By default, I will write this to <YOUR_HOME_DIRECTORY>/.config/autobot/auto.yml,
|
304
|
+
which is perfect for you if you're using the 'autobot' gem, because this is the
|
305
|
+
standard file for which the gem will look when executed.
|
306
|
+
|
307
|
+
However, if you are running a standalone installation, you probably want to
|
308
|
+
write this to your conf/ directory as auto.yml (if you're running #$0 from the
|
309
|
+
main directory, "conf/auto.yml"), as the standalone Auto will look for that
|
310
|
+
when it is executed.
|
311
|
+
|
312
|
+
In any event, you are free to write this anywhere you please. Just remember
|
313
|
+
that if it is not a default path, you must specify it when running Auto:
|
314
|
+
|
315
|
+
$ auto --config=path/to/config/file.yml
|
316
|
+
|
317
|
+
Caution: The specified file will be overwritten if it already exists.
|
318
|
+
EOM
|
319
|
+
puts final.green.bold
|
320
|
+
|
321
|
+
# Save our directories of interest into easily accessible variables.
|
322
|
+
configdir = File.join(Dir.home, '.config')
|
323
|
+
|
324
|
+
# Ensure that said directories exist regardless of any other conditions.
|
325
|
+
unless Dir.exists? configdir
|
326
|
+
puts "~ Creating missing directory #{configdir}".magenta
|
327
|
+
Dir.mkdir configdir
|
328
|
+
end
|
329
|
+
unless Dir.exists? AUTODIR
|
330
|
+
puts "~ Creating missing directory #{AUTODIR}".magenta
|
331
|
+
Dir.mkdir AUTODIR
|
332
|
+
end
|
333
|
+
|
334
|
+
# Ask for a path.
|
335
|
+
path = @hl.ask("#$S To where should the configuration be written? ", String) do |q|
|
336
|
+
|
337
|
+
# Default is ~/.config/autobot/auto.yml
|
338
|
+
q.default = File.join(autodir, 'auto.yml')
|
339
|
+
|
340
|
+
# A proc to validate the path
|
341
|
+
q.validate = proc do |path|
|
342
|
+
return false unless path =~ /\.yml$/ # it should end in .yml
|
343
|
+
return false unless Dir.exists? File.dirname(path) # the directory should exist
|
344
|
+
# We should be able to write to the file:
|
345
|
+
begin
|
346
|
+
File.open(path, 'w') { |io| io.puts "# Configuration file generated by auto-conf" }
|
347
|
+
rescue => e
|
348
|
+
return false
|
349
|
+
end
|
350
|
+
true
|
351
|
+
end
|
352
|
+
|
353
|
+
# A proc to be called in the event of an invalid path
|
354
|
+
q.responses[:not_valid] = proc do
|
355
|
+
|
356
|
+
# Choose an emergency file in ~/.config/autobot/ to which to save.
|
357
|
+
emerg_file = File.join(autodir, "auto.yml.#{Time.now.strftime('%s')}")
|
358
|
+
puts "Invalid path! Attempting to write to #{emerg_file}.....".red
|
359
|
+
File.open(path, 'w') do |io|
|
360
|
+
io.write data
|
361
|
+
end
|
362
|
+
|
363
|
+
end
|
364
|
+
|
365
|
+
end # ask()
|
366
|
+
|
367
|
+
File.open(path, 'w') { |io| io.write data } # Dump the data into the file.
|
368
|
+
|
369
|
+
# We're done.
|
370
|
+
puts "I have successfully written your configuration file to #{path}. Thank you for using Auto.".green.bold
|
371
|
+
|
372
|
+
end
|
373
|
+
|
374
|
+
end # class Configure
|
375
|
+
|
376
|
+
end # module Auto
|
377
|
+
|
378
|
+
# This will fix a certain undesirable output.
|
379
|
+
#
|
380
|
+
# HighLine::Question#append_default appends an ugly manifestation of the
|
381
|
+
# default answer.
|
382
|
+
#
|
383
|
+
# This destroys that provided by HighLine::Question and in lieu uses a prettier
|
384
|
+
# one.
|
385
|
+
class HighLine
|
386
|
+
class Question
|
387
|
+
def append_default
|
388
|
+
str = ''
|
389
|
+
if @default == 'y'
|
390
|
+
str = "<%= color('Y', :green) %>/<%= color('n', :red) %>"
|
391
|
+
elsif @default == 'n'
|
392
|
+
str = "<%= color('y', :green) %>/<%= color('N', :red) %>"
|
393
|
+
else
|
394
|
+
str = "<%= color('#@default', :bold) %>"
|
395
|
+
end
|
396
|
+
|
397
|
+
if @question =~ /([\t ]+)\Z/
|
398
|
+
@question << "[#{str}]#{$1}"
|
399
|
+
elsif @question == ""
|
400
|
+
@question << "[#{str}] "
|
401
|
+
elsif @question[-1, 1] == "\n"
|
402
|
+
@question[-2, 0] = " [#{str}]"
|
403
|
+
else
|
404
|
+
@question << " [#{str}]"
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
# vim: set ts=4 sts=2 sw=2 et:
|