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.
Files changed (248) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +365 -0
  3. data/LICENSE +7 -0
  4. data/README.md +393 -0
  5. data/bin/rpush +4 -0
  6. data/lib/generators/rpush_config_generator.rb +7 -0
  7. data/lib/generators/rpush_migration_generator.rb +66 -0
  8. data/lib/generators/templates/add_adm.rb +23 -0
  9. data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +9 -0
  10. data/lib/generators/templates/add_app_to_rapns.rb +11 -0
  11. data/lib/generators/templates/add_fail_after_to_rpush_notifications.rb +9 -0
  12. data/lib/generators/templates/add_gcm.rb +117 -0
  13. data/lib/generators/templates/add_rpush.rb +402 -0
  14. data/lib/generators/templates/add_wpns.rb +16 -0
  15. data/lib/generators/templates/create_rapns_apps.rb +16 -0
  16. data/lib/generators/templates/create_rapns_feedback.rb +25 -0
  17. data/lib/generators/templates/create_rapns_notifications.rb +36 -0
  18. data/lib/generators/templates/rename_rapns_to_rpush.rb +87 -0
  19. data/lib/generators/templates/rpush.rb +135 -0
  20. data/lib/generators/templates/rpush_2_0_0_updates.rb +79 -0
  21. data/lib/generators/templates/rpush_2_1_0_updates.rb +11 -0
  22. data/lib/generators/templates/rpush_2_6_0_updates.rb +10 -0
  23. data/lib/generators/templates/rpush_2_7_0_updates.rb +12 -0
  24. data/lib/generators/templates/rpush_3_0_0_updates.rb +11 -0
  25. data/lib/generators/templates/rpush_3_0_1_updates.rb +13 -0
  26. data/lib/generators/templates/rpush_3_1_0_add_pushy.rb +9 -0
  27. data/lib/generators/templates/rpush_3_1_1_updates.rb +15 -0
  28. data/lib/generators/templates/rpush_3_2_0_add_apns_p8.rb +15 -0
  29. data/lib/generators/templates/rpush_3_2_4_updates.rb +9 -0
  30. data/lib/generators/templates/rpush_3_3_0_updates.rb +9 -0
  31. data/lib/generators/templates/rpush_3_3_1_updates.rb +11 -0
  32. data/lib/rpush/apns_feedback.rb +17 -0
  33. data/lib/rpush/cli.rb +213 -0
  34. data/lib/rpush/client/active_model/adm/app.rb +23 -0
  35. data/lib/rpush/client/active_model/adm/data_validator.rb +14 -0
  36. data/lib/rpush/client/active_model/adm/notification.rb +28 -0
  37. data/lib/rpush/client/active_model/apns/app.rb +37 -0
  38. data/lib/rpush/client/active_model/apns/binary_notification_validator.rb +16 -0
  39. data/lib/rpush/client/active_model/apns/device_token_format_validator.rb +14 -0
  40. data/lib/rpush/client/active_model/apns/notification.rb +104 -0
  41. data/lib/rpush/client/active_model/apns2/app.rb +15 -0
  42. data/lib/rpush/client/active_model/apns2/notification.rb +9 -0
  43. data/lib/rpush/client/active_model/apnsp8/app.rb +23 -0
  44. data/lib/rpush/client/active_model/apnsp8/notification.rb +9 -0
  45. data/lib/rpush/client/active_model/gcm/app.rb +19 -0
  46. data/lib/rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +14 -0
  47. data/lib/rpush/client/active_model/gcm/notification.rb +59 -0
  48. data/lib/rpush/client/active_model/notification.rb +22 -0
  49. data/lib/rpush/client/active_model/payload_data_size_validator.rb +13 -0
  50. data/lib/rpush/client/active_model/pushy/app.rb +20 -0
  51. data/lib/rpush/client/active_model/pushy/notification.rb +31 -0
  52. data/lib/rpush/client/active_model/pushy/time_to_live_validator.rb +14 -0
  53. data/lib/rpush/client/active_model/registration_ids_count_validator.rb +13 -0
  54. data/lib/rpush/client/active_model/wns/app.rb +23 -0
  55. data/lib/rpush/client/active_model/wns/notification.rb +32 -0
  56. data/lib/rpush/client/active_model/wpns/app.rb +13 -0
  57. data/lib/rpush/client/active_model/wpns/notification.rb +28 -0
  58. data/lib/rpush/client/active_model.rb +34 -0
  59. data/lib/rpush/client/active_record/adm/app.rb +11 -0
  60. data/lib/rpush/client/active_record/adm/notification.rb +11 -0
  61. data/lib/rpush/client/active_record/apns/app.rb +11 -0
  62. data/lib/rpush/client/active_record/apns/feedback.rb +18 -0
  63. data/lib/rpush/client/active_record/apns/notification.rb +40 -0
  64. data/lib/rpush/client/active_record/apns2/app.rb +11 -0
  65. data/lib/rpush/client/active_record/apns2/notification.rb +10 -0
  66. data/lib/rpush/client/active_record/apnsp8/app.rb +11 -0
  67. data/lib/rpush/client/active_record/apnsp8/notification.rb +10 -0
  68. data/lib/rpush/client/active_record/app.rb +13 -0
  69. data/lib/rpush/client/active_record/gcm/app.rb +11 -0
  70. data/lib/rpush/client/active_record/gcm/notification.rb +11 -0
  71. data/lib/rpush/client/active_record/notification.rb +42 -0
  72. data/lib/rpush/client/active_record/pushy/app.rb +11 -0
  73. data/lib/rpush/client/active_record/pushy/notification.rb +11 -0
  74. data/lib/rpush/client/active_record/wns/app.rb +11 -0
  75. data/lib/rpush/client/active_record/wns/badge_notification.rb +15 -0
  76. data/lib/rpush/client/active_record/wns/notification.rb +11 -0
  77. data/lib/rpush/client/active_record/wns/raw_notification.rb +13 -0
  78. data/lib/rpush/client/active_record/wpns/app.rb +11 -0
  79. data/lib/rpush/client/active_record/wpns/notification.rb +11 -0
  80. data/lib/rpush/client/active_record.rb +33 -0
  81. data/lib/rpush/client/redis/adm/app.rb +14 -0
  82. data/lib/rpush/client/redis/adm/notification.rb +11 -0
  83. data/lib/rpush/client/redis/apns/app.rb +11 -0
  84. data/lib/rpush/client/redis/apns/feedback.rb +20 -0
  85. data/lib/rpush/client/redis/apns/notification.rb +11 -0
  86. data/lib/rpush/client/redis/apns2/app.rb +11 -0
  87. data/lib/rpush/client/redis/apns2/notification.rb +11 -0
  88. data/lib/rpush/client/redis/apnsp8/app.rb +11 -0
  89. data/lib/rpush/client/redis/apnsp8/notification.rb +11 -0
  90. data/lib/rpush/client/redis/app.rb +29 -0
  91. data/lib/rpush/client/redis/gcm/app.rb +11 -0
  92. data/lib/rpush/client/redis/gcm/notification.rb +11 -0
  93. data/lib/rpush/client/redis/notification.rb +74 -0
  94. data/lib/rpush/client/redis/pushy/app.rb +16 -0
  95. data/lib/rpush/client/redis/pushy/notification.rb +18 -0
  96. data/lib/rpush/client/redis/wns/app.rb +14 -0
  97. data/lib/rpush/client/redis/wns/badge_notification.rb +15 -0
  98. data/lib/rpush/client/redis/wns/notification.rb +11 -0
  99. data/lib/rpush/client/redis/wns/raw_notification.rb +11 -0
  100. data/lib/rpush/client/redis/wpns/app.rb +11 -0
  101. data/lib/rpush/client/redis/wpns/notification.rb +11 -0
  102. data/lib/rpush/client/redis.rb +56 -0
  103. data/lib/rpush/configuration.rb +115 -0
  104. data/lib/rpush/daemon/adm/delivery.rb +226 -0
  105. data/lib/rpush/daemon/adm.rb +9 -0
  106. data/lib/rpush/daemon/apns/delivery.rb +43 -0
  107. data/lib/rpush/daemon/apns/feedback_receiver.rb +90 -0
  108. data/lib/rpush/daemon/apns.rb +17 -0
  109. data/lib/rpush/daemon/apns2/delivery.rb +127 -0
  110. data/lib/rpush/daemon/apns2.rb +10 -0
  111. data/lib/rpush/daemon/apnsp8/delivery.rb +166 -0
  112. data/lib/rpush/daemon/apnsp8/token.rb +43 -0
  113. data/lib/rpush/daemon/apnsp8.rb +10 -0
  114. data/lib/rpush/daemon/app_runner.rb +190 -0
  115. data/lib/rpush/daemon/batch.rb +138 -0
  116. data/lib/rpush/daemon/constants.rb +59 -0
  117. data/lib/rpush/daemon/delivery.rb +46 -0
  118. data/lib/rpush/daemon/delivery_error.rb +27 -0
  119. data/lib/rpush/daemon/dispatcher/apns_http2.rb +51 -0
  120. data/lib/rpush/daemon/dispatcher/apns_tcp.rb +152 -0
  121. data/lib/rpush/daemon/dispatcher/apnsp8_http2.rb +33 -0
  122. data/lib/rpush/daemon/dispatcher/http.rb +21 -0
  123. data/lib/rpush/daemon/dispatcher/tcp.rb +22 -0
  124. data/lib/rpush/daemon/dispatcher_loop.rb +73 -0
  125. data/lib/rpush/daemon/errors.rb +18 -0
  126. data/lib/rpush/daemon/feeder.rb +69 -0
  127. data/lib/rpush/daemon/gcm/delivery.rb +241 -0
  128. data/lib/rpush/daemon/gcm.rb +9 -0
  129. data/lib/rpush/daemon/interruptible_sleep.rb +24 -0
  130. data/lib/rpush/daemon/loggable.rb +33 -0
  131. data/lib/rpush/daemon/proc_title.rb +17 -0
  132. data/lib/rpush/daemon/pushy/delivery.rb +90 -0
  133. data/lib/rpush/daemon/pushy.rb +9 -0
  134. data/lib/rpush/daemon/queue_payload.rb +12 -0
  135. data/lib/rpush/daemon/retry_header_parser.rb +23 -0
  136. data/lib/rpush/daemon/retryable_error.rb +22 -0
  137. data/lib/rpush/daemon/ring_buffer.rb +16 -0
  138. data/lib/rpush/daemon/rpc/client.rb +27 -0
  139. data/lib/rpush/daemon/rpc/server.rb +82 -0
  140. data/lib/rpush/daemon/rpc.rb +9 -0
  141. data/lib/rpush/daemon/service_config_methods.rb +51 -0
  142. data/lib/rpush/daemon/signal_handler.rb +75 -0
  143. data/lib/rpush/daemon/store/active_record/reconnectable.rb +80 -0
  144. data/lib/rpush/daemon/store/active_record.rb +214 -0
  145. data/lib/rpush/daemon/store/interface.rb +20 -0
  146. data/lib/rpush/daemon/store/redis.rb +166 -0
  147. data/lib/rpush/daemon/string_helpers.rb +15 -0
  148. data/lib/rpush/daemon/synchronizer.rb +62 -0
  149. data/lib/rpush/daemon/tcp_connection.rb +190 -0
  150. data/lib/rpush/daemon/wns/badge_request.rb +32 -0
  151. data/lib/rpush/daemon/wns/delivery.rb +178 -0
  152. data/lib/rpush/daemon/wns/post_request.rb +33 -0
  153. data/lib/rpush/daemon/wns/raw_request.rb +22 -0
  154. data/lib/rpush/daemon/wns/toast_request.rb +54 -0
  155. data/lib/rpush/daemon/wns.rb +9 -0
  156. data/lib/rpush/daemon/wpns/delivery.rb +132 -0
  157. data/lib/rpush/daemon/wpns.rb +9 -0
  158. data/lib/rpush/daemon.rb +179 -0
  159. data/lib/rpush/deprecatable.rb +24 -0
  160. data/lib/rpush/deprecation.rb +26 -0
  161. data/lib/rpush/embed.rb +41 -0
  162. data/lib/rpush/logger.rb +92 -0
  163. data/lib/rpush/multi_json_helper.rb +16 -0
  164. data/lib/rpush/plugin.rb +44 -0
  165. data/lib/rpush/push.rb +11 -0
  166. data/lib/rpush/reflectable.rb +13 -0
  167. data/lib/rpush/reflection_collection.rb +44 -0
  168. data/lib/rpush/reflection_public_methods.rb +11 -0
  169. data/lib/rpush/version.rb +14 -0
  170. data/lib/rpush.rb +43 -0
  171. data/lib/tasks/quality.rake +35 -0
  172. data/lib/tasks/test.rake +69 -0
  173. data/spec/.rubocop.yml +4 -0
  174. data/spec/functional/adm_spec.rb +50 -0
  175. data/spec/functional/apns2_spec.rb +232 -0
  176. data/spec/functional/apns_spec.rb +162 -0
  177. data/spec/functional/cli_spec.rb +36 -0
  178. data/spec/functional/embed_spec.rb +49 -0
  179. data/spec/functional/gcm_spec.rb +46 -0
  180. data/spec/functional/new_app_spec.rb +44 -0
  181. data/spec/functional/pushy_spec.rb +22 -0
  182. data/spec/functional/retry_spec.rb +42 -0
  183. data/spec/functional/synchronization_spec.rb +97 -0
  184. data/spec/functional/wpns_spec.rb +71 -0
  185. data/spec/functional_spec_helper.rb +32 -0
  186. data/spec/spec_helper.rb +69 -0
  187. data/spec/support/active_record_setup.rb +73 -0
  188. data/spec/support/cert_with_password.pem +90 -0
  189. data/spec/support/cert_without_password.pem +59 -0
  190. data/spec/support/config/database.yml +44 -0
  191. data/spec/support/simplecov_helper.rb +24 -0
  192. data/spec/support/simplecov_quality_formatter.rb +12 -0
  193. data/spec/tmp/.gitkeep +0 -0
  194. data/spec/unit/apns_feedback_spec.rb +28 -0
  195. data/spec/unit/client/active_record/adm/app_spec.rb +58 -0
  196. data/spec/unit/client/active_record/adm/notification_spec.rb +43 -0
  197. data/spec/unit/client/active_record/apns/app_spec.rb +29 -0
  198. data/spec/unit/client/active_record/apns/feedback_spec.rb +9 -0
  199. data/spec/unit/client/active_record/apns/notification_spec.rb +324 -0
  200. data/spec/unit/client/active_record/app_spec.rb +30 -0
  201. data/spec/unit/client/active_record/gcm/app_spec.rb +4 -0
  202. data/spec/unit/client/active_record/gcm/notification_spec.rb +67 -0
  203. data/spec/unit/client/active_record/notification_spec.rb +21 -0
  204. data/spec/unit/client/active_record/pushy/app_spec.rb +17 -0
  205. data/spec/unit/client/active_record/pushy/notification_spec.rb +65 -0
  206. data/spec/unit/client/active_record/wns/badge_notification_spec.rb +15 -0
  207. data/spec/unit/client/active_record/wns/raw_notification_spec.rb +26 -0
  208. data/spec/unit/client/active_record/wpns/app_spec.rb +4 -0
  209. data/spec/unit/client/active_record/wpns/notification_spec.rb +21 -0
  210. data/spec/unit/configuration_spec.rb +46 -0
  211. data/spec/unit/daemon/adm/delivery_spec.rb +253 -0
  212. data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +11 -0
  213. data/spec/unit/daemon/apns/delivery_spec.rb +108 -0
  214. data/spec/unit/daemon/apns/feedback_receiver_spec.rb +119 -0
  215. data/spec/unit/daemon/app_runner_spec.rb +188 -0
  216. data/spec/unit/daemon/batch_spec.rb +169 -0
  217. data/spec/unit/daemon/delivery_error_spec.rb +13 -0
  218. data/spec/unit/daemon/delivery_spec.rb +51 -0
  219. data/spec/unit/daemon/dispatcher/http_spec.rb +34 -0
  220. data/spec/unit/daemon/dispatcher/tcp_spec.rb +32 -0
  221. data/spec/unit/daemon/dispatcher_loop_spec.rb +53 -0
  222. data/spec/unit/daemon/feeder_spec.rb +96 -0
  223. data/spec/unit/daemon/gcm/delivery_spec.rb +387 -0
  224. data/spec/unit/daemon/proc_title_spec.rb +11 -0
  225. data/spec/unit/daemon/pushy/delivery_spec.rb +159 -0
  226. data/spec/unit/daemon/retryable_error_spec.rb +14 -0
  227. data/spec/unit/daemon/service_config_methods_spec.rb +36 -0
  228. data/spec/unit/daemon/signal_handler_spec.rb +99 -0
  229. data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +165 -0
  230. data/spec/unit/daemon/store/active_record_spec.rb +357 -0
  231. data/spec/unit/daemon/store/redis_spec.rb +365 -0
  232. data/spec/unit/daemon/tcp_connection_spec.rb +292 -0
  233. data/spec/unit/daemon/wns/delivery_spec.rb +176 -0
  234. data/spec/unit/daemon/wns/post_request_spec.rb +117 -0
  235. data/spec/unit/daemon/wpns/delivery_spec.rb +167 -0
  236. data/spec/unit/daemon_spec.rb +138 -0
  237. data/spec/unit/deprecatable_spec.rb +32 -0
  238. data/spec/unit/deprecation_spec.rb +15 -0
  239. data/spec/unit/embed_spec.rb +47 -0
  240. data/spec/unit/logger_spec.rb +127 -0
  241. data/spec/unit/notification_shared.rb +53 -0
  242. data/spec/unit/plugin_spec.rb +36 -0
  243. data/spec/unit/push_spec.rb +34 -0
  244. data/spec/unit/reflectable_spec.rb +27 -0
  245. data/spec/unit/reflection_collection_spec.rb +26 -0
  246. data/spec/unit/rpush_spec.rb +8 -0
  247. data/spec/unit_spec_helper.rb +26 -0
  248. 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,15 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveModel
4
+ module Apns2
5
+ module App
6
+ extend Rpush::Client::ActiveModel::Apns::App
7
+
8
+ def service_name
9
+ 'apns2'
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveModel
4
+ module Apns2
5
+ include Rpush::Client::ActiveModel::Apns
6
+ end
7
+ end
8
+ end
9
+ 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,9 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveModel
4
+ module Apnsp8
5
+ include Rpush::Client::ActiveModel::Apns
6
+ end
7
+ end
8
+ end
9
+ 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,13 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveModel
4
+ module Wpns
5
+ module App
6
+ def service_name
7
+ 'wpns'
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ 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,11 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveRecord
4
+ module Adm
5
+ class App < Rpush::Client::ActiveRecord::App
6
+ include Rpush::Client::ActiveModel::Adm::App
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveRecord
4
+ module Adm
5
+ class Notification < Rpush::Client::ActiveRecord::Notification
6
+ include Rpush::Client::ActiveModel::Adm::Notification
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveRecord
4
+ module Apns
5
+ class App < Rpush::Client::ActiveRecord::App
6
+ include Rpush::Client::ActiveModel::Apns::App
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -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