pubnub 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pubnub might be problematic. Click here for more details.

@@ -1 +1,297 @@
1
- require "pubnub_ruby/pubnub"
1
+ ## www.pubnub.com - PubNub realtime push service in the cloud.
2
+ ## http://www.pubnub.com/blog/ruby-push-api - Ruby Push API Blog
3
+
4
+ ## PubNub Real Time Push APIs and Notifications Framework
5
+ ## Copyright (c) 2010 Stephen Blum
6
+ ## http://www.pubnub.com/
7
+
8
+ ## -----------------------------------
9
+ ## PubNub 3.1 Real-time Push Cloud API
10
+ ## -----------------------------------
11
+
12
+ ## including required libraries
13
+ require 'openssl'
14
+ require 'base64'
15
+ require 'open-uri'
16
+ require 'uri'
17
+ require 'net/http'
18
+ require 'json'
19
+ require 'pp'
20
+ require 'rubygems'
21
+ require 'securerandom'
22
+ require 'digest'
23
+ require 'pubnub_ruby/pubnub_crypto'
24
+ require 'eventmachine'
25
+ require 'em-http'
26
+ require 'fiber'
27
+
28
+ class Pubnub
29
+ MAX_RETRIES = 3
30
+ retries=0
31
+ #**
32
+ #* Pubnub
33
+ #*
34
+ #* Init the Pubnub Client API
35
+ #*
36
+ #* @param string publish_key required key to send messages.
37
+ #* @param string subscribe_key required key to receive messages.
38
+ #* @param string secret_key required key to sign messages.
39
+ #* @param string cipher_key required to encrypt messages.
40
+ #* @param boolean ssl required for 2048 bit encrypted messages.
41
+ #*
42
+ def initialize( publish_key, subscribe_key, secret_key, cipher_key, ssl_on )
43
+ @publish_key = publish_key
44
+ @subscribe_key = subscribe_key
45
+ @secret_key = secret_key
46
+ @cipher_key = cipher_key
47
+ @ssl = ssl_on
48
+ @origin = 'pubsub.pubnub.com'
49
+
50
+ if @ssl
51
+ @origin = 'https://' + @origin
52
+ else
53
+ @origin = 'http://' + @origin
54
+ end
55
+ end
56
+
57
+ #**
58
+ #* Publish
59
+ #*
60
+ #* Send a message to a channel.
61
+ #*
62
+ #* @param array args with channel and message.
63
+ #* @return array success information.
64
+ #*
65
+ def publish(args)
66
+ ## Fail if bad input.
67
+ if !(args['channel'] && args['message'])
68
+ puts('Missing Channel or Message')
69
+ return false
70
+ end
71
+
72
+ ## Capture User Input
73
+ channel = args['channel']
74
+ message = args['message']
75
+
76
+ #encryption of message
77
+ if @cipher_key.length > 0
78
+ pc=PubnubCrypto.new(@cipher_key)
79
+ if message.is_a? Array
80
+ message=pc.encryptArray(message)
81
+ else
82
+ message=pc.encryptObject(message)
83
+ end
84
+ else
85
+ message = args['message'].to_json();
86
+ end
87
+
88
+ ## Sign message using HMAC
89
+ String signature = '0'
90
+ if @secret_key.length > 0
91
+ signature = "{@publish_key,@subscribe_key,@secret_key,channel,message}"
92
+ digest = OpenSSL::Digest.new("sha256")
93
+ key = [ @secret_key ]
94
+ hmac = OpenSSL::HMAC.hexdigest(digest, key.pack("H*"), signature)
95
+ signature = hmac
96
+ end
97
+
98
+ ## Send Message
99
+ return _request([
100
+ 'publish',
101
+ @publish_key,
102
+ @subscribe_key,
103
+ signature,
104
+ channel,
105
+ '0',
106
+ message
107
+ ])
108
+ end
109
+
110
+ #**
111
+ #* Subscribe
112
+ #*
113
+ #* This is NON-BLOCKING.
114
+ #* Listen for a message on a channel.
115
+ #*
116
+ #* @param array args with channel and message.
117
+ #* @return false on fail, array on success.
118
+ #*
119
+ def subscribe(args)
120
+ ## Capture User Input
121
+ channel = args['channel']
122
+ callback = args['callback']
123
+
124
+ ## Fail if missing channel
125
+ if !channel
126
+ puts "Missing Channel."
127
+ return false
128
+ end
129
+
130
+ ## Fail if missing callback
131
+ if !callback
132
+ puts "Missing Callback."
133
+ return false
134
+ end
135
+
136
+ ## Begin Subscribe
137
+ loop do
138
+ begin
139
+ timetoken = args['timetoken'] ? args['timetoken'] : 0
140
+
141
+ ## Wait for Message
142
+ response = _request([
143
+ 'subscribe',
144
+ @subscribe_key,
145
+ channel,
146
+ '0',
147
+ timetoken.to_s
148
+ ])
149
+
150
+ messages = response[0]
151
+ args['timetoken'] = response[1]
152
+
153
+ ## If it was a timeout
154
+ next if !messages.length
155
+
156
+ ## Run user Callback and Reconnect if user permits.
157
+ ## Capture the message and encrypt it
158
+ if @cipher_key.length > 0
159
+ pc = PubnubCrypto.new(@cipher_key)
160
+ messages.each do |message|
161
+ if message.is_a? Array
162
+ message=pc.decryptArray(message)
163
+ else
164
+ message=pc.decryptObject(message)
165
+ end
166
+ if !callback.call(message)
167
+ return
168
+ end
169
+ end
170
+ else
171
+ messages.each do |message|
172
+ if !callback.call(message)
173
+ return
174
+ end
175
+ end
176
+ end
177
+ rescue Timeout::Error
178
+ rescue
179
+ sleep(1)
180
+ end
181
+ end
182
+ end
183
+
184
+ #**
185
+ #* History
186
+ #*
187
+ #* Load history from a channel.
188
+ #*
189
+ #* @param array args with 'channel' and 'limit'.
190
+ #* @return mixed false on fail, array on success.
191
+ #*
192
+ def history(args)
193
+ ## Capture User Input
194
+ limit = +args['limit'] ? +args['limit'] : 5
195
+ channel = args['channel']
196
+
197
+ ## Fail if bad input.
198
+ if (!channel)
199
+ puts 'Missing Channel.'
200
+ return false
201
+ end
202
+
203
+ ## Get History
204
+ response = _request([ 'history', @subscribe_key, channel, '0', limit.to_s])
205
+ if @cipher_key.length > 0
206
+ myarr=Array.new()
207
+ response.each do |message|
208
+ pc=PubnubCrypto.new(@cipher_key)
209
+ if message.is_a? Array
210
+ message=pc.decryptArray(message)
211
+ else
212
+ message=pc.decryptObject(message)
213
+ end
214
+ myarr.push(message)
215
+ end
216
+ return myarr
217
+ else
218
+ return response
219
+ end
220
+ end
221
+
222
+ #**
223
+ #* Time
224
+ #*
225
+ #* Timestamp from PubNub Cloud.
226
+ #*
227
+ #* @return int timestamp.
228
+ #*
229
+ def time()
230
+ return _request([
231
+ 'time',
232
+ '0'
233
+ ])[0]
234
+ end
235
+
236
+ #**
237
+ #* UUID
238
+ #*
239
+ #* Unique identifier generation
240
+ #*
241
+ #* @return Unique Identifier
242
+ #*
243
+ def UUID()
244
+ uuid=SecureRandom.base64(32).gsub("/","_").gsub(/=+$/,"")
245
+ end
246
+
247
+ private
248
+
249
+ #**
250
+ #* Request URL
251
+ #*
252
+ #* @param array request of url directories.
253
+ #* @return array from JSON response.
254
+ #*
255
+ def _request(request)
256
+ ## Construct Request URL
257
+ url = '/' + request.map{ |bit| bit.split('').map{ |ch|
258
+ ' ~`!@#$%^&*()+=[]\\{}|;\':",./<>?'.index(ch) ?
259
+ '%' + ch.unpack('H2')[0].to_s.upcase : URI.encode(ch)
260
+ }.join('') }.join('/')
261
+
262
+ url = @origin + url
263
+ http_response = ''
264
+
265
+ EventMachine.run do
266
+ Fiber.new{
267
+ http = async_fetch(url)
268
+ http_response = http.response
269
+ EventMachine.stop
270
+ }.resume
271
+ end
272
+ JSON.parse(http_response)
273
+ end
274
+
275
+ ## Non-blocking IO using EventMachine
276
+ def async_fetch(url)
277
+ f = Fiber.current
278
+
279
+ request_options = {
280
+ :timeout => 310, # set request timeout
281
+ :query => {'V' => '3.1', 'User-Agent' => 'Ruby', 'Accept-Encoding' => 'gzip'}, # set request headers
282
+ }
283
+
284
+ http = EventMachine::HttpRequest.new(url).get request_options
285
+ http.callback { f.resume(http) }
286
+ http.errback { f.resume(http) }
287
+
288
+ Fiber.yield
289
+
290
+ if http.error
291
+ p [:HTTP_ERROR, http.error]
292
+ end
293
+
294
+ http
295
+ end
296
+
297
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 4
9
- version: 0.1.4
8
+ - 5
9
+ version: 0.1.5
10
10
  platform: ruby
