Exemple #1
0
    def validate_webhook(self, key, signature, body):
        """Used to validate incoming webhook messages. When used it guarantees
        that the sender is Pusher and not someone else impersonating it.

        :param key: key used to sign the body
        :param signature: signature that was given with the body
        :param body: content that needs to be verified
        """
        key = ensure_text(key, "key")
        signature = ensure_text(signature, "signature")
        body = ensure_text(body, "body")

        if key != self.key:
            return None

        if not verify(self.secret, body, signature):
            return None

        try:
            body_data = json.loads(body, cls=self._json_decoder)

        except ValueError:
            return None

        time_ms = body_data.get('time_ms')
        if not time_ms:
            return None

        if abs(time.time()*1000 - time_ms) > 300000:
            return None

        return body_data
    def __init__(self, app_id, key, secret, ssl=True, host=None, port=None, timeout=5, cluster=None,
                 json_encoder=None, json_decoder=None, backend=RequestsBackend, **backend_options):
        self._app_id = ensure_text(app_id, "app_id")
        if not app_id_re.match(self._app_id):
            raise ValueError("Invalid app id")

        self._key = ensure_text(key, "key")
        self._secret = ensure_text(secret, "secret")

        if not isinstance(ssl, bool):
            raise TypeError("SSL should be a boolean")
        self._ssl = ssl

        if host:
            self._host = ensure_text(host, "host")
        elif cluster:
            self._host = six.text_type("api-%s.pusher.com") % ensure_text(cluster, "cluster")
        else:
            self._host = six.text_type("api.pusherapp.com")

        if port and not isinstance(port, six.integer_types):
            raise TypeError("port should be an integer")
        self._port = port or (443 if ssl else 80)

        if not isinstance(timeout, six.integer_types):
            raise TypeError("timeout should be an integer")
        self._timeout = timeout
        self._json_encoder = json_encoder
        self._json_decoder = json_decoder

        self.http = backend(self, **backend_options)
Exemple #3
0
    def __init__(
            self, app_id, key, secret, ssl=True, host=None, port=None,
            timeout=5, cluster=None, json_encoder=None, json_decoder=None,
            backend=None, **backend_options):
        if backend is None:
              from .requests import RequestsBackend
              backend = RequestsBackend

        self._app_id = ensure_text(app_id, "app_id")
        if not app_id_re.match(self._app_id):
              raise ValueError("Invalid app id")

        self._key = ensure_text(key, "key")
        self._secret = ensure_text(secret, "secret")

        if not isinstance(ssl, bool):
              raise TypeError("SSL should be a boolean")

        self._ssl = ssl

        if port and not isinstance(port, six.integer_types):
              raise TypeError("port should be an integer")

        self._port = port or (443 if ssl else 80)

        if not isinstance(timeout, six.integer_types):
              raise TypeError("timeout should be an integer")

        self._timeout = timeout
        self._json_encoder = json_encoder
        self._json_decoder = json_decoder

        self.http = backend(self, **backend_options)
Exemple #4
0
    def __init__(self,
                 app_id,
                 key,
                 secret,
                 ssl=True,
                 host=None,
                 port=None,
                 timeout=5,
                 cluster=None,
                 json_encoder=None,
                 json_decoder=None,
                 backend=None,
                 **backend_options):
        super(PusherClient,
              self).__init__(app_id, key, secret, ssl, host, port, timeout,
                             cluster, json_encoder, json_decoder, backend,
                             **backend_options)

        if host:
            self._host = ensure_text(host, "host")

        elif cluster:
            self._host = (six.text_type("api-%s.pusher.com") %
                          ensure_text(cluster, "cluster"))
        else:
            self._host = six.text_type("api.pusherapp.com")
    def validate_webhook(self, key, signature, body):
        """Used to validate incoming webhook messages. When used it guarantees
        that the sender is Pusher and not someone else impersonating it.

        :param key: key used to sign the body
        :param signature: signature that was given with the body
        :param body: content that needs to be verified
        """
        key = ensure_text(key, "key")
        signature = ensure_text(signature, "signature")
        body = ensure_text(body, "body")

        if key != self.key:
            return None

        if not verify(self.secret, body, signature):
            return None

        try:
            body_data = json.loads(body, cls=self._json_decoder)
        except ValueError:
            return None

        time_ms = body_data.get('time_ms')
        if not time_ms:
            return None

        if abs(time.time()*1000 - time_ms) > 300000:
            return None

        return body_data
    def __init__(self,
                 app_id,
                 key,
                 secret,
                 ssl=True,
                 host=None,
                 port=None,
                 timeout=5,
                 cluster=None,
                 encryption_master_key=None,
                 json_encoder=None,
                 json_decoder=None,
                 backend=None,
                 max_num_channels=None,
                 max_len_event_name=None,
                 max_len_data=None,
                 **backend_options):
        super(PusherClient,
              self).__init__(app_id, key, secret, ssl, host, port, timeout,
                             cluster, encryption_master_key, json_encoder,
                             json_decoder, backend, **backend_options)

        self.max_num_channels = max_num_channels if max_num_channels is not None else 100
        self.max_len_event_name = max_len_event_name if max_len_event_name is not None else 200
        self.max_len_data = max_len_data if max_len_data is not None else 10240

        if host:
            self._host = ensure_text(host, "host")

        elif cluster:
            self._host = (six.text_type("api-%s.pusher.com") %
                          ensure_text(cluster, "cluster"))
        else:
            self._host = six.text_type("api.pusherapp.com")
