1
1
"""Pusher Push Notifications Python server SDK"""
2
2
3
+ import copy
3
4
import datetime
4
5
import json
5
6
import re
17
18
18
19
USER_ID_MAX_LENGTH = 164
19
20
AUTH_TOKEN_DURATION = datetime .timedelta (days = 1 )
21
+ MAX_NUMBER_OF_USER_IDS = 1000
20
22
21
23
22
24
class PusherError (Exception ):
@@ -40,6 +42,11 @@ class PusherServerError(PusherError, Exception):
40
42
error
41
43
"""
42
44
45
+ class PusherBadResponseError (PusherError , Exception ):
46
+ """Error thrown when the server returns a response the library cannot
47
+ understand
48
+ """
49
+
43
50
44
51
def handle_http_error (response_body , status_code ):
45
52
"""Handle different http error codes from the Push Notifications service"""
@@ -153,6 +160,7 @@ def publish(self, interests, publish_body):
153
160
+ 'numbers or one of _=@,.;-'
154
161
)
155
162
163
+ publish_body = copy .deepcopy (publish_body )
156
164
publish_body ['interests' ] = interests
157
165
session = requests .Session ()
158
166
request = requests .Request (
@@ -172,19 +180,118 @@ def publish(self, interests, publish_body):
172
180
)
173
181
174
182
response = session .send (request .prepare ())
183
+
184
+ if response .status_code != 200 :
185
+ try :
186
+ response_body = response .json ()
187
+ except ValueError :
188
+ response_body = {}
189
+ handle_http_error (response_body , response .status_code )
190
+
175
191
try :
176
192
response_body = response .json ()
177
193
except ValueError :
178
- response_body = {}
194
+ raise PusherBadResponseError (
195
+ 'The server returned a malformed response' ,
196
+ )
197
+
198
+ return response_body
199
+
200
+ def publish_to_users (self , user_ids , publish_body ):
201
+ """Publish the given publish_body to the specified users.
202
+
203
+ Args:
204
+ user_ids (list): List of ids of users that the publish body should
205
+ be sent to.
206
+ publish_body (dict): Dict containing the body of the push
207
+ notification publish request.
208
+ (see https://docs.pusher.com/push-notifications)
209
+
210
+ Returns:
211
+ A dict containing the publish response from the Pusher Push
212
+ Notifications service.
213
+ (see https://docs.pusher.com/push-notifications)
214
+
215
+ Raises:
216
+ PusherAuthError: if the secret_key is incorrect
217
+ PusherMissingInstanceError: if the instance_id is incorrect
218
+ PusherServerError: if the Push Notifications service returns
219
+ an error
220
+ PusherValidationError: if the publish_body is invalid
221
+ TypeError: if user_ids is not a list
222
+ TypeError: if publish_body is not a dict
223
+ TypeError: if any user id is not a string
224
+ ValueError: if len(user_ids) < 1
225
+ ValueError: if len(user_ids) is greater than the max
226
+ ValueError: if any user id length is greater than the max
227
+
228
+ """
229
+ if not isinstance (user_ids , list ):
230
+ raise TypeError ('user_ids must be a list' )
231
+ if not isinstance (publish_body , dict ):
232
+ raise TypeError ('publish_body must be a dictionary' )
233
+ if not user_ids :
234
+ raise ValueError ('Publishes must target at least one user' )
235
+ if len (user_ids ) > MAX_NUMBER_OF_USER_IDS :
236
+ raise ValueError (
237
+ 'Number of user ids ({}) exceeds maximum of {}' .format (
238
+ len (user_ids ),
239
+ MAX_NUMBER_OF_USER_IDS ,
240
+ ),
241
+ )
242
+ for user_id in user_ids :
243
+ if not isinstance (user_id , six .string_types ):
244
+ raise TypeError (
245
+ 'User id {} is not a string' .format (user_id )
246
+ )
247
+ if len (user_id ) > USER_ID_MAX_LENGTH :
248
+ raise ValueError (
249
+ 'User id "{}" is longer than the maximum of {} chars' .format (
250
+ user_id ,
251
+ USER_ID_MAX_LENGTH ,
252
+ )
253
+ )
254
+
255
+ publish_body = copy .deepcopy (publish_body )
256
+ publish_body ['users' ] = user_ids
257
+ session = requests .Session ()
258
+ request = requests .Request (
259
+ 'POST' ,
260
+ 'https://{}/publish_api/v1/instances/{}/publishes/users' .format (
261
+ self .endpoint ,
262
+ self .instance_id ,
263
+ ),
264
+ json = publish_body ,
265
+ headers = {
266
+ 'host' : self .endpoint ,
267
+ 'authorization' : 'Bearer {}' .format (self .secret_key ),
268
+ 'x-pusher-library' : 'pusher-push-notifications-python {}' .format (
269
+ SDK_VERSION ,
270
+ )
271
+ },
272
+ )
273
+
274
+ response = session .send (request .prepare ())
179
275
180
276
if response .status_code != 200 :
277
+ try :
278
+ response_body = response .json ()
279
+ except ValueError :
280
+ response_body = {}
181
281
handle_http_error (response_body , response .status_code )
182
282
283
+ try :
284
+ response_body = response .json ()
285
+ except ValueError :
286
+ raise PusherBadResponseError (
287
+ 'The server returned a malformed response' ,
288
+ )
289
+
183
290
return response_body
184
291
185
292
def authenticate_user (self , user_id ):
186
293
"""Generate an auth token which will allow devices to associate
187
- themselves with the given user id
294
+ themselves with the given user id
188
295
189
296
Args:
190
297
user_id (string): user id for which the token will be valid
0 commit comments