def __init__(self, key, secure=True, secret=None, user_data=None, log_level=logging.INFO, daemon=True, port=None, reconnect_interval=10, custom_host=None, auto_sub=False, **thread_kwargs): self.key = key self.secret = secret self.user_data = user_data or {} self.channels = {} self.url = self._build_url(key, secure, port, custom_host) if auto_sub: reconnect_handler = self._reconnect_handler else: reconnect_handler = None self.connection = Connection(self._connection_handler, self.url, reconnect_handler=reconnect_handler, log_level=log_level, daemon=daemon, reconnect_interval=reconnect_interval, **thread_kwargs)
def __init__(self, key, cluster="", secure=True, secret="", user_data=None, user_data_string=None, log_level=logging.INFO, daemon=True, port=443, reconnect_interval=10, custom_host="", auto_sub=False, http_proxy_host="", http_proxy_port=0, http_no_proxy=None, http_proxy_auth=None, **thread_kwargs): """Initialize the Pusher instance. :param str or bytes key: :param str cluster: :param bool secure: :param bytes or str secret: :param Optional[Dict] user_data: :param str user_data_string: :param str log_level: :param bool daemon: :param int port: :param int or float reconnect_interval: :param str custom_host: :param bool auto_sub: :param stt http_proxy_host: :param int http_proxy_port: :param http_no_proxy: :param http_proxy_auth: :param Any thread_kwargs: """ # https://pusher.com/docs/clusters if cluster: self.host = "ws-{cluster}.pusher.com".format(cluster=cluster) else: self.host = "ws.pusherapp.com" self.key = key self.secret = secret self.user_data_string = user_data_string self.user_data = user_data or {} self.channels = {} self.url = self._build_url(secure, port, custom_host) if auto_sub: reconnect_handler = self._reconnect_handler else: reconnect_handler = None self.connection = Connection(self._connection_handler, self.url, reconnect_handler=reconnect_handler, log_level=log_level, daemon=daemon, reconnect_interval=reconnect_interval, socket_kwargs=dict(http_proxy_host=http_proxy_host, http_proxy_port=http_proxy_port, http_no_proxy=http_no_proxy, http_proxy_auth=http_proxy_auth, ping_timeout=100), **thread_kwargs)
def __init__(self, key, cluster=None, secure=True, secret=None, user_data=None, log_level=logging.INFO, daemon=True, port=None, reconnect_interval=10, custom_host=None, auto_sub=False, http_proxy_host=None, http_proxy_port=None, http_no_proxy=None, http_proxy_auth=None, **thread_kwargs): # https://pusher.com/docs/clusters if cluster: self.host = "ws-{cluster}.pusher.com".format(cluster=cluster) else: self.host = "ws.pusherapp.com" self.key = key self.secret = secret self.user_data = user_data or {} self.channels = {} self.url = self._build_url(key, secure, cluster, port, custom_host) if auto_sub: reconnect_handler = self._reconnect_handler else: reconnect_handler = None self.connection = Connection(self._connection_handler, self.url, reconnect_handler=reconnect_handler, log_level=log_level, daemon=daemon, reconnect_interval=reconnect_interval, socket_kwargs=dict( http_proxy_host=http_proxy_host, http_proxy_port=http_proxy_port, http_no_proxy=http_no_proxy, http_proxy_auth=http_proxy_auth), **thread_kwargs)
class Pusher(object): host = "ws.pusherapp.com" client_id = 'PythonPusherClient' protocol = 6 def __init__(self, key, secure=True, secret=None, user_data=None, log_level=logging.INFO, daemon=True, port=None, reconnect_interval=10, custom_host=None, **thread_kwargs): self.key = key self.secret = secret self.user_data = user_data or {} self.channels = {} self.url = self._build_url(key, secure, port, custom_host) self.connection = Connection(self._connection_handler, self.url, log_level=log_level, daemon=daemon, reconnect_interval=reconnect_interval, **thread_kwargs) def connect(self): """Connect to Pusher""" self.connection.start() def disconnect(self): """Disconnect from Pusher""" self.connection.disconnect() self.channels = {} def subscribe(self, channel_name, auth=None): """Subscribe to a channel :param channel_name: The name of the channel to subscribe to. :type channel_name: str :param auth: The token to use if authenticated externally. :type auth: str :rtype : Channel """ data = {'channel': channel_name} if auth is None: if channel_name.startswith('presence-'): data['auth'] = self._generate_presence_key( self.connection.socket_id, self.key, channel_name, self.secret, self.user_data) data['channel_data'] = json.dumps(self.user_data) elif channel_name.startswith('private-'): data['auth'] = self._generate_private_key( self.connection.socket_id, self.key, channel_name, self.secret) else: data['auth'] = auth self.connection.send_event('pusher:subscribe', data) self.channels[channel_name] = Channel(channel_name, self.connection) return self.channels[channel_name] def unsubscribe(self, channel_name): """Unsubscribe from a channel :param channel_name: The name of the channel to unsubscribe from. :type channel_name: str """ if channel_name in self.channels: self.connection.send_event('pusher:unsubscribe', { 'channel': channel_name, }) del self.channels[channel_name] def channel(self, channel_name): """Get an existing channel object by name :param channel_name: The name of the channel you want to retrieve :type channel_name: str :rtype: Channel or None """ return self.channels.get(channel_name) def _connection_handler(self, event_name, data, channel_name): if channel_name in self.channels: self.channels[channel_name]._handle_event(event_name, data) @staticmethod def _generate_private_key(socket_id, key, channel_name, secret): auth_key = "" if socket_id and key and channel_name and secret: subject = "%s:%s" % (socket_id, channel_name) h = hmac.new(secret.encode("utf-8"), subject.encode("utf-8"), hashlib.sha256) auth_key = "%s:%s" % (key, h.hexdigest()) return auth_key @staticmethod def _generate_presence_key(socket_id, key, channel_name, secret, user_data): auth_key = "" if socket_id and key and channel_name and secret and user_data: subject = "%s:%s:%s" % (socket_id, channel_name, json.dumps(user_data)) h = hmac.new(secret, subject, hashlib.sha256) auth_key = "%s:%s" % (key, h.hexdigest()) return auth_key @classmethod def _build_url(cls, key, secure, port=None, custom_host=None): path = "/app/%s?client=%s&version=%s&protocol=%s" % ( key, cls.client_id, VERSION, cls.protocol) proto = "ws" if custom_host is None: host = cls.host else: host = custom_host if secure: proto = "wss" if port is None: if secure: port = 443 else: port = 80 return "%s://%s:%s%s" % (proto, host, port, path)
class Pusher(object): host = "ws.pusherapp.com" client_id = "Pysher" protocol = 6 def __init__(self, key, cluster="", secure=True, secret="", user_data=None, log_level=logging.INFO, daemon=True, port=443, reconnect_interval=10, custom_host="", auto_sub=False, http_proxy_host="", http_proxy_port=0, http_no_proxy=None, http_proxy_auth=None, **thread_kwargs): """Initialize the Pusher instance. :param str or bytes key: :param str cluster: :param bool secure: :param bytes or str secret: :param Optional[Dict] user_data: :param str log_level: :param bool daemon: :param int port: :param int or float reconnect_interval: :param str custom_host: :param bool auto_sub: :param stt http_proxy_host: :param int http_proxy_port: :param http_no_proxy: :param http_proxy_auth: :param Any thread_kwargs: """ # https://pusher.com/docs/clusters if cluster: self.host = "ws-{cluster}.pusher.com".format(cluster=cluster) else: self.host = "ws.pusherapp.com" self.key = key self.secret = secret self.user_data = user_data or {} self.channels = {} self.url = self._build_url(secure, port, custom_host) if auto_sub: reconnect_handler = self._reconnect_handler else: reconnect_handler = None self.connection = Connection(self._connection_handler, self.url, reconnect_handler=reconnect_handler, log_level=log_level, daemon=daemon, reconnect_interval=reconnect_interval, socket_kwargs=dict( http_proxy_host=http_proxy_host, http_proxy_port=http_proxy_port, http_no_proxy=http_no_proxy, http_proxy_auth=http_proxy_auth, ping_timeout=100), **thread_kwargs) @property def key_as_bytes(self): return self.key if isinstance(self.key, bytes) else self.key.encode('UTF-8') @property def secret_as_bytes(self): return self.secret if isinstance( self.secret, bytes) else self.secret.encode('UTF-8') def connect(self): """Connect to Pusher""" self.connection.start() def disconnect(self, timeout=None): """Disconnect from Pusher""" self.connection.disconnect(timeout) self.channels = {} def subscribe(self, channel_name, auth=None): """Subscribe to a channel. :param str channel_name: The name of the channel to subscribe to. :param str auth: The token to use if authenticated externally. :rtype: pysher.Channel """ data = {'channel': channel_name} if auth is None: if channel_name.startswith('presence-'): data['auth'] = self._generate_presence_token(channel_name) data['channel_data'] = json.dumps(self.user_data) elif channel_name.startswith('private-'): data['auth'] = self._generate_auth_token(channel_name) else: data['auth'] = auth self.connection.send_event('pusher:subscribe', data) self.channels[channel_name] = Channel(channel_name, self.connection) return self.channels[channel_name] def unsubscribe(self, channel_name): """Unsubscribe from a channel :param str channel_name: The name of the channel to unsubscribe from. """ if channel_name in self.channels: self.connection.send_event('pusher:unsubscribe', { 'channel': channel_name, }) del self.channels[channel_name] def channel(self, channel_name): """Get an existing channel object by name :param str channel_name: The name of the channel you want to retrieve :rtype: pysher.Channel or None """ return self.channels.get(channel_name) def _connection_handler(self, event_name, data, channel_name): """Handle incoming data. :param str event_name: Name of the event. :param Any data: Data received. :param str channel_name: Name of the channel this event and data belongs to. """ if channel_name in self.channels: self.channels[channel_name]._handle_event(event_name, data) def _reconnect_handler(self): """Handle a reconnect.""" for channel_name, channel in self.channels.items(): data = {'channel': channel_name} if channel.auth: data['auth'] = channel.auth self.connection.send_event('pusher:subscribe', data) def _generate_auth_token(self, channel_name): """Generate a token for authentication with the given channel. :param str channel_name: Name of the channel to generate a signature for. :rtype: str """ subject = "{}:{}".format(self.connection.socket_id, channel_name) h = hmac.new(self.secret_as_bytes, subject.encode('utf-8'), hashlib.sha256) auth_key = "{}:{}".format(self.key, h.hexdigest()) return auth_key def _generate_presence_token(self, channel_name): """Generate a presence token. :param str channel_name: Name of the channel to generate a signature for. :rtype: str """ subject = "{}:{}:{}".format(self.connection.socket_id, channel_name, json.dumps(self.user_data)) h = hmac.new(self.secret_as_bytes, subject.encode('utf-8'), hashlib.sha256) auth_key = "{}:{}".format(self.key, h.hexdigest()) return auth_key def _build_url(self, secure=True, port=None, custom_host=None): path = "/app/{}?client={}&version={}&protocol={}".format( self.key, self.client_id, VERSION, self.protocol) proto = "wss" if secure else "ws" host = custom_host or self.host if not port: port = 443 if secure else 80 return "{}://{}:{}{}".format(proto, host, port, path)