Push0r 0.4.4 → 0.5.0

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.
@@ -1,48 +1,48 @@
1
1
  module Push0r
2
- # FlushResult models the result of a single {Queue} flushing process.
3
- class FlushResult
4
- attr_reader :failed_messages
5
- attr_reader :new_token_messages
6
-
7
- def initialize(failed_message, new_token_messages)
8
- @failed_messages = failed_message
9
- @new_token_messages = new_token_messages
10
- end
11
-
12
- def to_s
13
- "FlushResult - Failed: #{@failed_messages.count} NewToken: #{@new_token_messages.count}"
14
- end
15
- end
16
-
17
- class FailedMessage
18
- attr_reader :error_code
19
- attr_reader :receivers
20
- attr_reader :message
21
-
22
- def initialize(error_code, receivers, message)
23
- @error_code = error_code
24
- @receivers = receivers
25
- @message = message
26
- end
27
-
28
- def to_s
29
- "FailedMessage: errorCode: #{@error_code} receivers: #{@receivers.inspect}"
30
- end
31
- end
32
-
33
- class NewTokenMessage
34
- attr_reader :message
35
- attr_reader :token
36
- attr_reader :new_token
37
-
38
- def initialize(token, new_token, message)
39
- @token = token
40
- @new_token = new_token
41
- @message = message
42
- end
43
-
44
- def to_s
45
- "NewTokenMessage: oldToken: #{@token} newToken: #{@new_token}"
46
- end
47
- end
2
+ # FlushResult models the result of a single {Queue} flushing process.
3
+ class FlushResult
4
+ attr_reader :failed_messages
5
+ attr_reader :new_token_messages
6
+
7
+ def initialize(failed_message, new_token_messages)
8
+ @failed_messages = failed_message
9
+ @new_token_messages = new_token_messages
10
+ end
11
+
12
+ def to_s
13
+ "FlushResult - Failed: #{@failed_messages.count} NewToken: #{@new_token_messages.count}"
14
+ end
15
+ end
16
+
17
+ class FailedMessage
18
+ attr_reader :error_code
19
+ attr_reader :receivers
20
+ attr_reader :message
21
+
22
+ def initialize(error_code, receivers, message)
23
+ @error_code = error_code
24
+ @receivers = receivers
25
+ @message = message
26
+ end
27
+
28
+ def to_s
29
+ "FailedMessage: errorCode: #{@error_code} receivers: #{@receivers.inspect}"
30
+ end
31
+ end
32
+
33
+ class NewTokenMessage
34
+ attr_reader :message
35
+ attr_reader :token
36
+ attr_reader :new_token
37
+
38
+ def initialize(token, new_token, message)
39
+ @token = token
40
+ @new_token = new_token
41
+ @message = message
42
+ end
43
+
44
+ def to_s
45
+ "NewTokenMessage: oldToken: #{@token} newToken: #{@new_token}"
46
+ end
47
+ end
48
48
  end
@@ -1,27 +1,27 @@
1
1
  module Push0r
