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.
- checksums.yaml +4 -4
- data/.yardopts +12 -0
- data/CHANGELOG.md +0 -0
- data/Gemfile +8 -0
- data/INSTALL.md +86 -0
- data/LICENSE +28 -0
- data/README.md +104 -0
- data/Rakefile +26 -0
- data/WINDOWS.md +64 -0
- data/bin/syndi +102 -0
- data/bin/syndi-conf +47 -0
- data/conf/example.yml +101 -0
- data/docs/Events.md +103 -0
- data/docs/Upgrade.md +16 -0
- data/ext/csyndi/events.c +50 -0
- data/ext/csyndi/extconf.rb +20 -0
- data/ext/csyndi/integer.c +53 -0
- data/ext/csyndi/libauto.c +37 -0
- data/ext/csyndi/logger.c +228 -0
- data/include/syndi/csyndi.h +38 -0
- data/include/syndi/events.h +19 -0
- data/include/syndi/integer.h +17 -0
- data/include/syndi/logger.h +57 -0
- data/include/syndi.h +22 -0
- data/lib/syndi/actress.rb +12 -0
- data/lib/syndi/api/events.rb +170 -0
- data/lib/syndi/api/object.rb +29 -0
- data/lib/syndi/api/plugin.rb +155 -0
- data/lib/syndi/api.rb +7 -0
- data/lib/syndi/bot.rb +270 -0
- data/lib/syndi/config.rb +113 -0
- data/lib/syndi/configure/cli.rb +23 -0
- data/lib/syndi/configure/generator.rb +410 -0
- data/lib/syndi/configure.rb +19 -0
- data/lib/syndi/dsl/base.rb +74 -0
- data/lib/syndi/dsl/irc.rb +13 -0
- data/lib/syndi/events.rb +114 -0
- data/lib/syndi/irc/common.rb +63 -0
- data/lib/syndi/irc/library.rb +89 -0
- data/lib/syndi/irc/object/channel.rb +21 -0
- data/lib/syndi/irc/object/entity.rb +90 -0
- data/lib/syndi/irc/object/message.rb +99 -0
- data/lib/syndi/irc/object/user.rb +139 -0
- data/lib/syndi/irc/protocol/numerics.rb +60 -0
- data/lib/syndi/irc/protocol.rb +164 -0
- data/lib/syndi/irc/sasl/diffie_hellman.rb +36 -0
- data/lib/syndi/irc/sasl/mech/dh_blowfish.rb +83 -0
- data/lib/syndi/irc/sasl/mech/plain.rb +39 -0
- data/lib/syndi/irc/sasl/mech.rb +15 -0
- data/lib/syndi/irc/server.rb +301 -0
- data/lib/syndi/irc/state/channel_manager.rb +6 -0
- data/lib/syndi/irc/state/support.rb +142 -0
- data/lib/syndi/irc/state/user_manager.rb +6 -0
- data/lib/syndi/irc/std/commands.rb +99 -0
- data/lib/syndi/irc/std/numerics.rb +216 -0
- data/lib/syndi/irc.rb +8 -0
- data/lib/syndi/jewel/specification.rb +121 -0
- data/lib/syndi/jewel/util.rb +27 -0
- data/lib/syndi/jewel.rb +5 -0
- data/lib/syndi/rubyext/string.rb +10 -0
- data/lib/syndi/verbosity.rb +10 -0
- data/lib/syndi/version.rb +38 -0
- data/lib/syndi.rb +129 -0
- data/spec/helper.rb +32 -0
- data/spec/syndi/events_spec.rb +43 -0
- data/tasks/compile.rake +15 -0
- data/tasks/install.rake +10 -0
- data/tasks/package.rake +13 -0
- data/tasks/spec.rake +12 -0
- metadata +101 -13
data/lib/syndi/config.rb
ADDED
@@ -0,0 +1,113 @@
|
|
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 'psych'
|
5
|
+
require 'syndi/verbosity'
|
6
|
+
require 'libsyndi'
|
7
|
+
|
8
|
+
# Namespace: Syndi
|
9
|
+
module Syndi
|
10
|
+
|
11
|
+
# A class which provides a functional, simple configuration interface. It uses
|
12
|
+
# YAML by means of Psych.
|
13
|
+
#
|
14
|
+
# @api Syndi
|
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
|
+
class Config
|
24
|
+
|
25
|
+
attr_reader :conf, :type
|
26
|
+
|
27
|
+
# Produce a new instance, and attempt to parse.
|
28
|
+
#
|
29
|
+
# @param [String] filepath Path to configuration file.
|
30
|
+
def initialize filepath
|
31
|
+
$m.verbose("Trying to initialize configuration from '#{filepath}'...", VSIMPLE) do
|
32
|
+
@path = filepath
|
33
|
+
parse
|
34
|
+
end # verbose
|
35
|
+
end
|
36
|
+
|
37
|
+
# Rehash the configuration.
|
38
|
+
#
|
39
|
+
# If an error occurs, it will revert the configuration to its prior state
|
40
|
+
# so that everything can continue to function.
|
41
|
+
def rehash!
|
42
|
+
|
43
|
+
$m.debug("Configuration file is rehashing.")
|
44
|
+
|
45
|
+
# Keep the old configuration in case of issues.
|
46
|
+
oldconf = @conf
|
47
|
+
@conf = {}
|
48
|
+
|
49
|
+
# Rehash
|
50
|
+
parse!
|
51
|
+
|
52
|
+
# Ensure it really succeeded.
|
53
|
+
if @conf.empty? or !@conf.instance_of? Hash
|
54
|
+
# Nope. Restore old configuration.
|
55
|
+
@conf = oldconf
|
56
|
+
$m.error 'Failed to rehash the configuration file (parser produced empty config)! Reverting to old configuration.'
|
57
|
+
return 0
|
58
|
+
end
|
59
|
+
|
60
|
+
$m.events.call :rehash
|
61
|
+
|
62
|
+
# This rescue is applicable to anything that happens in here, since if it is reached, there really was an error in general.
|
63
|
+
rescue => e
|
64
|
+
$m.error 'Failed to rehash configuration file! Reverting to old configuration.', false, e.backtrace
|
65
|
+
@conf = oldconf
|
66
|
+
return 0
|
67
|
+
end
|
68
|
+
|
69
|
+
# Return value of @conf[key].
|
70
|
+
#
|
71
|
+
# @return [Object] Value of @conf[key].
|
72
|
+
# @see @conf
|
73
|
+
def [] key
|
74
|
+
@conf[key]
|
75
|
+
end
|
76
|
+
|
77
|
+
#######
|
78
|
+
private
|
79
|
+
#######
|
80
|
+
|
81
|
+
# Parse the configuration file, and output the data to {#x}.
|
82
|
+
#
|
83
|
+
# @raise [ConfigError] If the file does not exist.
|
84
|
+
# @raise [ConfigError] If the file cannot be processed.
|
85
|
+
def parse
|
86
|
+
|
87
|
+
# Ensure foremost that the configuration file exists.
|
88
|
+
unless File.exists? @path
|
89
|
+
raise ConfigError, "Configuration file '#@path' does not exist!"
|
90
|
+
end
|
91
|
+
|
92
|
+
# Get the data from the file.
|
93
|
+
f = File.open(@path)
|
94
|
+
data = f.read
|
95
|
+
f.close
|
96
|
+
|
97
|
+
conf = {}
|
98
|
+
# Process the YAML.
|
99
|
+
begin
|
100
|
+
conf = Psych.load data
|
101
|
+
rescue => e
|
102
|
+
raise ConfigError, "Failed to process the YAML in '#@path'", e.backtrace
|
103
|
+
end
|
104
|
+
|
105
|
+
@conf = conf
|
106
|
+
|
107
|
+
end # def parse
|
108
|
+
|
109
|
+
end # class Config
|
110
|
+
|
111
|
+
end # module Syndi
|
112
|
+
|
113
|
+
# vim: set ts=4 sts=2 sw=2 et:
|
@@ -0,0 +1,23 @@
|
|
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 'thor'
|
5
|
+
require 'psych'
|
6
|
+
|
7
|
+
module Syndi
|
8
|
+
module Configure
|
9
|
+
|
10
|
+
# A command-line interface for making modifications to an existing Syndi
|
11
|
+
# configuration file (which is in YAML).
|
12
|
+
class CLI < Thor
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
# 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 (see LICENSE).
|
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 syndi. The ruby source code is located here http://ruby-lang.org/en/downloads
|
17
|
+
EOM
|
18
|
+
end
|
19
|
+
|
20
|
+
# namespace Syndi
|
21
|
+
module Syndi
|
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
|
+
syndiload :Shell, 'syndi/configure/shell'
|
37
|
+
# Load the shell.
|
38
|
+
def shell
|
39
|
+
Syndi::Configure::Shell.new(@hl)
|
40
|
+
end
|
41
|
+
|
42
|
+
VERSION = '1.02'.freeze
|
43
|
+
SYNDIDIR = File.join(Dir.home, '.config', 'syndibot')
|
44
|
+
|
45
|
+
attr_accessor :hl, :conf
|
46
|
+
|
47
|
+
# Produce a new instance of Syndi::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 Syndi. :) I suggest
|
64
|
+
that, if you're not already reading it, you consult the installation guide:
|
65
|
+
https://github.com/Syndi/Syndi/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/syndibot-talk, or to join the official IRC
|
71
|
+
channel at #syndi 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 = 'syndi' }
|
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 = 'syndi' }
|
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 = 'syndi' }
|
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 = 'Syndi (http://syndi.syndiproj.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 syndijoin.
|
194
|
+
conf_irc_syndijoin name
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
# Configure syndijoin.
|
199
|
+
#
|
200
|
+
# @param [String] name Name of IRC server.
|
201
|
+
def conf_irc_syndijoin(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]['syndijoin'] = []
|
204
|
+
|
205
|
+
while another
|
206
|
+
@conf['irc'][name]['syndijoin'] << 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 = '#syndi' }
|
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
|
+
>> Syndi 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/Syndi/Syndi/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('#{SYNDIDIR}', :blue, :bold) %>) ") do |q|
|
252
|
+
q.default = File.join SYNDIDIR, 'syndi.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 = 'syndi' }
|
265
|
+
username = @hl.ask("#$S What username should I use to connect to <%= color('#{type}', :blue, :bold) %> server? ") { |q| q.default = 'syndi' }
|
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 syndi-conf
|
291
|
+
# version #{Syndi::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/syndibot/syndi.yml,
|
304
|
+
which is perfect for you if you're using the 'syndibot' 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 syndi.yml (if you're running #$0 from the
|
309
|
+
main directory, "conf/syndi.yml"), as the standalone Syndi 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 Syndi:
|
314
|
+
|
315
|
+
$ syndi --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? SYNDIDIR
|
330
|
+
puts "~ Creating missing directory #{SYNDIDIR}".magenta
|
331
|
+
Dir.mkdir SYNDIDIR
|
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/syndibot/syndi.yml
|
338
|
+
q.default = File.join(syndidir, 'syndi.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 syndi-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/syndibot/ to which to save.
|
357
|
+
emerg_file = File.join(syndidir, "syndi.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 Syndi.".green.bold
|
371
|
+
|
372
|
+
end
|
373
|
+
|
374
|
+
end # class Configure
|
375
|
+
|
376
|
+
end # module Syndi
|
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:
|
@@ -0,0 +1,19 @@
|
|
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
|
+
module Syndi
|
5
|
+
|
6
|
+
# A configuration management suite.
|
7
|
+
module Configure
|
8
|
+
|
9
|
+
# syndi-conf version
|
10
|
+
VERSION = '2.00'
|
11
|
+
|
12
|
+
syndiload :CLI, 'syndi/configure/cli'
|
13
|
+
syndiload :Generator, 'syndi/configure/generator'
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
# vim: set ts=4 sts=2 sw=2 et:
|
@@ -0,0 +1,74 @@
|
|
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: DSL
|
8
|
+
module DSL
|
9
|
+
|
10
|
+
# A domain-specific language (DSL) wrapper mixin for simple usage of the events
|
11
|
+
# system, {Syndi::API::Events}, and the timers system, {Syndi::API::Timers}.
|
12
|
+
#
|
13
|
+
# @api DSL
|
14
|
+
# @author noxgirl
|
15
|
+
# @since 4.0.0
|
16
|
+
#
|
17
|
+
# @see Syndi::API::Events
|
18
|
+
# @see Syndi::API::Timers
|
19
|
+
module Base
|
20
|
+
|
21
|
+
# @see Syndi::API::Timers#spawn
|
22
|
+
def clock_do(*args); $m.clock.spawn(*args); end
|
23
|
+
# @see Syndi::API::Timers#del
|
24
|
+
def clock_stop(*args); $m.clock.del(*args); end
|
25
|
+
|
26
|
+
# Hook onto an event.
|
27
|
+
#
|
28
|
+
# @param [Symbol] system The events system to access.
|
29
|
+
# @param [Symbol] event The event onto which to hook.
|
30
|
+
#
|
31
|
+
# @see Syndi::API::Events#on
|
32
|
+
def on(sys, event, &prc)
|
33
|
+
if sys == :syndi # central system
|
34
|
+
$m.events.on(event, prc)
|
35
|
+
else
|
36
|
+
$m.send(sys).events.on(event, prc) if $m.respond_to? sys
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Emit an event.
|
41
|
+
#
|
42
|
+
# @param [Symbol] system The events system to access.
|
43
|
+
# @param [Symbol] event The event onto which to hook.
|
44
|
+
#
|
45
|
+
# @see Syndi::API::Events#call
|
46
|
+
def emit(sys, event, *args)
|
47
|
+
if sys == :syndi # central system
|
48
|
+
$m.events.call(event, *args)
|
49
|
+
else
|
50
|
+
$m.send(sys).events.call(event, *args) if $m.respond_to? sys
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Delete a hook.
|
55
|
+
#
|
56
|
+
# @param [Symbol] system The events system to access.
|
57
|
+
# @param [Array(Symbol, Integer, String)] hook The identification data of the hook.
|
58
|
+
#
|
59
|
+
# @see Syndi::API::Events#del
|
60
|
+
def undo_on(sys, hook)
|
61
|
+
if sys == :syndi # central system
|
62
|
+
$m.events.del(hook)
|
63
|
+
else
|
64
|
+
$m.send(sys).events.del(hook) if $m.respond_to? sys
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end # module Base
|
69
|
+
|
70
|
+
end # module DSL
|
71
|
+
|
72
|
+
end # module Syndi
|
73
|
+
|
74
|
+
# vim: set ts=4 sts=2 sw=2 et:
|