Exemple #7
0
    def __init__(self,
                 app_id,
                 key,
                 secret,
                 ssl=True,
                 host=None,
                 port=None,
                 timeout=5,
                 cluster=None,
                 encryption_master_key=None,
                 encryption_master_key_base64=None,
                 json_encoder=None,
                 json_decoder=None,
                 backend=None,
                 **backend_options):

        if backend is None:
            from .requests import RequestsBackend
            backend = RequestsBackend

        self._app_id = ensure_text(app_id, "app_id")
        if not app_id_re.match(self._app_id):
            raise ValueError("Invalid app id")

        self._key = ensure_text(key, "key")
        self._secret = ensure_text(secret, "secret")

        if not isinstance(ssl, bool):
            raise TypeError("SSL should be a boolean")

        self._ssl = ssl

        if host:
            self._host = ensure_text(host, "host")
        elif cluster:
            self._host = (six.text_type("api-%s.pusher.com") %
                          ensure_text(cluster, "cluster"))
        else:
            self._host = six.text_type("api.pusherapp.com")

        if port and not isinstance(port, six.integer_types):
            raise TypeError("port should be an integer")

        self._port = port or (443 if ssl else 80)

        if not isinstance(timeout, six.integer_types):
            raise TypeError("timeout should be an integer")

        self._timeout = timeout
        self._json_encoder = json_encoder
        self._json_decoder = json_decoder

        self._encryption_master_key = parse_master_key(
            encryption_master_key, encryption_master_key_base64)

        self.http = backend(self, **backend_options)
Exemple #8
0
    def __init__(self,
                 app_id,
                 key,
                 secret,
                 ssl=True,
                 host=None,
                 port=None,
                 timeout=5,
                 cluster=None,
                 encryption_master_key=None,
                 json_encoder=None,
                 json_decoder=None,
                 backend=None,
                 **backend_options):
        if backend is None:
            from .requests import RequestsBackend
            backend = RequestsBackend

        self._app_id = ensure_text(app_id, "app_id")
        if not app_id_re.match(self._app_id):
            raise ValueError("Invalid app id")

        self._key = ensure_text(key, "key")
        self._secret = ensure_text(secret, "secret")

        if not isinstance(ssl, bool):
            raise TypeError("SSL should be a boolean")

        self._ssl = ssl

        if port and not isinstance(port, six.integer_types):
            raise TypeError("port should be an integer")

        self._port = port or (443 if ssl else 80)

        if not isinstance(timeout, six.integer_types):
            raise TypeError("timeout should be an integer")

        self._timeout = timeout
        self._json_encoder = json_encoder
        self._json_decoder = json_decoder

        if encryption_master_key is not None:
            encryption_master_key = ensure_binary(encryption_master_key,
                                                  "encryption_master_key")

        self._encryption_master_key = encryption_master_key

        self.http = backend(self, **backend_options)
    def trigger_batch(self, batch=[], already_encoded=False):
        """Trigger multiple events with a single HTTP call.

        http://pusher.com/docs/rest_api#method-post-batch-events
        """
        if not already_encoded:
            for event in batch:

                validate_channel(event['channel'])

                event_name = ensure_text(event['name'], "event_name")
                if len(event['name']) > 200:
                    raise ValueError("event_name too long")

                event['data'] = data_to_string(event['data'], self._json_encoder)

                if len(event['data']) > 10240:
                    raise ValueError("Too much data")

                if is_encrypted_channel(event['channel']):
                    event['data'] = json.dumps(encrypt(event['channel'], event['data'], self._encryption_master_key), ensure_ascii=False)

        params = {
            'batch': batch}

        return Request(
            self, POST, "/apps/%s/batch_events" % self.app_id, params)