2
- # GcmPushMessage is a {PushMessage} implementation that encapsulates a single push notification to be sent to a single or multiple users.
3
- class GcmPushMessage < PushMessage
4
-
5
- # Returns a new GcmPushMessage instance that encapsulates a single push notification to be sent to a single or multiple users.
6
- # @param receiver_token [Array<String>] the apns push tokens (aka registration ids) to push the notification to
7
- # @param identifier [Fixnum] a unique identifier to identify this push message during error handling. If nil, a random identifier is automatically generated.
8
- # @param time_to_live [Fixnum] The time to live in seconds for this push messages. If nil, the time to live is set to four weeks.
9
- def initialize(receiver_token, identifier = nil, time_to_live = nil)
10
- if identifier.nil? ## make sure the message has an identifier
11
- identifier = Random.rand(2**32)
12
- end
13
-
14
- # for GCM the receiver_token is an array, so make sure we convert a single string to an array containing that string :-)
15
- if receiver_token.is_a?(String)
16
- receiver_token = [receiver_token]
17
- end
18
-
19
- super(receiver_token, identifier, time_to_live)
20
-
21
- if time_to_live && time_to_live.to_i >= 0
22
- self.attach({"time_to_live" => time_to_live.to_i})
23
- end
24
- end
25
- end
2
+ # GcmPushMessage is a {PushMessage} implementation that encapsulates a single push notification to be sent to a single or multiple users.
3
+ class GcmPushMessage < PushMessage
4
+
5
+ # Returns a new GcmPushMessage instance that encapsulates a single push notification to be sent to a single or multiple users.
6
+ # @param receiver_token [Array<String>] the apns push tokens (aka registration ids) to push the notification to
7
+ # @param identifier [Fixnum] a unique identifier to identify this push message during error handling. If nil, a random identifier is automatically generated.
8
+ # @param time_to_live [Fixnum] The time to live in seconds for this push messages. If nil, the time to live is set to four weeks.
9
+ def initialize(receiver_token, identifier = nil, time_to_live = nil)
10
+ if identifier.nil? ## make sure the message has an identifier
11
+ identifier = Random.rand(2**32)
12
+ end
13
+
14
+ # for GCM the receiver_token is an array, so make sure we convert a single string to an array containing that string :-)
15
+ if receiver_token.is_a?(String)
16
+ receiver_token = [receiver_token]
17
+ end
18
+
19
+ super(receiver_token, identifier, time_to_live)
20
+
21
+ if time_to_live && time_to_live.to_i >= 0
22
+ self.attach({'time_to_live' => time_to_live.to_i})
23
+ end
24
+ end
25
+ end
26
26
  end
27
27
 
@@ -2,128 +2,130 @@ require 'net/http'
2
2
 
3
3
  module Push0r
4
4
 
