1
- import urllib
2
- import urllib2
1
+ import requests
3
2
import json
4
3
from collections import defaultdict
5
4
import time
6
5
import random
7
6
7
+ try :
8
+ from urllib import quote_plus
9
+ except ImportError :
10
+ from urllib .parse import quote_plus
11
+
12
+
8
13
GCM_URL = 'https://android.googleapis.com/gcm/send'
9
14
10
15
@@ -80,17 +85,14 @@ def urlencode_utf8(params):
80
85
UTF-8 safe variant of urllib.urlencode.
81
86
http://stackoverflow.com/a/8152242
82
87
"""
83
-
84
88
if hasattr (params , 'items' ):
85
89
params = params .items ()
86
-
87
90
params = (
88
91
'=' .join ((
89
- urllib . quote_plus (k .encode ('utf8' ), safe = '/' ),
90
- urllib . quote_plus (v .encode ('utf8' ), safe = '/' )
92
+ quote_plus (k .encode ('utf8' ), safe = '/' ),
93
+ quote_plus (v .encode ('utf8' ), safe = '/' )
91
94
)) for k , v in params
92
95
)
93
-
94
96
return '&' .join (params )
95
97
96
98
@@ -99,6 +101,8 @@ class GCM(object):
99
101
# Timeunit is milliseconds.
100
102
BACKOFF_INITIAL_DELAY = 1000
101
103
MAX_BACKOFF_DELAY = 1024000
104
+ # TTL in seconds
105
+ GCM_TTL = 2419200
102
106
103
107
def __init__ (self , api_key , url = GCM_URL , proxy = None ):
104
108
""" api_key : google api key
@@ -107,18 +111,20 @@ def __init__(self, api_key, url=GCM_URL, proxy=None):
107
111
"""
108
112
self .api_key = api_key
109
113
self .url = url
110
- if proxy :
111
- if isinstance (proxy , basestring ):
112
- protocol = url .split (':' )[0 ]
113
- proxy = {protocol : proxy }
114
114
115
- auth = urllib2 .HTTPBasicAuthHandler ()
116
- opener = urllib2 .build_opener (
117
- urllib2 .ProxyHandler (proxy ), auth , urllib2 .HTTPHandler )
118
- urllib2 .install_opener (opener )
115
+ if isinstance (proxy , str ):
116
+ protocol = url .split (':' )[0 ]
117
+ self .proxy = {protocol : proxy }
118
+ else :
119
+ self .proxy = proxy
120
+
121
+ self .headers = {
122
+ 'Authorization' : 'key=%s' % self .api_key ,
123
+ }
124
+
119
125
120
126
def construct_payload (self , registration_ids , data = None , collapse_key = None ,
121
- delay_while_idle = False , time_to_live = None , is_json = True , dry_run = False ):
127
+ delay_while_idle = False , time_to_live = None , is_json = True , dry_run = False ):
122
128
"""
123
129
Construct the dictionary mapping of parameters.
124
130
Encodes the dictionary into JSON if for json requests.
@@ -129,21 +135,19 @@ def construct_payload(self, registration_ids, data=None, collapse_key=None,
129
135
"""
130
136
131
137
if time_to_live :
132
- four_weeks_in_secs = 2419200
133
- if not (0 <= time_to_live <= four_weeks_in_secs ):
138
+ if not (0 <= time_to_live <= self .GCM_TTL ):
134
139
raise GCMInvalidTtlException ("Invalid time to live value" )
135
140
141
+ payload = {}
136
142
if is_json :
137
- payload = { 'registration_ids' : registration_ids }
143
+ payload [ 'registration_ids' ] = registration_ids
138
144
if data :
139
145
payload ['data' ] = data
140
146
else :
141
- payload = { 'registration_id' : registration_ids }
147
+ payload [ 'registration_id' ] = registration_ids
142
148
if data :
143
- plaintext_data = data .copy ()
144
- for k in plaintext_data .keys ():
145
- plaintext_data ['data.%s' % k ] = plaintext_data .pop (k )
146
- payload .update (plaintext_data )
149
+ for key , value in data .items ():
150
+ payload ['data.%s' % key ] = value
147
151
148
152
if delay_while_idle :
149
153
payload ['delay_while_idle' ] = delay_while_idle
@@ -172,39 +176,38 @@ def make_request(self, data, is_json=True):
172
176
:raises GCMConnectionException: if GCM is screwed
173
177
"""
174
178
175
- headers = {
176
- 'Authorization' : 'key=%s' % self .api_key ,
177
- }
178
- # Default Content-Type is defaulted to
179
+ # Default Content-Type is
179
180
# application/x-www-form-urlencoded;charset=UTF-8
180
181
if is_json :
181
- headers ['Content-Type' ] = 'application/json'
182
+ self . headers ['Content-Type' ] = 'application/json'
182
183
183
184
if not is_json :
184
185
data = urlencode_utf8 (data )
185
- req = urllib2 .Request (self .url , data , headers )
186
-
187
- try :
188
- response = urllib2 .urlopen (req ).read ()
189
- except urllib2 .HTTPError as e :
190
- if e .code == 400 :
191
- raise GCMMalformedJsonException (
192
- "The request could not be parsed as JSON" )
193
- elif e .code == 401 :
194
- raise GCMAuthenticationException (
195
- "There was an error authenticating the sender account" )
196
- elif e .code == 503 :
197
- raise GCMUnavailableException ("GCM service is unavailable" )
198
- else :
199
- error = "GCM service error: %d" % e .code
200
- raise GCMUnavailableException (error )
201
- except urllib2 .URLError as e :
202
- raise GCMConnectionException (
203
- "There was an internal error in the GCM server while trying to process the request" )
204
186
205
- if is_json :
206
- response = json .loads (response )
207
- return response
187
+ response = requests .post (
188
+ self .url , data = data , headers = self .headers ,
189
+ proxies = self .proxy
190
+ )
191
+ # Successful response
192
+ if response .status_code == 200 :
193
+ if is_json :
194
+ response = response .json ()
195
+ else :
196
+ response = response .content
197
+ return response
198
+
199
+ # Failures
200
+ if response .status_code == 400 :
201
+ raise GCMMalformedJsonException (
202
+ "The request could not be parsed as JSON" )
203
+ elif response .status_code == 401 :
204
+ raise GCMAuthenticationException (
205
+ "There was an error authenticating the sender account" )
206
+ elif response .status_code == 503 :
207
+ raise GCMUnavailableException ("GCM service is unavailable" )
208
+ else :
209
+ error = "GCM service error: %d" % response .status_code
210
+ raise GCMUnavailableException (error )
208
211
209
212
def raise_error (self , error ):
210
213
if error == 'InvalidRegistration' :
@@ -305,7 +308,6 @@ def json_request(self, registration_ids, data=None, collapse_key=None,
305
308
raise GCMTooManyRegIdsException (
306
309
"Exceded number of registration_ids" )
307
310
308
- attempt = 0
309
311
backoff = self .BACKOFF_INITIAL_DELAY
310
312
for attempt in range (retries ):
311
313
payload = self .construct_payload (
@@ -324,5 +326,4 @@ def json_request(self, registration_ids, data=None, collapse_key=None,
324
326
backoff *= 2
325
327
else :
326
328
break
327
-
328
329
return info
0 commit comments