shove 0.4 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ shove.yml
2
+ example.rb
3
+ *.gem
data/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  gem install shove
8
8
 
9
9
  ##Install Step 2
10
- Grab your network id and API key from shove at [http://shove.io/customer/network/api_access]
10
+ Grab your network id and API key from shove at [http://shove.io/customer/network/api_access#ruby][0]
11
11
 
12
12
  ##Install Step 3
13
13
  Configure shover with your credentials
@@ -20,7 +20,7 @@
20
20
  :cluster => "cluster"
21
21
  )
22
22
 
23
- ##Broadcast messages
23
+ ##Broadcasting
24
24
 
25
25
  # broadcast the "hello" event on the "default" channel with
26
26
  # Hello World! as the data
@@ -30,18 +30,32 @@
30
30
  puts response.message
31
31
  end
32
32
 
33
- ##Direct messages
33
+ ##Send direct messages
34
34
 
35
35
  Shove.direct(userid, "hello", "Hello World!") do |response|
36
36
  # handle response
37
37
  end
38
38
 
39
- ##Authorize a user
39
+ ##Subscription Authorization
40
40
 
41
41
  # authorize user with id userid on channel "default"
42
42
  Shove.authorize(userid, "default") do |response|
43
43
  # handle response
44
44
  end
45
+
46
+ ##Channel Streaming
47
+
48
+ # stream all data on channel "default"
49
+ Shove.stream("default") do |msg|
50
+
51
+ # msg has several properties
52
+ puts msg[:channel]
53
+ puts msg[:event]
54
+ puts msg[:to] # this will either be empty or self
55
+ puts msg[:from] # message sender
56
+ puts msg[:data] # the payload
57
+
58
+ end
45
59
 
46
60
  ##Block and Non-blocking
47
61
  shover does both. If the shover code happens to run inside of an EM.run block, the HTTP calls
@@ -50,6 +64,8 @@
50
64
 
51
65
  ##CLI (Command line interface)
52
66
  The shove gem comes with a command line tool for controlling the network.
53
- View documentation @ [http://shove.io/documentation/cli]
54
-
55
-
67
+ View documentation @ [http://shove.io/documentation/cli][1]
68
+
69
+
70
+ [0]: http://shove.io/customer/network/api_access
71
+ [1]: http://shove.io/documentation/cli
data/bin/shove CHANGED
@@ -16,7 +16,6 @@ unless FileTest.exist?(ymlpath)
16
16
  say "Please enter your network information."
17
17
  say "Visit http://shove.io/customer/network/api_access for more info."
18
18
 
19
- access[:cluster] = ask "Enter Cluster Group: "
20
19
  access[:network] = ask "Enter Network Id: "
21
20
  access[:key] = ask "Enter Network Key: "
22
21
 
@@ -56,7 +55,14 @@ command :stream do |c|
56
55
  say_invalid c
57
56
  else
58
57
  EM.run do
59
- Shove.stream(args.first) { |m| say(m) }
58
+ Shove.stream(args.first) { |m|
59
+ puts m[:channel]
60
+ puts m[:event]
61
+ puts m[:to] # this will either be empty or self
62
+ puts m[:from] # message sender
63
+ puts m[:data] # the payload
64
+ puts "============"
65
+ }
60
66
  end
61
67
  end
62
68
  end
data/lib/shove/client.rb CHANGED
@@ -6,14 +6,12 @@ module Shove
6
6
  # +key+ the api access key
7
7
  # +opts+ hash with a few options, such as:
8
8
  # :secure true or false
9
- # :host leave as default unless you are given a private cluster
10
- def initialize network, key, opts={}
11
- @network = network
12
- @cluster = opts[:cluster] || "a04"
13
- @key = key
14
- @auth_header = { "api-key" => key }
9
+ # :host leave as default unless you have a dedicated cluster
10
+ def initialize opts={}
11
+ @network = opts[:network]
15
12
  @secure = opts[:secure] || false
16
- @host = opts[:host] || "api.#{@cluster}.shove.io"
13
+ @host = opts[:host] || "api.shove.io"
14
+ @port = opts[:port] || (@secure ? 443 : 80)
17
15
  end
18
16
 
19
17
  # broadcast a message
@@ -21,7 +19,7 @@ module Shove
21
19
  # +event+ the event to trigger
22
20
  # +message+ the message to send, UTF-8 encoded kthx
23
21
  def broadcast channel, event, message, &block
24
- Request.new("#{uri}/#{@network}/broadcast/#{channel}/#{event}", @auth_header).post(message, &block)
22
+ Request.new("#{uri}/broadcast/#{channel}/#{event}").post(message, &block)
25
23
  end
26
24
 
27
25
  # direct a message to a specific user
@@ -29,27 +27,35 @@ module Shove
29
27
  # +event+ the event to trigger
30
28
  # +message+ the message to send, UTF-8 encoded kthx
31
29
  def direct uid, event, message, &block
32
- Request.new("#{uri}/#{@network}/direct/#{event}/#{uid}", @auth_header).post(message, &block)
30
+ Request.new("#{uri}/direct/#{event}/#{uid}").post(message, &block)
33
31
  end
34
32
 
35
33
  # authorize a user on a private channel
36
34
  # +uid+ the users id
37
35
  # +channel+ the channel to authorize them on
38
36
  def authorize uid, channel="*", &block
39
- Request.new("#{uri}/#{@network}/authorize/#{channel}/#{uid}", @auth_header).post(&block)
37
+ Request.new("#{uri}/authorize/#{channel}/#{uid}").post(&block)
40
38
  end
41
39
 
40
+ # validate current API settings
42
41
  def validate
43
- Request.new("#{uri}/#{@network}/validate", @auth_header).post do |response|
42
+ Request.new("#{uri}/validate").post do |response|
44
43
  return response
45
44
  end
46
45
  end
47
46
 
47
+ # fetch a list of hosts for streaming websockets and comet
48
+ def hosts
49
+ Request.new("#{uri}/hosts").get do |response|
50
+ return response
51
+ end
52
+ end
53
+
48
54
  protected
49
55
 
50
56
  def uri
51
- (@secure ? "https" : "http") + "://#{@host}"
57
+ (@secure ? "https" : "http") + "://#{@host}:#{@port}/#{@network}"
52
58
  end
53
59
 
54
60
  end
55
- end
61
+ end
data/lib/shove/request.rb CHANGED
@@ -1,33 +1,78 @@
1
1
  module Shove
2
2
  class Request
3
3
 
4
+ include EventMachine::HttpEncoding
5
+
4
6
  attr_accessor :url, :headers
5
7
 
6
8
  def initialize url, headers={}
7
9
  self.url = url
8
- self.headers = headers
10
+ self.headers = headers.merge({
11
+ "api-key" => Shove.config[:key]
12
+ })
13
+ end
14
+
15
+ # HTTP Delete request
16
+ def delete &block
17
+ exec :delete, &block
18
+ end
19
+
20
+ # HTTP Post request for new content
21
+ def post params={}, &block
22
+ exec :post, params, &block
23
+ end
24
+
25
+ # HTTP Put request for updates
26
+ def put params={}, &block
27
+ exec :put, params, &block
28
+ end
29
+
30
+ # HTTP Get request
31
+ def get &block
32
+ exec :get, &block
9
33
  end
10
34
 
11
- def post params="", &block
35
+ private
36
+
37
+ # exec a HTTP request, and callback with
38
+ # a response via block
39
+ def exec method, params={}, &block
40
+
41
+ # run async so we don't block if EM is running
12
42
  if EM.reactor_running?
13
- http = EventMachine::HttpRequest.new(url).post(:body => params, :head => headers)
14
- if block
15
- http.errback {
16
- block.call(Response.new(http.response_header.status, http.response, true))
17
- }
18
- http.callback {
19
- block.call(Response.new(http.response_header.status, http.response, false))
20
- }
21
- end
43
+ http = EventMachine::HttpRequest.new(url).send(method, {
44
+ :body => params,
45
+ :head => headers
46
+ })
47
+
48
+ # handle error
49
+ http.errback {
50
+ block.call(Response.new(http.response_header.status, http.response, true)) if block_given?
51
+ }
52
+
53
+ # handle success
54
+ http.callback {
55
+ status = http.response_header.status
56
+ block.call(Response.new(status, http.response, status >= 400)) if block_given?
57
+ }
58
+
59
+ # fallback to standard lib for http
22
60
  else
23
61
  uri = URI.parse(url)
24
- res = Net::HTTP.new(uri.host, uri.port).post(uri.path, params, headers)
25
- if block
26
- block.call(Response.new(res.code, res.body, res.code.to_i < 400))
62
+ case method
63
+ when :post, :put
64
+ res = Net::HTTP.new(uri.host, uri.port).send(method, uri.path, normalize_body(params), headers)
65
+ when :get, :delete
66
+ res = Net::HTTP.new(uri.host, uri.port).send(method, uri.path, headers)
27
67
  end
68
+ block.call(Response.new(res.code, res.body, res.code.to_i >= 400)) if block_given?
28
69
  end
29
70
  end
30
-
71
+
72
+ def normalize_body(body)
73
+ body.is_a?(Hash) ? form_encode_body(body) : body
74
+ end
75
+
31
76
  end
32
77
  end
33
78
 
@@ -9,9 +9,20 @@ module Shove
9
9
  self.error = error
10
10
  end
11
11
 
12
+ # was there an error with the request?
12
13
  def error?
13
14
  error
14
15
  end
16
+
17
+ # parse a json response
18
+ def parse
19
+ @parsed ||= Yajl::Parser.new(:symbolize_keys => true).parse(message)
20
+ end
21
+
22
+ # alias parse
23
+ def to_hash
24
+ parse
25
+ end
15
26
 
16
27
  end
17
28
  end
data/lib/shove.rb CHANGED
@@ -3,15 +3,18 @@ $:.unshift File.dirname(__FILE__)
3
3
  require "rubygems"
4
4
  require "net/http"
5
5
  require "em-http-request"
6
+ require "yajl"
6
7
  require "yaml"
7
8
 
8
9
  ##
9
10
  # Shove
10
11
  #
11
- # See http://shove.io for an account
12
+ # See http://shove.io for an account and client documentation
13
+ # See https://github.com/shove/shover for gem documentation
14
+ # See https://github.com/shove/shove for client documentation
12
15
  module Shove
13
16
 
14
- Version = 0.4
17
+ Version = 0.60
15
18
 
16
19
  class << self
17
20
 
@@ -21,22 +24,16 @@ module Shove
21
24
  # +settings+ the settings for the created client as
22
25
  # a string for a yaml file, or as a hash
23
26
  def configure settings
24
-
25
27
  if settings.kind_of? String
26
28
  self.config = YAML.load_file(settings)
29
+ self.config
27
30
  elsif settings.kind_of? Hash
28
31
  self.config = settings
29
32
  else
30
33
  raise "Unsupported configuration type"
31
34
  end
32
-
33
- # symbolize keys
34
- # self.config = {}
35
- # tmp.each_pair do |k,v|
36
- # self.config[k.to_sym] = v
37
- # end
38
-
39
- self.client = Client.new config[:network], config[:key], config
35
+
36
+ self.client = Client.new(config)
40
37
  end
41
38
 
42
39
  # broadcast a message
@@ -67,18 +64,32 @@ module Shove
67
64
  def validate
68
65
  client.validate
69
66
  end
70
-
67
+
68
+ # fetch the available stream hosts
69
+ # for this network.
70
+ def hosts
71
+ client.hosts
72
+ end
73
+
71
74
  # act as a stream client. requires EM
72
75
  # +channel+ the channel to stream
73
76
  def stream channel, &block
74
77
 
75
78
  unless EM.reactor_running?
76
- raise "You can stream when running in an Eventmachine event loop. EM.run { #code here }"
79
+ puts "You can stream when running in an Eventmachine event loop. EM.run { #code here }"
80
+ exit
77
81
  end
78
82
 
79
- uid = ""
83
+ ## Fetch hosts
84
+ hostnames = hosts
85
+
86
+ if hostnames.empty?
87
+ puts "Error fetching hosts for network #{config[:network]}"
88
+ exit
89
+ end
80
90
 
81
- http = EventMachine::HttpRequest.new("ws://ws.shove.io/#{config[:network]}").get :timeout => 0
91
+ uid = ""
92
+ http = EventMachine::HttpRequest.new("ws://ws-#{hostnames.first}.shove.io/#{config[:network]}").get :timeout => 0
82
93
 
83
94
  http.errback {
84
95
  block.call("Connection Error")
@@ -90,7 +101,7 @@ module Shove
90
101
  }
91
102
 
92
103
  http.stream { |msg|
93
-
104
+
94
105
  parts = msg.split "!"
95
106
 
96
107
  case parts[1]
@@ -100,7 +111,13 @@ module Shove
100
111
  Shove.authorize uid, channel
101
112
  end
102
113
 
103
- block.call(msg)
114
+ block.call({
115
+ :channel => parts[0],
116
+ :event => parts[1],
117
+ :to => parts[2],
118
+ :from => parts[3],
119
+ :data => parts[4]
120
+ })
104
121
  }
105
122
 
106
123
  end
data/shove.gemspec CHANGED
@@ -1,31 +1,23 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = "shove"
3
- s.version = "0.4"
4
- s.date = "2010-12-16"
3
+ s.version = "0.6.0"
4
+ s.date = "2011-07-23"
5
5
  s.summary = "Ruby gem for leveraging shove.io, the web push platform"
6
6
  s.email = "dan@shove.io"
7
7
  s.homepage = "https://github.com/shove/shover"
8
8
  s.description = "Client side implementation for the shove.io API. See http://shove.io/documentation"
9
9
  s.has_rdoc = true
10
10
 
11
- s.add_dependency("em-http-request", ">= 0.3.0")
11
+ s.add_dependency("em-http-request", "= 0.3.0")
12
12
  s.add_dependency("commander", ">= 4.0.3")
13
+ s.add_dependency("yajl-ruby", ">= 0.8.1")
13
14
 
14
15
  s.bindir = "bin"
15
- s.executables = ["shove"]
16
-
16
+
17
17
  s.authors = ["Dan Simpson"]
18
18
 
19
- s.files = [
20
- "README.md",
21
- "shove.gemspec",
22
- "Rakefile",
23
- "spec/helper.rb",
24
- "spec/shove_spec.rb",
25
- "lib/shove.rb",
26
- "lib/shove/request.rb",
27
- "lib/shove/response.rb",
28
- "lib/shove/client.rb",
29
- "bin/shove"
30
- ]
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+
31
23
  end
data/spec/shove_spec.rb CHANGED
@@ -3,7 +3,7 @@ require File.dirname(__FILE__) + "/helper"
3
3
  describe Shove do
4
4
 
5
5
  before do
6
- Shove.configure "./shove.yml"
6
+ Shove.configure "shove.yml"
7
7
  end
8
8
 
9
9
  it "should have a version" do
@@ -11,7 +11,40 @@ describe Shove do
11
11
  end
12
12
 
13
13
  it "should have config" do
14
- Shove.config["network"].should == "shove"
14
+ Shove.config[:network].should == "test"
15
+ end
16
+
17
+ it "should be able to authorize with the server" do
18
+ response = Shove.validate
19
+ response.error?.should == false
20
+ end
21
+
22
+ it "should get a set of hosts for the network" do
23
+ response = Shove.hosts
24
+ response.status.should == 200
25
+ end
26
+
27
+ it "should be able to broadcast a message" do
28
+ Shove.broadcast("default", "event", "test") do |response|
29
+ response.error?.should == false
30
+ end
31
+ end
32
+
33
+ it "should be able to broadcast a message with EM" do
34
+ EM.run do
35
+
36
+ ##
37
+ # Setup stream and capture for validation
38
+ ##
39
+
40
+ Shove.broadcast("default", "event", "test2") do |response|
41
+ response.error?.should == false
42
+ end
43
+
44
+ EM.add_timer(0.2) do
45
+ EM.stop
46
+ end
47
+ end
15
48
  end
16
49
 
17
50
  end
metadata CHANGED
@@ -1,11 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shove
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 4
8
- version: "0.4"
4
+ prerelease:
5
+ version: 0.6.0
9
6
  platform: ruby
10
7
  authors:
11
8
  - Dan Simpson
@@ -13,8 +10,7 @@ autorequire:
13
10
  bindir: bin
14
11
  cert_chain: []
15
12
 
16
- date: 2010-12-16 00:00:00 -08:00
17
- default_executable:
13
+ date: 2011-07-23 00:00:00 Z
18
14
  dependencies:
19
15
  - !ruby/object:Gem::Dependency
20
16
  name: em-http-request
@@ -22,12 +18,8 @@ dependencies:
22
18
  requirement: &id001 !ruby/object:Gem::Requirement
23
19
  none: false
24
20
  requirements:
25
- - - ">="
21
+ - - "="
26
22
  - !ruby/object:Gem::Version
27
- segments:
28
- - 0
29
- - 3
30
- - 0
31
23
  version: 0.3.0
32
24
  type: :runtime
33
25
  version_requirements: *id001
@@ -39,13 +31,20 @@ dependencies:
39
31
  requirements:
40
32
  - - ">="
41
33
  - !ruby/object:Gem::Version
42
- segments:
43
- - 4
44
- - 0
45
- - 3
46
34
  version: 4.0.3
47
35
  type: :runtime
48
36
  version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: yajl-ruby
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: 0.8.1
46
+ type: :runtime
47
+ version_requirements: *id003
49
48
  description: Client side implementation for the shove.io API. See http://shove.io/documentation
50
49
  email: dan@shove.io
51
50
  executables:
@@ -55,17 +54,17 @@ extensions: []
55
54
  extra_rdoc_files: []
56
55
 
57
56
  files:
57
+ - .gitignore
58
58
  - README.md
59
- - shove.gemspec
60
59
  - Rakefile
61
- - spec/helper.rb
62
- - spec/shove_spec.rb
60
+ - bin/shove
63
61
  - lib/shove.rb
62
+ - lib/shove/client.rb
64
63
  - lib/shove/request.rb
65
64
  - lib/shove/response.rb
66
- - lib/shove/client.rb
67
- - bin/shove
68
- has_rdoc: true
65
+ - shove.gemspec
66
+ - spec/helper.rb
67
+ - spec/shove_spec.rb
69
68
  homepage: https://github.com/shove/shover
70
69
  licenses: []
71
70
 
@@ -79,21 +78,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
79
78
  requirements:
80
79
  - - ">="
81
80
  - !ruby/object:Gem::Version
82
- segments:
83
- - 0
84
81
  version: "0"
85
82
  required_rubygems_version: !ruby/object:Gem::Requirement
86
83
  none: false
87
84
  requirements:
88
85
  - - ">="
89
86
  - !ruby/object:Gem::Version
90
- segments:
91
- - 0
92
87
  version: "0"
93
88
  requirements: []
94
89
 
95
90
  rubyforge_project:
96
- rubygems_version: 1.3.7
91
+ rubygems_version: 1.8.3
97
92
  signing_key:
98
93
  specification_version: 3
99
94
  summary: Ruby gem for leveraging shove.io, the web push platform