Push0r 0.4.4 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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'