1- import urllib
2- import urllib2
1+ import requests
32import json
43from collections import defaultdict
54import time
65import random
76
7+ try :
8+ from urllib import quote_plus
9+ except ImportError :
10+ from urllib .parse import quote_plus
11+
12+
813GCM_URL = 'https://android.googleapis.com/gcm/send'
914
1015
@@ -80,17 +85,14 @@ def urlencode_utf8(params):
8085 UTF-8 safe variant of urllib.urlencode.
8186 http://stackoverflow.com/a/8152242
8287 """
83-
8488 if hasattr (params , 'items' ):
8589 params = params .items ()
86-
8790 params = (
8891 '=' .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 = '/' )
9194 )) for k , v in params
9295 )
93-
9496 return '&' .join (params )
9597
9698
@@ -99,6 +101,8 @@ class GCM(object):
99101 # Timeunit is milliseconds.
100102 BACKOFF_INITIAL_DELAY = 1000
101103 MAX_BACKOFF_DELAY = 1024000
104+ # TTL in seconds
105+ GCM_TTL = 2419200
102106
103107 def __init__ (self , api_key , url = GCM_URL , proxy = None ):
104108 """ api_key : google api key
@@ -107,18 +111,20 @@ def __init__(self, api_key, url=GCM_URL, proxy=None):
107111 """
108112 self .api_key = api_key
109113 self .url = url
110- if proxy :
111- if isinstance (proxy , basestring ):
112- protocol = url .split (':' )[0 ]
113- proxy = {protocol : proxy }
114114
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+
119125
120126 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 ):
122128 """
123129 Construct the dictionary mapping of parameters.
124130 Encodes the dictionary into JSON if for json requests.
@@ -129,21 +135,19 @@ def construct_payload(self, registration_ids, data=None, collapse_key=None,
129135 """
130136
131137 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 ):
134139 raise GCMInvalidTtlException ("Invalid time to live value" )
135140
141+ payload = {}
136142 if is_json :
137- payload = { 'registration_ids' : registration_ids }
143+ payload [ 'registration_ids' ] = registration_ids
138144 if data :
139145 payload ['data' ] = data
140146 else :
141- payload = { 'registration_id' : registration_ids }
147+ payload [ 'registration_id' ] = registration_ids
142148 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
147151
148152 if delay_while_idle :
149153 payload ['delay_while_idle' ] = delay_while_idle
@@ -172,39 +176,38 @@ def make_request(self, data, is_json=True):
172176 :raises GCMConnectionException: if GCM is screwed
173177 """
174178
175- headers = {
176- 'Authorization' : 'key=%s' % self .api_key ,
177- }
178- # Default Content-Type is defaulted to
179+ # Default Content-Type is
179180 # application/x-www-form-urlencoded;charset=UTF-8
180181 if is_json :
181- headers ['Content-Type' ] = 'application/json'
182+ self . headers ['Content-Type' ] = 'application/json'
182183
183184 if not is_json :
184185 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" )
204186
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 )
208211
209212 def raise_error (self , error ):
210213 if error == 'InvalidRegistration' :
@@ -305,7 +308,6 @@ def json_request(self, registration_ids, data=None, collapse_key=None,
305308 raise GCMTooManyRegIdsException (
306309 "Exceded number of registration_ids" )
307310
308- attempt = 0
309311 backoff = self .BACKOFF_INITIAL_DELAY
310312 for attempt in range (retries ):
311313 payload = self .construct_payload (
@@ -324,5 +326,4 @@ def json_request(self, registration_ids, data=None, collapse_key=None,
324326 backoff *= 2
325327 else :
326328 break
327-
328329 return info
0 commit comments