5
- # A module that contains constants for Google Cloud Messaging error codes
6
- module GcmErrorCodes
7
- UNKNOWN_ERROR = 1
8
- INVALID_REGISTRATION = 2
9
- UNAVAILABLE = 3
10
- NOT_REGISTERED = 4
11
- MISMATCH_SENDER_ID = 5
12
- MISSING_REGISTRATION = 6
13
- MESSAGE_TOO_BIG = 7
14
- INVALID_DATA_KEY = 8
15
- INVALID_TTL = 9
16
- INVALID_PACKAGE_NAME = 10
17
- CONNECTION_ERROR = 11
18
- UNABLE_TO_PARSE_JSON = 400
19
- NOT_AUTHENTICATED = 401
20
- INTERNAL_ERROR = 500
21
- end
22
-
23
- # GcmService is a {Service} implementation to push notifications to Android users using the Google Cloud Messaging Service.
24
- # @example
25
- # queue = Push0r::Queue.new
26
- #
27
- # gcm_service = Push0r::GcmService.new("__gcm_api_token__")
28
- # queue.register_service(gcm_service)
29
- class GcmService < Service
30
-
31
- # Returns a new ApnsService instance
32
- # @param api_key [String] the GCM API key obtained from the Google Developers Console
33
- def initialize(api_key)
34
- @api_key = api_key
35
- @messages = []
36
- end
37
-
38
- # @see Service#can_send?
39
- def can_send?(message)
40
- return message.is_a?(GcmPushMessage)
41
- end
42
-
43
- # @see Service#send
44
- def send(message)
45
- @messages << message
46
- end
47
-
48
- # @see Service#init_push
49
- def init_push
50
- ## not used for gcm
51
- end
52
-
53
- # @see Service#end_push
54
- def end_push
55
- failed_messages = []
56
- new_registration_messages = []
57
-
58
- uri = URI.parse("https://android.googleapis.com/gcm/send")
59
- http = Net::HTTP.new(uri.host, uri.port)
60
- http.use_ssl = true
61
-
62
- @messages.each do |message|
63
- begin
64
- request = Net::HTTP::Post.new(uri.path, {"Content-Type" => "application/json", "Authorization" => "key=#{@api_key}"})
65
- request.body = message.attach({"registration_ids" => message.receiver_token}).payload.to_json
66
- response = http.request(request)
67
- rescue SocketError
68
- ## connection error
69
- failed_messages << FailedMessage.new(Push0r::GcmErrorCodes::CONNECTION_ERROR, message.receiver_token, message)
70
- next
71
- end
72
-
73
- if response.code.to_i == 200
74
- json = JSON.parse(response.body)
75
-
76
- if json["failure"].to_i > 0 || json["canonical_ids"].to_i > 0
77
- error_receivers = {}
78
-
79
- json["results"].each_with_index do |result,i|
80
- receiver_token = message.receiver_token[i]
81
- error = result["error"]
82
- message_id = result["message_id"]
83
- registration_id = result["registration_id"]
84
-
85
- if message_id && registration_id
86
- new_registration_messages << NewTokenMessage.new(receiver_token, registration_id, message)
87
- elsif error
88
- error_code = Push0r::GcmErrorCodes::UNKNOWN_ERROR
89
- if error == "InvalidRegistration"
90
- error_code = Push0r::GcmErrorCodes::INVALID_REGISTRATION
91
- elsif error == "Unavailable"
92
- error_code = Push0r::GcmErrorCodes::UNAVAILABLE
93
- elsif error == "NotRegistered"
94
- error_code = Push0r::GcmErrorCodes::NOT_REGISTERED
95
- elsif error == "MismatchSenderId"
96
- error_code = Push0r::GcmErrorCodes::MISMATCH_SENDER_ID
97
- elsif error == "MissingRegistration"
98
- error_code = Push0r::GcmErrorCodes::MISSING_REGISTRATION
99
- elsif error == "MessageTooBig"
100
- error_code = Push0r::GcmErrorCodes::MESSAGE_TOO_BIG
101
- elsif error == "InvalidDataKey"
102
- error_code = Push0r::GcmErrorCodes::INVALID_DATA_KEY
103
- elsif error == "InvalidTtl"
104
- error_code = Push0r::GcmErrorCodes::INVALID_TTL
105
- elsif error == "InvalidPackageName"
106
- error_code = Push0r::GcmErrorCodes::INVALID_PACKAGE_NAME
107
- end
108
- if error_receivers[error_code].nil? then error_receivers[error_code] = [] end
109
- error_receivers[error_code] << receiver_token
110
- end
111
- end
112
-
113
- ## if there are any receivers with errors: add a hash for every distinct error code and the related receivers to the failed_messages array
114
- error_receivers.each do |error_code, receivers|
115
- failed_messages << FailedMessage.new(error_code, receivers, message)
116
- end
117
- end
118
- elsif response.code.to_i >= 500 && response.code.to_i <= 599
119
- failed_messages << FailedMessage.new(Push0r::GcmErrorCodes::INTERNAL_ERROR, message.receiver_token, message)
120
- else
121
- failed_messages << FailedMessage.new(response.code.to_i, message.receiver_token, message)
122
- end
123
- end
124
-
125
- @messages = [] ## reset
126
- return [failed_messages, new_registration_messages]
127
- end
128
- end
5
+ # A module that contains constants for Google Cloud Messaging error codes
6
+ module GcmErrorCodes
7
+ UNKNOWN_ERROR = 1
8
+ INVALID_REGISTRATION = 2
9
+ UNAVAILABLE = 3
10
+ NOT_REGISTERED = 4
11
+ MISMATCH_SENDER_ID = 5
12
+ MISSING_REGISTRATION = 6
13
+ MESSAGE_TOO_BIG = 7
14
+ INVALID_DATA_KEY = 8
15
+ INVALID_TTL = 9
16
+ INVALID_PACKAGE_NAME = 10
17
+ CONNECTION_ERROR = 11
18
+ UNABLE_TO_PARSE_JSON = 400
19
+ NOT_AUTHENTICATED = 401
20
+ INTERNAL_ERROR = 500
21
+ end
22
+
23
+ # GcmService is a {Service} implementation to push notifications to Android users using the Google Cloud Messaging Service.
24
+ # @example
25
+ # queue = Push0r::Queue.new
26
+ #
27
+ # gcm_service = Push0r::GcmService.new("__gcm_api_token__")
28
+ # queue.register_service(gcm_service)
29
+ class GcmService < Service
30
+
31
+ # Returns a new ApnsService instance
32
+ # @param api_key [String] the GCM API key obtained from the Google Developers Console
33
+ def initialize(api_key)
34
+ @api_key = api_key
35
+ @messages = []
36
+ end
37
+
38
+ # @see Service#can_send?
39
+ def can_send?(message)
40
+ return message.is_a?(GcmPushMessage)
41
+ end
42
+
43
+ # @see Service#send
44
+ def send(message)
45
+ @messages << message
46
+ end
47
+
48
+ # @see Service#init_push
49
+ def init_push
50
+ ## not used for gcm
51
+ end
52
+
53
+ # @see Service#end_push
54
+ def end_push
55
+ failed_messages = []
56
+ new_registration_messages = []
57
+
58
+ uri = URI.parse('https://android.googleapis.com/gcm/send')
59
+ http = Net::HTTP.new(uri.host, uri.port)
60
+ http.use_ssl = true
61
+
62
+ @messages.each do |message|
63
+ begin
64
+ request = Net::HTTP::Post.new(uri.path, {'Content-Type' => 'application/json', 'Authorization' => "key=#{@api_key}"})
65
+ request.body = message.attach({'registration_ids' => message.receiver_token}).payload.to_json
66
+ response = http.request(request)
67
+ rescue SocketError
68
+ ## connection error
69
+ failed_messages << FailedMessage.new(Push0r::GcmErrorCodes::CONNECTION_ERROR, message.receiver_token, message)
70
+ next
71
+ end
72
+
73
+ if response.code.to_i == 200
74
+ json = JSON.parse(response.body)
75
+
76
+ if json['failure'].to_i > 0 || json['canonical_ids'].to_i > 0
77
+ error_receivers = {}
78
+
79
+ json['results'].each_with_index do |result, i|
80
+ receiver_token = message.receiver_token[i]
81
+ error = result['error']
82
+ message_id = result['message_id']
83
+ registration_id = result['registration_id']
84
+
85
+ if message_id && registration_id
86
+ new_registration_messages << NewTokenMessage.new(receiver_token, registration_id, message)
87
+ elsif error
88
+ error_code = Push0r::GcmErrorCodes::UNKNOWN_ERROR
89
+ if error == 'InvalidRegistration'
90
+ error_code = Push0r::GcmErrorCodes::INVALID_REGISTRATION
91
+ elsif error == 'Unavailable'
92
+ error_code = Push0r::GcmErrorCodes::UNAVAILABLE
93
+ elsif error == 'NotRegistered'
94
+ error_code = Push0r::GcmErrorCodes::NOT_REGISTERED
95
+ elsif error == 'MismatchSenderId'
96
+ error_code = Push0r::GcmErrorCodes::MISMATCH_SENDER_ID
97
+ elsif error == 'MissingRegistration'
98
+ error_code = Push0r::GcmErrorCodes::MISSING_REGISTRATION
99
+ elsif error == 'MessageTooBig'
100
+ error_code = Push0r::GcmErrorCodes::MESSAGE_TOO_BIG
101
+ elsif error == 'InvalidDataKey'
102
+ error_code = Push0r::GcmErrorCodes::INVALID_DATA_KEY
103
+ elsif error == 'InvalidTtl'
104
+ error_code = Push0r::GcmErrorCodes::INVALID_TTL
105
+ elsif error == 'InvalidPackageName'
106
+ error_code = Push0r::GcmErrorCodes::INVALID_PACKAGE_NAME
107
+ end
108
+ if error_receivers[error_code].nil? then
109
+ error_receivers[error_code] = []
110
+ end
111
+ error_receivers[error_code] << receiver_token
112
+ end
113
+ end
114
+
115
+ ## if there are any receivers with errors: add a hash for every distinct error code and the related receivers to the failed_messages array
116
+ error_receivers.each do |error_code, receivers|
117
+ failed_messages << FailedMessage.new(error_code, receivers, message)
118
+ end
119
+ end
120
+ elsif response.code.to_i >= 500 && response.code.to_i <= 599
121
+ failed_messages << FailedMessage.new(Push0r::GcmErrorCodes::INTERNAL_ERROR, message.receiver_token, message)
122
+ else
123
+ failed_messages << FailedMessage.new(response.code.to_i, message.receiver_token, message)
124
+ end
125
+ end
126
+
127
+ @messages = [] ## reset
128
+ return [failed_messages, new_registration_messages]
129
+ end
130
+ end
129
131
  end
