pusher-client-nc 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +31 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +103 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/examples/subscribe.rb +31 -0
- data/examples/subscribe_async.rb +18 -0
- data/lib/pusher-client.rb +26 -0
- data/lib/pusher-client/channel.rb +53 -0
- data/lib/pusher-client/channels.rb +37 -0
- data/lib/pusher-client/socket.rb +202 -0
- data/lib/pusher-client/subscription.rb +54 -0
- data/lib/pusher-client/subscriptions.rb +46 -0
- data/lib/pusher-client/websocket.rb +62 -0
- data/pusher-client-nc.gemspec +85 -0
- data/pusher-client.gemspec +84 -0
- data/test/pusherclient_test.rb +246 -0
- data/test/test.watchr +63 -0
- data/test/teststrap.rb +69 -0
- metadata +194 -0
data/.document
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
addressable (2.2.8)
|
5
|
+
bacon (1.1.0)
|
6
|
+
git (1.2.5)
|
7
|
+
jeweler (1.5.2)
|
8
|
+
bundler (~> 1.0.0)
|
9
|
+
git (>= 1.2.5)
|
10
|
+
rake
|
11
|
+
json (1.4.6)
|
12
|
+
json (1.4.6-java)
|
13
|
+
libwebsocket (0.1.3)
|
14
|
+
addressable
|
15
|
+
rake (0.8.7)
|
16
|
+
rcov (0.9.9)
|
17
|
+
rcov (0.9.9-java)
|
18
|
+
ruby-hmac (0.4.0)
|
19
|
+
|
20
|
+
PLATFORMS
|
21
|
+
java
|
22
|
+
ruby
|
23
|
+
|
24
|
+
DEPENDENCIES
|
25
|
+
bacon
|
26
|
+
bundler (~> 1.0.0)
|
27
|
+
jeweler (~> 1.5.2)
|
28
|
+
json
|
29
|
+
libwebsocket (~> 0.1.3)
|
30
|
+
rcov
|
31
|
+
ruby-hmac
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Logan Koester
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
= pusher-client (Ruby)
|
2
|
+
|
3
|
+
pusher-client is a ruby gem for consuming WebSockets from the Pusher[http://pusherapp.com] web service.
|
4
|
+
|
5
|
+
The connection to Pusher can optionally be maintained in its own thread (see Asynchronous Usage).
|
6
|
+
|
7
|
+
This gem is compatible with jruby since 0.2.
|
8
|
+
|
9
|
+
== Installation
|
10
|
+
|
11
|
+
gem install pusher-client
|
12
|
+
|
13
|
+
== Single-Threaded Usage
|
14
|
+
|
15
|
+
The application will pause at socket.connect and handle events from Pusher as they happen.
|
16
|
+
|
17
|
+
require 'pusher-client'
|
18
|
+
|
19
|
+
PusherClient.logger = Logger.new(STDOUT)
|
20
|
+
options = {:secret => YOUR_APP_SECRET}
|
21
|
+
socket = PusherClient::Socket.new(YOUR_APP_KEY, options)
|
22
|
+
|
23
|
+
# Subscribe to a public channel
|
24
|
+
socket.subscribe('channel')
|
25
|
+
|
26
|
+
# Subscribe to an authenticated channel
|
27
|
+
socket.subscribe('presence-channel', 'user_id')
|
28
|
+
|
29
|
+
# Subscribe to an authenticated channel with optional :user_info
|
30
|
+
socket.subscribe('presence-channel', 'user_id', { :name => 'name' })
|
31
|
+
|
32
|
+
# Subscribe to array of channels
|
33
|
+
['channel1', 'channel2'].each do |c|
|
34
|
+
socket.subscribe("presence-#{c}", 'user_id')
|
35
|
+
end
|
36
|
+
|
37
|
+
# Bind to global events (a catch-all for any 'event' across subscribed channels)
|
38
|
+
socket.bind('event') do |data|
|
39
|
+
puts data
|
40
|
+
end
|
41
|
+
|
42
|
+
# Bind to events that occur on a specific channel
|
43
|
+
socket['channel'].bind('event') do |data|
|
44
|
+
puts data
|
45
|
+
end
|
46
|
+
|
47
|
+
socket.connect
|
48
|
+
|
49
|
+
== Asynchronous Usage
|
50
|
+
|
51
|
+
The socket will remain open in the background as long as your main application thread is running,
|
52
|
+
and you can continue to subscribe/unsubscribe to channels and bind new events.
|
53
|
+
|
54
|
+
require 'pusher-client'
|
55
|
+
|
56
|
+
PusherClient.logger = Logger.new(STDOUT)
|
57
|
+
options = {:secret => YOUR_APP_SECRET}
|
58
|
+
socket = PusherClient::Socket.new(YOUR_APP_KEY, options)
|
59
|
+
socket.connect(true) # Connect asynchronously
|
60
|
+
|
61
|
+
# Subscribe to a channel
|
62
|
+
socket.subscribe('channel')
|
63
|
+
|
64
|
+
# Bind to a global event
|
65
|
+
socket.bind('event') do |data|
|
66
|
+
puts data
|
67
|
+
end
|
68
|
+
|
69
|
+
loop do
|
70
|
+
sleep(1) # Keep your main thread running
|
71
|
+
end
|
72
|
+
|
73
|
+
For further documentation, read the source & test suite. Some features of the JavaScript client
|
74
|
+
are not yet implemented.
|
75
|
+
|
76
|
+
== Gotchas
|
77
|
+
|
78
|
+
When binding to a global event, note that you still must be subscribed to the channels the event
|
79
|
+
may be sent on. You can't just bind a global event without subscribing to any channels and call it a day.
|
80
|
+
|
81
|
+
== Contributing to pusher-client
|
82
|
+
|
83
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
84
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
85
|
+
* Fork the project
|
86
|
+
* Start a feature/bugfix branch
|
87
|
+
* Commit and push until you are happy with your contribution
|
88
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
89
|
+
* 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.
|
90
|
+
|
91
|
+
== TODOs
|
92
|
+
|
93
|
+
* Implement Channel instances associated with Subscription instances.
|
94
|
+
* Remove Subscriptions#find_for_bind workaround for lack of Channel instances
|
95
|
+
* Remove the duplication between Socket#subscribe and #subscribe_existing
|
96
|
+
* Test Socket.rb bind('pusher:connection_disconnected')
|
97
|
+
* Identify subscriptions on :channel and :user_id (rather than :user_data).
|
98
|
+
|
99
|
+
== Copyright
|
100
|
+
|
101
|
+
Copyright (c) 2010 Logan Koester. See LICENSE.txt for
|
102
|
+
further details.
|
103
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |gem|
|
14
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
+
gem.name = "pusher-client-nc"
|
16
|
+
gem.homepage = "http://github.com/logankoester/pusher-client"
|
17
|
+
gem.license = "MIT"
|
18
|
+
gem.summary = %Q{Ruby client for consuming WebSockets from http://pusherapp.com}
|
19
|
+
gem.description = %Q{Ruby client for consuming WebSockets from http://pusherapp.com}
|
20
|
+
gem.email = "support@nur.ph"
|
21
|
+
gem.authors = ["Logan Koester, Neil Cauldwell"]
|
22
|
+
end
|
23
|
+
Jeweler::RubygemsDotOrgTasks.new
|
24
|
+
|
25
|
+
require 'rake/testtask'
|
26
|
+
Rake::TestTask.new(:test) do |test|
|
27
|
+
test.libs << 'lib' << 'test'
|
28
|
+
test.pattern = 'test/**/*_test.rb'
|
29
|
+
test.verbose = true
|
30
|
+
end
|
31
|
+
|
32
|
+
require 'rcov/rcovtask'
|
33
|
+
Rcov::RcovTask.new do |test|
|
34
|
+
test.libs << 'test'
|
35
|
+
test.pattern = 'test/**/*_test.rb'
|
36
|
+
test.verbose = true
|
37
|
+
end
|
38
|
+
|
39
|
+
task :default => :test
|
40
|
+
|
41
|
+
require 'rake/rdoctask'
|
42
|
+
Rake::RDocTask.new do |rdoc|
|
43
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
44
|
+
|
45
|
+
rdoc.rdoc_dir = 'rdoc'
|
46
|
+
rdoc.title = "pusher-client #{version}"
|
47
|
+
rdoc.rdoc_files.include('README*')
|
48
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
49
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.1
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'pusher-client'
|
2
|
+
|
3
|
+
PusherClient.logger = Logger.new(STDOUT)
|
4
|
+
options = {:secret => YOUR_APP_SECRET}
|
5
|
+
socket = PusherClient::Socket.new(YOUR_APP_KEY, options)
|
6
|
+
|
7
|
+
# Subscribe to a public channel
|
8
|
+
socket.subscribe('channel')
|
9
|
+
|
10
|
+
# Subscribe to an authenticated channel (presence or private)
|
11
|
+
socket.subscribe('presence-channel', 'user_id')
|
12
|
+
|
13
|
+
# Subscribe to an authenticated channel with optional :user_info
|
14
|
+
socket.subscribe('presence-channel', 'user_id', { :name => 'name' })
|
15
|
+
|
16
|
+
# Subscribe to array of channels
|
17
|
+
['channel1', 'channel2'].each do |c|
|
18
|
+
socket.subscribe("presence-#{c}", 'user_id')
|
19
|
+
end
|
20
|
+
|
21
|
+
# Bind to global events (a catch-all for any 'event' across subscribed channels)
|
22
|
+
socket.bind('event') do |data|
|
23
|
+
puts data
|
24
|
+
end
|
25
|
+
|
26
|
+
# Bind to events that occur on a specific channel
|
27
|
+
socket['channel'].bind('event') do |data|
|
28
|
+
puts data
|
29
|
+
end
|
30
|
+
|
31
|
+
socket.connect
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'pusher-client'
|
2
|
+
|
3
|
+
PusherClient.logger = Logger.new(STDOUT)
|
4
|
+
options = {:secret => YOUR_APP_SECRET}
|
5
|
+
socket = PusherClient::Socket.new(YOUR_APP_KEY, options)
|
6
|
+
socket.connect(true) # Connect asynchronously
|
7
|
+
|
8
|
+
# Subscribe to a channel
|
9
|
+
socket.subscribe('channel')
|
10
|
+
|
11
|
+
# Bind to a global event
|
12
|
+
socket.bind('event') do |data|
|
13
|
+
puts data
|
14
|
+
end
|
15
|
+
|
16
|
+
loop do
|
17
|
+
sleep(1) # Keep your main thread running
|
18
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
autoload :Logger, 'logger'
|
2
|
+
|
3
|
+
module PusherClient
|
4
|
+
HOST = 'ws.pusherapp.com'
|
5
|
+
WS_PORT = 80
|
6
|
+
WSS_PORT = 443
|
7
|
+
|
8
|
+
@logger = Logger.new(STDOUT)
|
9
|
+
|
10
|
+
def self.logger
|
11
|
+
@logger
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.logger=(logger)
|
15
|
+
@logger = logger
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Thread.abort_on_exception = true
|
20
|
+
|
21
|
+
require File.dirname(__FILE__) + '/pusher-client/websocket.rb'
|
22
|
+
require File.dirname(__FILE__) + '/pusher-client/socket.rb'
|
23
|
+
require File.dirname(__FILE__) + '/pusher-client/channel.rb'
|
24
|
+
require File.dirname(__FILE__) + '/pusher-client/channels.rb'
|
25
|
+
require File.dirname(__FILE__) + '/pusher-client/subscription.rb'
|
26
|
+
require File.dirname(__FILE__) + '/pusher-client/subscriptions.rb'
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module PusherClient
|
2
|
+
class Channel
|
3
|
+
attr_accessor :global, :subscribed
|
4
|
+
attr_reader :name, :callbacks, :global_callbacks
|
5
|
+
|
6
|
+
def initialize(channel_name)
|
7
|
+
@name = channel_name
|
8
|
+
@global = false
|
9
|
+
@callbacks = {}
|
10
|
+
@global_callbacks = {}
|
11
|
+
@subscribed = false
|
12
|
+
end
|
13
|
+
|
14
|
+
def bind(event_name, &callback)
|
15
|
+
@callbacks[event_name] = callbacks[event_name] || []
|
16
|
+
@callbacks[event_name] << callback
|
17
|
+
return self
|
18
|
+
end
|
19
|
+
|
20
|
+
def dispatch_with_all(event_name, data)
|
21
|
+
dispatch(event_name, data)
|
22
|
+
dispatch_global_callbacks(event_name, data)
|
23
|
+
end
|
24
|
+
|
25
|
+
def dispatch(event_name, data)
|
26
|
+
PusherClient.logger.debug "Dispatching callbacks for #{event_name}"
|
27
|
+
if @callbacks[event_name]
|
28
|
+
@callbacks[event_name].each do |callback|
|
29
|
+
callback.call(data)
|
30
|
+
end
|
31
|
+
else
|
32
|
+
PusherClient.logger.debug "No callbacks to dispatch for #{event_name}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def dispatch_global_callbacks(event_name, data)
|
37
|
+
if @global_callbacks[event_name]
|
38
|
+
PusherClient.logger.debug "Dispatching global callbacks for #{event_name}"
|
39
|
+
@global_callbacks[event_name].each do |callback|
|
40
|
+
callback.call(data)
|
41
|
+
end
|
42
|
+
else
|
43
|
+
PusherClient.logger.debug "No global callbacks to dispatch for #{event_name}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def acknowledge_subscription(data)
|
48
|
+
@subscribed = true
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module PusherClient
|
2
|
+
class Channels
|
3
|
+
attr_reader :channels
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@channels = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def add(channel_name)
|
10
|
+
unless @channels[channel_name]
|
11
|
+
@channels[channel_name] = Channel.new(channel_name)
|
12
|
+
end
|
13
|
+
@channels[channel_name]
|
14
|
+
end
|
15
|
+
|
16
|
+
def find(channel_name)
|
17
|
+
@channels[channel_name]
|
18
|
+
end
|
19
|
+
|
20
|
+
def remove(channel_name)
|
21
|
+
@channels.delete(channel_name)
|
22
|
+
@channels
|
23
|
+
end
|
24
|
+
|
25
|
+
def empty?
|
26
|
+
@channels.empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
def size
|
30
|
+
@channels.size
|
31
|
+
end
|
32
|
+
|
33
|
+
alias :<< :add
|
34
|
+
alias :[] :find
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'hmac-sha2'
|
3
|
+
require 'digest/md5'
|
4
|
+
|
5
|
+
module PusherClient
|
6
|
+
class Socket
|
7
|
+
|
8
|
+
# Mimick the JavaScript client
|
9
|
+
CLIENT_ID = 'js'
|
10
|
+
VERSION = '1.7.1'
|
11
|
+
|
12
|
+
attr_accessor :encrypted, :secure
|
13
|
+
attr_reader :path, :connected, :subscriptions, :global_channel, :socket_id
|
14
|
+
|
15
|
+
def initialize(application_key, options={})
|
16
|
+
raise ArgumentError if (!application_key.is_a?(String) || application_key.size < 1)
|
17
|
+
|
18
|
+
@path = "/app/#{application_key}?client=#{CLIENT_ID}&version=#{VERSION}"
|
19
|
+
@key = application_key
|
20
|
+
@secret = options[:secret]
|
21
|
+
@socket_id = nil
|
22
|
+
@subscriptions = Subscriptions.new
|
23
|
+
@global_channel = Channel.new('pusher_global_channel')
|
24
|
+
@global_channel.global = true
|
25
|
+
@secure = false
|
26
|
+
@connected = false
|
27
|
+
@encrypted = options[:encrypted] || false
|
28
|
+
|
29
|
+
bind('pusher:connection_established') do |data|
|
30
|
+
socket = JSON.parse(data)
|
31
|
+
@connected = true
|
32
|
+
@socket_id = socket['socket_id']
|
33
|
+
subscribe_all
|
34
|
+
end
|
35
|
+
|
36
|
+
bind('pusher:connection_disconnected') do |data|
|
37
|
+
@subscriptions.subscriptions.each { |s| s.disconnect }
|
38
|
+
end
|
39
|
+
|
40
|
+
bind('pusher:error') do |data|
|
41
|
+
PusherClient.logger.fatal("Pusher : error : #{data.inspect}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def connect(async = false)
|
46
|
+
if @encrypted || @secure
|
47
|
+
url = "wss://#{HOST}:#{WSS_PORT}#{@path}"
|
48
|
+
else
|
49
|
+
url = "ws://#{HOST}:#{WS_PORT}#{@path}"
|
50
|
+
end
|
51
|
+
PusherClient.logger.debug("Pusher : connecting : #{url}")
|
52
|
+
|
53
|
+
@connection_thread = Thread.new {
|
54
|
+
@connection = WebSocket.new(url)
|
55
|
+
PusherClient.logger.debug "Websocket connected"
|
56
|
+
loop do
|
57
|
+
msg = @connection.receive[0]
|
58
|
+
params = parser(msg)
|
59
|
+
next if (params['socket_id'] && params['socket_id'] == self.socket_id)
|
60
|
+
event_name = params['event']
|
61
|
+
event_data = params['data']
|
62
|
+
channel_name = params['channel']
|
63
|
+
send_local_event(event_name, event_data, channel_name)
|
64
|
+
end
|
65
|
+
}
|
66
|
+
|
67
|
+
@connection_thread.run
|
68
|
+
@connection_thread.join unless async
|
69
|
+
return self
|
70
|
+
end
|
71
|
+
|
72
|
+
def disconnect
|
73
|
+
if @connected
|
74
|
+
PusherClient.logger.debug "Pusher : disconnecting"
|
75
|
+
@connection.close
|
76
|
+
@connection_thread.kill if @connection_thread
|
77
|
+
@connected = false
|
78
|
+
else
|
79
|
+
PusherClient.logger.warn "Disconnect attempted... not connected"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def subscribe(channel_name, user_id = nil, options={})
|
84
|
+
if user_id
|
85
|
+
user_data = {:user_id => user_id, :user_info => options}.to_json
|
86
|
+
else
|
87
|
+
user_data = {:user_id => '', :user_info => ''}.to_json
|
88
|
+
end
|
89
|
+
|
90
|
+
subscription = @subscriptions.add(channel_name, user_data)
|
91
|
+
if @connected
|
92
|
+
authorize(subscription, method(:authorize_callback))
|
93
|
+
end
|
94
|
+
return subscription
|
95
|
+
end
|
96
|
+
|
97
|
+
def subscribe_existing(subscription)
|
98
|
+
if @connected
|
99
|
+
authorize(subscription, method(:authorize_callback))
|
100
|
+
end
|
101
|
+
return subscription
|
102
|
+
end
|
103
|
+
|
104
|
+
def subscribe_all
|
105
|
+
@subscriptions.subscriptions.each{ |s| subscribe_existing(s) }
|
106
|
+
end
|
107
|
+
|
108
|
+
def unsubscribe(channel_name, user_data)
|
109
|
+
subscription = @subscriptions.remove(channel_name, user_data)
|
110
|
+
if @connected
|
111
|
+
send_event('pusher:unsubscribe', {
|
112
|
+
'channel' => channel_name
|
113
|
+
})
|
114
|
+
end
|
115
|
+
return subscription
|
116
|
+
end
|
117
|
+
|
118
|
+
def bind(event_name, &callback)
|
119
|
+
@global_channel.bind(event_name, &callback)
|
120
|
+
return self
|
121
|
+
end
|
122
|
+
|
123
|
+
def [](channel_name)
|
124
|
+
if @subscriptions[channel_name]
|
125
|
+
@subscriptions[channel_name]
|
126
|
+
else
|
127
|
+
@subscriptions << channel_name
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def authorize(subscription, callback)
|
132
|
+
if is_private_channel(subscription)
|
133
|
+
auth_data = get_private_auth(subscription)
|
134
|
+
elsif is_presence_channel(subscription)
|
135
|
+
auth_data = get_presence_auth(subscription)
|
136
|
+
end
|
137
|
+
callback.call(subscription, auth_data)
|
138
|
+
end
|
139
|
+
|
140
|
+
def authorize_callback(subscription, auth_data)
|
141
|
+
send_event('pusher:subscribe', {
|
142
|
+
'channel' => subscription.channel,
|
143
|
+
'auth' => auth_data,
|
144
|
+
'channel_data' => subscription.user_data
|
145
|
+
})
|
146
|
+
subscription.acknowledge_subscription(nil)
|
147
|
+
end
|
148
|
+
|
149
|
+
def is_private_channel(subscription)
|
150
|
+
subscription.channel.match(/^private-/)
|
151
|
+
end
|
152
|
+
|
153
|
+
def is_presence_channel(subscription)
|
154
|
+
subscription.channel.match(/^presence-/)
|
155
|
+
end
|
156
|
+
|
157
|
+
def get_private_auth(subscription)
|
158
|
+
string_to_sign = @socket_id + ':' + subscription.channel + ':' + subscription.user_data
|
159
|
+
signature = HMAC::SHA256.hexdigest(@secret, string_to_sign)
|
160
|
+
return "#{@key}:#{signature}"
|
161
|
+
end
|
162
|
+
|
163
|
+
def get_presence_auth(subscription)
|
164
|
+
string_to_sign = @socket_id + ':' + subscription.channel + ':' + subscription.user_data
|
165
|
+
signature = HMAC::SHA256.hexdigest(@secret, string_to_sign)
|
166
|
+
return "#{@key}:#{signature}"
|
167
|
+
end
|
168
|
+
|
169
|
+
# For compatibility with JavaScript client API
|
170
|
+
alias :subscribeAll :subscribe_all
|
171
|
+
|
172
|
+
def send_event(event_name, data)
|
173
|
+
payload = {'event' => event_name, 'data' => data}.to_json
|
174
|
+
@connection.send(payload)
|
175
|
+
PusherClient.logger.debug("Pusher : sending event : #{payload}")
|
176
|
+
end
|
177
|
+
|
178
|
+
protected
|
179
|
+
|
180
|
+
def send_local_event(event_name, event_data, channel_name)
|
181
|
+
if (channel_name)
|
182
|
+
subs = @subscriptions.find_all(channel_name)
|
183
|
+
if (subs)
|
184
|
+
subs.each {|s| s.dispatch_with_all(event_name, event_data)}
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
@global_channel.dispatch_with_all(event_name, event_data)
|
189
|
+
PusherClient.logger.debug("Pusher : event received : channel: #{channel_name}; event: #{event_name}")
|
190
|
+
end
|
191
|
+
|
192
|
+
def parser(data)
|
193
|
+
begin
|
194
|
+
return JSON.parse(data)
|
195
|
+
rescue => err
|
196
|
+
PusherClient.logger.warn(err)
|
197
|
+
PusherClient.logger.warn("Pusher : data attribute not valid JSON - you may wish to implement your own Pusher::Client.parser")
|
198
|
+
return data
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|