pushmeup 0.1.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MWVmYjczNGEwYjE4ZTkzNGFhOWJlYjE5NDFhNDg2OTk1YjMyYjJhYg==
5
+ data.tar.gz: !binary |-
6
+ OGYyNzFkMzdlZTY1MTM3NWVlMjE0YTEwYThmZWU4ZTE0NTg2ZTllNw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ M2FiNjA1MWQ2YzRiNGI5OGYzNjBlODFjM2NiYzUwY2E3ZjQwYmVlYzZiYWJj
10
+ YTI0MTU0ODU0ZWU4ODBkN2U5YmY0OWU4MmIxNDU0ZjNhNjEzMmMwMzE0ZDdk
11
+ MjA4ZmE4ZWZkODc0NmI3N2M5MTIwNmVlNDM1Y2EwZDQ2ZjYwMzc=
12
+ data.tar.gz: !binary |-
13
+ NTM1YjA1NzhjZWNhMmQzMjAwNmVkM2VjZmQ5MjY1YjA0MGY4MDg5YmE1NjZi
14
+ MDk0Yzk2NTAyZTI3M2U0NTk5NmI4ZDExMzAzOTAwNmEzOGNmNTE4N2QyOTE5
15
+ NTY0ZWFkMTdlZjc0ZDVhMDUyMDg0MDYyMTExYTE2NDk5NTk5MDE=
data/.gitignore CHANGED
@@ -15,3 +15,5 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ NEW_README.md
19
+ .idea/
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ pushmeup
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-1.9.3
data/.travis.yml CHANGED
@@ -1,11 +1,7 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.8.7
4
- - 1.9.2
5
3
  - 1.9.3
6
- - jruby-18mode # JRuby in 1.8 mode
4
+ - 2.0.0
7
5
  - jruby-19mode # JRuby in 1.9 mode
8
- - rbx-18mode
9
- - rbx-19mode
10
6
  # uncomment this line if your project needs to run something other than `rake`:
11
- # script: bundle exec rspec spec
7
+ # script: bundle exec rspec spec
data/README.md CHANGED
@@ -12,7 +12,7 @@ Pushmeup is an attempt to create an push notifications center that could send pu
12
12
  - Windows Phone
13
13
  - And many others
14
14
 
15
- Currently we have only support for ``iOS`` and ``Android`` but we are planning code for more plataforms.
15
+ Currently we have only support for ``iOS``, ``Android`` and ``Kindle Fire`` but we are planning code for more plataforms.
16
16
 
17
17
  ## Installation
18
18
 
@@ -41,14 +41,15 @@ and install it with
41
41
  3. After you have created your ``pem`` file. Set the host, port and certificate file location on the APNS class. You just need to set this once:
42
42
 
43
43
  APNS.host = 'gateway.push.apple.com'
44
- # gateway.sandbox.push.apple.com is default
44
+ # gateway.sandbox.push.apple.com is default and only for development
45
+ # gateway.push.apple.com is only for production
45
46
 
46
47
  APNS.port = 2195
47
48
  # this is also the default. Shouldn't ever have to set this, but just in case Apple goes crazy, you can.
48
-
49
+
49
50
  APNS.pem = '/path/to/pem/file'
50
51
  # this is the file you just created
51
-
52
+
52
53
  APNS.pass = ''
53
54
  # Just in case your pem need a password
54
55
 
@@ -56,25 +57,49 @@ and install it with
56
57
 
57
58
  #### Sending a single notification:
58
59
 
