shove 0.52 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +63 -0
- data/README.markdown +263 -0
- data/Rakefile +47 -0
- data/bin/shove +128 -106
- data/lib/shove/app.rb +78 -0
- data/lib/shove/app_directory.rb +104 -0
- data/lib/shove/client/callback.rb +24 -0
- data/lib/shove/client/channel.rb +81 -0
- data/lib/shove/client/connection.rb +167 -0
- data/lib/shove/http/channel_context.rb +60 -0
- data/lib/shove/http/client_context.rb +82 -0
- data/lib/shove/http/request.rb +94 -0
- data/lib/shove/http/response.rb +30 -0
- data/lib/shove/protocol.rb +53 -0
- data/lib/shove.rb +60 -78
- data/shove.gemspec +11 -20
- data/spec/app_directory_spec.rb +66 -0
- data/spec/cassettes/should_authorize_oneself.yml +24 -0
- data/spec/cassettes/should_be_able_to_authorize_with_the_server.yml +24 -0
- data/spec/cassettes/should_cancel_a_binding.yml +24 -0
- data/spec/cassettes/should_configure_the_default.yml +24 -0
- data/spec/cassettes/should_configure_the_from_the_previous_test.yml +24 -0
- data/spec/cassettes/should_create_a_channel_context.yml +24 -0
- data/spec/cassettes/should_deny_a_connection.yml +24 -0
- data/spec/cassettes/should_deny_a_control_to_a_client.yml +24 -0
- data/spec/cassettes/should_deny_a_publishing_to_a_client.yml +24 -0
- data/spec/cassettes/should_deny_a_subscriptions_to_a_client.yml +24 -0
- data/spec/cassettes/should_deny_publishing_on_a_channel_context.yml +24 -0
- data/spec/cassettes/should_deny_subscriptions_on_a_channel_context.yml +24 -0
- data/spec/cassettes/should_get_a_set_of_nodes_for_the_network.yml +24 -0
- data/spec/cassettes/should_get_a_subscribe_granted_event.yml +24 -0
- data/spec/cassettes/should_grant_a_connection.yml +24 -0
- data/spec/cassettes/should_grant_a_control_to_a_client.yml +24 -0
- data/spec/cassettes/should_grant_a_publishing_to_a_client.yml +24 -0
- data/spec/cassettes/should_grant_a_subscriptions_to_a_client.yml +24 -0
- data/spec/cassettes/should_grant_publishing_on_a_channel_context.yml +24 -0
- data/spec/cassettes/should_grant_subscriptions_on_a_channel_context.yml +24 -0
- data/spec/cassettes/should_publish.yml +24 -0
- data/spec/cassettes/should_publish_on_a_channel_context.yml +24 -0
- data/spec/cassettes/should_publish_to_a_client.yml +24 -0
- data/spec/cassettes/should_receive_an_unsubscribe_event.yml +24 -0
- data/spec/cassettes/should_receive_messages_on_a_channel.yml +24 -0
- data/spec/cassettes/should_send_a_connect_op.yml +24 -0
- data/spec/cassettes/should_send_a_connect_op_with_an_id.yml +24 -0
- data/spec/cassettes/should_spawn_a_client.yml +24 -0
- data/spec/cassettes/should_subscribe_to_a_channel.yml +24 -0
- data/spec/cassettes/should_trigger_a_connect_denied_event.yml +24 -0
- data/spec/cassettes/should_trigger_a_connect_event.yml +24 -0
- data/spec/cassettes/should_trigger_a_disconnect_event.yml +24 -0
- data/spec/cassettes/should_trigger_an_error_event.yml +24 -0
- data/spec/cassettes/should_unsubscribe_from_a_channel.yml +24 -0
- data/spec/cassettes/should_update_the_default_app.yml +24 -0
- data/spec/helper.rb +60 -0
- data/spec/shove_client_spec.rb +194 -0
- data/spec/shove_http_spec.rb +142 -0
- metadata +111 -81
- data/README.md +0 -71
- data/lib/shove/client.rb +0 -54
- data/lib/shove/request.rb +0 -80
- data/lib/shove/response.rb +0 -23
- data/spec/shove_spec.rb +0 -40
data/.gitignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# A sample Gemfile
|
2
|
+
source "http://rubygems.org"
|
3
|
+
|
4
|
+
group :development do
|
5
|
+
gem "rake"
|
6
|
+
gem "redcarpet"
|
7
|
+
gem "albino"
|
8
|
+
end
|
9
|
+
|
10
|
+
group :test do
|
11
|
+
gem "rspec"
|
12
|
+
gem "vcr", "2.0.0.rc1"
|
13
|
+
gem "webmock"
|
14
|
+
gem "net-http-spy"
|
15
|
+
end
|
16
|
+
|
17
|
+
gemspec
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
shove (1.0.1)
|
5
|
+
confstruct (>= 0.2.1)
|
6
|
+
em-http-request (>= 1.0.0)
|
7
|
+
em-ws-client (>= 0.1.1)
|
8
|
+
yajl-ruby (>= 1.1.0)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: http://rubygems.org/
|
12
|
+
specs:
|
13
|
+
addressable (2.2.6)
|
14
|
+
albino (1.3.3)
|
15
|
+
posix-spawn (>= 0.3.6)
|
16
|
+
confstruct (0.2.1)
|
17
|
+
cookiejar (0.3.0)
|
18
|
+
crack (0.3.1)
|
19
|
+
diff-lcs (1.1.3)
|
20
|
+
em-http-request (1.0.1)
|
21
|
+
addressable (>= 2.2.3)
|
22
|
+
cookiejar
|
23
|
+
em-socksify
|
24
|
+
eventmachine (>= 1.0.0.beta.4)
|
25
|
+
http_parser.rb (>= 0.5.3)
|
26
|
+
em-socksify (0.1.0)
|
27
|
+
eventmachine
|
28
|
+
em-ws-client (0.1.1)
|
29
|
+
eventmachine (~> 1.0.0.beta.3)
|
30
|
+
state_machine (~> 1.0.2)
|
31
|
+
eventmachine (1.0.0.beta.4)
|
32
|
+
http_parser.rb (0.5.3)
|
33
|
+
net-http-spy (0.2.1)
|
34
|
+
posix-spawn (0.3.6)
|
35
|
+
rake (0.9.2.2)
|
36
|
+
redcarpet (2.1.0)
|
37
|
+
rspec (2.8.0)
|
38
|
+
rspec-core (~> 2.8.0)
|
39
|
+
rspec-expectations (~> 2.8.0)
|
40
|
+
rspec-mocks (~> 2.8.0)
|
41
|
+
rspec-core (2.8.0)
|
42
|
+
rspec-expectations (2.8.0)
|
43
|
+
diff-lcs (~> 1.1.2)
|
44
|
+
rspec-mocks (2.8.0)
|
45
|
+
state_machine (1.0.3)
|
46
|
+
vcr (2.0.0.rc1)
|
47
|
+
webmock (1.7.10)
|
48
|
+
addressable (~> 2.2, > 2.2.5)
|
49
|
+
crack (>= 0.1.7)
|
50
|
+
yajl-ruby (1.1.0)
|
51
|
+
|
52
|
+
PLATFORMS
|
53
|
+
ruby
|
54
|
+
|
55
|
+
DEPENDENCIES
|
56
|
+
albino
|
57
|
+
net-http-spy
|
58
|
+
rake
|
59
|
+
redcarpet
|
60
|
+
rspec
|
61
|
+
shove!
|
62
|
+
vcr (= 2.0.0.rc1)
|
63
|
+
webmock
|
data/README.markdown
ADDED
@@ -0,0 +1,263 @@
|
|
1
|
+
shove ruby client
|
2
|
+
=================
|
3
|
+
Ruby client and CLI for the shove.io HTTP and WebSocket APIs
|
4
|
+
|
5
|
+
Installation
|
6
|
+
------------
|
7
|
+
|
8
|
+
```bash
|
9
|
+
gem install shove
|
10
|
+
```
|
11
|
+
|
12
|
+
Grab your App ID and App Key from shove at [https://shove.io/apps][0]
|
13
|
+
|
14
|
+
Configuring Shove
|
15
|
+
-----------------
|
16
|
+
|
17
|
+
If you are using a single shove app within your project, you can configure
|
18
|
+
shove though the Shove module:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
Shove.configure do
|
22
|
+
app_id "myappid"
|
23
|
+
app_key "myappkey"
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
If you want to work with different shove apps in one project, you can
|
28
|
+
create App objects
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
app = Shove::App.new do
|
32
|
+
app_id "myappid"
|
33
|
+
app_key "myappkey"
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
Using the HTTP Client
|
38
|
+
---------------------
|
39
|
+
The HTTP client gives publishing and access control capabilities without
|
40
|
+
a persistent WebSocket connection
|
41
|
+
|
42
|
+
Publish "Hello World!" to all connections on the notifications channel
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
Shove.channel("notifications").publish("Hello World!") do |response|
|
46
|
+
# handle response
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
Publish "Hey buddy" to the client with id buddy.
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
Shove.channel("direct:buddy").publish("Hey buddy") do |response|
|
54
|
+
# handle response
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
58
|
+
Apps, channels, and clients can be controlled from the HTTP API
|
59
|
+
|
60
|
+
Grant a connection to dan@shove.io
|
61
|
+
```ruby
|
62
|
+
Shove.grant_connect("dan@shove.io") do |response|
|
63
|
+
# handle response
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
67
|
+
Grant subscription on the notifications channel to client dan
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
Shove.channel("notifications").grant_subscribe("dan") do |response|
|
71
|
+
# handle response
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
Grant subscription on all channels to client dan
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
Shove.channel("*").grant_subscribe("dan@shove.io") do |response|
|
79
|
+
# handle response
|
80
|
+
end
|
81
|
+
```
|
82
|
+
|
83
|
+
Grant publishing on chat:client_22733 channel to client dan
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
Shove.channel("chat:client_22733").grant_publish("dan") do |response|
|
87
|
+
# handle response
|
88
|
+
end
|
89
|
+
```
|
90
|
+
|
91
|
+
Deny publishing on chat:client_22733 channel to dan
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
Shove.channel("chat:client_22733").deny_publish("dan") do |response|
|
95
|
+
# handle response
|
96
|
+
end
|
97
|
+
```
|
98
|
+
|
99
|
+
Using the WebSocket Client
|
100
|
+
--------------------------
|
101
|
+
|
102
|
+
Create a WebSocket client on the default app
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
client = Shove.app.connect
|
106
|
+
```
|
107
|
+
|
108
|
+
Or
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
app = Shove::App.new do
|
112
|
+
app_id "myappid"
|
113
|
+
end
|
114
|
+
client = app.connect
|
115
|
+
```
|
116
|
+
|
117
|
+
Create a client with a custom ID
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
client = Shove.app.connect("unique_id")
|
121
|
+
```
|
122
|
+
|
123
|
+
### Client events
|
124
|
+
|
125
|
+
Handle connect event
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
client.on("connect") do
|
129
|
+
# Connected!
|
130
|
+
end
|
131
|
+
```
|
132
|
+
|
133
|
+
Handle connect denies (private app)
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
client.on("connect_denied") do |id|
|
137
|
+
# Silly, but:
|
138
|
+
Shove.client(id).grant_connect do |response|
|
139
|
+
# At this point, the client should receive
|
140
|
+
# a connect event (through the shove app)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
```
|
144
|
+
|
145
|
+
And disconnect events
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
client.on("disconnect") do
|
149
|
+
end
|
150
|
+
```
|
151
|
+
|
152
|
+
If there is any kind of error, log it
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
client.on("error") do |error|
|
156
|
+
log.error "Shove error: #{error}"
|
157
|
+
end
|
158
|
+
```
|
159
|
+
|
160
|
+
### Clients and Channels
|
161
|
+
|
162
|
+
Subscribe to a channel or get a subscribed channel
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
channel = client.channel("channel")
|
166
|
+
```
|
167
|
+
|
168
|
+
Handle a message published on a channel
|
169
|
+
|
170
|
+
```ruby
|
171
|
+
channel.on("message") do |msg|
|
172
|
+
widget.append msg
|
173
|
+
end
|
174
|
+
```
|
175
|
+
|
176
|
+
Handle the subscribe callback for a given channel
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
channel.on("subscribe") do
|
180
|
+
# channel is subscribed
|
181
|
+
end
|
182
|
+
```
|
183
|
+
|
184
|
+
If the app denies subscriptions by default, you should
|
185
|
+
handle the subscribe_denied event
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
channel.on("subscribe_denied") do
|
189
|
+
# Silly example
|
190
|
+
Shove.client(client.id).grant_subscribe(channel.name)
|
191
|
+
end
|
192
|
+
```
|
193
|
+
|
194
|
+
You can get the binding for a callback and cancel it
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
binding = channel.on("message") do |msg|
|
198
|
+
end
|
199
|
+
|
200
|
+
binding.cancel
|
201
|
+
```
|
202
|
+
|
203
|
+
Handle a direct message
|
204
|
+
|
205
|
+
```ruby
|
206
|
+
client.channel("direct").on("message") do |msg|
|
207
|
+
# handle direct message
|
208
|
+
end
|
209
|
+
```
|
210
|
+
|
211
|
+
Unsubscribe from a channel, optionally handle the event
|
212
|
+
|
213
|
+
```ruby
|
214
|
+
channel.on("unsubscribe_complete") do
|
215
|
+
end
|
216
|
+
|
217
|
+
channel.unsubscribe
|
218
|
+
```
|
219
|
+
|
220
|
+
Publish a message from the WebSocket client
|
221
|
+
|
222
|
+
```ruby
|
223
|
+
channel.publish("hi!")
|
224
|
+
|
225
|
+
# publish json
|
226
|
+
channel.publish(obj.to_json)
|
227
|
+
```
|
228
|
+
|
229
|
+
Using the Command Line
|
230
|
+
----------------------
|
231
|
+
|
232
|
+
A CLI utility is included with the gem, run help to see options
|
233
|
+
|
234
|
+
```bash
|
235
|
+
shove help
|
236
|
+
```
|
237
|
+
|
238
|
+
Publish a message
|
239
|
+
|
240
|
+
```bash
|
241
|
+
shove publish -c channel1 -m "Hello world!"
|
242
|
+
```
|
243
|
+
|
244
|
+
Publish to a specific app
|
245
|
+
|
246
|
+
```bash
|
247
|
+
shove publish -a app_id -c chan1 -m "hi"
|
248
|
+
```
|
249
|
+
|
250
|
+
Set the default app for the CLI
|
251
|
+
|
252
|
+
```bash
|
253
|
+
shove apps:default -a app_id
|
254
|
+
```
|
255
|
+
|
256
|
+
Watch all activity on a channel
|
257
|
+
|
258
|
+
```bash
|
259
|
+
shove watch -c chan
|
260
|
+
```
|
261
|
+
|
262
|
+
[0]: https://shove.io/apps
|
263
|
+
[1]: http://shove.io/documentation/cli
|
data/Rakefile
CHANGED
@@ -4,3 +4,50 @@ RSpec::Core::RakeTask.new(:spec)
|
|
4
4
|
|
5
5
|
task :default => :spec
|
6
6
|
|
7
|
+
task :autospec => :spec do
|
8
|
+
require "eventmachine"
|
9
|
+
|
10
|
+
$time = Time.now
|
11
|
+
|
12
|
+
module Handler
|
13
|
+
def file_modified
|
14
|
+
if Time.now - $time > 1
|
15
|
+
$time = Time.now
|
16
|
+
Rake::Task["spec"].execute
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
EM.kqueue = true if EM.kqueue?
|
22
|
+
EM.run do
|
23
|
+
["spec","lib"].collect { |dir|
|
24
|
+
Dir.glob(File.dirname(__FILE__) + "/#{dir}/**/*.rb")
|
25
|
+
}.flatten.each do |file|
|
26
|
+
EM.watch_file file, Handler
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "Generate the README HTML"
|
33
|
+
task :readme do
|
34
|
+
|
35
|
+
require "redcarpet"
|
36
|
+
require "albino"
|
37
|
+
|
38
|
+
# Create a custom renderer that uses albino to
|
39
|
+
# make pretty code
|
40
|
+
class Colorizer < Redcarpet::Render::HTML
|
41
|
+
def block_code(code, language)
|
42
|
+
Albino.colorize(code, language)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
content = Redcarpet::Markdown.new(Colorizer, :fenced_code_blocks => true)
|
47
|
+
.render(File.read("README.markdown"))
|
48
|
+
|
49
|
+
File.open("README.html", "w") do |f|
|
50
|
+
f << content
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
data/bin/shove
CHANGED
@@ -1,133 +1,155 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
4
|
+
|
5
|
+
require "optparse"
|
5
6
|
require "shove"
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
access[:network] = ask "Enter Network Id: "
|
21
|
-
access[:key] = ask "Enter Network Key: "
|
22
|
-
|
23
|
-
Shove.configure access
|
24
|
-
|
25
|
-
check = Shove.validate
|
26
|
-
if check.status >= 400
|
27
|
-
say "Unable to validate network settings. Error: #{check.message}"
|
28
|
-
else
|
29
|
-
break
|
30
|
-
end
|
31
|
-
|
8
|
+
action = ARGV[0]
|
9
|
+
channel = nil
|
10
|
+
client = nil
|
11
|
+
message = nil
|
12
|
+
app = nil
|
13
|
+
app_dir = Shove::AppDirectory.new
|
14
|
+
|
15
|
+
OptionParser.new do |o|
|
16
|
+
|
17
|
+
o.banner = "Usage: shove "
|
18
|
+
|
19
|
+
o.on("-h", "--help") do
|
20
|
+
action = "help"
|
32
21
|
end
|
33
22
|
|
34
|
-
|
35
|
-
|
23
|
+
o.on("-v", "--version") do
|
24
|
+
action = "version"
|
36
25
|
end
|
37
|
-
|
38
|
-
end
|
39
26
|
|
40
|
-
|
27
|
+
o.on("-l", "--list") do
|
28
|
+
action = "apps"
|
29
|
+
end
|
41
30
|
|
42
|
-
|
31
|
+
o.on("-a", "--app app", "the app to work with") do |arg|
|
32
|
+
app = arg
|
33
|
+
end
|
43
34
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
program :help, "Author", "Dan Simpson <dan@shove.io>"
|
48
|
-
program :formatter, :compact
|
35
|
+
o.on("-c", "--channel channel", "the channel to operate on") do |arg|
|
36
|
+
channel = arg
|
37
|
+
end
|
49
38
|
|
50
|
-
|
51
|
-
|
52
|
-
c.example "Streams the default channel", "shove stream default"
|
53
|
-
c.description = "Stream all data on a given channel to the console"
|
54
|
-
c.action do |args, opts|
|
55
|
-
if args.empty?
|
56
|
-
say_invalid c
|
57
|
-
else
|
58
|
-
EM.run do
|
59
|
-
Shove.stream(args.first) { |m|
|
60
|
-
puts m[:channel]
|
61
|
-
puts m[:event]
|
62
|
-
puts m[:to] # this will either be empty or self
|
63
|
-
puts m[:from] # message sender
|
64
|
-
puts m[:data] # the payload
|
65
|
-
puts "============"
|
66
|
-
}
|
67
|
-
end
|
68
|
-
end
|
39
|
+
o.on("-u", "--client client", "the client to operate on") do |arg|
|
40
|
+
client = arg
|
69
41
|
end
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
command :broadcast do |c|
|
74
|
-
c.syntax = "shove broadcast channel event data"
|
75
|
-
c.example "Broadcast x,y coordinates on the grid channel", "shove broadcast grid coords '1522,234'"
|
76
|
-
c.description = "Broadcast event and data to all subscribers of a given channel"
|
77
|
-
c.action do |args, opts|
|
78
|
-
if args.length != 3
|
79
|
-
say_invalid c
|
80
|
-
else
|
81
|
-
say "Broadcasting on channel #{args.first}"
|
82
|
-
Shove.broadcast(*args) do |response|
|
83
|
-
say response.message
|
84
|
-
end
|
85
|
-
end
|
42
|
+
|
43
|
+
o.on("-m", "--message message", "the message to publish") do |arg|
|
44
|
+
message = arg
|
86
45
|
end
|
46
|
+
|
47
|
+
o.parse!(ARGV)
|
87
48
|
end
|
88
49
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
50
|
+
begin
|
51
|
+
|
52
|
+
case action
|
53
|
+
when "version"
|
54
|
+
puts "shove version #{Shove::Version}"
|
55
|
+
when "apps"
|
56
|
+
|
57
|
+
apps = app_dir.apps
|
58
|
+
|
59
|
+
if apps.empty?
|
60
|
+
puts "No apps found. Run: shove apps:add"
|
96
61
|
else
|
97
|
-
|
98
|
-
|
99
|
-
|
62
|
+
puts "App Id\t\tApp Key"
|
63
|
+
puts "-----------------------"
|
64
|
+
apps.each_pair do |id,key|
|
65
|
+
puts "#{id}\t\t#{key}"
|
100
66
|
end
|
101
67
|
end
|
102
|
-
end
|
103
|
-
end
|
104
68
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
69
|
+
when "apps:add"
|
70
|
+
app_dir.get_config app
|
71
|
+
when "apps:default"
|
72
|
+
app_dir.default = app
|
73
|
+
when "hosts"
|
74
|
+
Shove.configure(app_dir.get_config(app))
|
75
|
+
|
76
|
+
Shove.hosts.each do |host|
|
77
|
+
puts host
|
78
|
+
end
|
79
|
+
|
80
|
+
when "publish"
|
81
|
+
|
82
|
+
Shove.configure(app_dir.get_config(app))
|
83
|
+
|
84
|
+
errors = []
|
85
|
+
errors << "channel not defined" unless channel
|
86
|
+
errors << "message not defined" unless message
|
87
|
+
|
88
|
+
if errors.empty?
|
89
|
+
Shove.channel(channel).publish(message) do |r|
|
90
|
+
if r.error?
|
91
|
+
puts "Error: #{r.message}"
|
92
|
+
else
|
93
|
+
puts "Published"
|
94
|
+
end
|
116
95
|
end
|
96
|
+
else
|
97
|
+
puts "Errors: #{errors.join(",")}"
|
117
98
|
end
|
118
|
-
end
|
119
|
-
end
|
120
99
|
|
100
|
+
when "watch"
|
121
101
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
102
|
+
Shove.configure(app_dir.get_config(app))
|
103
|
+
|
104
|
+
if channel
|
105
|
+
|
106
|
+
EM.run do
|
107
|
+
client = Shove.connect
|
108
|
+
client.authorize(app_dir.key(app))
|
109
|
+
|
110
|
+
client.on("error") do |error|
|
111
|
+
puts "Watch Error #{error}"
|
112
|
+
EM.stop
|
113
|
+
end
|
114
|
+
|
115
|
+
channel = client.channel(channel)
|
116
|
+
channel.on("message") do |msg|
|
117
|
+
puts "#{Time.now}: #{msg}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
else
|
122
|
+
puts "You must provide the channel with: -c channel_name"
|
130
123
|
end
|
124
|
+
|
125
|
+
else
|
126
|
+
puts File.read(__FILE__).split("__END__").last
|
131
127
|
end
|
128
|
+
|
129
|
+
|
130
|
+
rescue Exception => ex
|
131
|
+
|
132
|
+
puts ex.message
|
133
|
+
puts ex.backtrace
|
134
|
+
|
135
|
+
abort File.read(__FILE__).split("__END__").last
|
132
136
|
end
|
133
137
|
|
138
|
+
__END__
|
139
|
+
Usage: shove action [options]
|
140
|
+
|
141
|
+
|
142
|
+
Options
|
143
|
+
-h, --help
|
144
|
+
Show this message
|
145
|
+
|
146
|
+
Actions
|
147
|
+
publish publish a message to the app
|
148
|
+
example: shove publish -c chan -m "Hello"
|
149
|
+
|
150
|
+
hosts List available hosts for your app
|
151
|
+
watch Watch the messages on a given channel
|
152
|
+
|
153
|
+
apps List known apps
|
154
|
+
apps:default Use a particular app
|
155
|
+
apps:add Add a new app
|