Auto 4.0.0.alpha.1-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|