notify_user 0.0.28 → 0.0.29
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.
- checksums.yaml +4 -4
- data/README.md +9 -0
- data/app/mailers/notify_user/notification_mailer.rb +6 -2
- data/app/models/notify_user/apn_connection.rb +41 -0
- data/app/models/notify_user/apns.rb +18 -27
- data/app/models/notify_user/base_notification.rb +42 -64
- data/app/models/notify_user/houston.rb +98 -0
- data/app/models/notify_user/urban_airship.rb +33 -0
- data/lib/generators/notify_user/install/templates/initializer.rb +13 -0
- data/lib/notify_user.rb +16 -0
- data/lib/notify_user/channels/apns/apns_channel.rb +15 -12
- data/lib/notify_user/version.rb +1 -1
- data/spec/dummy/rails-3.2.17/Gemfile +38 -0
- data/spec/dummy/rails-3.2.17/README.rdoc +261 -0
- data/spec/dummy/rails-3.2.17/Rakefile +7 -0
- data/spec/dummy/rails-3.2.17/app/assets/images/rails.png +0 -0
- data/spec/dummy/rails-3.2.17/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/rails-3.2.17/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/rails-3.2.17/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/rails-3.2.17/app/controllers/notify_user/notifications_controller.rb +9 -0
- data/spec/dummy/rails-3.2.17/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/rails-3.2.17/app/models/user.rb +3 -0
- data/spec/dummy/rails-3.2.17/app/notifications/new_post_notification.rb +11 -0
- data/spec/dummy/rails-3.2.17/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/rails-3.2.17/app/views/notify_user/layouts/action_mailer.html.erb +39 -0
- data/spec/dummy/rails-3.2.17/app/views/notify_user/new_post_notification/action_mailer/notification.html.erb +1 -0
- data/spec/dummy/rails-3.2.17/app/views/notify_user/new_post_notification/mobile_sdk/notification.html.erb +1 -0
- data/spec/dummy/rails-3.2.17/config.ru +4 -0
- data/spec/dummy/rails-3.2.17/config/application.rb +62 -0
- data/spec/dummy/rails-3.2.17/config/boot.rb +6 -0
- data/spec/dummy/rails-3.2.17/config/database.yml +24 -0
- data/spec/dummy/rails-3.2.17/config/environment.rb +5 -0
- data/spec/dummy/rails-3.2.17/config/environments/development.rb +37 -0
- data/spec/dummy/rails-3.2.17/config/environments/production.rb +67 -0
- data/spec/dummy/rails-3.2.17/config/environments/test.rb +37 -0
- data/spec/dummy/rails-3.2.17/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/rails-3.2.17/config/initializers/inflections.rb +15 -0
- data/spec/dummy/rails-3.2.17/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/rails-3.2.17/config/initializers/notify_user.rb +14 -0
- data/spec/dummy/rails-3.2.17/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/rails-3.2.17/config/initializers/session_store.rb +8 -0
- data/spec/dummy/rails-3.2.17/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/rails-3.2.17/config/locales/en.yml +5 -0
- data/spec/dummy/rails-3.2.17/config/routes.rb +58 -0
- data/spec/dummy/rails-3.2.17/db/migrate/20150106040852_create_users.rb +9 -0
- data/spec/dummy/rails-3.2.17/db/migrate/20150106040854857857604000_create_notify_user_notifications.rb +13 -0
- data/spec/dummy/rails-3.2.17/db/migrate/20150106040854860860323000_create_notify_user_unsubscribes.rb +10 -0
- data/spec/dummy/rails-3.2.17/db/migrate/20150106040854862862248000_create_notify_user_user_hashes.rb +12 -0
- data/spec/dummy/rails-3.2.17/db/schema.rb +50 -0
- data/spec/dummy/rails-3.2.17/db/seeds.rb +7 -0
- data/spec/dummy/rails-3.2.17/doc/README_FOR_APP +2 -0
- data/spec/dummy/rails-3.2.17/log/test.log +933 -0
- data/spec/dummy/rails-3.2.17/public/404.html +26 -0
- data/spec/dummy/rails-3.2.17/public/422.html +26 -0
- data/spec/dummy/rails-3.2.17/public/500.html +25 -0
- data/spec/dummy/rails-3.2.17/public/favicon.ico +0 -0
- data/spec/dummy/rails-3.2.17/public/index.html +241 -0
- data/spec/dummy/rails-3.2.17/public/robots.txt +5 -0
- data/spec/dummy/rails-3.2.17/script/rails +6 -0
- data/spec/dummy/rails-3.2.17/test/fixtures/users.yml +7 -0
- data/spec/dummy/rails-3.2.17/test/performance/browsing_test.rb +12 -0
- data/spec/dummy/rails-3.2.17/test/test_helper.rb +13 -0
- data/spec/dummy/rails-3.2.17/test/unit/user_test.rb +7 -0
- data/spec/dummy/rails-4.0.4/log/test.log +38719 -0
- data/spec/models/notify_user/houston_spec.rb +33 -0
- data/spec/models/notify_user/notification_spec.rb +62 -96
- metadata +151 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0a577a48ef571d2031ff5df80e68446265b7c4f1
|
|
4
|
+
data.tar.gz: 007bc887cd900949443af637df989638d61b46ae
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1e8be63dd0b8d2fa14de7ccbfbe7a927b521b3d086ff9ef344116b48170c6e68e37d9bfae0fbe95d01061d9f698c5e88fb06f6d1543ce9e2a0b2ecefb8777058
|
|
7
|
+
data.tar.gz: 0e98eb7957dd725d95d8750429cd06bf38f01a4d558adcdbcab02265768124b8cfe93028b581de64e551e2c13c9dedde4772f1f19bce19c0e04f8ec662fbfd12
|
data/README.md
CHANGED
|
@@ -22,6 +22,15 @@ Then send:
|
|
|
22
22
|
```
|
|
23
23
|
NotifyUser.send_notification('new_my_property').to(user).with("listing_address" => "123 Main St").notify
|
|
24
24
|
```
|
|
25
|
+
Dynamic email titles use %{tags} that correspond to your params hash (Will throw an exception if key is missing)
|
|
26
|
+
```
|
|
27
|
+
channel :action_mailer,
|
|
28
|
+
subject: "%{name} sent you a message",
|
|
29
|
+
aggregate: {
|
|
30
|
+
subject: "%{name} sent you %{count} messages"
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
25
34
|
|
|
26
35
|
To enable APNS add this line to your app/notification/notification_type.rb
|
|
27
36
|
```
|
|
@@ -8,7 +8,7 @@ module NotifyUser
|
|
|
8
8
|
@notification = notification
|
|
9
9
|
|
|
10
10
|
mail to: notification.target.email,
|
|
11
|
-
subject: options[:subject],
|
|
11
|
+
subject: subject(notification, options[:subject]),
|
|
12
12
|
template_name: "notification",
|
|
13
13
|
template_path: "notify_user/action_mailer",
|
|
14
14
|
from: NotifyUser.mailer_sender
|
|
@@ -21,10 +21,14 @@ module NotifyUser
|
|
|
21
21
|
mail to: @notifications.first.target.email,
|
|
22
22
|
template_name: "aggregate_notification",
|
|
23
23
|
template_path: ["notify_user/#{notifications.first.class.name.underscore}/action_mailer", "notify_user/action_mailer"],
|
|
24
|
-
subject: options[:aggregate][:subject],
|
|
24
|
+
subject: subject(@notification, options[:aggregate][:subject]),
|
|
25
25
|
from: NotifyUser.mailer_sender
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
def subject(notification, subject)
|
|
29
|
+
subject % notification.params.symbolize_keys
|
|
30
|
+
end
|
|
31
|
+
|
|
28
32
|
protected
|
|
29
33
|
end
|
|
30
34
|
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module NotifyUser
|
|
2
|
+
class APNConnection
|
|
3
|
+
|
|
4
|
+
attr_accessor :connection
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
setup
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def setup
|
|
11
|
+
@uri, @certificate = if Rails.env.production? || apn_environment == :production
|
|
12
|
+
[
|
|
13
|
+
::Houston::APPLE_PRODUCTION_GATEWAY_URI,
|
|
14
|
+
File.read("#{Rails.root}/config/keys/production_push.pem")
|
|
15
|
+
]
|
|
16
|
+
else
|
|
17
|
+
[
|
|
18
|
+
::Houston::APPLE_DEVELOPMENT_GATEWAY_URI,
|
|
19
|
+
File.read("#{Rails.root}/config/keys/development_push.pem")
|
|
20
|
+
]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
@connection = ::Houston::Connection.new(@uri, @certificate, nil)
|
|
24
|
+
@connection.open
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def write(data)
|
|
28
|
+
raise "Connection is closed" unless @connection.open?
|
|
29
|
+
@connection.write(data)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def apn_environment
|
|
35
|
+
return nil unless ENV['APN_ENVIRONMENT']
|
|
36
|
+
|
|
37
|
+
ENV['APN_ENVIRONMENT'].downcase.to_sym
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -1,37 +1,28 @@
|
|
|
1
1
|
module NotifyUser
|
|
2
2
|
class Apns
|
|
3
|
-
SYMBOL_NAMES_SIZE = 10
|
|
3
|
+
SYMBOL_NAMES_SIZE = 10
|
|
4
4
|
PAYLOAD_LIMIT = 255
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
def initialize(notification, options)
|
|
7
|
+
@notification = notification
|
|
8
|
+
@options = options
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Sends push notification:
|
|
12
|
+
def push
|
|
13
|
+
raise "Base APNS class should not be used."
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
# Calculates the bytes already used:
|
|
19
|
+
def used_space
|
|
20
|
+
used_space = SYMBOL_NAMES_SIZE + @notification.id.size + @notification.created_at.to_time.to_i.size +
|
|
21
|
+
@notification.type.size
|
|
15
22
|
|
|
16
|
-
|
|
17
|
-
:alias => notification.target_id,
|
|
18
|
-
:aps => {alert: notification.mobile_message(space_allowance), badge: notification.count_for_target},
|
|
19
|
-
:n_data => {
|
|
20
|
-
'#' => notification.id,
|
|
21
|
-
t: notification.created_at.to_time.to_i,
|
|
22
|
-
'?' => notification.type
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
payload[:n_data]['!'] = notification.params[:action_id] if notification.params[:action_id]
|
|
23
|
+
used_space += @notification.params[:action_id].size if @notification.params[:action_id]
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
if response.success?
|
|
29
|
-
Rails.logger.info "Push notification sent successfully."
|
|
30
|
-
return true
|
|
31
|
-
else
|
|
32
|
-
Rails.logger.info "Push notification failed."
|
|
33
|
-
return false
|
|
34
|
-
end
|
|
25
|
+
used_space
|
|
35
26
|
end
|
|
36
27
|
end
|
|
37
28
|
end
|
|
@@ -7,6 +7,9 @@ module NotifyUser
|
|
|
7
7
|
include ActionView::Helpers::TextHelper
|
|
8
8
|
include AASM
|
|
9
9
|
|
|
10
|
+
after_commit :deliver!, on: :create
|
|
11
|
+
after_commit :deliver, on: :create
|
|
12
|
+
|
|
10
13
|
if ActiveRecord::VERSION::MAJOR < 4
|
|
11
14
|
attr_accessible :params, :target, :type, :state
|
|
12
15
|
end
|
|
@@ -32,6 +35,9 @@ module NotifyUser
|
|
|
32
35
|
# Created, not sent yet. Possibly waiting for aggregation.
|
|
33
36
|
state :pending, initial: true
|
|
34
37
|
|
|
38
|
+
# Delivers without aggregation
|
|
39
|
+
state :pending_no_aggregation
|
|
40
|
+
|
|
35
41
|
# Email/SMS/APNS has been sent.
|
|
36
42
|
state :sent
|
|
37
43
|
|
|
@@ -40,7 +46,11 @@ module NotifyUser
|
|
|
40
46
|
|
|
41
47
|
# Record that we have sent message(s) to the user about this notification.
|
|
42
48
|
event :mark_as_sent do
|
|
43
|
-
transitions from: :pending, to: :sent
|
|
49
|
+
transitions from: [:pending, :pending_no_aggregation], to: :sent
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
event :dont_aggregate do
|
|
53
|
+
transitions from: :pending, to: :pending_no_aggregation
|
|
44
54
|
end
|
|
45
55
|
|
|
46
56
|
# Record that the user has seen this notification, usually on a page or in the app.
|
|
@@ -59,6 +69,7 @@ module NotifyUser
|
|
|
59
69
|
end
|
|
60
70
|
end
|
|
61
71
|
|
|
72
|
+
# returns the global unread notification count for a user
|
|
62
73
|
def count_for_target
|
|
63
74
|
NotifyUser::BaseNotification.for_target(target).where('state IN (?)', ["sent", "pending"]).count
|
|
64
75
|
end
|
|
@@ -92,30 +103,14 @@ module NotifyUser
|
|
|
92
103
|
end
|
|
93
104
|
|
|
94
105
|
def notify!
|
|
95
|
-
save
|
|
96
|
-
|
|
97
106
|
# Bang version of 'notify' ignores aggregation
|
|
98
|
-
|
|
107
|
+
dont_aggregate!
|
|
99
108
|
end
|
|
100
109
|
|
|
101
110
|
# Send any Emails/SMS/APNS
|
|
102
111
|
def notify
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
#if aggregation is false bypass aggregation completely
|
|
107
|
-
self.channels.each do |channel_name, options|
|
|
108
|
-
if(options[:aggregate_per] == false)
|
|
109
|
-
self.class.delay.deliver_notification_channel(self.id, channel_name)
|
|
110
|
-
else
|
|
111
|
-
if not aggregation_pending?
|
|
112
|
-
self.class.delay_for(options[:aggregate_per] || self.aggregate_per).notify_aggregated_channel(self.id, channel_name)
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
end
|
|
118
|
-
|
|
112
|
+
# Sends with aggregation if enabled
|
|
113
|
+
save
|
|
119
114
|
end
|
|
120
115
|
|
|
121
116
|
def generate_unsubscribe_hash
|
|
@@ -172,32 +167,37 @@ module NotifyUser
|
|
|
172
167
|
return (self.class.pending_aggregation_with(self).where('id != ?', id).count > 0)
|
|
173
168
|
end
|
|
174
169
|
|
|
175
|
-
#
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
170
|
+
# Aggregates appropriately
|
|
171
|
+
def deliver
|
|
172
|
+
if pending? and not user_has_unsubscribed?
|
|
173
|
+
self.mark_as_sent!
|
|
179
174
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
175
|
+
# if aggregation is false bypass aggregation completely
|
|
176
|
+
self.channels.each do |channel_name, options|
|
|
177
|
+
if(options[:aggregate_per] == false)
|
|
178
|
+
self.class.delay.deliver_notification_channel(self.id, channel_name)
|
|
179
|
+
else
|
|
180
|
+
# only notifies channels if no pending aggreagte notifications
|
|
181
|
+
if not aggregation_pending?
|
|
182
|
+
self.class.delay_for(options[:aggregate_per] || self.aggregate_per).notify_aggregated_channel(self.id, channel_name)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
183
188
|
|
|
189
|
+
# Sends immediately and without aggregation
|
|
184
190
|
def deliver!
|
|
185
|
-
|
|
186
|
-
self.mark_as_sent
|
|
187
|
-
self.save
|
|
191
|
+
if pending_no_aggregation? and not user_has_unsubscribed?
|
|
192
|
+
self.mark_as_sent!
|
|
188
193
|
self.class.deliver_channels(self.id)
|
|
189
194
|
end
|
|
190
195
|
end
|
|
191
196
|
|
|
192
197
|
# Deliver a single notification across each channel.
|
|
193
198
|
def self.deliver_channels(notification_id)
|
|
194
|
-
notification = self.where(id: notification_id).first
|
|
195
|
-
return unless notification
|
|
196
199
|
self.channels.each do |channel_name, options|
|
|
197
|
-
|
|
198
|
-
channel = (channel_name.to_s + "_channel").camelize.constantize
|
|
199
|
-
channel.deliver(notification, options)
|
|
200
|
-
end
|
|
200
|
+
self.deliver_notification_channel(notification_id, channel_name)
|
|
201
201
|
end
|
|
202
202
|
end
|
|
203
203
|
|
|
@@ -215,11 +215,11 @@ module NotifyUser
|
|
|
215
215
|
|
|
216
216
|
# Deliver a single notification to a specific channel.
|
|
217
217
|
def self.deliver_notification_channel(notification_id, channel_name)
|
|
218
|
-
notification = self.
|
|
219
|
-
return unless notification
|
|
220
|
-
channel_options = channels[channel_name.to_sym]
|
|
218
|
+
notification = self.find(notification_id) # Raise an exception if not found.
|
|
221
219
|
|
|
220
|
+
channel_options = channels[channel_name.to_sym]
|
|
222
221
|
channel = (channel_name.to_s + "_channel").camelize.constantize
|
|
222
|
+
|
|
223
223
|
unless self.unsubscribed_from_channel?(notification.target, channel_name)
|
|
224
224
|
channel.deliver(notification, channel_options)
|
|
225
225
|
end
|
|
@@ -236,7 +236,7 @@ module NotifyUser
|
|
|
236
236
|
end
|
|
237
237
|
end
|
|
238
238
|
|
|
239
|
-
#
|
|
239
|
+
# Prepares a single channel for aggregation
|
|
240
240
|
def self.notify_aggregated_channel(notification_id, channel_name)
|
|
241
241
|
notification = self.find(notification_id) # Raise an exception if not found.
|
|
242
242
|
|
|
@@ -247,7 +247,6 @@ module NotifyUser
|
|
|
247
247
|
notifications.map(&:save)
|
|
248
248
|
|
|
249
249
|
return if notifications.empty?
|
|
250
|
-
|
|
251
250
|
if notifications.length == 1
|
|
252
251
|
# Despite waiting for more to aggregate, we only got one in the end.
|
|
253
252
|
self.deliver_notification_channel(notifications.first.id, channel_name)
|
|
@@ -257,27 +256,8 @@ module NotifyUser
|
|
|
257
256
|
end
|
|
258
257
|
end
|
|
259
258
|
|
|
260
|
-
def self.notify_aggregated(notification_id)
|
|
261
|
-
notification = self.find(notification_id) # Raise an exception if not found.
|
|
262
|
-
|
|
263
|
-
# Find any pending notifications with the same type and target, which can all be sent in one message.
|
|
264
|
-
notifications = self.pending_aggregation_with(notification)
|
|
265
|
-
|
|
266
|
-
notifications.map(&:mark_as_sent)
|
|
267
|
-
notifications.map(&:save)
|
|
268
|
-
|
|
269
|
-
return if notifications.empty?
|
|
270
|
-
|
|
271
|
-
if notifications.length == 1
|
|
272
|
-
# Despite waiting for more to aggregate, we only got one in the end.
|
|
273
|
-
self.deliver_channels(notifications.first.id)
|
|
274
|
-
else
|
|
275
|
-
# We got several notifications while waiting, send them aggregated.
|
|
276
|
-
self.deliver_channels_aggregated(notifications)
|
|
277
|
-
end
|
|
278
|
-
end
|
|
279
|
-
|
|
280
259
|
private
|
|
260
|
+
|
|
281
261
|
def unsubscribed_validation
|
|
282
262
|
errors.add(:target, (" has unsubscribed from this type")) if user_has_unsubscribed?
|
|
283
263
|
end
|
|
@@ -291,9 +271,7 @@ module NotifyUser
|
|
|
291
271
|
|
|
292
272
|
def self.unsubscribed_from_channel?(user, type)
|
|
293
273
|
#return true if user has unsubscribed
|
|
294
|
-
return
|
|
295
|
-
|
|
296
|
-
return false
|
|
274
|
+
return !NotifyUser::Unsubscribe.has_unsubscribed_from(user, type).empty?
|
|
297
275
|
end
|
|
298
276
|
|
|
299
277
|
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
require_relative 'apn_connection'
|
|
2
|
+
require 'houston'
|
|
3
|
+
|
|
4
|
+
module NotifyUser
|
|
5
|
+
class Houston < Apns
|
|
6
|
+
|
|
7
|
+
NO_ERROR = -42
|
|
8
|
+
INVALID_TOKEN_ERROR = 8
|
|
9
|
+
APN_POOL = ConnectionPool.new(
|
|
10
|
+
size: NotifyUser.connection_pool_size,
|
|
11
|
+
timeout: NotifyUser.connection_pool_timeout) do
|
|
12
|
+
APNConnection.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attr_accessor :push_options
|
|
16
|
+
|
|
17
|
+
def initialize(notification, options)
|
|
18
|
+
super(notification, options)
|
|
19
|
+
|
|
20
|
+
@push_options = setup_options
|
|
21
|
+
|
|
22
|
+
device_method = @options[:device_method] || :devices
|
|
23
|
+
begin
|
|
24
|
+
@devices = @notification.target.send(device_method)
|
|
25
|
+
rescue
|
|
26
|
+
Rails.logger.info "Notification target, #{@notification.target.class}, does not respond to the method, #{device_method}."
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def push
|
|
31
|
+
send_notifications
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def setup_options
|
|
37
|
+
space_allowance = PAYLOAD_LIMIT - used_space
|
|
38
|
+
|
|
39
|
+
push_options = {
|
|
40
|
+
alert: @notification.mobile_message(space_allowance),
|
|
41
|
+
badge: @notification.count_for_target,
|
|
42
|
+
category: @notification.params[:category] || @notification.type,
|
|
43
|
+
custom_data: @notification.params,
|
|
44
|
+
sound: 'default'
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if @options[:silent]
|
|
48
|
+
push_options.merge!({
|
|
49
|
+
sound: '',
|
|
50
|
+
content_available: true
|
|
51
|
+
})
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
push_options
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def send_notifications
|
|
58
|
+
APN_POOL.with do |connection|
|
|
59
|
+
if !connection.connection.open?
|
|
60
|
+
connection = APNConnection.new
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
ssl = connection.connection.ssl
|
|
64
|
+
error_index = NO_ERROR
|
|
65
|
+
|
|
66
|
+
@devices.each_with_index do |device, index|
|
|
67
|
+
notification = ::Houston::Notification.new(@push_options.dup.merge({ token: device.token, id: index }))
|
|
68
|
+
connection.write(notification.message)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
read_socket, write_socket = IO.select([ssl], [], [ssl], 1)
|
|
72
|
+
if (read_socket && read_socket[0])
|
|
73
|
+
if error = connection.connection.read(6)
|
|
74
|
+
command, status, error_index = error.unpack("ccN")
|
|
75
|
+
|
|
76
|
+
# Remove all the devices prior to the error (we assume they were successful), and close the current connection:
|
|
77
|
+
if error_index != NO_ERROR
|
|
78
|
+
device = @devices.at(error_index)
|
|
79
|
+
Rails.logger.info "Error: #{status} with id: #{error_index}. Token: #{device.token}."
|
|
80
|
+
|
|
81
|
+
# If we encounter the Invalid Token error from APNS, just remove the device:
|
|
82
|
+
if status == ERROR_INVALID_TOKEN
|
|
83
|
+
Rails.logger.info "Invalid token encountered, removing device. Token: #{device.token}."
|
|
84
|
+
device.destroy
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
@devices.slice!(0..error_index)
|
|
88
|
+
connection.connection.close
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Resend all notifications after the once that produced the error:
|
|
94
|
+
send_notifications if error_index != NO_ERROR
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module NotifyUser
|
|
2
|
+
class UrbanAirship < Apns
|
|
3
|
+
|
|
4
|
+
def push
|
|
5
|
+
space_allowance = PAYLOAD_LIMIT - used_space
|
|
6
|
+
|
|
7
|
+
payload = {
|
|
8
|
+
:alias => notification.target_id,
|
|
9
|
+
:aps => {
|
|
10
|
+
:alert => notification.mobile_message(space_allowance),
|
|
11
|
+
:badge => notification.count_for_target
|
|
12
|
+
},
|
|
13
|
+
:n_data => {
|
|
14
|
+
'#' => notification.id,
|
|
15
|
+
:t => notification.created_at.to_time.to_i,
|
|
16
|
+
'?' => notification.type
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
payload[:n_data]['!'] = notification.params[:action_id] if notification.params[:action_id]
|
|
21
|
+
|
|
22
|
+
response = Urbanairship.push(payload)
|
|
23
|
+
if response.success?
|
|
24
|
+
Rails.logger.info "Push notification sent successfully."
|
|
25
|
+
return true
|
|
26
|
+
else
|
|
27
|
+
Rails.logger.info "Push notification failed."
|
|
28
|
+
return false
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
end
|