twke 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +7 -1
- data/Gemfile.lock +14 -6
- data/README.md +56 -5
- data/VERSION +1 -1
- data/bin/twke +1 -4
- data/dot.rvmrc +1 -0
- data/lib/twke.rb +23 -2
- data/lib/twke/conf.rb +120 -0
- data/lib/twke/plugin.rb +19 -8
- data/lib/twke/routes.rb +73 -14
- data/plugins/admin.rb +62 -4
- data/plugins/config.rb +70 -0
- data/plugins/jenkins.rb +11 -0
- data/plugins/lolcats.rb +10 -0
- data/plugins/twiki.rb +5 -5
- data/test/helper.rb +1 -0
- data/test/test_conf.rb +51 -0
- data/twke.gemspec +14 -6
- metadata +116 -63
- data/test/test_twke.rb +0 -7
data/Gemfile
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
# Add dependencies required to use your gem here.
|
3
3
|
# Example:
|
4
|
-
gem "scamp", "~> 0.1.1"
|
4
|
+
#gem "scamp", "~> 0.1.1"
|
5
|
+
|
6
|
+
#gem "scamp", :path => ENV['HOME'] + "/git/clones/Scamp"
|
7
|
+
|
8
|
+
gem "scamp", :git => 'https://github.com/mheffner/Scamp.git', :branch => 'feature/pass_action_context'
|
9
|
+
|
10
|
+
gem "can-has-lolcat", "~> 1.1.0"
|
5
11
|
|
6
12
|
# Add dependencies to develop your gem here.
|
7
13
|
# Include everything needed to run rake, tests, features, etc.
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,18 @@
|
|
1
|
+
GIT
|
2
|
+
remote: https://github.com/mheffner/Scamp.git
|
3
|
+
revision: 362b8385db9b16ce09607c824e5b0d9f9ade0bcc
|
4
|
+
branch: feature/pass_action_context
|
5
|
+
specs:
|
6
|
+
scamp (0.1.2)
|
7
|
+
em-http-request (~> 1.0.0.beta.4)
|
8
|
+
eventmachine (~> 1.0.0.beta.4)
|
9
|
+
yajl-ruby (~> 0.8.3)
|
10
|
+
|
1
11
|
GEM
|
2
12
|
remote: http://rubygems.org/
|
3
13
|
specs:
|
4
14
|
addressable (2.2.6)
|
15
|
+
can-has-lolcat (1.1.0)
|
5
16
|
em-http-request (1.0.0)
|
6
17
|
addressable (>= 2.2.3)
|
7
18
|
em-socksify
|
@@ -11,17 +22,13 @@ GEM
|
|
11
22
|
eventmachine
|
12
23
|
eventmachine (1.0.0.beta.4)
|
13
24
|
git (1.2.5)
|
14
|
-
http_parser.rb (0.5.
|
25
|
+
http_parser.rb (0.5.3)
|
15
26
|
jeweler (1.6.4)
|
16
27
|
bundler (~> 1.0)
|
17
28
|
git (>= 1.2.5)
|
18
29
|
rake
|
19
30
|
rake (0.9.2)
|
20
31
|
rcov (0.9.10)
|
21
|
-
scamp (0.1.1)
|
22
|
-
em-http-request (~> 1.0.0.beta.4)
|
23
|
-
eventmachine (~> 1.0.0.beta.4)
|
24
|
-
yajl-ruby (~> 0.8.3)
|
25
32
|
shoulda (2.11.3)
|
26
33
|
yajl-ruby (0.8.3)
|
27
34
|
|
@@ -30,7 +37,8 @@ PLATFORMS
|
|
30
37
|
|
31
38
|
DEPENDENCIES
|
32
39
|
bundler (~> 1.0.0)
|
40
|
+
can-has-lolcat (~> 1.1.0)
|
33
41
|
jeweler (~> 1.6.4)
|
34
42
|
rcov
|
35
|
-
scamp
|
43
|
+
scamp!
|
36
44
|
shoulda
|
data/README.md
CHANGED
@@ -18,13 +18,13 @@ following template:
|
|
18
18
|
|
19
19
|
```ruby
|
20
20
|
class Plugin::PluginName < Plugin
|
21
|
-
def add_routes(rp)
|
22
|
-
rp.route 'foo' do
|
23
|
-
say 'bar'
|
21
|
+
def add_routes(rp, opts)
|
22
|
+
rp.route 'foo' do |act|
|
23
|
+
act.say 'bar'
|
24
24
|
end
|
25
25
|
|
26
|
-
rp.route
|
27
|
-
say "Hello
|
26
|
+
rp.route /hello (?<person>.+)$/ do |act|
|
27
|
+
act.say "Hello #{act.person}!"
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
@@ -33,6 +33,57 @@ following template:
|
|
33
33
|
1. Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
34
34
|
1. Submit a pull request from your fork to josephruscio/twke
|
35
35
|
|
36
|
+
## More examples
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
def add_routes(rp, opts)
|
40
|
+
#
|
41
|
+
# Create command scopes.
|
42
|
+
#
|
43
|
+
# Example, listen for the following:
|
44
|
+
# <bot> admin version
|
45
|
+
# <bot> admin quit
|
46
|
+
#
|
47
|
+
|
48
|
+
rp.admin do
|
49
|
+
rp.route 'version' do |act|
|
50
|
+
act.say "Version is 0.1.2"
|
51
|
+
end
|
52
|
+
|
53
|
+
rp.route 'quit' do |act|
|
54
|
+
act.say "Leaving"
|
55
|
+
exit 0
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# Don't require the <bot> string prefix.
|
61
|
+
#
|
62
|
+
# Example, listen for the following:
|
63
|
+
#
|
64
|
+
# admin version
|
65
|
+
#
|
66
|
+
|
67
|
+
rp.admin(:noprefix => true) do
|
68
|
+
rp.route 'version' do |act|
|
69
|
+
act.say "Version cmd without <bot> prefix!"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# Top-level route without <bot> prefix
|
75
|
+
#
|
76
|
+
# Example, listen for the following:
|
77
|
+
#
|
78
|
+
# bark
|
79
|
+
#
|
80
|
+
|
81
|
+
rp.route 'bark', :noprefix => true do |act|
|
82
|
+
act.play 'barking'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
36
87
|
## Colophon
|
37
88
|
|
38
89
|
twke is named after the [ambuquad designated
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/bin/twke
CHANGED
data/dot.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use ruby-1.9.2
|
data/lib/twke.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
module Twke
|
2
2
|
require 'scamp'
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
$:.unshift File.join(File.dirname(__FILE__), 'twke')
|
5
|
+
|
6
|
+
require 'conf'
|
7
|
+
require 'routes'
|
8
|
+
require 'plugin'
|
6
9
|
|
7
10
|
def self.version
|
8
11
|
File.read(File.join(File.dirname(__FILE__), '../VERSION')).chomp
|
@@ -12,6 +15,24 @@ module Twke
|
|
12
15
|
puts "Registering plugin #{plgn.plugin_name}"
|
13
16
|
end
|
14
17
|
|
18
|
+
def self.start(scamp)
|
19
|
+
Twke::Conf.load
|
20
|
+
Twke::Routes.load(scamp)
|
21
|
+
|
22
|
+
# XXX: Scamp needs an on_connect callback, fake one with a timer
|
23
|
+
# here.
|
24
|
+
# EM::Timer.new(5) do
|
25
|
+
# Twke::Routes.on_connect
|
26
|
+
# end
|
27
|
+
|
28
|
+
# Any rooms configured to join via the CLI will be done in the
|
29
|
+
# on_connect CB.
|
30
|
+
#
|
31
|
+
scamp.connect!([]) do
|
32
|
+
Twke::Routes.on_connect
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
15
36
|
def self.shutdown
|
16
37
|
exit 0
|
17
38
|
end
|
data/lib/twke/conf.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
#
|
4
|
+
# Simple configuration system.
|
5
|
+
#
|
6
|
+
# Variable names are dot-separated, similar to how sysctl(8) names
|
7
|
+
# work.
|
8
|
+
#
|
9
|
+
# For example, a 'heroku' module could prefix all variables with
|
10
|
+
# "heroku.":
|
11
|
+
#
|
12
|
+
# heroku.sites.metrics-prod.giturl
|
13
|
+
# heroku.sites.metrics-prod.token
|
14
|
+
#
|
15
|
+
# The conf system can also lookup all the sub-variables rooted at a
|
16
|
+
# single prefix. So for example, assume the following variables are
|
17
|
+
# also set:
|
18
|
+
#
|
19
|
+
# heroku.sites.metrics-stg.giturl
|
20
|
+
# heroku.sites.metrics-stg.token
|
21
|
+
#
|
22
|
+
# A list command on 'heroku.sites' would return:
|
23
|
+
# ['metrics-prod', 'metrics-stg']
|
24
|
+
#
|
25
|
+
######
|
26
|
+
|
27
|
+
module Twke
|
28
|
+
module Conf
|
29
|
+
class << self
|
30
|
+
def conf
|
31
|
+
@conf ||= {}
|
32
|
+
end
|
33
|
+
|
34
|
+
# Everytime a value is modified the config DB is written
|
35
|
+
def set(varname, value)
|
36
|
+
if varname =~ /^\./ || varname =~ /\.$/ || varname.length == 0
|
37
|
+
raise "Invalid variable name"
|
38
|
+
end
|
39
|
+
|
40
|
+
conf[varname.to_s] = value
|
41
|
+
|
42
|
+
save
|
43
|
+
end
|
44
|
+
|
45
|
+
def get(varname)
|
46
|
+
conf[varname.to_s]
|
47
|
+
end
|
48
|
+
|
49
|
+
def exists?(varname)
|
50
|
+
conf.has_key?(varname)
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# This will return a list of the unique commands that begin with
|
55
|
+
# the varpfx prefix assumed to be a sub-command prefix.
|
56
|
+
#
|
57
|
+
# For example, assume the following variables are set:
|
58
|
+
#
|
59
|
+
# net.tcp.foobar => 1
|
60
|
+
# net.tcp.barbar => 2
|
61
|
+
#
|
62
|
+
# So:
|
63
|
+
# list('net.tcp') would return: ["barbar", "foobar"]
|
64
|
+
# list('net') would return: ["tcp"]
|
65
|
+
#
|
66
|
+
# list('net.tc') would return: []
|
67
|
+
# Because there are no sub-commands with 'net.tc.' as
|
68
|
+
# their prefix
|
69
|
+
#
|
70
|
+
def list(varpfx)
|
71
|
+
# Strip leading/trailing periods
|
72
|
+
varpfx = varpfx[1, varpfx.length] if varpfx =~ /^\./
|
73
|
+
varpfx = varpfx[0, varpfx.length - 1] if varpfx =~ /\.$/
|
74
|
+
|
75
|
+
# XXX: Really need a tree structure to do this efficiently
|
76
|
+
conf.keys.inject([]) do |ar, k|
|
77
|
+
if k =~ /^#{varpfx}\./
|
78
|
+
ar << k.gsub(/^#{varpfx}\./, '').split(".")[0]
|
79
|
+
end
|
80
|
+
ar
|
81
|
+
end.sort.uniq
|
82
|
+
end
|
83
|
+
|
84
|
+
def load
|
85
|
+
begin
|
86
|
+
yml = YAML.load_file(config_file)
|
87
|
+
@conf = yml
|
88
|
+
rescue Errno::ENOENT => err
|
89
|
+
@conf = {}
|
90
|
+
rescue => err
|
91
|
+
raise "Unknown error reading config file: #{err.message}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
#
|
96
|
+
# Files are saved atomically.
|
97
|
+
#
|
98
|
+
def save
|
99
|
+
unless File.exist?(config_dir)
|
100
|
+
FileUtils.mkdir_p(config_dir, :mode => 0700)
|
101
|
+
end
|
102
|
+
|
103
|
+
tmpfile = File.join(config_dir, "tmpconfig_#{rand 999999}")
|
104
|
+
File.open(tmpfile, "w") do |f|
|
105
|
+
YAML.dump(conf, f )
|
106
|
+
end
|
107
|
+
|
108
|
+
FileUtils.mv(tmpfile, config_file)
|
109
|
+
end
|
110
|
+
|
111
|
+
def config_dir
|
112
|
+
File.join(ENV['HOME'], '.twke')
|
113
|
+
end
|
114
|
+
|
115
|
+
def config_file
|
116
|
+
File.join(config_dir, 'config.yml')
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
data/lib/twke/plugin.rb
CHANGED
@@ -18,15 +18,15 @@ class Plugin
|
|
18
18
|
@plugins ||= []
|
19
19
|
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
def routes(rp)
|
25
|
-
plgin = new()
|
21
|
+
def loaded_plugins
|
22
|
+
@loaded_plugins ||= []
|
23
|
+
end
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
# Invoked to load this plugin. Will initialize and add to the
|
26
|
+
# loaded plugins list.
|
27
|
+
# TODO: Add initialization parameters here??
|
28
|
+
def load_plugin
|
29
|
+
Plugin.loaded_plugins << new()
|
30
30
|
end
|
31
31
|
|
32
32
|
# Registers the current plugin with the system.
|
@@ -38,4 +38,15 @@ class Plugin
|
|
38
38
|
super
|
39
39
|
end
|
40
40
|
end
|
41
|
+
|
42
|
+
# Invoked to send an event to this plugin. Checks if plugins
|
43
|
+
# responds to the event. All events take a routing prefix and
|
44
|
+
# the CLI options.
|
45
|
+
#
|
46
|
+
def event(name, rp, opts)
|
47
|
+
if self.respond_to?(name.to_sym)
|
48
|
+
self.send(name.to_sym, rp, opts)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
41
52
|
end
|
data/lib/twke/routes.rb
CHANGED
@@ -6,16 +6,49 @@ module Twke
|
|
6
6
|
@levels.push(str) if str
|
7
7
|
end
|
8
8
|
|
9
|
-
def route(
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
def route(trigger, *opts, &blk)
|
10
|
+
if trigger.class == Regexp
|
11
|
+
if prefix.length > 0 && !no_prefix?(*opts)
|
12
|
+
trigger = Regexp.new("#{prefix} #{trigger.to_s}")
|
13
|
+
end
|
14
|
+
|
15
|
+
Routes.add(trigger, *opts, &blk)
|
16
|
+
else
|
17
|
+
# Send trigger as a prefix
|
18
|
+
self.send(trigger, *opts) do
|
19
|
+
Routes.add(prefix, *opts, &blk)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Run a raw command and the connection scope level
|
25
|
+
def cmd(&blk)
|
26
|
+
Routes.cmd(&blk)
|
27
|
+
end
|
28
|
+
|
29
|
+
def method_missing(name, *opts, &blk)
|
30
|
+
if no_prefix?(*opts)
|
31
|
+
# If they requested no prefix, save the current prefix
|
32
|
+
# and execute the block starting with the current prefix
|
33
|
+
save_levels = @levels.dup
|
34
|
+
@levels = [name]
|
35
|
+
yield
|
36
|
+
@levels = save_levels
|
37
|
+
else
|
38
|
+
@levels.push(name)
|
39
|
+
yield
|
40
|
+
@levels.pop
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def no_prefix?(options = {})
|
47
|
+
options[:noprefix]
|
13
48
|
end
|
14
49
|
|
15
|
-
def
|
16
|
-
@levels.
|
17
|
-
yield
|
18
|
-
@levels.pop
|
50
|
+
def prefix
|
51
|
+
@levels.join(" ")
|
19
52
|
end
|
20
53
|
end
|
21
54
|
|
@@ -25,18 +58,44 @@ module Twke
|
|
25
58
|
def load(scamp)
|
26
59
|
@@conn = scamp
|
27
60
|
|
28
|
-
# TODO: Only load the configured plugins
|
61
|
+
# TODO: Only load the configured plugins.
|
62
|
+
# XXX: doesn't feel right to do this in routes...
|
29
63
|
Plugin.plugins.each do |plgin|
|
30
|
-
|
31
|
-
|
64
|
+
plgin.load_plugin
|
65
|
+
end
|
66
|
+
|
67
|
+
# Now ask all loaded plugins to add routes
|
68
|
+
Plugin.loaded_plugins.each do |plgin|
|
69
|
+
plgin.event(:add_routes, RoutePrefix.new($options[:name]), $options)
|
32
70
|
end
|
33
71
|
end
|
34
72
|
|
35
|
-
|
36
|
-
|
37
|
-
|
73
|
+
# Invoked (in theory) after we're connected to campfire
|
74
|
+
def on_connect
|
75
|
+
Plugin.loaded_plugins.each do |plgin|
|
76
|
+
plgin.event(:on_connect, RoutePrefix.new($options[:name]), $options)
|
38
77
|
end
|
39
78
|
end
|
79
|
+
|
80
|
+
def add(trigger, *opts, &blk)
|
81
|
+
cmd do
|
82
|
+
match(trigger, *opts) do
|
83
|
+
# This yields the action (ie, room) context to the
|
84
|
+
# callback. All actions that could be done in the Scamp
|
85
|
+
# 'match' context can be performed on the yielded
|
86
|
+
# object. This lets you pass the context to an EM context
|
87
|
+
# later.
|
88
|
+
#
|
89
|
+
|
90
|
+
yield(self)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Run a raw command
|
96
|
+
def cmd(&blk)
|
97
|
+
@@conn.behaviour(&blk)
|
98
|
+
end
|
40
99
|
end
|
41
100
|
end
|
42
101
|
end
|
data/plugins/admin.rb
CHANGED
@@ -1,13 +1,71 @@
|
|
1
|
+
|
1
2
|
class Plugin::Admin < Plugin
|
2
|
-
#
|
3
|
-
|
3
|
+
#
|
4
|
+
# Plugin methods
|
5
|
+
#
|
6
|
+
|
7
|
+
# Add routes
|
8
|
+
def add_routes(rp, opts)
|
4
9
|
rp.admin do
|
5
|
-
rp.route 'respawn' do
|
6
|
-
say "Initiating respawn"
|
10
|
+
rp.route 'respawn' do |act|
|
11
|
+
act.say "Initiating respawn"
|
7
12
|
EM::Timer.new(2) do
|
8
13
|
Twke::shutdown
|
9
14
|
end
|
10
15
|
end
|
16
|
+
|
17
|
+
rp.route /join (?<room>.+)$/ do |act|
|
18
|
+
# Convert to an integer if possible
|
19
|
+
id = get_room_id(rp, act.room)
|
20
|
+
|
21
|
+
if !id
|
22
|
+
act.say "No room by the name/ID: #{act.room}"
|
23
|
+
else
|
24
|
+
join_room(rp, id)
|
25
|
+
|
26
|
+
# Save this room so we rejoin on startup
|
27
|
+
rooms = (Twke::Conf.get('admin.join_rooms') || []) + [act.room]
|
28
|
+
Twke::Conf.set('admin.join_rooms', rooms.sort.uniq)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# On connection
|
35
|
+
def on_connect(rp, opts)
|
36
|
+
join_rooms(rp, opts)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
#
|
42
|
+
# Helper routines
|
43
|
+
#
|
44
|
+
def get_room_id(rp, room)
|
45
|
+
begin
|
46
|
+
id = Integer(room)
|
47
|
+
rescue
|
48
|
+
id = rp.cmd { room_id_from_room_name(room) }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def join_room(rp, id)
|
53
|
+
rp.cmd { join_and_stream(id) }
|
54
|
+
end
|
55
|
+
|
56
|
+
# Automatically join saved rooms on startup
|
57
|
+
def join_rooms(rp, opts)
|
58
|
+
rooms = Twke::Conf.get('admin.join_rooms') || []
|
59
|
+
|
60
|
+
rooms << opts[:rooms] if opts[:rooms]
|
61
|
+
|
62
|
+
rooms.sort.uniq.each do |room|
|
63
|
+
id = get_room_id(rp, room)
|
64
|
+
if id
|
65
|
+
join_room(rp, id)
|
66
|
+
else
|
67
|
+
puts "ERROR: Unable to find autojoin room #{room}(id: #{id})"
|
68
|
+
end
|
11
69
|
end
|
12
70
|
end
|
13
71
|
end
|
data/plugins/config.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
#
|
2
|
+
# Provides access to the configuration system via chat commands.
|
3
|
+
#
|
4
|
+
class Plugin::Config < Plugin
|
5
|
+
# Invoked to define routes.
|
6
|
+
def add_routes(rp, opts)
|
7
|
+
rp.route /set (?<var>[^ ]+)[ ]+(?<value>.*[^ ])[ ]*$/ do |act|
|
8
|
+
varstr = act.var
|
9
|
+
valstr = act.value
|
10
|
+
|
11
|
+
# "value" or 'value' implies string
|
12
|
+
if valstr =~ /^".*"$/ || valstr =~ /^'.*'$/
|
13
|
+
valstr = valstr[1, valstr.length - 2]
|
14
|
+
set_var(act, varstr, valstr)
|
15
|
+
next
|
16
|
+
end
|
17
|
+
|
18
|
+
# Try as an integer
|
19
|
+
as_int = Integer(valstr) rescue nil
|
20
|
+
unless as_int.nil?
|
21
|
+
set_var(act, varstr, as_int)
|
22
|
+
next
|
23
|
+
end
|
24
|
+
|
25
|
+
# Try as a float
|
26
|
+
as_float = Float(valstr) rescue nil
|
27
|
+
unless as_float.nil?
|
28
|
+
set_var(act, varstr, as_float)
|
29
|
+
next
|
30
|
+
end
|
31
|
+
|
32
|
+
# Try to eval it
|
33
|
+
begin
|
34
|
+
as_eval = eval(valstr)
|
35
|
+
set_var(act, varstr, as_eval)
|
36
|
+
rescue
|
37
|
+
# Fall back to just a string
|
38
|
+
set_var(act, varstr, valstr)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
rp.route /get (?<var>[^ ]+)[ ]*$/ do |act|
|
43
|
+
if Twke::Conf::exists?(act.var)
|
44
|
+
act.say "#{act.var} = #{Twke::Conf::get(act.var).inspect}"
|
45
|
+
else
|
46
|
+
act.say "#{act.var} is not set!"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
rp.route /list (?<var>[^ ]+)[ ]*$/ do |act|
|
51
|
+
l = Twke::Conf::list(act.var)
|
52
|
+
if l.length == 0
|
53
|
+
act.say "#{act.var} is empty"
|
54
|
+
else
|
55
|
+
act.say "#{act.var} = #{l.inspect}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
# XXX: really should be private but scoping problems require this
|
63
|
+
def set_var(act, var, value)
|
64
|
+
begin
|
65
|
+
Twke::Conf::set(var, value)
|
66
|
+
rescue => err
|
67
|
+
act.say "Failure setting variable #{var}=#{value}: #{err.inspect}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/plugins/jenkins.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
class Plugin::Jenkins < Plugin
|
2
|
+
def add_routes(rp, opts)
|
3
|
+
rp.route /^\w+ #\d+ ".*?": (FAILURE|UNSTABLE) \(.*?\)$/, :noprefix => true do |act|
|
4
|
+
act.play "drama"
|
5
|
+
end
|
6
|
+
|
7
|
+
rp.route /^\w+ #\d+ ".*?": success$/, :noprefix => true do |act|
|
8
|
+
act.play "yeah"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/plugins/lolcats.rb
ADDED
data/plugins/twiki.rb
CHANGED
@@ -2,13 +2,13 @@
|
|
2
2
|
#
|
3
3
|
class Plugin::Twiki < Plugin
|
4
4
|
# Invoked to define routes.
|
5
|
-
def add_routes(rp)
|
6
|
-
rp.route 'bidi' do
|
7
|
-
say 'bidi-bidi-bidi!'
|
5
|
+
def add_routes(rp, opts)
|
6
|
+
rp.route 'bidi' do |act|
|
7
|
+
act.say 'bidi-bidi-bidi!'
|
8
8
|
end
|
9
9
|
|
10
|
-
rp.route 'version' do
|
11
|
-
say "Twke version: #{Twke.version}"
|
10
|
+
rp.route 'version' do |act|
|
11
|
+
act.say "Twke version: #{Twke.version}"
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
data/test/helper.rb
CHANGED
data/test/test_conf.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestConf < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
FileUtils.rm_rf(Conf::config_file)
|
6
|
+
end
|
7
|
+
|
8
|
+
def teardown
|
9
|
+
FileUtils.rm_rf(Conf::config_file)
|
10
|
+
end
|
11
|
+
|
12
|
+
def validate_settings
|
13
|
+
assert_equal(1, Conf::get('net.tcp.foobar'))
|
14
|
+
assert_equal('blah', Conf::get('net.tcp.barbar'))
|
15
|
+
assert(Conf::exists?('net.tcp.foobar'))
|
16
|
+
assert(Conf::exists?('net.tcp.barbar'))
|
17
|
+
assert(!Conf::exists?('net.tcp'))
|
18
|
+
|
19
|
+
assert_equal(['barbar', 'foobar'].sort, Conf::list('net.tcp'))
|
20
|
+
assert_equal(['tcp'].sort, Conf::list('net'))
|
21
|
+
|
22
|
+
assert_equal([], Conf::list(''))
|
23
|
+
assert_equal([], Conf::list('net.tc'))
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_config
|
27
|
+
Conf::set('net.tcp.foobar', 1)
|
28
|
+
Conf::set('net.tcp.barbar', "blah")
|
29
|
+
|
30
|
+
validate_settings
|
31
|
+
|
32
|
+
['.sys.blah', 'sys.blah.', ''].each do |bad|
|
33
|
+
begin
|
34
|
+
Conf::set(bad, rand(5))
|
35
|
+
rescue
|
36
|
+
# Should throw exception
|
37
|
+
else
|
38
|
+
assert(false, "Did not throw exception setting: #{bad}")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
assert(File.exist?(Conf::config_file), "Conf file doesn't exist")
|
43
|
+
|
44
|
+
# Now reload
|
45
|
+
#
|
46
|
+
Conf::load
|
47
|
+
|
48
|
+
# retest after reload
|
49
|
+
validate_settings
|
50
|
+
end
|
51
|
+
end
|
data/twke.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{twke}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Joseph Ruscio", "Mike Heffner"]
|
12
|
-
s.date = %q{2011-
|
12
|
+
s.date = %q{2011-10-07}
|
13
13
|
s.default_executable = %q{twke}
|
14
14
|
s.description = %q{The ambuquad that has your back.}
|
15
15
|
s.email = %q{joe@ruscio.org}
|
@@ -27,13 +27,18 @@ Gem::Specification.new do |s|
|
|
27
27
|
"Rakefile",
|
28
28
|
"VERSION",
|
29
29
|
"bin/twke",
|
30
|
+
"dot.rvmrc",
|
30
31
|
"lib/twke.rb",
|
32
|
+
"lib/twke/conf.rb",
|
31
33
|
"lib/twke/plugin.rb",
|
32
34
|
"lib/twke/routes.rb",
|
33
35
|
"plugins/admin.rb",
|
36
|
+
"plugins/config.rb",
|
37
|
+
"plugins/jenkins.rb",
|
38
|
+
"plugins/lolcats.rb",
|
34
39
|
"plugins/twiki.rb",
|
35
40
|
"test/helper.rb",
|
36
|
-
"test/
|
41
|
+
"test/test_conf.rb",
|
37
42
|
"twke.gemspec"
|
38
43
|
]
|
39
44
|
s.homepage = %q{http://github.com/josephruscio/twke}
|
@@ -46,20 +51,23 @@ Gem::Specification.new do |s|
|
|
46
51
|
s.specification_version = 3
|
47
52
|
|
48
53
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
49
|
-
s.add_runtime_dependency(%q<scamp>, ["
|
54
|
+
s.add_runtime_dependency(%q<scamp>, [">= 0"])
|
55
|
+
s.add_runtime_dependency(%q<can-has-lolcat>, ["~> 1.1.0"])
|
50
56
|
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
51
57
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
52
58
|
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
53
59
|
s.add_development_dependency(%q<rcov>, [">= 0"])
|
54
60
|
else
|
55
|
-
s.add_dependency(%q<scamp>, ["
|
61
|
+
s.add_dependency(%q<scamp>, [">= 0"])
|
62
|
+
s.add_dependency(%q<can-has-lolcat>, ["~> 1.1.0"])
|
56
63
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
57
64
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
58
65
|
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
59
66
|
s.add_dependency(%q<rcov>, [">= 0"])
|
60
67
|
end
|
61
68
|
else
|
62
|
-
s.add_dependency(%q<scamp>, ["
|
69
|
+
s.add_dependency(%q<scamp>, [">= 0"])
|
70
|
+
s.add_dependency(%q<can-has-lolcat>, ["~> 1.1.0"])
|
63
71
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
64
72
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
65
73
|
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
metadata
CHANGED
@@ -1,82 +1,124 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: twke
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Joseph Ruscio
|
9
14
|
- Mike Heffner
|
10
15
|
autorequire:
|
11
16
|
bindir: bin
|
12
17
|
cert_chain: []
|
13
|
-
|
18
|
+
|
19
|
+
date: 2011-10-07 00:00:00 -07:00
|
14
20
|
default_executable: twke
|
15
|
-
dependencies:
|
16
|
-
- !ruby/object:Gem::Dependency
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
23
|
+
type: :runtime
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
17
33
|
name: scamp
|
18
|
-
|
34
|
+
version_requirements: *id001
|
35
|
+
prerelease: false
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
type: :runtime
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
19
39
|
none: false
|
20
|
-
requirements:
|
40
|
+
requirements:
|
21
41
|
- - ~>
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
|
24
|
-
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 19
|
44
|
+
segments:
|
45
|
+
- 1
|
46
|
+
- 1
|
47
|
+
- 0
|
48
|
+
version: 1.1.0
|
49
|
+
name: can-has-lolcat
|
50
|
+
version_requirements: *id002
|
25
51
|
prerelease: false
|
26
|
-
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: shoulda
|
29
|
-
requirement: &2153515080 !ruby/object:Gem::Requirement
|
30
|
-
none: false
|
31
|
-
requirements:
|
32
|
-
- - ! '>='
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version: '0'
|
52
|
+
- !ruby/object:Gem::Dependency
|
35
53
|
type: :development
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 3
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
name: shoulda
|
64
|
+
version_requirements: *id003
|
36
65
|
prerelease: false
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
requirement: &2153514320 !ruby/object:Gem::Requirement
|
66
|
+
- !ruby/object:Gem::Dependency
|
67
|
+
type: :development
|
68
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
41
69
|
none: false
|
42
|
-
requirements:
|
70
|
+
requirements:
|
43
71
|
- - ~>
|
44
|
-
- !ruby/object:Gem::Version
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
hash: 23
|
74
|
+
segments:
|
75
|
+
- 1
|
76
|
+
- 0
|
77
|
+
- 0
|
45
78
|
version: 1.0.0
|
46
|
-
|
79
|
+
name: bundler
|
80
|
+
version_requirements: *id004
|
47
81
|
prerelease: false
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
requirement: &2153513580 !ruby/object:Gem::Requirement
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
type: :development
|
84
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
52
85
|
none: false
|
53
|
-
requirements:
|
86
|
+
requirements:
|
54
87
|
- - ~>
|
55
|
-
- !ruby/object:Gem::Version
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
hash: 7
|
90
|
+
segments:
|
91
|
+
- 1
|
92
|
+
- 6
|
93
|
+
- 4
|
56
94
|
version: 1.6.4
|
57
|
-
|
95
|
+
name: jeweler
|
96
|
+
version_requirements: *id005
|
58
97
|
prerelease: false
|
59
|
-
|
60
|
-
- !ruby/object:Gem::Dependency
|
61
|
-
name: rcov
|
62
|
-
requirement: &2153512780 !ruby/object:Gem::Requirement
|
63
|
-
none: false
|
64
|
-
requirements:
|
65
|
-
- - ! '>='
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
68
99
|
type: :development
|
100
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
hash: 3
|
106
|
+
segments:
|
107
|
+
- 0
|
108
|
+
version: "0"
|
109
|
+
name: rcov
|
110
|
+
version_requirements: *id006
|
69
111
|
prerelease: false
|
70
|
-
version_requirements: *2153512780
|
71
112
|
description: The ambuquad that has your back.
|
72
113
|
email: joe@ruscio.org
|
73
|
-
executables:
|
114
|
+
executables:
|
74
115
|
- twke
|
75
116
|
extensions: []
|
76
|
-
|
117
|
+
|
118
|
+
extra_rdoc_files:
|
77
119
|
- LICENSE.txt
|
78
120
|
- README.md
|
79
|
-
files:
|
121
|
+
files:
|
80
122
|
- .document
|
81
123
|
- Gemfile
|
82
124
|
- Gemfile.lock
|
@@ -85,41 +127,52 @@ files:
|
|
85
127
|
- Rakefile
|
86
128
|
- VERSION
|
87
129
|
- bin/twke
|
130
|
+
- dot.rvmrc
|
88
131
|
- lib/twke.rb
|
132
|
+
- lib/twke/conf.rb
|
89
133
|
- lib/twke/plugin.rb
|
90
134
|
- lib/twke/routes.rb
|
91
135
|
- plugins/admin.rb
|
136
|
+
- plugins/config.rb
|
137
|
+
- plugins/jenkins.rb
|
138
|
+
- plugins/lolcats.rb
|
92
139
|
- plugins/twiki.rb
|
93
140
|
- test/helper.rb
|
94
|
-
- test/
|
141
|
+
- test/test_conf.rb
|
95
142
|
- twke.gemspec
|
96
143
|
has_rdoc: true
|
97
144
|
homepage: http://github.com/josephruscio/twke
|
98
|
-
licenses:
|
145
|
+
licenses:
|
99
146
|
- MIT
|
100
147
|
post_install_message:
|
101
148
|
rdoc_options: []
|
102
|
-
|
149
|
+
|
150
|
+
require_paths:
|
103
151
|
- lib
|
104
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
152
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
105
153
|
none: false
|
106
|
-
requirements:
|
107
|
-
- -
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
|
110
|
-
segments:
|
154
|
+
requirements:
|
155
|
+
- - ">="
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
hash: 3
|
158
|
+
segments:
|
111
159
|
- 0
|
112
|
-
|
113
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
|
+
version: "0"
|
161
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
162
|
none: false
|
115
|
-
requirements:
|
116
|
-
- -
|
117
|
-
- !ruby/object:Gem::Version
|
118
|
-
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
hash: 3
|
167
|
+
segments:
|
168
|
+
- 0
|
169
|
+
version: "0"
|
119
170
|
requirements: []
|
171
|
+
|
120
172
|
rubyforge_project:
|
121
173
|
rubygems_version: 1.6.2
|
122
174
|
signing_key:
|
123
175
|
specification_version: 3
|
124
176
|
summary: Bidi-Bidi-Bidi!
|
125
177
|
test_files: []
|
178
|
+
|