@@ -1,33 +1,33 @@
1
1
  module Push0r
2
- # PushMessage is the base class for all implemented push message types. A PushMessage encapsulates values like the notification's payload, its receiver, etc.
3
- # @abstract
4
- # @attr_reader [Hash] payload the payload for this push message
5
- # @attr_reader [Fixnum] identifier the unique identifier for this push message
6
- # @attr_reader [String, Array] receiver_token the receiver's push token
7
- # @attr_reader [Fixnum] time_to_live the time to live in seconds for this push message
8
- class PushMessage
9
- attr_reader :payload, :identifier, :receiver_token, :time_to_live
2
+ # PushMessage is the base class for all implemented push message types. A PushMessage encapsulates values like the notification's payload, its receiver, etc.
3
+ # @abstract
4
+ # @attr_reader [Hash] payload the payload for this push message
5
+ # @attr_reader [Fixnum] identifier the unique identifier for this push message
6
+ # @attr_reader [String, Array] receiver_token the receiver's push token
7
+ # @attr_reader [Fixnum] time_to_live the time to live in seconds for this push message
8
+ class PushMessage
9
+ attr_reader :payload, :identifier, :receiver_token, :time_to_live
10
10
 
11
- # Creates a new PushMessage instance
12
- # @param receiver_token [String, Array] the receiver's push token. Some subclasses might also accept an Array of tokens.
13
- # @param identifier [Fixnum] a unique identifier to identify this push message during error handling. If nil, a random identifier is automatically generated.
14
- # @param time_to_live [Fixnum] The time to live in seconds for this push messages. If nil, the time to live depends on the service used to transmit the message.
15
- def initialize(receiver_token, identifier = nil, time_to_live = nil)
16
- @receiver_token = receiver_token
17
- @identifier = identifier
18
- @time_to_live = time_to_live
19
- @payload = {}
20
- end
11
+ # Creates a new PushMessage instance
12
+ # @param receiver_token [String, Array] the receiver's push token. Some subclasses might also accept an Array of tokens.
13
+ # @param identifier [Fixnum] a unique identifier to identify this push message during error handling. If nil, a random identifier is automatically generated.
14
+ # @param time_to_live [Fixnum] The time to live in seconds for this push messages. If nil, the time to live depends on the service used to transmit the message.
15
+ def initialize(receiver_token, identifier = nil, time_to_live = nil)
16
+ @receiver_token = receiver_token
17
+ @identifier = identifier
18
+ @time_to_live = time_to_live
19
+ @payload = {}
20
+ end
21
21
 
22
- # Attaches the given payload to the push message.
23
- # @note attaching is done using the merge! method of the Hash class, i.e. be careful not to overwrite previously set Hash keys.
24
- # @param payload [Hash] the payload to attach to the message.
25
- # @return [self] self
26
- def attach(payload = {})
27
- @payload.merge!(payload)
28
- return self
29
- end
30
- end
22
+ # Attaches the given payload to the push message.
23
+ # @note attaching is done using the merge! method of the Hash class, i.e. be careful not to overwrite previously set Hash keys.
24
+ # @param payload [Hash] the payload to attach to the message.
25
+ # @return [self] self
26
+ def attach(payload = {})
27
+ @payload.merge!(payload)
28
+ return self
29
+ end
30
+ end
31
31
  end
32
32
 
33
33
  require_relative 'APNS/ApnsPushMessage'