shove 0.4 → 0.6.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.
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