59
- device_token = '123abc456def'
60
- APNS.send_notification(device_token, 'Hello iPhone!' )
61
- APNS.send_notification(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default')
60
+ device_token = '123abc456def'
61
+ APNS.send_notification(device_token, 'Hello iPhone!' )
62
+ APNS.send_notification(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default')
62
63
 
63
64
  #### Sending multiple notifications
64
65
 
65
- device_token = '123abc456def'
66
- n1 = APNS::Notification.new(device_token, 'Hello iPhone!' )
67
- n2 = APNS::Notification.new(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default')
68
- APNS.send_notifications([n1, n2])
66
+ device_token = '123abc456def'
67
+ n1 = APNS::Notification.new(device_token, 'Hello iPhone!' )
68
+ n2 = APNS::Notification.new(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default')
69
+ APNS.send_notifications([n1, n2])
70
+
71
+ > All notifications passed as a parameter will be sent on a single connection, this is done to improve
72
+ > reliability with APNS servers.
73
+
74
+ #### Another way to send multiple notifications is to send notifications in a persistent connection (thread safe)
75
+
76
+ # Define that you want persistent connection
77
+ APNS.start_persistence
78
+
79
+ device_token = '123abc456def'
80
+
81
+ # Send single notifications
82
+ APNS.send_notification(device_token, 'Hello iPhone!' )
83
+ APNS.send_notification(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default')
84
+
85
+ # Send multiple notifications
86
+ n1 = APNS::Notification.new(device_token, 'Hello iPhone!' )
87
+ n2 = APNS::Notification.new(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default')
88
+ APNS.send_notifications([n1, n2])
89
+
90
+ ...
91
+
92
+ # Stop persistence, from this point each new push will open and close connections
93
+ APNS.stop_persistence
69
94
 
70
95
  #### Sending more information along
71
96
 
72
- APNS.send_notification(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default',
73
- :other => {:sent => 'with apns gem', :custom_param => "value"})
97
+ APNS.send_notification(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default',
98
+ :other => {:sent => 'with apns gem', :custom_param => "value"})
74
99
 
75
100
  this will result in a payload like this:
76
101
 
77
- {"aps":{"alert":"Hello iPhone!","badge":1,"sound":"default"},"sent":"with apns gem", "custom_param":"value"}
102
+ {"aps":{"alert":"Hello iPhone!","badge":1,"sound":"default"},"sent":"with apns gem", "custom_param":"value"}
78
103
 
79
104
  ### Getting your iOS device token
80
105
 
@@ -168,29 +193,101 @@ You can use multiple keys to send notifications, to do it just do this changes i
168
193
  # For single notification
169
194
  GCM.send_notification( destination, :identity => :key1 )
170
195
  # Empty notification
171
-
196
+
172
197
  GCM.send_notification( destination, data, :identity => :key1 )
173
198
  # Notification with custom information
174
-
199
+
175
200
  GCM.send_notification( destination, data, :collapse_key => "placar_score_global", :time_to_live => 3600, :delay_while_idle => false, :identity => :key1 )
176
201
  # Notification with custom information and parameters
177
-
202
+
178
203
  # For multiple notifications
179
204
  options1 = {}
180
205
  options2 = {..., :identity => :key2}
181
206
  n1 = GCM::Notification.new(destination1, data1, options1.merge({:identity => :key2}))
182
207
  n2 = GCM::Notification.new(destination2, data2, :identity => :key1)
183
208
  n3 = GCM::Notification.new(destination3, data3, options2)
184
-
209
+
185
210
  GCM.send_notifications( [n1, n2, n3] )
186
211
  # In this case, every notification has his own parameters, options and key
187
212
 
188
- ## Build Status [![Build Status](https://secure.travis-ci.org/NicosKaralis/pushmeup.png?branch=master)](http://travis-ci.org/NicosKaralis/pushmeup) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/NicosKaralis/pushmeup)
213
+ ## FIRE (Amazon Messaging)
214
+
215
+ ### Configure
216
+
217
+ FIRE.client_id = "amzn1.application-oa2-client.12345678sdfgsdfg"
218
+ # this is the Client ID obtained from your Security Profile Management on amazon developers
219
+
220
+ FIRE.client_secret = "fkgjsbegksklwr863485245ojowe345"
221
+ # this is the Client Secret obtained from your Security Profile Management on amazon developers
222
+
223
+ ### Usage
224
+
225
+ #### Sending a single notification:
226
+
227
+ destination = "tydgfhewgnwe37586329586ejthe93053th346hrth3t"
228
+ # can be an string or an array of strings containing the regId of the device you want to send
229
+
230
+ data = {:key => "value", :key2 => "some value2"}
231
+ # must be an hash with all values you want inside you notification, strings only, no arrays
232
+
233
+ FIRE.send_notification( destination )
234
+ # Empty notification
235
+
236
+ FIRE.send_notification( destination, data )
237
+ # Notification with custom information
238
+
239
+ FIRE.send_notification( destination, data, :consolidationKey => "placar_score_global", :expiresAfter => 3600)
240
+ # Notification with custom information and parameters
241
+
242
+ for more information on parameters check documentation: [Amazon Messaging | Developers](https://developer.amazon.com/public/apis/engage/device-messaging/tech-docs/06-sending-a-message#Request Format)
243
+
244
+ #### Sending multiple notifications:
245
+
246
+ destination1 = "device1"
247
+ destination2 = ["device2"]
248
+ destination3 = ["device1", "device2", "device3"]
249
+ # can be an string or an array of strings containing the regIds of the devices you want to send
250
+
251
+ data1 = {:key => "value", :key2 => ["array", "value"]}
252
+ # must be an hash with all values you want inside you notification
253
+
254
+ options1 = {:consolidationKey => "placar_score_global", :expiresAfter => 3600}
255
+ # options for the notification
256
+
257
+ n1 = FIRE::Notification.new(destination1, data1, options1)
258
+ n2 = FIRE::Notification.new(destination2, data2)
259
+ n3 = FIRE::Notification.new(destination3, data3, options2)
260
+
261
+ FIRE.send_notifications( [n1, n2, n3] )
262
+ # In this case, every notification has his own parameters
263
+
264
+ for more information on parameters check documentation: [Amazon Messaging | Developers](https://developer.amazon.com/public/apis/engage/device-messaging/tech-docs/06-sending-a-message#Request Format)
265
+
266
+ #### Getting your Kindle Fire device token (regId)
267
+
268
+ Check this link [Amazon Messaging: Getting Started](https://developer.amazon.com/public/apis/engage/device-messaging)
269
+
189
270
 
190
- ## Dependency Status [![Dependency Status](https://gemnasium.com/NicosKaralis/pushmeup.png?travis)](https://gemnasium.com/NicosKaralis/pushmeup)
271
+ ## Status
272
+
273
+ #### Build Status
274
+ [![Build Status](https://travis-ci.org/NicosKaralis/pushmeup.png?branch=master)](https://travis-ci.org/NicosKaralis/pushmeup)
275
+ [![Code Climate](https://codeclimate.com/github/NicosKaralis/pushmeup.png)](https://codeclimate.com/github/NicosKaralis/pushmeup)
276
+
277
+ #### Dependency Status [![Dependency Status](https://gemnasium.com/NicosKaralis/pushmeup.png?travis)](https://gemnasium.com/NicosKaralis/pushmeup)
278
+
279
+ ## Contributing
280
+
281
+ We would be very pleased if you want to help us!
282
+
283
+ Currently we need a lot of testing so if you are good at writing tests please help us
191
284
 
192
285
  ## License
193
286
 
194
287
  Pushmeup is released under the MIT license:
195
288
 
196
289
  http://www.opensource.org/licenses/MIT
290
+
291
+
292
+ [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/NicosKaralis/pushmeup/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
293
+
data/Rakefile CHANGED
@@ -5,4 +5,9 @@ require "rspec/core/rake_task"
5
5
  RSpec::Core::RakeTask.new
6
6
 
7
7
  task :default => :spec
8
- task :test => :spec
8
+ task :test => :spec
9
+
10
+ desc "Open an irb session preloaded with this library"
11
+ task :console do
12
+ sh "irb -rubygems -I lib -r pushmeup.rb"
13
+ end
@@ -0,0 +1,2 @@
1
+ require "pushmeup/fire/core"
2
+ require "pushmeup/fire/notification"
@@ -10,36 +10,52 @@ module APNS
10
10
  @pem = nil # this should be the path of the pem file not the contentes
11
11
  @pass = nil
12
12
 
13
+ @persistent = false
14
+ @mutex = Mutex.new
15
+ @retries = 3 # TODO: check if we really need this
16
+
17
+ @sock = nil
18
+ @ssl = nil
19
+
13
20
  class << self
14
21
  attr_accessor :host, :pem, :port, :pass
15
22
  end
16
23
 
24
+ def self.start_persistence
25
+ @persistent = true
26
+ end
27
+
28
+ def self.stop_persistence
29
+ @persistent = false
30
+
31
+ @ssl.close
32
+ @sock.close
33
+ end
34
+
17
35
  def self.send_notification(device_token, message)
18
36
  n = APNS::Notification.new(device_token, message)
19
37
  self.send_notifications([n])
20
38
  end
21
39
 
22
40
  def self.send_notifications(notifications)
23
- sock, ssl = self.open_connection
24
-
25
- notifications.each do |n|
26
- ssl.write(n.packaged_notification)
41
+ @mutex.synchronize do
42
+ self.with_connection do
43
+ notifications.each do |n|
44
+ @ssl.write(n.packaged_notification)
45
+ end
46
+ end
27
47
  end
28
-
29
- ssl.close
30
- sock.close
31
48
  end
32
49
 
33
50
  def self.feedback
34
- raise "Not implemented yet"
35
51
  sock, ssl = self.feedback_connection
36
52
 
37
53
  apns_feedback = []
38
54
 
39
- while line = sock.gets # Read lines from the socket
55
+ while line = ssl.read(38) # Read lines from the socket
40
56
  line.strip!
41
57
  f = line.unpack('N1n1H140')
42
- apns_feedback << [Time.at(f[0]), f[2]]
58
+ apns_feedback << { :timestamp => Time.at(f[0]), :token => f[2] }
43
59
  end
44
60
 
45
61
  ssl.close
@@ -48,8 +64,38 @@ module APNS
48
64
  return apns_feedback
49
65
  end
50
66
 
51
- protected
52
-
67
+ protected
68
+
69
+ def self.with_connection
70
+ attempts = 1
71
+
72
+ begin
73
+ # If no @ssl is created or if @ssl is closed we need to start it
74
+ if @ssl.nil? || @sock.nil? || @ssl.closed? || @sock.closed?
75
+ @sock, @ssl = self.open_connection
76
+ end
77
+
78
+ yield
79
+
80
+ rescue StandardError, Errno::EPIPE
81
+ raise unless attempts < @retries
82
+
83
+ @ssl.close
84
+ @sock.close
85
+
86
+ attempts += 1
87
+ retry
88
+ end
89
+
90
+ # Only force close if not persistent
91
+ unless @persistent
92
+ @ssl.close
93
+ @ssl = nil
94
+ @sock.close
95
+ @sock = nil
96
+ end
97
+ end
98
+
53
99
  def self.open_connection
54
100
  raise "The path to your pem file is not set. (APNS.pem = /path/to/cert.pem)" unless self.pem
55
101
  raise "The path to your pem file does not exist!" unless File.exist?(self.pem)
@@ -74,13 +120,12 @@ module APNS
74
120
  context.key = OpenSSL::PKey::RSA.new(File.read(self.pem), self.pass)
75
121
 
76
122
  fhost = self.host.gsub('gateway','feedback')
77
- puts fhost
78
123
 
79
124
  sock = TCPSocket.new(fhost, 2196)
80
- ssl = OpenSSL::SSL::SSLSocket.new(sock,context)
125
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, context)
81
126
  ssl.connect
82
127
 
83
128
  return sock, ssl
84
129
  end
85
130
 
86
- end
131
+ end
@@ -1,7 +1,7 @@
1
1
  module APNS
2
2
  class Notification
3
3
  attr_accessor :device_token, :alert, :badge, :sound, :other
4
-
4
+
5
5
  def initialize(device_token, message)
6
6
  self.device_token = device_token
7
7
  if message.is_a?(Hash)
@@ -12,28 +12,36 @@ module APNS
12
12
  elsif message.is_a?(String)
13
13
  self.alert = message
14
14
  else
15
- raise "Notification needs to have either a hash or string"
15
+ raise "Notification needs to have either a Hash or String"
16
16
  end
17
17
  end
18
-
18
+
19
19
  def packaged_notification
20
20
  pt = self.packaged_token
21
21
  pm = self.packaged_message
22
22
  [0, 0, 32, pt, 0, pm.bytesize, pm].pack("ccca*cca*")
23
23
  end
24
-
24
+
25
25
  def packaged_token
26
26
  [device_token.gsub(/[\s|<|>]/,'')].pack('H*')
27
27
  end
28
-
28
+
29
29
  def packaged_message
30
30
  aps = {'aps'=> {} }
31
31
  aps['aps']['alert'] = self.alert if self.alert
32
32
  aps['aps']['badge'] = self.badge if self.badge
33
33
  aps['aps']['sound'] = self.sound if self.sound
34
34
  aps.merge!(self.other) if self.other
35
- aps.to_json
35
+ aps.to_json.gsub(/\\u([\da-fA-F]{4})/) {|m| [$1].pack("H*").unpack("n*").pack("U*")}
36
36
  end
37
-
37
+
38
+ def ==(that)
39
+ device_token == that.device_token &&
40
+ alert == that.alert &&
41
+ badge == that.badge &&
42
+ sound == that.sound &&
43
+ other == that.other
44
+ end
45
+
38
46
  end
39
- end
47
+ end
@@ -0,0 +1,103 @@
1
+ require 'httparty'
2
+ # require 'cgi'
3
+ require 'json'
4
+
5
+ module FIRE
6
+ include HTTParty
7
+
8
+ @host = 'https://api.amazon.com/messaging/registrations/%s/messages'
9
+ @client_id = nil
10
+ @client_secret = nil
11
+
12
+ @access_token_expiration = Time.new(0)
13
+ @access_token = nil
14
+
15
+ class << self
16
+ attr_accessor :host, :client_id, :client_secret, :access_token, :access_token_expiration
17
+ end
18
+
19
+ def self.send_notification(device_token, data = {}, options = {})
20
+ n = FIRE::Notification.new(device_token, data, options)
21
+ self.send_notifications([n])
22
+ end
23
+
24
+ def self.send_notifications(notifications)
25
+ self.prepare_token
26
+ responses = []
27
+ notifications.each do |n|
28
+ responses << self.prepare_and_send(n)
29
+ end
30
+ responses
31
+ end
32
+
33
+ def self.prepare_token
34
+ return if Time.now < self.access_token_expiration
35
+
36
+ token = self.get_access_token
37
+ self.access_token = token['access_token']
38
+ expires_in_sec = token['expires_in']
39
+ self.access_token_expiration = Time.now + expires_in_sec - 60
40
+ end
41
+
42
+ def self.get_access_token
43
+ headers = {'Content-Type' => 'application/x-www-form-urlencoded'}
44
+ body = {grant_type: 'client_credentials',
45
+ scope: 'messaging:push',
46
+ client_id: self.client_id,
47
+ client_secret: self.client_secret
48
+ }
49
+ params = {headers: headers, body: body}
50
+ res = self.post('https://api.amazon.com/auth/O2/token', params)
51
+ return res.parsed_response if res.response.code.to_i == 200
52
+ raise 'Error getting access token'
53
+ end
54
+
55
+ private
56
+
57
+ def self.prepare_and_send(n)
58
+ if !n.consolidationKey.nil? && n.expiresAfter.nil?
59
+ raise %q{If you are defining a "colapse key" you need a "time to live"}
60
+ end
61
+ self.send_push(n)
62
+ end
63
+
64
+ def self.send_push(n)
65
+ headers = {
66
+ 'Authorization' => "Bearer #{self.access_token}",
67
+ 'Content-Type' => 'application/json',
68
+ 'Accept' => 'application/json',
69
+ 'X-Amzn-Accept-Type' => 'com.amazon.device.messaging.ADMSendResult@1.0',
70
+ 'X-Amzn-Type-Version' => 'com.amazon.device.messaging.ADMMessage@1.0'
71
+ }
72
+
73
+ body = {
74
+ :data => n.data
75
+ }
76
+ body.merge!({consolidationKey: n.consolidationKey}) if n.consolidationKey
77
+ body.merge!({expiresAfter: n.expiresAfter}) if n.expiresAfter
78
+ return self.send_to_server(headers, body.to_json, n.device_token)
79
+ end
80
+
81
+ def self.send_to_server(headers, body, token)
82
+ params = {:headers => headers, :body => body}
83
+ device_dest = self.host % [token]
84
+ response = self.post(device_dest, params)
85
+ return build_response(response)
86
+ end
87
+
88
+ def self.build_response(response)
89
+ case response.code
90
+ when 200
91
+ {:response => 'success', :body => JSON.parse(response.body), :headers => response.headers, :status_code => response.code}
92
+ when 400
93
+ {:response => response.parsed_response, :status_code => response.code}
94
+ when 401
95
+ {:response => 'There was an error authenticating the sender account.', :status_code => response.code}
96
+ when 500
97
+ {:response => 'There was an internal error in the Amazaon server while trying to process the request.', :status_code => response.code}
98
+ when 503
99
+ {:response => 'Server is temporarily unavailable.', :status_code => response.code}
100
+ end
101
+ end
102
+
103
+ end
@@ -0,0 +1,46 @@
1
+ module FIRE
2
+ class Notification
3
+ attr_accessor :device_token, :data, :consolidationKey, :expiresAfter
4
+
5
+ def initialize(token, data, options = {})
6
+ self.device_token = token
7
+ self.data = data
8
+
9
+ @consolidationKey = options[:consolidationKey]
10
+ @expiresAfter = options[:expiresAfter]
11
+ end
12
+
13
+ def device_token=(token)
14
+
15
+ if token.is_a?(String)
16
+ @device_token = token
17
+ else
18
+ raise "device_token needs to be String"
19
+ end
20
+ end
21
+
22
+ def data=(data)
23
+ if data.is_a?(Hash)
24
+ @data = data
25
+ else
26
+ raise "data parameter must be the type of Hash"
27
+ end
28
+ end
29
+
30
+ def expiresAfter=(expiresAfter)
31
+ if expiresAfter.is_a?(Integer)
32
+ @expiresAfter = expiresAfter
33
+ else
34
+ raise %q{"expiresAfter" must be seconds as an integer value, like "100"}
35
+ end
36
+ end
37
+
38
+ def ==(that)
39
+ device_token == that.device_token &&
40
+ data == that.data &&
41
+ consolidationKey == that.consolidationKey &&
42
+ expiresAfter == that.expiresAfter
43
+ end
44
+
45
+ end
46
+ end
@@ -4,14 +4,14 @@ require 'json'
4
4
 
5
5
  module GCM
6
6
  include HTTParty
7
-
7
+
8
8
  @host = 'https://android.googleapis.com/gcm/send'
9
9
  @format = :json
10
10
  @key = nil
11
11
 
12
12
  class << self
13
13
  attr_accessor :host, :format, :key
14
-
14
+
15
15
  def key(identity = nil)
16
16
  if @key.is_a?(Hash)
17
17
  raise %{If your key is a hash of keys you'l need to pass a identifier to the notification!} if identity.nil?
@@ -20,13 +20,21 @@ module GCM
20
20
  return @key
21
21
  end
22
22
  end
23
+
24
+ def key_identities
25
+ if @key.is_a?(Hash)
26
+ return @key.keys
27
+ else
28
+ return nil
29
+ end
30
+ end
23
31
  end
24
-
32
+
25
33
  def self.send_notification(device_tokens, data = {}, options = {})
26
34
  n = GCM::Notification.new(device_tokens, data, options)
27
35
  self.send_notifications([n])
28
36
  end
29
-
37
+
30
38
  def self.send_notifications(notifications)
31
39
  responses = []
32
40
  notifications.each do |n|
@@ -36,7 +44,7 @@ module GCM
36
44
  end
37
45
 
38
46
  private
39
-
47
+
40
48
  def self.prepare_and_send(n)
41
49
  if n.device_tokens.count < 1 || n.device_tokens.count > 1000
42
50
  raise "Number of device_tokens invalid, keep it betwen 1 and 1000"
@@ -47,7 +55,7 @@ module GCM
47
55
  if @key.is_a?(Hash) && n.identity.nil?
48
56
  raise %{If your key is a hash of keys you'l need to pass a identifier to the notification!}
49
57
  end
50
-
58
+
51
59
  if self.format == :json
52
60
  self.send_push_as_json(n)
53
61
  elsif self.format == :text
@@ -56,7 +64,7 @@ module GCM
56
64
  raise "Invalid format"
57
65
  end
58
66
  end
59
-
67
+
60
68
  def self.send_push_as_json(n)
61
69
  headers = {
62
70
  'Authorization' => "key=#{ self.key(n.identity) }",
@@ -71,7 +79,7 @@ module GCM
71
79
  }
72
80
  return self.send_to_server(headers, body.to_json)
73
81
  end
74
-
82
+
75
83
  def self.send_push_as_plain_text(n)
76
84
  raise "Still has to be done: http://developer.android.com/guide/google/gcm/gcm.html"
77
85
  headers = {
@@ -81,13 +89,13 @@ module GCM
81
89
  }
82
90
  return self.send_to_server(headers, body)
83
91
  end
84
-
92
+
85
93
  def self.send_to_server(headers, body)
86
94
  params = {:headers => headers, :body => body}
87
- response = self.post('https://android.googleapis.com/gcm/send', params)
95
+ response = self.post(self.host, params)
88
96
  return build_response(response)
89
97
  end
90
-
98
+
91
99
  def self.build_response(response)
92
100
  case response.code
93
101
  when 200
@@ -102,5 +110,5 @@ module GCM
102
110
  {:response => 'Server is temporarily unavailable.', :status_code => response.code}
103
111
  end
104
112
  end
105
-
113
+
106
114
  end
@@ -1,39 +1,39 @@
1
1
  module GCM
2
2
  class Notification
3
3
  attr_accessor :device_tokens, :data, :collapse_key, :time_to_live, :delay_while_idle, :identity
4
-
4
+
5
5
  def initialize(tokens, data, options = {})
6
6
  self.device_tokens = tokens
7
7
  self.data = data
8
-
8
+
9
9
  @collapse_key = options[:collapse_key]
10
10
  @time_to_live = options[:time_to_live]
11
11
  @delay_while_idle = options[:delay_while_idle]
12
12
  @identity = options[:identity]
13
13
  end
14
-
14
+
15
15
  def device_tokens=(tokens)
16
16
  if tokens.is_a?(Array)
17
17
  @device_tokens = tokens
18
18
  elsif tokens.is_a?(String)
19
19
  @device_tokens = [tokens]
20
20
  else
21
- raise "device_tokens needs to be either a hash or string"
21
+ raise "device_tokens needs to be either a Hash or String"
22
22
  end
23
23
  end
24
-
24
+
25
25
  def data=(data)
26
26
  if data.is_a?(Hash)
27
27
  @data = data
28
28
  else
29
- raise "data parameter must be the tpe of Hash"
29
+ raise "data parameter must be the type of Hash"
30
30
  end
31
31
  end
32
-
32
+
33
33
  def delay_while_idle=(delay_while_idle)
34
34
  @delay_while_idle = (delay_while_idle == true || delay_while_idle == :true)
35
35
  end
36
-
36
+
37
37
  def time_to_live=(time_to_live)
38
38
  if time_to_live.is_a?(Integer)
39
39
  @time_to_live = time_to_live
@@ -41,6 +41,15 @@ module GCM
41
41
  raise %q{"time_to_live" must be seconds as an integer value, like "100"}
42
42
  end
43
43
  end
44
-
44
+
45
+ def ==(that)
46
+ device_tokens == that.device_tokens &&
47
+ data == that.data &&
48
+ collapse_key == that.collapse_key &&
49
+ time_to_live == that.time_to_live &&
50
+ delay_while_idle == that.delay_while_idle &&
51
+ identity == that.identity
52
+ end
53
+
45
54
  end
46
- end
55
+ end
@@ -1,3 +1,3 @@
1
1
  module Pushmeup
2
- VERSION = "0.1.2"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/pushmeup.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  require "pushmeup/version"
2
2
  require "pushmeup/apple"
3
3
  require "pushmeup/android"
4
+ require "pushmeup/amazon"
@@ -5,23 +5,37 @@ describe Pushmeup do
5
5
  it "should have a APNS object" do
6
6
  defined?(APNS).should_not be_false
7
7
  end
8
-
8
+
9
9
  it "should not forget the APNS default parameters" do
10
10
  APNS.host.should == "gateway.sandbox.push.apple.com"
11
11
  APNS.port.should == 2195
12
12
  APNS.pem.should be_equal(nil)
13
13
  APNS.pass.should be_equal(nil)
14
14
  end
15
-
15
+
16
+ describe "Notifications" do
17
+
18
+ describe "#==" do
19
+
20
+ it "should properly equate objects without caring about object identity" do
21
+ a = APNS::Notification.new("123", {:alert => "hi"})
22
+ b = APNS::Notification.new("123", {:alert => "hi"})
23
+ a.should eq(b)
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+
16
30
  end
17
-
31
+
18
32
  describe "GCM" do
19
33
  it "should have a GCM object" do
20
34
  defined?(GCM).should_not be_false
21
35
  end
22
-
36
+
23
37
  describe "Notifications" do
24
-
38
+
25
39
  before do
26
40
  @options = {:data => "dummy data"}
27
41
  end
@@ -38,20 +52,30 @@ describe Pushmeup do
38
52
  end
39
53
 
40
54
  it "should allow only notifications with data as hash with :data root" do
41
- n = GCM::Notification.new("id", {:data => "data"})
42
-
55
+ n = GCM::Notification.new("id", { :data => "data" })
56
+
43
57
  n.data.is_a?(Hash).should be_true
44
58
  n.data.should == {:data => "data"}
45
59
 
46
60
  n.data = {:a => ["a", "b", "c"]}
47
61
  n.data.is_a?(Hash).should be_true
48
62
  n.data.should == {:a => ["a", "b", "c"]}
49
-
63
+
50
64
  n.data = {:a => "a"}
51
65
  n.data.is_a?(Hash).should be_true
52
66
  n.data.should == {:a => "a"}
53
67
  end
54
-
68
+
69
+ describe "#==" do
70
+
71
+ it "should properly equate objects without caring about object identity" do
72
+ a = GCM::Notification.new("id", { :data => "data" })
73
+ b = GCM::Notification.new("id", { :data => "data" })
74
+ a.should eq(b)
75
+ end
76
+
77
+ end
78
+
55
79
  end
56
80
  end
57
81
  end
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pushmeup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
5
- prerelease:
4
+ version: 0.3.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Nicos Karalis
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-11-14 00:00:00.000000000 Z
11
+ date: 2014-07-26 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: httparty
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ! '>='
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ! '>='
28
25
  - !ruby/object:Gem::Version
@@ -30,7 +27,6 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: json
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ! '>='
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ! '>='
44
39
  - !ruby/object:Gem::Version
@@ -46,7 +41,6 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: rake
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - ! '>='
52
46
  - !ruby/object:Gem::Version
@@ -54,7 +48,6 @@ dependencies:
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
52
  - - ! '>='
60
53
  - !ruby/object:Gem::Version
@@ -62,7 +55,6 @@ dependencies:
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: rspec
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
59
  - - ! '>='
68
60
  - !ruby/object:Gem::Version
@@ -70,7 +62,6 @@ dependencies:
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
66
  - - ! '>='
76
67
  - !ruby/object:Gem::Version
@@ -88,7 +79,8 @@ extensions: []
88
79
  extra_rdoc_files: []
89
80
  files:
90
81
  - .gitignore
91
- - .rvmrc
82
+ - .ruby-gemset
83
+ - .ruby-version
92
84
  - .travis.yml
93
85
  - Gemfile
94
86
  - Keychain Access.jpg
@@ -96,10 +88,13 @@ files:
96
88
  - README.md
97
89
  - Rakefile
98
90
  - lib/pushmeup.rb
91
+ - lib/pushmeup/amazon.rb
99
92
  - lib/pushmeup/android.rb
100
93
  - lib/pushmeup/apns/core.rb
101
94
  - lib/pushmeup/apns/notification.rb
102
95
  - lib/pushmeup/apple.rb
96
+ - lib/pushmeup/fire/core.rb
97
+ - lib/pushmeup/fire/notification.rb
103
98
  - lib/pushmeup/gcm/core.rb
104
99
  - lib/pushmeup/gcm/notification.rb
105
100
  - lib/pushmeup/version.rb
@@ -108,33 +103,26 @@ files:
108
103
  - spec/spec_helper.rb
109
104
  homepage: https://github.com/NicosKaralis/pushmeup
110
105
  licenses: []
106
+ metadata: {}
111
107
  post_install_message:
112
108
  rdoc_options: []
113
109
  require_paths:
114
110
  - lib
115
111
  required_ruby_version: !ruby/object:Gem::Requirement
116
- none: false
117
112
  requirements:
118
113
  - - ! '>='
119
114
  - !ruby/object:Gem::Version
120
115
  version: '0'
121
- segments:
122
- - 0
123
- hash: -2951185572715016947
124
116
  required_rubygems_version: !ruby/object:Gem::Requirement
125
- none: false
126
117
  requirements:
127
118
  - - ! '>='
128
119
  - !ruby/object:Gem::Version
129
120
  version: '0'
130
- segments:
131
- - 0
132
- hash: -2951185572715016947
133
121
  requirements: []
134
122
  rubyforge_project: pushmeup
135
- rubygems_version: 1.8.24
123
+ rubygems_version: 2.2.2
136
124
  signing_key:
137
- specification_version: 3
125
+ specification_version: 4
138
126
  summary: Send push notifications to Apple devices through ANPS and Android devices
139
127
  through GCM
140
128
  test_files:
data/.rvmrc DELETED
@@ -1,48 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
- # development environment upon cd'ing into the directory
5
-
6
- # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
7
- # Only full ruby name is supported here, for short names use:
8
- # echo "rvm use 1.9.3" > .rvmrc
9
- environment_id="ruby-1.9.3-p125@pushmeup"
10
-
11
- # Uncomment the following lines if you want to verify rvm version per project
12
- # rvmrc_rvm_version="1.11.5 (master)" # 1.10.1 seams as a safe start
13
- # eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
14
- # echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
15
- # return 1
16
- # }
17
-
18
- # First we attempt to load the desired environment directly from the environment
19
- # file. This is very fast and efficient compared to running through the entire
20
- # CLI and selector. If you want feedback on which environment was used then
21
- # insert the word 'use' after --create as this triggers verbose mode.
22
- if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
23
- && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
24
- then
25
- \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
26
- [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
27
- \. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
28
- else
29
- # If the environment file has not yet been created, use the RVM CLI to select.
30
- rvm --create "$environment_id" || {
31
- echo "Failed to create RVM environment '${environment_id}'."
32
- return 1
33
- }
34
- fi
35
-
36
- # If you use bundler, this might be useful to you:
37
- if [[ -s Gemfile ]] && {
38
- ! builtin command -v bundle >/dev/null ||
39
- builtin command -v bundle | grep $rvm_path/bin/bundle >/dev/null
40
- }
41
- then
42
- printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
43
- gem install bundler
44
- fi
45
- if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
46
- then
47
- bundle install | grep -vE '^Using|Your bundle is complete'
48
- fi