def connect(self): self.reader = Reader() self.writer = Writer() self._connect() buf = self.writer.start_stream( self.SERVER, "%s-%s-%d" % (PROTOCOL_DEVICE, PROTOCOL_VERSION, PORT)) self._write(buf) # Send features node features = Node("stream:features") features.add(Node("readreceipts")) features.add(Node("groups_v2")) features.add(Node("privacy")) features.add(Node("presence")) self._write(features) # Send auth node auth = Node("auth", mechanism="WAUTH-2", user=self.number) if self.auth_blob: encryption = AuthBlobEncryption(self.secret, self.auth_blob) logger.debug("Session Keys (re-using auth challenge): %s", [key.encode("hex") for key in encryption.keys]) self.reader.decrypt = encryption.decrypt # From WhatsAPI. It does not encrypt the data, but generates a MAC # based on the keys. data = "%s%s%s" % (self.number, self.auth_blob, utils.timestamp()) auth.data = encryption.encrypt("", False) + data self._write(auth) def on_success(node): self.auth_blob = node.data self.account_info = node.attributes if node["status"] == "expired": self._disconnect() raise LoginError("Account marked as expired.") self._write(Node("presence", name=self.nickname)) def on_failure(node): self._disconnect() raise LoginError("Incorrect number and/or secret.") # Wait for either success, or failure self.register_callback_and_wait(LoginSuccessCallback(on_success), LoginFailedCallback(on_failure))
def __init__(self, number, secret, nickname=None, keep_alive=True): self.number = number self.secret = secret self.nickname = nickname self.addrinfo = None self.portindex = 0 self.debug = False self.socket = None self.reader = Reader() self.writer = Writer() self.messages = [] self.account_info = None self.last_ping = time() self.keep_alive = keep_alive self.callbacks = {}