11
11
  authors:
12
12
  - Luke Carpenter / PubNub.com
@@ -71,8 +71,7 @@ files:
71
71
  - examples/subscribe_example.rb
72
72
  - examples/uuid_example.rb
73
73
  - lib/pubnub.rb
74
- - lib/pubnub/pubnub.rb
75
- - lib/pubnub/pubnub_crypto.rb
74
+ - lib/pubnub_crypto.rb
76
75
  - tests/unit_test.rb
77
76
  - README
78
77
  has_rdoc: true
@@ -1,297 +0,0 @@
1
- ## www.pubnub.com - PubNub realtime push service in the cloud.
2
- ## http://www.pubnub.com/blog/ruby-push-api - Ruby Push API Blog
3
-
4
- ## PubNub Real Time Push APIs and Notifications Framework
5
- ## Copyright (c) 2010 Stephen Blum
6
- ## http://www.pubnub.com/
7
-
8
- ## -----------------------------------
9
- ## PubNub 3.1 Real-time Push Cloud API
10
- ## -----------------------------------
11
-
12
- ## including required libraries
13
- require 'openssl'
14
- require 'base64'
15
- require 'open-uri'
16
- require 'uri'
17
- require 'net/http'
18
- require 'json'
19
- require 'pp'
20
- require 'rubygems'
21
- require 'securerandom'
22
- require 'digest'
23
- require 'pubnub_ruby/pubnub_crypto'
24
- require 'eventmachine'
25
- require 'em-http'
26
- require 'fiber'
27
-
28
- class Pubnub
29
- MAX_RETRIES = 3
30
- retries=0
31
- #**
32
- #* Pubnub
33
- #*
34
- #* Init the Pubnub Client API
35
- #*
36
- #* @param string publish_key required key to send messages.
37
- #* @param string subscribe_key required key to receive messages.
38
- #* @param string secret_key required key to sign messages.
39
- #* @param string cipher_key required to encrypt messages.
40
- #* @param boolean ssl required for 2048 bit encrypted messages.
41
- #*
42
- def initialize( publish_key, subscribe_key, secret_key, cipher_key, ssl_on )
43
- @publish_key = publish_key
44
- @subscribe_key = subscribe_key
45
- @secret_key = secret_key
46
- @cipher_key = cipher_key
47
- @ssl = ssl_on
48
- @origin = 'pubsub.pubnub.com'
49
-
50
- if @ssl
51
- @origin = 'https://' + @origin
52
- else
53
- @origin = 'http://' + @origin
54
- end
55
- end
56
-
57
- #**
58
- #* Publish
59
- #*
60
- #* Send a message to a channel.
61
- #*
62
- #* @param array args with channel and message.
63
- #* @return array success information.
64
- #*
65
- def publish(args)
66
- ## Fail if bad input.
67
- if !(args['channel'] && args['message'])
68
- puts('Missing Channel or Message')
69
- return false
70
- end
71
-
72
- ## Capture User Input
73
- channel = args['channel']
74
- message = args['message']
75
-
76
- #encryption of message
77
- if @cipher_key.length > 0
78
- pc=PubnubCrypto.new(@cipher_key)
79
- if message.is_a? Array
80
- message=pc.encryptArray(message)
81
- else
82
- message=pc.encryptObject(message)
83
- end
84
- else
85
- message = args['message'].to_json();
86
- end
87
-
88
- ## Sign message using HMAC
89
- String signature = '0'
90
- if @secret_key.length > 0
91
- signature = "{@publish_key,@subscribe_key,@secret_key,channel,message}"
92
- digest = OpenSSL::Digest.new("sha256")
93
- key = [ @secret_key ]
94
- hmac = OpenSSL::HMAC.hexdigest(digest, key.pack("H*"), signature)
95
- signature = hmac
96
- end
97
-
98
- ## Send Message
99
- return _request([
100
- 'publish',
101
- @publish_key,
102
- @subscribe_key,
103
- signature,
104
- channel,
105
- '0',
106
- message
107
- ])
108
- end
109
-
110
- #**
111
- #* Subscribe
112
- #*
113
- #* This is NON-BLOCKING.
114
- #* Listen for a message on a channel.
115
- #*
116
- #* @param array args with channel and message.
117
- #* @return false on fail, array on success.
118
- #*
119
- def subscribe(args)
120
- ## Capture User Input
121
- channel = args['channel']
122
- callback = args['callback']
123
-
124
- ## Fail if missing channel
125
- if !channel
126
- puts "Missing Channel."
127
- return false
128
- end
129
-
130
- ## Fail if missing callback
131
- if !callback
132
- puts "Missing Callback."
133
- return false
134
- end
135
-
136
- ## Begin Subscribe
137
- loop do
138
- begin
139
- timetoken = args['timetoken'] ? args['timetoken'] : 0
140
-
141
- ## Wait for Message
142
- response = _request([
143
- 'subscribe',
144
- @subscribe_key,
145
- channel,
146
- '0',
147
- timetoken.to_s
148
- ])
149
-
150
- messages = response[0]
151
- args['timetoken'] = response[1]
152
-
153
- ## If it was a timeout
154
- next if !messages.length
155
-
156
- ## Run user Callback and Reconnect if user permits.
157
- ## Capture the message and encrypt it
158
- if @cipher_key.length > 0
159
- pc = PubnubCrypto.new(@cipher_key)
160
- messages.each do |message|
161
- if message.is_a? Array
162
- message=pc.decryptArray(message)
163
- else
164
- message=pc.decryptObject(message)
165
- end
166
- if !callback.call(message)
167
- return
168
- end
169
- end
170
- else
171
- messages.each do |message|
172
- if !callback.call(message)
173
- return
174
- end
175
- end
176
- end
177
- rescue Timeout::Error
178
- rescue
179
- sleep(1)
180
- end
181
- end
182
- end
183
-
184
- #**
185
- #* History
186
- #*
187
- #* Load history from a channel.
188
- #*
189
- #* @param array args with 'channel' and 'limit'.
190
- #* @return mixed false on fail, array on success.
191
- #*
192
- def history(args)
193
- ## Capture User Input
194
- limit = +args['limit'] ? +args['limit'] : 5
195
- channel = args['channel']
196
-
197
- ## Fail if bad input.
198
- if (!channel)
199
- puts 'Missing Channel.'
200
- return false
201
- end
202
-
203
- ## Get History
204
- response = _request([ 'history', @subscribe_key, channel, '0', limit.to_s])
205
- if @cipher_key.length > 0
206
- myarr=Array.new()
207
- response.each do |message|
208
- pc=PubnubCrypto.new(@cipher_key)
209
- if message.is_a? Array
210
- message=pc.decryptArray(message)
211
- else
212
- message=pc.decryptObject(message)
213
- end
214
- myarr.push(message)
215
- end
216
- return myarr
217
- else
218
- return response
219
- end
220
- end
221
-
222
- #**
223
- #* Time
224
- #*
225
- #* Timestamp from PubNub Cloud.
226
- #*
227
- #* @return int timestamp.
228
- #*
229
- def time()
230
- return _request([
231
- 'time',
232
- '0'
233
- ])[0]
234
- end
235
-
236
- #**
237
- #* UUID
238
- #*
239
- #* Unique identifier generation
240
- #*
241
- #* @return Unique Identifier
242
- #*
243
- def UUID()
244
- uuid=SecureRandom.base64(32).gsub("/","_").gsub(/=+$/,"")
245
- end
246
-
247
- private
248
-
249
- #**
250
- #* Request URL
251
- #*
252
- #* @param array request of url directories.
253
- #* @return array from JSON response.
254
- #*
255
- def _request(request)
256
- ## Construct Request URL
257
- url = '/' + request.map{ |bit| bit.split('').map{ |ch|
258
- ' ~`!@#$%^&*()+=[]\\{}|;\':",./<>?'.index(ch) ?
259
- '%' + ch.unpack('H2')[0].to_s.upcase : URI.encode(ch)
260
- }.join('') }.join('/')
261
-
262
- url = @origin + url
263
- http_response = ''
264
-
265
- EventMachine.run do
266
- Fiber.new{
267
- http = async_fetch(url)
268
- http_response = http.response
269
- EventMachine.stop
270
- }.resume
271
- end
272
- JSON.parse(http_response)
273
- end
274
-
275
- ## Non-blocking IO using EventMachine
276
- def async_fetch(url)
277
- f = Fiber.current
278
-
279
- request_options = {
280
- :timeout => 310, # set request timeout
281
- :query => {'V' => '3.1', 'User-Agent' => 'Ruby', 'Accept-Encoding' => 'gzip'}, # set request headers
282
- }
283
-
284
- http = EventMachine::HttpRequest.new(url).get request_options
285
- http.callback { f.resume(http) }
286
- http.errback { f.resume(http) }
287
-
288
- Fiber.yield
289
-
290
- if http.error
291
- p [:HTTP_ERROR, http.error]
292
- end
293
-
294
- http
295
- end
296
-
297
- end