11# -*- coding: utf-8 -*-
22
3- from __future__ import (print_function , unicode_literals , absolute_import ,
4- division )
3+ from __future__ import (
4+ print_function ,
5+ unicode_literals ,
6+ absolute_import ,
7+ division )
8+
9+ from pusher .util import (
10+ ensure_text ,
11+ validate_channel ,
12+ validate_socket_id ,
13+ join_attributes ,
14+ data_to_string )
15+
516from pusher .http import GET , POST , Request , request_method
6- from pusher .signature import sign , verify
7- from pusher .util import ensure_text , validate_channel , validate_socket_id , pusher_url_re , channel_name_re , join_attributes
817from pusher .client import Client
918
10-
1119import collections
1220import hashlib
1321import json
1826
1927
2028class PusherClient (Client ):
21- def __init__ (self , app_id , key , secret , ssl = True , host = None , port = None , timeout = 5 , cluster = None ,
22- json_encoder = None , json_decoder = None , backend = None , notification_host = None ,
23- notification_ssl = True , ** backend_options ):
29+ def __init__ (
30+ self , app_id , key , secret , ssl = True , host = None , port = None ,
31+ timeout = 5 , cluster = None , json_encoder = None , json_decoder = None ,
32+ backend = None , notification_host = None , notification_ssl = True ,
33+ ** backend_options ):
2434 super (PusherClient , self ).__init__ (
25- app_id , key , secret , ssl ,
26- host , port , timeout , cluster ,
27- json_encoder , json_decoder , backend ,
28- ** backend_options )
35+ app_id , key , secret , ssl , host , port , timeout , cluster ,
36+ json_encoder , json_decoder , backend , ** backend_options )
2937
3038 if host :
3139 self ._host = ensure_text (host , "host" )
40+
3241 elif cluster :
33- self ._host = six .text_type ("api-%s.pusher.com" ) % ensure_text (cluster , "cluster" )
42+ self ._host = six .text_type ("api-%s.pusher.com" ) %
43+ ensure_text (cluster , "cluster" )
44+
3445 else :
3546 self ._host = six .text_type ("api.pusherapp.com" )
3647
@@ -40,7 +51,8 @@ def trigger(self, channels, event_name, data, socket_id=None):
4051 if isinstance (channels , six .string_types ):
4152 channels = [channels ]
4253
43- if isinstance (channels , dict ) or not isinstance (channels , (collections .Sized , collections .Iterable )):
54+ if isinstance (channels , dict ) or not isinstance (
55+ channels , (collections .Sized , collections .Iterable )):
4456 raise TypeError ("Expected a single or a list of channels" )
4557
4658 if len (channels ) > 10 :
@@ -53,16 +65,16 @@ def trigger(self, channels, event_name, data, socket_id=None):
5365 if len (event_name ) > 200 :
5466 raise ValueError ("event_name too long" )
5567
56- data = self . _data_to_string (data )
68+ data = data_to_string (data , self . _json_encoder )
5769
5870 if len (data ) > 10240 :
5971 raise ValueError ("Too much data" )
6072
6173 params = {
6274 'name' : event_name ,
6375 'channels' : channels ,
64- 'data' : data
65- }
76+ 'data' : data }
77+
6678 if socket_id :
6779 params ['socket_id' ] = validate_socket_id (socket_id )
6880
@@ -79,13 +91,14 @@ def trigger_batch(self, batch=[], already_encoded=False):
7991
8092 if not already_encoded :
8193 for event in batch :
82- event ['data' ] = self ._data_to_string (event ['data' ])
94+ event ['data' ] = data_to_string (event ['data' ],
95+ self ._json_encoder )
8396
8497 params = {
85- 'batch' : batch
86- }
98+ 'batch' : batch }
8799
88- return Request (self , POST , "/apps/%s/batch_events" % self .app_id , params )
100+ return Request (
101+ self , POST , "/apps/%s/batch_events" % self .app_id , params )
89102
90103
91104 @request_method
@@ -98,9 +111,13 @@ def channels_info(self, prefix_filter=None, attributes=[]):
98111 params = {}
99112 if attributes :
100113 params ['info' ] = join_attributes (attributes )
114+
101115 if prefix_filter :
102- params ['filter_by_prefix' ] = ensure_text (prefix_filter , "prefix_filter" )
103- return Request (self , GET , six .text_type ("/apps/%s/channels" ) % self .app_id , params )
116+ params ['filter_by_prefix' ] = ensure_text (
117+ prefix_filter , "prefix_filter" )
118+
119+ return Request (
120+ self , GET , six .text_type ("/apps/%s/channels" ) % self .app_id , params )
104121
105122
106123 @request_method
@@ -115,7 +132,9 @@ def channel_info(self, channel, attributes=[]):
115132 params = {}
116133 if attributes :
117134 params ['info' ] = join_attributes (attributes )
118- return Request (self , GET , "/apps/%s/channels/%s" % (self .app_id , channel ), params )
135+
136+ return Request (
137+ self , GET , "/apps/%s/channels/%s" % (self .app_id , channel ), params )
119138
120139
121140 @request_method
@@ -127,77 +146,5 @@ def users_info(self, channel):
127146 '''
128147 validate_channel (channel )
129148
130- return Request (self , GET , "/apps/%s/channels/%s/users" % (self .app_id , channel ))
131-
132-
133- def authenticate (self , channel , socket_id , custom_data = None ):
134- """Used to generate delegated client subscription token.
135-
136- :param channel: name of the channel to authorize subscription to
137- :param socket_id: id of the socket that requires authorization
138- :param custom_data: used on presence channels to provide user info
139- """
140- channel = validate_channel (channel )
141-
142- if not channel_name_re .match (channel ):
143- raise ValueError ('Channel should be a valid channel, got: %s' % channel )
144-
145- socket_id = validate_socket_id (socket_id )
146-
147- if custom_data :
148- custom_data = json .dumps (custom_data , cls = self ._json_encoder )
149-
150- string_to_sign = "%s:%s" % (socket_id , channel )
151-
152- if custom_data :
153- string_to_sign += ":%s" % custom_data
154-
155- signature = sign (self .secret , string_to_sign )
156-
157- auth = "%s:%s" % (self .key , signature )
158- result = {'auth' : auth }
159-
160- if custom_data :
161- result ['channel_data' ] = custom_data
162-
163- return result
164-
165-
166- def validate_webhook (self , key , signature , body ):
167- """Used to validate incoming webhook messages. When used it guarantees
168- that the sender is Pusher and not someone else impersonating it.
169-
170- :param key: key used to sign the body
171- :param signature: signature that was given with the body
172- :param body: content that needs to be verified
173- """
174- key = ensure_text (key , "key" )
175- signature = ensure_text (signature , "signature" )
176- body = ensure_text (body , "body" )
177-
178- if key != self .key :
179- return None
180-
181- if not verify (self .secret , body , signature ):
182- return None
183-
184- try :
185- body_data = json .loads (body , cls = self ._json_decoder )
186- except ValueError :
187- return None
188-
189- time_ms = body_data .get ('time_ms' )
190- if not time_ms :
191- return None
192-
193- if abs (time .time ()* 1000 - time_ms ) > 300000 :
194- return None
195-
196- return body_data
197-
198-
199- def _data_to_string (self , data ):
200- if isinstance (data , six .string_types ):
201- return ensure_text (data , "data" )
202- else :
203- return json .dumps (data , cls = self ._json_encoder )
149+ return Request (
150+ self , GET , "/apps/%s/channels/%s/users" % (self .app_id , channel ))
0 commit comments