rpush_extended 3.2.5
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 +7 -0
- data/CHANGELOG.md +365 -0
- data/LICENSE +7 -0
- data/README.md +393 -0
- data/bin/rpush +4 -0
- data/lib/generators/rpush_config_generator.rb +7 -0
- data/lib/generators/rpush_migration_generator.rb +66 -0
- data/lib/generators/templates/add_adm.rb +23 -0
- data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +9 -0
- data/lib/generators/templates/add_app_to_rapns.rb +11 -0
- data/lib/generators/templates/add_fail_after_to_rpush_notifications.rb +9 -0
- data/lib/generators/templates/add_gcm.rb +117 -0
- data/lib/generators/templates/add_rpush.rb +402 -0
- data/lib/generators/templates/add_wpns.rb +16 -0
- data/lib/generators/templates/create_rapns_apps.rb +16 -0
- data/lib/generators/templates/create_rapns_feedback.rb +25 -0
- data/lib/generators/templates/create_rapns_notifications.rb +36 -0
- data/lib/generators/templates/rename_rapns_to_rpush.rb +87 -0
- data/lib/generators/templates/rpush.rb +135 -0
- data/lib/generators/templates/rpush_2_0_0_updates.rb +79 -0
- data/lib/generators/templates/rpush_2_1_0_updates.rb +11 -0
- data/lib/generators/templates/rpush_2_6_0_updates.rb +10 -0
- data/lib/generators/templates/rpush_2_7_0_updates.rb +12 -0
- data/lib/generators/templates/rpush_3_0_0_updates.rb +11 -0
- data/lib/generators/templates/rpush_3_0_1_updates.rb +13 -0
- data/lib/generators/templates/rpush_3_1_0_add_pushy.rb +9 -0
- data/lib/generators/templates/rpush_3_1_1_updates.rb +15 -0
- data/lib/generators/templates/rpush_3_2_0_add_apns_p8.rb +15 -0
- data/lib/generators/templates/rpush_3_2_4_updates.rb +9 -0
- data/lib/generators/templates/rpush_3_3_0_updates.rb +9 -0
- data/lib/generators/templates/rpush_3_3_1_updates.rb +11 -0
- data/lib/rpush/apns_feedback.rb +17 -0
- data/lib/rpush/cli.rb +213 -0
- data/lib/rpush/client/active_model/adm/app.rb +23 -0
- data/lib/rpush/client/active_model/adm/data_validator.rb +14 -0
- data/lib/rpush/client/active_model/adm/notification.rb +28 -0
- data/lib/rpush/client/active_model/apns/app.rb +37 -0
- data/lib/rpush/client/active_model/apns/binary_notification_validator.rb +16 -0
- data/lib/rpush/client/active_model/apns/device_token_format_validator.rb +14 -0
- data/lib/rpush/client/active_model/apns/notification.rb +104 -0
- data/lib/rpush/client/active_model/apns2/app.rb +15 -0
- data/lib/rpush/client/active_model/apns2/notification.rb +9 -0
- data/lib/rpush/client/active_model/apnsp8/app.rb +23 -0
- data/lib/rpush/client/active_model/apnsp8/notification.rb +9 -0
- data/lib/rpush/client/active_model/gcm/app.rb +19 -0
- data/lib/rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +14 -0
- data/lib/rpush/client/active_model/gcm/notification.rb +59 -0
- data/lib/rpush/client/active_model/notification.rb +22 -0
- data/lib/rpush/client/active_model/payload_data_size_validator.rb +13 -0
- data/lib/rpush/client/active_model/pushy/app.rb +20 -0
- data/lib/rpush/client/active_model/pushy/notification.rb +31 -0
- data/lib/rpush/client/active_model/pushy/time_to_live_validator.rb +14 -0
- data/lib/rpush/client/active_model/registration_ids_count_validator.rb +13 -0
- data/lib/rpush/client/active_model/wns/app.rb +23 -0
- data/lib/rpush/client/active_model/wns/notification.rb +32 -0
- data/lib/rpush/client/active_model/wpns/app.rb +13 -0
- data/lib/rpush/client/active_model/wpns/notification.rb +28 -0
- data/lib/rpush/client/active_model.rb +34 -0
- data/lib/rpush/client/active_record/adm/app.rb +11 -0
- data/lib/rpush/client/active_record/adm/notification.rb +11 -0
- data/lib/rpush/client/active_record/apns/app.rb +11 -0
- data/lib/rpush/client/active_record/apns/feedback.rb +18 -0
- data/lib/rpush/client/active_record/apns/notification.rb +40 -0
- data/lib/rpush/client/active_record/apns2/app.rb +11 -0
- data/lib/rpush/client/active_record/apns2/notification.rb +10 -0
- data/lib/rpush/client/active_record/apnsp8/app.rb +11 -0
- data/lib/rpush/client/active_record/apnsp8/notification.rb +10 -0
- data/lib/rpush/client/active_record/app.rb +13 -0
- data/lib/rpush/client/active_record/gcm/app.rb +11 -0
- data/lib/rpush/client/active_record/gcm/notification.rb +11 -0
- data/lib/rpush/client/active_record/notification.rb +42 -0
- data/lib/rpush/client/active_record/pushy/app.rb +11 -0
- data/lib/rpush/client/active_record/pushy/notification.rb +11 -0
- data/lib/rpush/client/active_record/wns/app.rb +11 -0
- data/lib/rpush/client/active_record/wns/badge_notification.rb +15 -0
- data/lib/rpush/client/active_record/wns/notification.rb +11 -0
- data/lib/rpush/client/active_record/wns/raw_notification.rb +13 -0
- data/lib/rpush/client/active_record/wpns/app.rb +11 -0
- data/lib/rpush/client/active_record/wpns/notification.rb +11 -0
- data/lib/rpush/client/active_record.rb +33 -0
- data/lib/rpush/client/redis/adm/app.rb +14 -0
- data/lib/rpush/client/redis/adm/notification.rb +11 -0
- data/lib/rpush/client/redis/apns/app.rb +11 -0
- data/lib/rpush/client/redis/apns/feedback.rb +20 -0
- data/lib/rpush/client/redis/apns/notification.rb +11 -0
- data/lib/rpush/client/redis/apns2/app.rb +11 -0
- data/lib/rpush/client/redis/apns2/notification.rb +11 -0
- data/lib/rpush/client/redis/apnsp8/app.rb +11 -0
- data/lib/rpush/client/redis/apnsp8/notification.rb +11 -0
- data/lib/rpush/client/redis/app.rb +29 -0
- data/lib/rpush/client/redis/gcm/app.rb +11 -0
- data/lib/rpush/client/redis/gcm/notification.rb +11 -0
- data/lib/rpush/client/redis/notification.rb +74 -0
- data/lib/rpush/client/redis/pushy/app.rb +16 -0
- data/lib/rpush/client/redis/pushy/notification.rb +18 -0
- data/lib/rpush/client/redis/wns/app.rb +14 -0
- data/lib/rpush/client/redis/wns/badge_notification.rb +15 -0
- data/lib/rpush/client/redis/wns/notification.rb +11 -0
- data/lib/rpush/client/redis/wns/raw_notification.rb +11 -0
- data/lib/rpush/client/redis/wpns/app.rb +11 -0
- data/lib/rpush/client/redis/wpns/notification.rb +11 -0
- data/lib/rpush/client/redis.rb +56 -0
- data/lib/rpush/configuration.rb +115 -0
- data/lib/rpush/daemon/adm/delivery.rb +226 -0
- data/lib/rpush/daemon/adm.rb +9 -0
- data/lib/rpush/daemon/apns/delivery.rb +43 -0
- data/lib/rpush/daemon/apns/feedback_receiver.rb +90 -0
- data/lib/rpush/daemon/apns.rb +17 -0
- data/lib/rpush/daemon/apns2/delivery.rb +127 -0
- data/lib/rpush/daemon/apns2.rb +10 -0
- data/lib/rpush/daemon/apnsp8/delivery.rb +166 -0
- data/lib/rpush/daemon/apnsp8/token.rb +43 -0
- data/lib/rpush/daemon/apnsp8.rb +10 -0
- data/lib/rpush/daemon/app_runner.rb +190 -0
- data/lib/rpush/daemon/batch.rb +138 -0
- data/lib/rpush/daemon/constants.rb +59 -0
- data/lib/rpush/daemon/delivery.rb +46 -0
- data/lib/rpush/daemon/delivery_error.rb +27 -0
- data/lib/rpush/daemon/dispatcher/apns_http2.rb +51 -0
- data/lib/rpush/daemon/dispatcher/apns_tcp.rb +152 -0
- data/lib/rpush/daemon/dispatcher/apnsp8_http2.rb +33 -0
- data/lib/rpush/daemon/dispatcher/http.rb +21 -0
- data/lib/rpush/daemon/dispatcher/tcp.rb +22 -0
- data/lib/rpush/daemon/dispatcher_loop.rb +73 -0
- data/lib/rpush/daemon/errors.rb +18 -0
- data/lib/rpush/daemon/feeder.rb +69 -0
- data/lib/rpush/daemon/gcm/delivery.rb +241 -0
- data/lib/rpush/daemon/gcm.rb +9 -0
- data/lib/rpush/daemon/interruptible_sleep.rb +24 -0
- data/lib/rpush/daemon/loggable.rb +33 -0
- data/lib/rpush/daemon/proc_title.rb +17 -0
- data/lib/rpush/daemon/pushy/delivery.rb +90 -0
- data/lib/rpush/daemon/pushy.rb +9 -0
- data/lib/rpush/daemon/queue_payload.rb +12 -0
- data/lib/rpush/daemon/retry_header_parser.rb +23 -0
- data/lib/rpush/daemon/retryable_error.rb +22 -0
- data/lib/rpush/daemon/ring_buffer.rb +16 -0
- data/lib/rpush/daemon/rpc/client.rb +27 -0
- data/lib/rpush/daemon/rpc/server.rb +82 -0
- data/lib/rpush/daemon/rpc.rb +9 -0
- data/lib/rpush/daemon/service_config_methods.rb +51 -0
- data/lib/rpush/daemon/signal_handler.rb +75 -0
- data/lib/rpush/daemon/store/active_record/reconnectable.rb +80 -0
- data/lib/rpush/daemon/store/active_record.rb +214 -0
- data/lib/rpush/daemon/store/interface.rb +20 -0
- data/lib/rpush/daemon/store/redis.rb +166 -0
- data/lib/rpush/daemon/string_helpers.rb +15 -0
- data/lib/rpush/daemon/synchronizer.rb +62 -0
- data/lib/rpush/daemon/tcp_connection.rb +190 -0
- data/lib/rpush/daemon/wns/badge_request.rb +32 -0
- data/lib/rpush/daemon/wns/delivery.rb +178 -0
- data/lib/rpush/daemon/wns/post_request.rb +33 -0
- data/lib/rpush/daemon/wns/raw_request.rb +22 -0
- data/lib/rpush/daemon/wns/toast_request.rb +54 -0
- data/lib/rpush/daemon/wns.rb +9 -0
- data/lib/rpush/daemon/wpns/delivery.rb +132 -0
- data/lib/rpush/daemon/wpns.rb +9 -0
- data/lib/rpush/daemon.rb +179 -0
- data/lib/rpush/deprecatable.rb +24 -0
- data/lib/rpush/deprecation.rb +26 -0
- data/lib/rpush/embed.rb +41 -0
- data/lib/rpush/logger.rb +92 -0
- data/lib/rpush/multi_json_helper.rb +16 -0
- data/lib/rpush/plugin.rb +44 -0
- data/lib/rpush/push.rb +11 -0
- data/lib/rpush/reflectable.rb +13 -0
- data/lib/rpush/reflection_collection.rb +44 -0
- data/lib/rpush/reflection_public_methods.rb +11 -0
- data/lib/rpush/version.rb +14 -0
- data/lib/rpush.rb +43 -0
- data/lib/tasks/quality.rake +35 -0
- data/lib/tasks/test.rake +69 -0
- data/spec/.rubocop.yml +4 -0
- data/spec/functional/adm_spec.rb +50 -0
- data/spec/functional/apns2_spec.rb +232 -0
- data/spec/functional/apns_spec.rb +162 -0
- data/spec/functional/cli_spec.rb +36 -0
- data/spec/functional/embed_spec.rb +49 -0
- data/spec/functional/gcm_spec.rb +46 -0
- data/spec/functional/new_app_spec.rb +44 -0
- data/spec/functional/pushy_spec.rb +22 -0
- data/spec/functional/retry_spec.rb +42 -0
- data/spec/functional/synchronization_spec.rb +97 -0
- data/spec/functional/wpns_spec.rb +71 -0
- data/spec/functional_spec_helper.rb +32 -0
- data/spec/spec_helper.rb +69 -0
- data/spec/support/active_record_setup.rb +73 -0
- data/spec/support/cert_with_password.pem +90 -0
- data/spec/support/cert_without_password.pem +59 -0
- data/spec/support/config/database.yml +44 -0
- data/spec/support/simplecov_helper.rb +24 -0
- data/spec/support/simplecov_quality_formatter.rb +12 -0
- data/spec/tmp/.gitkeep +0 -0
- data/spec/unit/apns_feedback_spec.rb +28 -0
- data/spec/unit/client/active_record/adm/app_spec.rb +58 -0
- data/spec/unit/client/active_record/adm/notification_spec.rb +43 -0
- data/spec/unit/client/active_record/apns/app_spec.rb +29 -0
- data/spec/unit/client/active_record/apns/feedback_spec.rb +9 -0
- data/spec/unit/client/active_record/apns/notification_spec.rb +324 -0
- data/spec/unit/client/active_record/app_spec.rb +30 -0
- data/spec/unit/client/active_record/gcm/app_spec.rb +4 -0
- data/spec/unit/client/active_record/gcm/notification_spec.rb +67 -0
- data/spec/unit/client/active_record/notification_spec.rb +21 -0
- data/spec/unit/client/active_record/pushy/app_spec.rb +17 -0
- data/spec/unit/client/active_record/pushy/notification_spec.rb +65 -0
- data/spec/unit/client/active_record/wns/badge_notification_spec.rb +15 -0
- data/spec/unit/client/active_record/wns/raw_notification_spec.rb +26 -0
- data/spec/unit/client/active_record/wpns/app_spec.rb +4 -0
- data/spec/unit/client/active_record/wpns/notification_spec.rb +21 -0
- data/spec/unit/configuration_spec.rb +46 -0
- data/spec/unit/daemon/adm/delivery_spec.rb +253 -0
- data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +11 -0
- data/spec/unit/daemon/apns/delivery_spec.rb +108 -0
- data/spec/unit/daemon/apns/feedback_receiver_spec.rb +119 -0
- data/spec/unit/daemon/app_runner_spec.rb +188 -0
- data/spec/unit/daemon/batch_spec.rb +169 -0
- data/spec/unit/daemon/delivery_error_spec.rb +13 -0
- data/spec/unit/daemon/delivery_spec.rb +51 -0
- data/spec/unit/daemon/dispatcher/http_spec.rb +34 -0
- data/spec/unit/daemon/dispatcher/tcp_spec.rb +32 -0
- data/spec/unit/daemon/dispatcher_loop_spec.rb +53 -0
- data/spec/unit/daemon/feeder_spec.rb +96 -0
- data/spec/unit/daemon/gcm/delivery_spec.rb +387 -0
- data/spec/unit/daemon/proc_title_spec.rb +11 -0
- data/spec/unit/daemon/pushy/delivery_spec.rb +159 -0
- data/spec/unit/daemon/retryable_error_spec.rb +14 -0
- data/spec/unit/daemon/service_config_methods_spec.rb +36 -0
- data/spec/unit/daemon/signal_handler_spec.rb +99 -0
- data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +165 -0
- data/spec/unit/daemon/store/active_record_spec.rb +357 -0
- data/spec/unit/daemon/store/redis_spec.rb +365 -0
- data/spec/unit/daemon/tcp_connection_spec.rb +292 -0
- data/spec/unit/daemon/wns/delivery_spec.rb +176 -0
- data/spec/unit/daemon/wns/post_request_spec.rb +117 -0
- data/spec/unit/daemon/wpns/delivery_spec.rb +167 -0
- data/spec/unit/daemon_spec.rb +138 -0
- data/spec/unit/deprecatable_spec.rb +32 -0
- data/spec/unit/deprecation_spec.rb +15 -0
- data/spec/unit/embed_spec.rb +47 -0
- data/spec/unit/logger_spec.rb +127 -0
- data/spec/unit/notification_shared.rb +53 -0
- data/spec/unit/plugin_spec.rb +36 -0
- data/spec/unit/push_spec.rb +34 -0
- data/spec/unit/reflectable_spec.rb +27 -0
- data/spec/unit/reflection_collection_spec.rb +26 -0
- data/spec/unit/rpush_spec.rb +8 -0
- data/spec/unit_spec_helper.rb +26 -0
- metadata +709 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module Apns
|
|
5
|
+
module App
|
|
6
|
+
def self.included(base)
|
|
7
|
+
base.instance_eval do
|
|
8
|
+
validates :environment, presence: true, inclusion: { in: %w(development production sandbox) }
|
|
9
|
+
validates :certificate, presence: true
|
|
10
|
+
validate :certificate_has_matching_private_key
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def service_name
|
|
15
|
+
'apns'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def certificate_has_matching_private_key
|
|
21
|
+
result = false
|
|
22
|
+
if certificate.present?
|
|
23
|
+
begin
|
|
24
|
+
x509 = OpenSSL::X509::Certificate.new(certificate)
|
|
25
|
+
pkey = OpenSSL::PKey::RSA.new(certificate, password)
|
|
26
|
+
result = x509 && pkey
|
|
27
|
+
rescue OpenSSL::OpenSSLError
|
|
28
|
+
errors.add :certificate, 'value must contain a certificate and a private key.'
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
result
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module Apns
|
|
5
|
+
class BinaryNotificationValidator < ::ActiveModel::Validator
|
|
6
|
+
MAX_BYTES = 2048
|
|
7
|
+
|
|
8
|
+
def validate(record)
|
|
9
|
+
return unless record.payload.bytesize > MAX_BYTES
|
|
10
|
+
record.errors[:base] << "APN notification cannot be larger than #{MAX_BYTES} bytes. Try condensing your alert and device attributes."
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module Apns
|
|
5
|
+
class DeviceTokenFormatValidator < ::ActiveModel::Validator
|
|
6
|
+
def validate(record)
|
|
7
|
+
return if record.device_token =~ /^[a-z0-9]\w+$/i
|
|
8
|
+
record.errors[:device_token] << "is invalid"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module Apns
|
|
5
|
+
module Notification
|
|
6
|
+
APNS_DEFAULT_EXPIRY = 1.day.to_i
|
|
7
|
+
APNS_PRIORITY_IMMEDIATE = 10
|
|
8
|
+
APNS_PRIORITY_CONSERVE_POWER = 5
|
|
9
|
+
APNS_PRIORITIES = [APNS_PRIORITY_IMMEDIATE, APNS_PRIORITY_CONSERVE_POWER]
|
|
10
|
+
|
|
11
|
+
def self.included(base)
|
|
12
|
+
base.instance_eval do
|
|
13
|
+
validates :device_token, presence: true
|
|
14
|
+
validates :badge, numericality: true, allow_nil: true
|
|
15
|
+
validates :priority, inclusion: { in: APNS_PRIORITIES }, allow_nil: true
|
|
16
|
+
|
|
17
|
+
validates_with Rpush::Client::ActiveModel::Apns::DeviceTokenFormatValidator
|
|
18
|
+
validates_with Rpush::Client::ActiveModel::Apns::BinaryNotificationValidator
|
|
19
|
+
|
|
20
|
+
base.const_set('APNS_DEFAULT_EXPIRY', APNS_DEFAULT_EXPIRY) unless base.const_defined?('APNS_DEFAULT_EXPIRY')
|
|
21
|
+
base.const_set('APNS_PRIORITY_IMMEDIATE', APNS_PRIORITY_IMMEDIATE) unless base.const_defined?('APNS_PRIORITY_IMMEDIATE')
|
|
22
|
+
base.const_set('APNS_PRIORITY_CONSERVE_POWER', APNS_PRIORITY_CONSERVE_POWER) unless base.const_defined?('APNS_PRIORITY_CONSERVE_POWER')
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def device_token=(token)
|
|
27
|
+
write_attribute(:device_token, token.delete(" <>")) unless token.nil?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
MDM_KEY = '__rpush_mdm__'
|
|
31
|
+
def mdm=(magic)
|
|
32
|
+
self.data = (data || {}).merge(MDM_KEY => magic)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
MUTABLE_CONTENT_KEY = '__rpush_mutable_content__'
|
|
36
|
+
def mutable_content=(bool)
|
|
37
|
+
return unless bool
|
|
38
|
+
self.data = (data || {}).merge(MUTABLE_CONTENT_KEY => true)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
CONTENT_AVAILABLE_KEY = '__rpush_content_available__'
|
|
42
|
+
def content_available=(bool)
|
|
43
|
+
return unless bool
|
|
44
|
+
self.data = (data || {}).merge(CONTENT_AVAILABLE_KEY => true)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def as_json(options = nil) # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
|
|
48
|
+
json = ActiveSupport::OrderedHash.new
|
|
49
|
+
|
|
50
|
+
if data && data.key?(MDM_KEY)
|
|
51
|
+
json['mdm'] = data[MDM_KEY]
|
|
52
|
+
else
|
|
53
|
+
json['aps'] = ActiveSupport::OrderedHash.new
|
|
54
|
+
json['aps']['alert'] = alert if alert
|
|
55
|
+
json['aps']['badge'] = badge if badge
|
|
56
|
+
json['aps']['sound'] = sound if sound
|
|
57
|
+
json['aps']['category'] = category if category
|
|
58
|
+
json['aps']['url-args'] = url_args if url_args
|
|
59
|
+
json['aps']['thread-id'] = thread_id if thread_id
|
|
60
|
+
|
|
61
|
+
if data && data[MUTABLE_CONTENT_KEY]
|
|
62
|
+
json['aps']['mutable-content'] = 1
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
if data && data[CONTENT_AVAILABLE_KEY]
|
|
66
|
+
json['aps']['content-available'] = 1
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
if data
|
|
70
|
+
non_aps_attributes = data.reject { |k, _| k == CONTENT_AVAILABLE_KEY || k == MUTABLE_CONTENT_KEY }
|
|
71
|
+
non_aps_attributes.each { |k, v| json[k.to_s] = v }
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
json
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def to_binary(options = {})
|
|
79
|
+
frame_payload = payload
|
|
80
|
+
frame_id = options[:for_validation] ? 0 : send(options.fetch(:id_attribute, :id))
|
|
81
|
+
frame = ""
|
|
82
|
+
frame << [1, 32, device_token].pack("cnH*")
|
|
83
|
+
frame << [2, frame_payload.bytesize, frame_payload].pack("cna*")
|
|
84
|
+
frame << [3, 4, frame_id].pack("cnN")
|
|
85
|
+
frame << [4, 4, expiry ? Time.now.to_i + expiry.to_i : 0].pack("cnN")
|
|
86
|
+
frame << [5, 1, priority_for_frame].pack("cnc")
|
|
87
|
+
[2, frame.bytesize].pack("cN") + frame
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
private
|
|
91
|
+
|
|
92
|
+
def priority_for_frame
|
|
93
|
+
# It is an error to use APNS_PRIORITY_IMMEDIATE for a notification that only contains content-available.
|
|
94
|
+
if as_json['aps'].try(:keys) == ['content-available']
|
|
95
|
+
APNS_PRIORITY_CONSERVE_POWER
|
|
96
|
+
else
|
|
97
|
+
priority || APNS_PRIORITY_IMMEDIATE
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module Apnsp8
|
|
5
|
+
module App
|
|
6
|
+
def self.included(base)
|
|
7
|
+
base.instance_eval do
|
|
8
|
+
validates :environment, presence: true, inclusion: { in: %w(development production sandbox) }
|
|
9
|
+
validates :apn_key, presence: true
|
|
10
|
+
validates :apn_key_id, presence: true
|
|
11
|
+
validates :team_id, presence: true
|
|
12
|
+
validates :bundle_id, presence: true
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def service_name
|
|
17
|
+
'apnsp8'
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module Gcm
|
|
5
|
+
module App
|
|
6
|
+
def self.included(base)
|
|
7
|
+
base.instance_eval do
|
|
8
|
+
validates :auth_key, presence: true
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def service_name
|
|
13
|
+
'gcm'
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module Gcm
|
|
5
|
+
class ExpiryCollapseKeyMutualInclusionValidator < ::ActiveModel::Validator
|
|
6
|
+
def validate(record)
|
|
7
|
+
return unless record.collapse_key && !record.expiry
|
|
8
|
+
record.errors[:expiry] << 'must be set when using a collapse_key'
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module Gcm
|
|
5
|
+
module Notification
|
|
6
|
+
GCM_PRIORITY_HIGH = Rpush::Client::ActiveModel::Apns::Notification::APNS_PRIORITY_IMMEDIATE
|
|
7
|
+
GCM_PRIORITY_NORMAL = Rpush::Client::ActiveModel::Apns::Notification::APNS_PRIORITY_CONSERVE_POWER
|
|
8
|
+
GCM_PRIORITIES = [GCM_PRIORITY_HIGH, GCM_PRIORITY_NORMAL]
|
|
9
|
+
|
|
10
|
+
def self.included(base)
|
|
11
|
+
base.instance_eval do
|
|
12
|
+
validates :registration_ids, presence: true
|
|
13
|
+
validates :priority, inclusion: { in: GCM_PRIORITIES }, allow_nil: true
|
|
14
|
+
|
|
15
|
+
validates_with Rpush::Client::ActiveModel::PayloadDataSizeValidator, limit: 4096
|
|
16
|
+
validates_with Rpush::Client::ActiveModel::RegistrationIdsCountValidator, limit: 1000
|
|
17
|
+
|
|
18
|
+
validates_with Rpush::Client::ActiveModel::Gcm::ExpiryCollapseKeyMutualInclusionValidator
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# This is a hack. The schema defines `priority` to be an integer, but GCM expects a string.
|
|
23
|
+
# But for users of rpush to have an API they might expect (setting priority to `high`, not 10)
|
|
24
|
+
# we do a little conversion here.
|
|
25
|
+
# I'm not happy about it, but this will have to do until I can take a further look.
|
|
26
|
+
def priority=(priority)
|
|
27
|
+
case priority
|
|
28
|
+
when 'high'
|
|
29
|
+
super(GCM_PRIORITY_HIGH)
|
|
30
|
+
when 'normal'
|
|
31
|
+
super(GCM_PRIORITY_NORMAL)
|
|
32
|
+
else
|
|
33
|
+
errors.add(:priority, 'must be one of either "normal" or "high"')
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def as_json(options = nil)
|
|
38
|
+
json = {
|
|
39
|
+
'registration_ids' => registration_ids,
|
|
40
|
+
'delay_while_idle' => delay_while_idle,
|
|
41
|
+
'data' => data
|
|
42
|
+
}
|
|
43
|
+
json['collapse_key'] = collapse_key if collapse_key
|
|
44
|
+
json['content_available'] = content_available if content_available
|
|
45
|
+
json['notification'] = notification if notification
|
|
46
|
+
json['priority'] = priority_for_notification if priority
|
|
47
|
+
json['time_to_live'] = expiry if expiry
|
|
48
|
+
json
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def priority_for_notification
|
|
52
|
+
return 'high' if priority == GCM_PRIORITY_HIGH
|
|
53
|
+
'normal' if priority == GCM_PRIORITY_NORMAL
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module Notification
|
|
5
|
+
def self.included(base)
|
|
6
|
+
base.instance_eval do
|
|
7
|
+
validates :expiry, numericality: true, allow_nil: true
|
|
8
|
+
validates :app, presence: true
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def payload
|
|
13
|
+
multi_json_dump(as_json)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def payload_data_size
|
|
17
|
+
multi_json_dump(as_json['data']).bytesize
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveModel
|
|
4
|
+
class PayloadDataSizeValidator < ::ActiveModel::Validator
|
|
5
|
+
def validate(record)
|
|
6
|
+
limit = options[:limit] || 1024
|
|
7
|
+
return unless record.data && record.payload_data_size > limit
|
|
8
|
+
record.errors[:base] << "Notification payload data cannot be larger than #{limit} bytes."
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module Pushy
|
|
5
|
+
module App
|
|
6
|
+
def self.included(base)
|
|
7
|
+
base.instance_eval do
|
|
8
|
+
alias_attribute :api_key, :auth_key
|
|
9
|
+
validates :api_key, presence: true
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def service_name
|
|
14
|
+
'pushy'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module Pushy
|
|
5
|
+
module Notification
|
|
6
|
+
def self.included(base)
|
|
7
|
+
base.instance_eval do
|
|
8
|
+
alias_attribute :time_to_live, :expiry
|
|
9
|
+
|
|
10
|
+
validates :time_to_live, numericality: { only_integer: true, greater_than: 0 }, allow_nil: true
|
|
11
|
+
validates :registration_ids, presence: true
|
|
12
|
+
validates :data, presence: true
|
|
13
|
+
|
|
14
|
+
validates_with Rpush::Client::ActiveModel::Pushy::TimeToLiveValidator
|
|
15
|
+
validates_with Rpush::Client::ActiveModel::PayloadDataSizeValidator, limit: 4096
|
|
16
|
+
validates_with Rpush::Client::ActiveModel::RegistrationIdsCountValidator, limit: 1000
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def as_json(_options = nil)
|
|
21
|
+
{
|
|
22
|
+
'data' => data,
|
|
23
|
+
'time_to_live' => time_to_live,
|
|
24
|
+
'registration_ids' => registration_ids
|
|
25
|
+
}
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module Pushy
|
|
5
|
+
class TimeToLiveValidator < ::ActiveModel::Validator
|
|
6
|
+
def validate(record)
|
|
7
|
+
return if record.time_to_live.blank? || record.time_to_live <= 1.year.seconds
|
|
8
|
+
record.errors.add(:time_to_live, 'The maximum value is 1 year')
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveModel
|
|
4
|
+
class RegistrationIdsCountValidator < ::ActiveModel::Validator
|
|
5
|
+
def validate(record)
|
|
6
|
+
limit = options[:limit] || 100
|
|
7
|
+
return unless record.registration_ids && record.registration_ids.size > limit
|
|
8
|
+
record.errors[:base] << "Number of registration_ids cannot be larger than #{limit}."
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module Wns
|
|
5
|
+
module App
|
|
6
|
+
def self.included(base)
|
|
7
|
+
base.instance_eval do
|
|
8
|
+
validates :client_id, :client_secret, presence: true
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def access_token_expired?
|
|
13
|
+
access_token_expiration.nil? || access_token_expiration < Time.now
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def service_name
|
|
17
|
+
'wns'
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module Wns
|
|
5
|
+
module Notification
|
|
6
|
+
module InstanceMethods
|
|
7
|
+
def alert=(value)
|
|
8
|
+
return unless value
|
|
9
|
+
data = self.data || {}
|
|
10
|
+
data['title'] = value
|
|
11
|
+
self.data = data
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def skip_data_validation?
|
|
15
|
+
false
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.included(base)
|
|
20
|
+
base.instance_eval do
|
|
21
|
+
include InstanceMethods
|
|
22
|
+
|
|
23
|
+
validates :uri, presence: true
|
|
24
|
+
validates :uri, format: { with: %r{https?://[\S]+} }
|
|
25
|
+
validates :data, presence: true, unless: :skip_data_validation?
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveModel
|
|
4
|
+
module Wpns
|
|
5
|
+
module Notification
|
|
6
|
+
module InstanceMethods
|
|
7
|
+
def alert=(value)
|
|
8
|
+
return unless value
|
|
9
|
+
data = self.data || {}
|
|
10
|
+
data['title'] = value
|
|
11
|
+
self.data = data
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.included(base)
|
|
16
|
+
base.instance_eval do
|
|
17
|
+
include InstanceMethods
|
|
18
|
+
|
|
19
|
+
validates :uri, presence: true
|
|
20
|
+
validates :uri, format: { with: %r{https?://[\S]+} }
|
|
21
|
+
validates :data, presence: true
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require 'active_model'
|
|
2
|
+
|
|
3
|
+
require 'rpush/client/active_model/notification'
|
|
4
|
+
require 'rpush/client/active_model/payload_data_size_validator'
|
|
5
|
+
require 'rpush/client/active_model/registration_ids_count_validator'
|
|
6
|
+
|
|
7
|
+
require 'rpush/client/active_model/apns/binary_notification_validator'
|
|
8
|
+
require 'rpush/client/active_model/apns/device_token_format_validator'
|
|
9
|
+
require 'rpush/client/active_model/apns/app'
|
|
10
|
+
require 'rpush/client/active_model/apns/notification'
|
|
11
|
+
|
|
12
|
+
require 'rpush/client/active_model/apns2/app'
|
|
13
|
+
require 'rpush/client/active_model/apns2/notification'
|
|
14
|
+
|
|
15
|
+
require 'rpush/client/active_model/apnsp8/app'
|
|
16
|
+
require 'rpush/client/active_model/apnsp8/notification'
|
|
17
|
+
|
|
18
|
+
require 'rpush/client/active_model/adm/data_validator'
|
|
19
|
+
require 'rpush/client/active_model/adm/app'
|
|
20
|
+
require 'rpush/client/active_model/adm/notification'
|
|
21
|
+
|
|
22
|
+
require 'rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator'
|
|
23
|
+
require 'rpush/client/active_model/gcm/app'
|
|
24
|
+
require 'rpush/client/active_model/gcm/notification'
|
|
25
|
+
|
|
26
|
+
require 'rpush/client/active_model/wpns/app'
|
|
27
|
+
require 'rpush/client/active_model/wpns/notification'
|
|
28
|
+
|
|
29
|
+
require 'rpush/client/active_model/wns/app'
|
|
30
|
+
require 'rpush/client/active_model/wns/notification'
|
|
31
|
+
|
|
32
|
+
require 'rpush/client/active_model/pushy/app'
|
|
33
|
+
require 'rpush/client/active_model/pushy/notification'
|
|
34
|
+
require 'rpush/client/active_model/pushy/time_to_live_validator'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Rpush
|
|
2
|
+
module Client
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Apns
|
|
5
|
+
class Feedback < ::ActiveRecord::Base
|
|
6
|
+
self.table_name = 'rpush_feedback'
|
|
7
|
+
|
|
8
|
+
belongs_to :app, class_name: 'Rpush::Client::ActiveRecord::App'
|
|
9
|
+
|
|
10
|
+
validates :device_token, presence: true
|
|
11
|
+
validates :failed_at, presence: true
|
|
12
|
+
|
|
13
|
+
validates_with Rpush::Client::ActiveModel::Apns::DeviceTokenFormatValidator
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|