class WAXMPP(): message_store = None def __init__(self,domain,resource,user,push_name,password): WADebug.attach(self); self.domain = domain; self.resource = resource; self.user=user; self.push_name=push_name; self.password = password; self.jid = user+'@'+domain self.fromm = user+'@'+domain+'/'+resource; self.supports_receipt_acks = False; self.msg_id = 0; self.state = 0 #0 disconnected 1 connecting 2 connected self.retry = True self.eventHandler = WAEventHandler(self); self.conn =MySocketConnection(); self.stanzaReader = None self.login = None; self.disconnectRequested = False self.connTries = 0; self.verbose = True self.iqId = 0; self.lock = threading.Lock() self.waiting = 0; #super(WAXMPP,self).__init__(); self.eventHandler.initialConnCheck(); #self.do_login(); def setContactsManager(self,contactsManager): self.contactsManager = contactsManager def setReceiptAckCapable(self,can): #print "Switching to True" self.supports_receipt_acks = True; #print self.supports_receipt_acks def onLoginSuccess(self): self.changeState(4) self.connectionTries = 0 c = StanzaReader(self); c.setEventHandler(self.eventHandler); #initial presence self.stanzaReader = c self.stanzaReader.start(); self.sendClientConfig('','',False,''); self.sendAvailableForChat(); self.eventHandler.connected.emit(); def onConnectionError(self): self.login.wait() self.conn.close() self.changeState(3) ''' if self.connTries < 4: print "trying connect "+str(self.connTries) self.retryLogin() else: print "Too many tries, trying in 30000" t = QTimer.singleShot(30000,self.retryLogin) ''' def disconnect(self): self.conn.close() def retryLogin(self): self.changeState(3); def changeState(self,newState): self._d("Entering critical area") self.waiting+=1 self.lock.acquire() self.waiting-=1 self._d("inside critical area") if self.state == 0: if newState == 2: self.state = 1 self.do_login(); elif self.state == 1: #raise Exception("mutex violated! I SHOULDN'T BE HERE !!!") if newState == 0: self.retry = False elif newState == 2: self.retry = True elif newState == 3: #failed if self.retry: if self.connTries >= 3: self._d("%i or more failed connections. Will try again in 30 seconds" % self.connTries) QTimer.singleShot(30000,self.retryLogin) self.connTries-=1 else: self.do_login() self.connTries+=1 else: self.connTries = 0 self.state = 0 self.retry = True elif newState == 4:#connected self.connTries = 0 self.retry = True self.state = 2 elif self.state == 2: if newState == 2: self.disconnect() self.state = 1 self.do_login() elif newState == 0: self.disconnect() self.state = 0 self._d("Releasing lock") self.lock.release() def do_login(self): self.conn = conn = MySocketConnection(); #conn.connect((HOST, PORT)); self.inn = BinTreeNodeReader(conn,WALogin.dictionary); self.out = BinTreeNodeWriter(conn,WALogin.dictionary); self.login = WALogin(conn,self.inn,self.out,S40MD5Digest()); self.login.setConnection(self); self.login.loginSuccess.connect(self.onLoginSuccess) self.login.loginFailed.connect(self.eventHandler.onLoginFailed); self.login.connectionError.connect(self.onConnectionError) self.login.start(); '''try: self.login.login(); except: print "LOGIN FAILED" #sys.exit() return ''' #fmsg = FMessage(); #fmsg.setData('*****@*****.**',True,"Hello World"); #self.sendIq(); #self.inn.nextTree(); #print self.inn.inn.buf; #exit(); #self.inn.nextTree(); #self.sendMessageWithBody("ok"); #node = self.inn.nextTree(); #print node.toString(); #self.sendSubscribe("*****@*****.**"); #self.sendMessageWithBody("OK"); #self.sendMessageWithBody("OK"); #node = self.inn.nextTree(); #print node.toString(); #raw_input(); #self.sendMessageWithBody(fmsg); def resendUnsent(self): ''' Resends all unsent messages, should invoke on connect ''' messages = WAXMPP.message_store.getUnsent(); self._d("Resending %i old messages"%(len(messages))) for m in messages: self.sendMessageWithBody(m); def sendTyping(self,jid): self._d("SEND TYPING TO JID") composing = ProtocolTreeNode("composing",{"xmlns":"http://jabber.org/protocol/chatstates"}) message = ProtocolTreeNode("message",{"to":jid,"type":"chat"},[composing]); self.out.write(message); def sendPaused(self,jid): self._d("SEND PAUSED TO JID") composing = ProtocolTreeNode("paused",{"xmlns":"http://jabber.org/protocol/chatstates"}) message = ProtocolTreeNode("message",{"to":jid,"type":"chat"},[composing]); self.out.write(message); def getSubjectMessage(self,to,msg_id,child): messageNode = ProtocolTreeNode("message",{"to":to,"type":"subject","id":msg_id},[child]); return messageNode def sendSubjectReceived(self,to,msg_id): self._d("Sending subject recv receipt") receivedNode = ProtocolTreeNode("received",{"xmlns": "urn:xmpp:receipts"}); messageNode = self.getSubjectMessage(to,msg_id,receivedNode); self.out.write(messageNode); def sendMessageReceived(self,fmsg): receivedNode = ProtocolTreeNode("received",{"xmlns": "urn:xmpp:receipts"}) messageNode = ProtocolTreeNode("message",{"to":fmsg.key.remote_jid,"type":"chat","id":fmsg.key.id},[receivedNode]); self.out.write(messageNode); def sendDeliveredReceiptAck(self,to,msg_id): self.out.write(self.getReceiptAck(to,msg_id,"delivered")); def sendVisibleReceiptAck(self,to,msg_id): self.out.write(self.getReceiptAck(to,msg_id,"visible")); def getReceiptAck(self,to,msg_id,receiptType): ackNode = ProtocolTreeNode("ack",{"xmlns":"urn:xmpp:receipts","type":receiptType}) messageNode = ProtocolTreeNode("message",{"to":to,"type":"chat","id":msg_id},[ackNode]); return messageNode; def makeId(self,prefix): self.iqId += 1 idx = "" if self.verbose: idx += prefix + str(self.iqId); else: idx = "%x" % self.iqId return idx def sendPing(self): idx = self.makeId("ping_") self.stanzaReader.requests[idx] = self.stanzaReader.handlePingResponse; pingNode = ProtocolTreeNode("ping",{"xmlns":"w:p"}); iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":self.domain},[pingNode]); self.out.write(iqNode); def sendPong(self,idx): iqNode = ProtocolTreeNode("iq",{"type":"result","to":self.domain,"id":idx}) self.out.write(iqNode); def getLastOnline(self,jid): if len(jid.split('-')) == 2: #SUPER CANCEL SUBSCRIBE TO GROUP return self.sendSubscribe(jid); self._d("presence request Initiated for %s"%(jid)) idx = self.makeId("last_") self.stanzaReader.requests[idx] = self.stanzaReader.handleLastOnline; query = ProtocolTreeNode("query",{"xmlns":"jabber:iq:last"}); iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":jid},[query]); self.out.write(iqNode) def sendIq(self): node = ProtocolTreeNode("iq",{"to":"g.us","type":"get","id":str(int(time.time()))+"-0"},None,'expired'); self.out.write(node); node = ProtocolTreeNode("iq",{"to":"s.whatsapp.net","type":"set","id":str(int(time.time()))+"-1"},None,'expired'); self.out.write(node); def sendAvailableForChat(self): presenceNode = ProtocolTreeNode("presence",{"name":self.push_name}) self.out.write(presenceNode); def sendAvailable(self): if self.state != 2: return presenceNode = ProtocolTreeNode("presence",{"type":"available"}) self.out.write(presenceNode); def sendUnavailable(self): if self.state != 2: return presenceNode = ProtocolTreeNode("presence",{"type":"unavailable"}) self.out.write(presenceNode); def sendSubscribe(self,to): presenceNode = ProtocolTreeNode("presence",{"type":"subscribe","to":to}); self.out.write(presenceNode); def sendMessageWithBody(self,fmsg): #bodyNode = ProtocolTreeNode("body",None,message.data); #self.out.write(self.getMessageNode(message,bodyNode)); bodyNode = ProtocolTreeNode("body",None,None,fmsg.content); self.out.write(self.getMessageNode(fmsg,bodyNode)); self.msg_id+=1; def sendClientConfig(self,sound,pushID,preview,platform): idx = self.makeId("config_"); configNode = ProtocolTreeNode("config",{"xmlns":"urn:xmpp:whatsapp:push","sound":sound,"id":pushID,"preview":"1" if preview else "0","platform":platform}) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":self.domain},[configNode]); self.out.write(iqNode); def sendGetGroupInfo(self,jid): idx = self.makeId("get_g_info_") self.stanzaReader.requests[idx] = self.stanzaReader.handleGroupInfo; queryNode = ProtocolTreeNode("query",{"xmlns":"w:g"}) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":jid},[queryNode]) self.out.write(iqNode) def getMessageNode(self,fmsg,child): requestNode = None; serverNode = ProtocolTreeNode("server",None); xNode = ProtocolTreeNode("x",{"xmlns":"jabber:x:event"},[serverNode]); childCount = (0 if requestNode is None else 1) +2; messageChildren = [None]*childCount; i = 0; if requestNode is not None: messageChildren[i] = requestNode; i+=1; #System.currentTimeMillis() / 1000L + "-"+1 messageChildren[i] = xNode; i+=1; messageChildren[i]= child; i+=1; key = eval(fmsg.key) messageNode = ProtocolTreeNode("message",{"to":key.remote_jid,"type":"chat","id":key.id},messageChildren) return messageNode;
class WAXMPP(): message_store = None def __init__(self, domain, resource, user, push_name, password): self.domain = domain self.resource = resource self.user = user self.push_name = push_name self.password = password self.jid = user + '@' + domain self.fromm = user + '@' + domain + '/' + resource self.supports_receipt_acks = False self.msg_id = 0 self.state = 0 #0 disconnected 1 connecting 2 connected self.retry = True self.eventHandler = WAEventHandler(self) self.conn = MySocketConnection() self.stanzaReader = None self.login = None self.disconnectRequested = False self.connTries = 0 self.verbose = True self.iqId = 0 self.lock = threading.Lock() self.waiting = 0 #super(WAXMPP,self).__init__(); self.eventHandler.initialConnCheck() #self.do_login(); def setContactsManager(self, contactsManager): self.contactsManager = contactsManager def setReceiptAckCapable(self, can): #print "Switching to True" self.supports_receipt_acks = True #print self.supports_receipt_acks def onLoginSuccess(self): self.changeState(4) self.connectionTries = 0 c = StanzaReader(self) c.setEventHandler(self.eventHandler) #initial presence self.stanzaReader = c self.stanzaReader.start() self.sendClientConfig('', '', False, '') self.sendAvailableForChat() self.eventHandler.connected.emit() def onConnectionError(self): self.login.wait() self.conn.close() self.changeState(3) ''' if self.connTries < 4: print "trying connect "+str(self.connTries) self.retryLogin() else: print "Too many tries, trying in 30000" t = QTimer.singleShot(30000,self.retryLogin) ''' def disconnect(self): self.conn.close() def retryLogin(self): self.changeState(3) def changeState(self, newState): print "Entering critical area" self.waiting += 1 self.lock.acquire() self.waiting -= 1 print "inside critical area" if self.state == 0: if newState == 2: self.state = 1 self.do_login() elif self.state == 1: #raise Exception("mutex violated! I SHOULDN'T BE HERE !!!") if newState == 0: self.retry = False elif newState == 2: self.retry = True elif newState == 3: #failed if self.retry: if self.connTries >= 3: print "%i or more failed connections. Will try again in 30 seconds" % self.connTries QTimer.singleShot(30000, self.retryLogin) self.connTries -= 1 else: self.do_login() self.connTries += 1 else: self.connTries = 0 self.state = 0 self.retry = True elif newState == 4: #connected self.connTries = 0 self.retry = True self.state = 2 elif self.state == 2: if newState == 2: self.disconnect() self.state = 1 self.do_login() elif newState == 0: self.disconnect() self.state = 0 print "Releasing lock" self.lock.release() def do_login(self): self.conn = conn = MySocketConnection() #conn.connect((HOST, PORT)); self.inn = BinTreeNodeReader(conn, WALogin.dictionary) self.out = BinTreeNodeWriter(conn, WALogin.dictionary) self.login = WALogin(conn, self.inn, self.out, S40MD5Digest()) self.login.setConnection(self) self.login.loginSuccess.connect(self.onLoginSuccess) self.login.loginFailed.connect(self.eventHandler.onLoginFailed) self.login.connectionError.connect(self.onConnectionError) self.login.start() '''try: self.login.login(); except: print "LOGIN FAILED" #sys.exit() return ''' #fmsg = FMessage(); #fmsg.setData('*****@*****.**',True,"Hello World"); #self.sendIq(); #self.inn.nextTree(); #print self.inn.inn.buf; #exit(); #self.inn.nextTree(); #self.sendMessageWithBody("ok"); #node = self.inn.nextTree(); #print node.toString(); #self.sendSubscribe("*****@*****.**"); #self.sendMessageWithBody("OK"); #self.sendMessageWithBody("OK"); #node = self.inn.nextTree(); #print node.toString(); #raw_input(); #self.sendMessageWithBody(fmsg); def resendUnsent(self): ''' Resends all unsent messages, should invoke on connect ''' messages = WAXMPP.message_store.getUnsent() print "Resending %i old messages" % (len(messages)) for m in messages: self.sendMessageWithBody(m) def sendTyping(self, jid): print "SEND TYPING TO JID" composing = ProtocolTreeNode( "composing", {"xmlns": "http://jabber.org/protocol/chatstates"}) message = ProtocolTreeNode("message", { "to": jid, "type": "chat" }, [composing]) self.out.write(message) def sendPaused(self, jid): print "SEND PAUSED TO JID" composing = ProtocolTreeNode( "paused", {"xmlns": "http://jabber.org/protocol/chatstates"}) message = ProtocolTreeNode("message", { "to": jid, "type": "chat" }, [composing]) self.out.write(message) def getSubjectMessage(self, to, msg_id, child): messageNode = ProtocolTreeNode("message", { "to": to, "type": "subject", "id": msg_id }, [child]) return messageNode def sendSubjectReceived(self, to, msg_id): print "Sending subject recv receipt" receivedNode = ProtocolTreeNode("received", {"xmlns": "urn:xmpp:receipts"}) messageNode = self.getSubjectMessage(to, msg_id, receivedNode) self.out.write(messageNode) def sendMessageReceived(self, fmsg): receivedNode = ProtocolTreeNode("received", {"xmlns": "urn:xmpp:receipts"}) messageNode = ProtocolTreeNode("message", { "to": fmsg.key.remote_jid, "type": "chat", "id": fmsg.key.id }, [receivedNode]) self.out.write(messageNode) def sendDeliveredReceiptAck(self, to, msg_id): self.out.write(self.getReceiptAck(to, msg_id, "delivered")) def sendVisibleReceiptAck(self, to, msg_id): self.out.write(self.getReceiptAck(to, msg_id, "visible")) def getReceiptAck(self, to, msg_id, receiptType): ackNode = ProtocolTreeNode("ack", { "xmlns": "urn:xmpp:receipts", "type": receiptType }) messageNode = ProtocolTreeNode("message", { "to": to, "type": "chat", "id": msg_id }, [ackNode]) return messageNode def makeId(self, prefix): self.iqId += 1 idx = "" if self.verbose: idx += prefix + str(self.iqId) else: idx = "%x" % self.iqId return idx def sendPing(self): idx = self.makeId("ping_") self.stanzaReader.requests[idx] = self.stanzaReader.handlePingResponse pingNode = ProtocolTreeNode("ping", {"xmlns": "w:p"}) iqNode = ProtocolTreeNode("iq", { "id": idx, "type": "get", "to": self.domain }, [pingNode]) self.out.write(iqNode) def sendPong(self, idx): iqNode = ProtocolTreeNode("iq", { "type": "result", "to": self.domain, "id": idx }) self.out.write(iqNode) def getLastOnline(self, jid): if len(jid.split('-')) == 2: #SUPER CANCEL SUBSCRIBE TO GROUP return self.sendSubscribe(jid) print "presence request Initiated for %s" % (jid) idx = self.makeId("last_") self.stanzaReader.requests[idx] = self.stanzaReader.handleLastOnline query = ProtocolTreeNode("query", {"xmlns": "jabber:iq:last"}) iqNode = ProtocolTreeNode("iq", { "id": idx, "type": "get", "to": jid }, [query]) self.out.write(iqNode) def sendIq(self): node = ProtocolTreeNode("iq", { "to": "g.us", "type": "get", "id": str(int(time.time())) + "-0" }, None, 'expired') self.out.write(node) node = ProtocolTreeNode( "iq", { "to": "s.whatsapp.net", "type": "set", "id": str(int(time.time())) + "-1" }, None, 'expired') self.out.write(node) def sendAvailableForChat(self): presenceNode = ProtocolTreeNode("presence", {"name": self.push_name}) self.out.write(presenceNode) def sendAvailable(self): if self.state != 2: return presenceNode = ProtocolTreeNode("presence", {"type": "available"}) self.out.write(presenceNode) def sendUnavailable(self): if self.state != 2: return presenceNode = ProtocolTreeNode("presence", {"type": "unavailable"}) self.out.write(presenceNode) def sendSubscribe(self, to): presenceNode = ProtocolTreeNode("presence", { "type": "subscribe", "to": to }) self.out.write(presenceNode) def sendMessageWithBody(self, fmsg): #bodyNode = ProtocolTreeNode("body",None,message.data); #self.out.write(self.getMessageNode(message,bodyNode)); bodyNode = ProtocolTreeNode("body", None, None, fmsg.content) self.out.write(self.getMessageNode(fmsg, bodyNode)) self.msg_id += 1 def sendClientConfig(self, sound, pushID, preview, platform): idx = self.makeId("config_") configNode = ProtocolTreeNode( "config", { "xmlns": "urn:xmpp:whatsapp:push", "sound": sound, "id": pushID, "preview": "1" if preview else "0", "platform": platform }) iqNode = ProtocolTreeNode("iq", { "id": idx, "type": "set", "to": self.domain }, [configNode]) self.out.write(iqNode) def getMessageNode(self, fmsg, child): requestNode = None serverNode = ProtocolTreeNode("server", None) xNode = ProtocolTreeNode("x", {"xmlns": "jabber:x:event"}, [serverNode]) childCount = (0 if requestNode is None else 1) + 2 messageChildren = [None] * childCount i = 0 if requestNode is not None: messageChildren[i] = requestNode i += 1 #System.currentTimeMillis() / 1000L + "-"+1 messageChildren[i] = xNode i += 1 messageChildren[i] = child i += 1 key = eval(fmsg.key) messageNode = ProtocolTreeNode("message", { "to": key.remote_jid, "type": "chat", "id": key.id }, messageChildren) return messageNode
class WAXMPP: SERVER = 's.whatsapp.net' USER_AGENT = "iPhone-2.8.3" def __init__( self, user, push_name, password, ): self.domain = WAXMPP.SERVER self.resource = WAXMPP.USER_AGENT self.user = user self.push_name = push_name self.password = password self.jid = user + '@' + WAXMPP.SERVER self.fromm = user + '@' + WAXMPP.SERVER + '/' + WAXMPP.USER_AGENT self.supports_receipt_acks = False self.msg_id = 0 self.retry = True self.event = WAEventHandler(self) self.stanzaReader = None self.disconnectRequested = False self.connTries = 0 self.verbose = True self.iqId = 0 self.lock = threading.Lock() self.waiting = 0 self.conn = None self.inn = None self.out = None self.event.loginSuccess.connect(self.onLoginSuccess) self.event.connectionError.connect(self.onConnectionError) def onLoginSuccess(self): self.connectionTries = 0 c = StanzaReader(self) self.stanzaReader = c self.stanzaReader.start() self.sendClientConfig('', '', False, '') self.sendAvailableForChat() self.event.connected.emit() def onConnectionError(self): pass def disconnect(self): self.event.disconnectRequested.emit() self.disconnectRequested = True def login(self): self.conn = MySocketConnection() self.inn = BinTreeNodeReader(self.conn, Login.dictionary) self.out = BinTreeNodeWriter(self.conn, Login.dictionary) self.walogin = Login(self) self.walogin.start() def sendTyping(self, jid): composing = ProtocolTreeNode('composing', {'xmlns': 'http://jabber.org/protocol/chatstates'}) message = ProtocolTreeNode('message', {'to': jid, 'type': 'chat' }, [composing]) self.out.write(message) def sendPaused(self, jid): composing = ProtocolTreeNode('paused', {'xmlns': 'http://jabber.org/protocol/chatstates'}) message = ProtocolTreeNode('message', {'to': jid, 'type': 'chat' }, [composing]) self.out.write(message) def getSubjectMessage( self, to, msg_id, child, ): messageNode = ProtocolTreeNode('message', {'to': to, 'type': 'subject', 'id': msg_id}, [child]) return messageNode def sendSubjectReceived(self, to, msg_id): receivedNode = ProtocolTreeNode('received', {'xmlns': 'urn:xmpp:receipts'}) messageNode = self.getSubjectMessage(to, msg_id, receivedNode) self.out.write(messageNode) def sendMessageReceived(self, fmsg): receivedNode = ProtocolTreeNode('received', {'xmlns': 'urn:xmpp:receipts'}) messageNode = ProtocolTreeNode('message', {'to': fmsg.remote, 'type': 'chat', 'id': fmsg.id}, [receivedNode]) self.out.write(messageNode) def sendDeliveredReceiptAck(self, to, msg_id): self.out.write(self.getReceiptAck(to, msg_id, 'delivered')) def sendVisibleReceiptAck(self, to, msg_id): self.out.write(self.getReceiptAck(to, msg_id, 'visible')) def getReceiptAck( self, to, msg_id, receiptType, ): ackNode = ProtocolTreeNode('ack', {'xmlns': 'urn:xmpp:receipts' , 'type': receiptType}) messageNode = ProtocolTreeNode('message', {'to': to, 'type': 'chat', 'id': msg_id}, [ackNode]) return messageNode def makeId(self, prefix): self.iqId += 1 idx = '' if self.verbose: idx += prefix + str(self.iqId) else: idx = '%x' % self.iqId return idx def sendPing(self): idx = self.makeId('ping_') self.stanzaReader.requests[idx] = \ self.stanzaReader.handlePingResponse pingNode = ProtocolTreeNode('ping', {'xmlns': 'w:p'}) iqNode = ProtocolTreeNode('iq', {'id': idx, 'type': 'get', 'to': self.domain}, [pingNode]) self.out.write(iqNode) def sendPong(self, idx): iqNode = ProtocolTreeNode('iq', {'type': 'result', 'to': self.domain, 'id': idx}) self.out.write(iqNode) def getLastOnline(self, jid): if len(jid.split('-')) == 2: return self.sendSubscribe(jid) idx = self.makeId('last_') self.stanzaReader.requests[idx] = \ self.stanzaReader.handleLastOnline query = ProtocolTreeNode('query', {'xmlns': 'jabber:iq:last'}) iqNode = ProtocolTreeNode('iq', {'id': idx, 'type': 'get', 'to': jid}, [query]) self.out.write(iqNode) def sendIq(self): node = ProtocolTreeNode('iq', {'to': 'g.us', 'type': 'get', 'id': str(int(time.time())) + '-0'}, None, 'expired') self.out.write(node) node = ProtocolTreeNode('iq', {'to': 's.whatsapp.net', 'type': 'set', 'id': str(int(time.time())) + '-1'}, None, 'expired') self.out.write(node) def leaveGroup(self, group): group_nodes = [ProtocolTreeNode('group', {'id': group})] node = ProtocolTreeNode('leave', {'xmlns': 'w:g'}, group_nodes) node_out = ProtocolTreeNode('iq', { 'id': str(int(time.time())) + '-0', 'type': 'set', 'to': 'g.us' }, [node]) self.out.write(node_out) def addParticipant(self, group, participant): self.addParticipants(group, [participant]) def removeParticipant(self, group, participant): self.removeParticipants(group, [participant]) def addParticipants(self, group, participants): self.sendVerbParticipants(group, participants, 'add') def removeParticipants(self, group, participants): self.sendVerbParticipants(group, participants, 'remove') def sendVerbParticipants(self, group, participants, verb): participant_nodes = map(lambda p: ProtocolTreeNode('participants', {'jid': p}), participants) node = ProtocolTreeNode(verb, {'xmlns': 'w:g'}, participant_nodes) node_out = ProtocolTreeNode('iq', { 'id': str(int(time.time())) + '-0', 'type': 'set', 'to': group }, [node]) self.out.write(node_out) def setGroupSubject(self, group, subject): node = ProtocolTreeNode('subject', {'xmlns': 'w:g', 'value': subject}) node_out = ProtocolTreeNode('iq', { 'id': str(int(time.time())) + '-0', 'type': 'set', 'to': group }, [node]) self.out.write(node_out) def sendAvailableForChat(self): presenceNode = ProtocolTreeNode('presence', {'name': self.push_name}) self.out.write(presenceNode) def sendAvailable(self): presenceNode = ProtocolTreeNode('presence', {'type': 'available'}) self.out.write(presenceNode) def sendUnavailable(self): presenceNode = ProtocolTreeNode('presence', {'type': 'unavailable'}) self.out.write(presenceNode) def sendSubscribe(self, to): presenceNode = ProtocolTreeNode('presence', {'type': 'subscribe', 'to': to}) self.out.write(presenceNode) def getGroups(self): self.sendGetGroups('participating') def getOwningGroups(self): self.sendGetGroups('owning') def getParticipants(self, group): node = ProtocolTreeNode('list', {'xmlns': 'w:g'}) node_out = ProtocolTreeNode('iq', { 'id': str(int(time.time())) + '-0', 'type': 'get', 'to': group }, [node]) self.out.write(node_out) def getServerProperties(self): node = ProtocolTreeNode('list', {'xmlns': 'w:g', 'type': 'props'}) node_out = ProtocolTreeNode('iq', { 'id': str(int(time.time())) + '-0', 'type': 'get', 'to': 'g.us' }, [node]) self.out.write(node_out) def sendGetGroups(self, group_type): node = ProtocolTreeNode('list', {'xmlns': 'w:g', 'type': group_type}) node_out = ProtocolTreeNode('iq', { 'id': str(int(time.time())) + '-0', 'type': 'get', 'to': 'g.us' }, [node]) self.out.write(node_out) def sendMessage(self, fmsg): bodyNode = ProtocolTreeNode('body', None, None, fmsg.data) msgNode = self.getMessageNode(fmsg, bodyNode) self.out.write(msgNode) self.msg_id += 1 def sendClientConfig( self, sound, pushID, preview, platform, ): idx = self.makeId('config_') configNode = ProtocolTreeNode('config', { 'xmlns': 'urn:xmpp:whatsapp:push', 'sound': sound, 'id': pushID, 'preview': ('1' if preview else '0'), 'platform': platform, }) iqNode = ProtocolTreeNode('iq', {'id': idx, 'type': 'set', 'to': self.domain}, [configNode]) self.out.write(iqNode) def getMessageNode(self, fmsg, child): requestNode = None serverNode = ProtocolTreeNode('server', None) xNode = ProtocolTreeNode('x', {'xmlns': 'jabber:x:event'}, [serverNode]) childCount = ((0 if requestNode is None else 1)) + 2 messageChildren = [None] * childCount i = 0 if requestNode is not None: messageChildren[i] = requestNode i += 1 messageChildren[i] = xNode i += 1 messageChildren[i] = child i += 1 messageNode = ProtocolTreeNode('message', {'to': fmsg.remote, 'type': 'chat', 'id': fmsg.id}, messageChildren) return messageNode
class WAXMPP: SERVER = 's.whatsapp.net' USER_AGENT = "iPhone-2.8.3" def __init__( self, user, push_name, password, ): self.domain = WAXMPP.SERVER self.resource = WAXMPP.USER_AGENT self.user = user self.push_name = push_name self.password = password self.jid = user + '@' + WAXMPP.SERVER self.fromm = user + '@' + WAXMPP.SERVER + '/' + WAXMPP.USER_AGENT self.supports_receipt_acks = False self.msg_id = 0 self.retry = True self.event = WAEventHandler(self) self.stanzaReader = None self.disconnectRequested = False self.connTries = 0 self.verbose = True self.iqId = 0 self.lock = threading.Lock() self.waiting = 0 self.conn = None self.inn = None self.out = None self.event.loginSuccess.connect(self.onLoginSuccess) self.event.connectionError.connect(self.onConnectionError) def onLoginSuccess(self): self.connectionTries = 0 c = StanzaReader(self) self.stanzaReader = c self.stanzaReader.start() self.sendClientConfig('', '', False, '') self.sendAvailableForChat() self.event.connected.emit() def onConnectionError(self): pass def disconnect(self): self.event.disconnectRequested.emit() self.disconnectRequested = True def login(self): self.conn = MySocketConnection() self.inn = BinTreeNodeReader(self.conn, Login.dictionary) self.out = BinTreeNodeWriter(self.conn, Login.dictionary) self.walogin = Login(self) self.walogin.start() def sendTyping(self, jid): composing = ProtocolTreeNode( 'composing', {'xmlns': 'http://jabber.org/protocol/chatstates'}) message = ProtocolTreeNode('message', { 'to': jid, 'type': 'chat' }, [composing]) self.out.write(message) def sendPaused(self, jid): composing = ProtocolTreeNode( 'paused', {'xmlns': 'http://jabber.org/protocol/chatstates'}) message = ProtocolTreeNode('message', { 'to': jid, 'type': 'chat' }, [composing]) self.out.write(message) def getSubjectMessage( self, to, msg_id, child, ): messageNode = ProtocolTreeNode('message', { 'to': to, 'type': 'subject', 'id': msg_id }, [child]) return messageNode def sendSubjectReceived(self, to, msg_id): receivedNode = ProtocolTreeNode('received', {'xmlns': 'urn:xmpp:receipts'}) messageNode = self.getSubjectMessage(to, msg_id, receivedNode) self.out.write(messageNode) def sendMessageReceived(self, fmsg): receivedNode = ProtocolTreeNode('received', {'xmlns': 'urn:xmpp:receipts'}) messageNode = ProtocolTreeNode('message', { 'to': fmsg.remote, 'type': 'chat', 'id': fmsg.id }, [receivedNode]) self.out.write(messageNode) def sendDeliveredReceiptAck(self, to, msg_id): self.out.write(self.getReceiptAck(to, msg_id, 'delivered')) def sendVisibleReceiptAck(self, to, msg_id): self.out.write(self.getReceiptAck(to, msg_id, 'visible')) def getReceiptAck( self, to, msg_id, receiptType, ): ackNode = ProtocolTreeNode('ack', { 'xmlns': 'urn:xmpp:receipts', 'type': receiptType }) messageNode = ProtocolTreeNode('message', { 'to': to, 'type': 'chat', 'id': msg_id }, [ackNode]) return messageNode def makeId(self, prefix): self.iqId += 1 idx = '' if self.verbose: idx += prefix + str(self.iqId) else: idx = '%x' % self.iqId return idx def sendPing(self): idx = self.makeId('ping_') self.stanzaReader.requests[idx] = \ self.stanzaReader.handlePingResponse pingNode = ProtocolTreeNode('ping', {'xmlns': 'w:p'}) iqNode = ProtocolTreeNode('iq', { 'id': idx, 'type': 'get', 'to': self.domain }, [pingNode]) self.out.write(iqNode) def sendPong(self, idx): iqNode = ProtocolTreeNode('iq', { 'type': 'result', 'to': self.domain, 'id': idx }) self.out.write(iqNode) def getLastOnline(self, jid): if len(jid.split('-')) == 2: return self.sendSubscribe(jid) idx = self.makeId('last_') self.stanzaReader.requests[idx] = \ self.stanzaReader.handleLastOnline query = ProtocolTreeNode('query', {'xmlns': 'jabber:iq:last'}) iqNode = ProtocolTreeNode('iq', { 'id': idx, 'type': 'get', 'to': jid }, [query]) self.out.write(iqNode) def sendIq(self): node = ProtocolTreeNode('iq', { 'to': 'g.us', 'type': 'get', 'id': str(int(time.time())) + '-0' }, None, 'expired') self.out.write(node) node = ProtocolTreeNode( 'iq', { 'to': 's.whatsapp.net', 'type': 'set', 'id': str(int(time.time())) + '-1' }, None, 'expired') self.out.write(node) def leaveGroup(self, group): group_nodes = [ProtocolTreeNode('group', {'id': group})] node = ProtocolTreeNode('leave', {'xmlns': 'w:g'}, group_nodes) node_out = ProtocolTreeNode('iq', { 'id': str(int(time.time())) + '-0', 'type': 'set', 'to': 'g.us' }, [node]) self.out.write(node_out) def addParticipant(self, group, participant): self.addParticipants(group, [participant]) def removeParticipant(self, group, participant): self.removeParticipants(group, [participant]) def addParticipants(self, group, participants): self.sendVerbParticipants(group, participants, 'add') def removeParticipants(self, group, participants): self.sendVerbParticipants(group, participants, 'remove') def sendVerbParticipants(self, group, participants, verb): participant_nodes = map( lambda p: ProtocolTreeNode('participants', {'jid': p}), participants) node = ProtocolTreeNode(verb, {'xmlns': 'w:g'}, participant_nodes) node_out = ProtocolTreeNode('iq', { 'id': str(int(time.time())) + '-0', 'type': 'set', 'to': group }, [node]) self.out.write(node_out) def setGroupSubject(self, group, subject): node = ProtocolTreeNode('subject', {'xmlns': 'w:g', 'value': subject}) node_out = ProtocolTreeNode('iq', { 'id': str(int(time.time())) + '-0', 'type': 'set', 'to': group }, [node]) self.out.write(node_out) def sendAvailableForChat(self): presenceNode = ProtocolTreeNode('presence', {'name': self.push_name}) self.out.write(presenceNode) def sendAvailable(self): presenceNode = ProtocolTreeNode('presence', {'type': 'available'}) self.out.write(presenceNode) def sendUnavailable(self): presenceNode = ProtocolTreeNode('presence', {'type': 'unavailable'}) self.out.write(presenceNode) def sendSubscribe(self, to): presenceNode = ProtocolTreeNode('presence', { 'type': 'subscribe', 'to': to }) self.out.write(presenceNode) def getGroups(self): self.sendGetGroups('participating') def getOwningGroups(self): self.sendGetGroups('owning') def getParticipants(self, group): node = ProtocolTreeNode('list', {'xmlns': 'w:g'}) node_out = ProtocolTreeNode('iq', { 'id': str(int(time.time())) + '-0', 'type': 'get', 'to': group }, [node]) self.out.write(node_out) def getServerProperties(self): node = ProtocolTreeNode('list', {'xmlns': 'w:g', 'type': 'props'}) node_out = ProtocolTreeNode('iq', { 'id': str(int(time.time())) + '-0', 'type': 'get', 'to': 'g.us' }, [node]) self.out.write(node_out) def sendGetGroups(self, group_type): node = ProtocolTreeNode('list', {'xmlns': 'w:g', 'type': group_type}) node_out = ProtocolTreeNode('iq', { 'id': str(int(time.time())) + '-0', 'type': 'get', 'to': 'g.us' }, [node]) self.out.write(node_out) def sendMessage(self, fmsg): bodyNode = ProtocolTreeNode('body', None, None, fmsg.data) msgNode = self.getMessageNode(fmsg, bodyNode) self.out.write(msgNode) self.msg_id += 1 def sendClientConfig( self, sound, pushID, preview, platform, ): idx = self.makeId('config_') configNode = ProtocolTreeNode( 'config', { 'xmlns': 'urn:xmpp:whatsapp:push', 'sound': sound, 'id': pushID, 'preview': ('1' if preview else '0'), 'platform': platform, }) iqNode = ProtocolTreeNode('iq', { 'id': idx, 'type': 'set', 'to': self.domain }, [configNode]) self.out.write(iqNode) def getMessageNode(self, fmsg, child): requestNode = None serverNode = ProtocolTreeNode('server', None) xNode = ProtocolTreeNode('x', {'xmlns': 'jabber:x:event'}, [serverNode]) childCount = ((0 if requestNode is None else 1)) + 2 messageChildren = [None] * childCount i = 0 if requestNode is not None: messageChildren[i] = requestNode i += 1 messageChildren[i] = xNode i += 1 messageChildren[i] = child i += 1 messageNode = ProtocolTreeNode('message', { 'to': fmsg.remote, 'type': 'chat', 'id': fmsg.id }, messageChildren) return messageNode