Exemple #10
0
    def from_url(cls, url, **options):
        """Alternative constructor that extracts the information from a URL.

        :param url: String containing a URL

        Usage::

          >> from pusher import Pusher
          >> p =
            Pusher.from_url("http://*****:*****@api.pusher.com/apps/432")
        """
        m = pusher_url_re.match(ensure_text(url, "url"))
        if not m:
            raise Exception("Unparsable url: %s" % url)

        ssl = m.group(1) == 'https'

        options_ = {
            'key': m.group(2),
            'secret': m.group(3),
            'host': m.group(4),
            'app_id': m.group(5),
            'ssl': ssl}

        options_.update(options)

        return cls(**options_)
    def trigger_batch(self, batch=[], already_encoded=False):
        """Trigger multiple events with a single HTTP call.

        http://pusher.com/docs/rest_api#method-post-batch-events
        """
        if not already_encoded:
            for event in batch:
                validate_channel(event['channel'])

                event_name = ensure_text(event['name'], "event_name")
                if len(event['name']) > 200:
                    raise ValueError("event_name too long")

                event['data'] = data_to_string(event['data'],
                                               self._json_encoder)

                if len(event['data']) > 10240:
                    raise ValueError("Too much data")

                if is_encrypted_channel(event['channel']):
                    event['data'] = json.dumps(encrypt(
                        event['channel'], event['data'],
                        self._encryption_master_key),
                                               ensure_ascii=False)

        params = {'batch': batch}

        return Request(self, POST, "/apps/%s/batch_events" % self.app_id,
                       params)
Exemple #12
0
    def trigger(self, channels, event_name, data, socket_id=None):
        """Trigger an event on one or more channels, see:

        http://pusher.com/docs/rest_api#method-post-event
        """
        if isinstance(channels, six.string_types):
            channels = [channels]

        if isinstance(channels, dict) or not isinstance(
                channels, (collections.Sized, collections.Iterable)):
            raise TypeError("Expected a single or a list of channels")

        if len(channels) > 10:
            raise ValueError("Too many channels")

        channels = list(map(validate_channel, channels))

        event_name = ensure_text(event_name, "event_name")

        if len(event_name) > 200:
            raise ValueError("event_name too long")

        data = data_to_string(data, self._json_encoder)

        if len(data) > 10240:
            raise ValueError("Too much data")

        params = {'name': event_name, 'channels': channels, 'data': data}

        if socket_id:
            params['socket_id'] = validate_socket_id(socket_id)

        return Request(self, POST, "/apps/%s/events" % self.app_id, params)
Exemple #13
0
    def __init__(
            self, app_id, key, secret, ssl=True, host=None, port=None,
            timeout=5, cluster=None, json_encoder=None, json_decoder=None,
            backend=None, **backend_options):
        super(AuthenticationClient, self).__init__(
            app_id, key, secret, ssl, host, port, timeout, cluster,
            json_encoder, json_decoder, backend, **backend_options)

        if host:
            self._host = ensure_text(host, "host")

        elif cluster:
            self._host = (
                six.text_type("api-%s.pusher.com") %
                ensure_text(cluster, "cluster"))
        else:
            self._host = six.text_type("api.pusherapp.com")
Exemple #14
0
    def channels_info(self, prefix_filter=None, attributes=[]):
        '''
        Get information on multiple channels, see:

        http://pusher.com/docs/rest_api#method-get-channels
        '''
        params = {}
        if attributes:
            params['info'] = join_attributes(attributes)
        if prefix_filter:
            params['filter_by_prefix'] = ensure_text(prefix_filter, "prefix_filter")
        return Request(self, GET, six.text_type("/apps/%s/channels") % self.app_id, params)
Exemple #15
0
    def trigger(self, channels, event_name, data, socket_id=None):
        '''
        Trigger an event on one or more channels, see:

        http://pusher.com/docs/rest_api#method-post-event
        '''
        
        if isinstance(channels, six.string_types):
            channels = [channels]

        if isinstance(channels, dict) or not isinstance(channels, (collections.Sized, collections.Iterable)):
            raise TypeError("Expected a single or a list of channels")

        if len(channels) > 10:
            raise ValueError("Too many channels")

        channels = list(map(validate_channel, channels))

        event_name = ensure_text(event_name, "event_name")

        if len(event_name) > 200:
            raise ValueError("event_name too long")

        if isinstance(data, six.string_types):
            data = ensure_text(data, "data")
        else:
            data = json.dumps(data, cls=self._json_encoder)

        if len(data) > 10240:
            raise ValueError("Too much data")

        params = {
            'name': event_name,
            'channels': channels,
            'data': data
        }
        if socket_id:
            params['socket_id'] = validate_socket_id(socket_id)

        return Request(self, POST, "/apps/%s/events" % self.app_id, params)
Exemple #16
0
    def __init__(
            self, app_id, key, secret, ssl=True, host=None, port=None,
            timeout=5, cluster=None, json_encoder=None, json_decoder=None,
            backend=None, **backend_options):
        super(NotificationClient, self).__init__(
            app_id, key, secret, ssl, host, port, timeout, cluster,
            json_encoder, json_decoder, backend, **backend_options)

        if host:
            self._host = ensure_text(host, "host")

        else:
            self._host = DEFAULT_HOST
    def __init__(
            self, app_id, key, secret, ssl=True, host=None, port=None,
            timeout=30, cluster=None, encryption_master_key=None, json_encoder=None, json_decoder=None,
            backend=None, **backend_options):
        super(NotificationClient, self).__init__(
            app_id, key, secret, ssl, host, port, timeout, cluster, encryption_master_key,
            json_encoder, json_decoder, backend, **backend_options)

        if host:
            self._host = ensure_text(host, "host")

        else:
            self._host = DEFAULT_HOST
Exemple #18
0
    def channels_info(self, prefix_filter=None, attributes=[]):
        """Get information on multiple channels, see:

        http://pusher.com/docs/rest_api#method-get-channels
        """
        params = {}
        if attributes:
            params['info'] = join_attributes(attributes)

        if prefix_filter:
            params['filter_by_prefix'] = ensure_text(
                prefix_filter, "prefix_filter")

        return Request(
            self, GET, six.text_type("/apps/%s/channels") % self.app_id, params)
    def trigger(self, channels, event_name, data, socket_id=None):
        """Trigger an event on one or more channels, see:

        http://pusher.com/docs/rest_api#method-post-event
        """
        if isinstance(channels, six.string_types):
            channels = [channels]

        if isinstance(channels, dict) or not isinstance(
                channels, (collections.Sized, collections.Iterable)):
            raise TypeError("Expected a single or a list of channels")

        if len(channels) > self.max_num_channels:
            raise ValueError("Too many channels")

        event_name = ensure_text(event_name, "event_name")
        if len(event_name) > self.max_len_event_name:
            raise ValueError("event_name too long")

        data = data_to_string(data, self._json_encoder)
        if len(data) > self.max_len_data:
            raise ValueError("Too much data")

        channels = list(map(validate_channel, channels))

        if len(channels) > 1:
            for chan in channels:
                if is_encrypted_channel(chan):
                    raise ValueError(
                        "You cannot trigger to multiple channels when using encrypted channels"
                    )

        if is_encrypted_channel(channels[0]):
            data = json.dumps(encrypt(channels[0], data,
                                      self._encryption_master_key),
                              ensure_ascii=False)

        params = {'name': event_name, 'channels': channels, 'data': data}

        if socket_id:
            params['socket_id'] = validate_socket_id(socket_id)

        return Request(self, POST, "/apps/%s/events" % self.app_id, params)
    def trigger(self, channels, event_name, data, socket_id=None):
        """Trigger an event on one or more channels, see:

        http://pusher.com/docs/rest_api#method-post-event
        """
        if isinstance(channels, six.string_types):
            channels = [channels]

        if isinstance(channels, dict) or not isinstance(
                channels, (collections.Sized, collections.Iterable)):
            raise TypeError("Expected a single or a list of channels")

        if len(channels) > 100:
            raise ValueError("Too many channels")

        event_name = ensure_text(event_name, "event_name")
        if len(event_name) > 200:
            raise ValueError("event_name too long")

        data = data_to_string(data, self._json_encoder)
        if len(data) > 10240:
            raise ValueError("Too much data")

        channels = list(map(validate_channel, channels))

        if len(channels) > 1:
            for chan in channels:
                if is_encrypted_channel(chan):
                    raise ValueError("You cannot trigger to multiple channels when using encrypted channels")

        if is_encrypted_channel(channels[0]):
            data = json.dumps(encrypt(channels[0], data, self._encryption_master_key), ensure_ascii=False)

        params = {
            'name': event_name,
            'channels': channels,
            'data': data}

        if socket_id:
            params['socket_id'] = validate_socket_id(socket_id)

        return Request(self, POST, "/apps/%s/events" % self.app_id, params)
 def _data_to_string(self, data):
     if isinstance(data, six.string_types):
         return ensure_text(data, "data")
     else:
         return json.dumps(data, cls=self._json_encoder)