def __init__(self): Debugger.attach(self) self.currKeyId = 1 self.iqId = 0 self.verbose = True self.state = 0 self.lock = threading.Lock() self.autoPong = True self.domain = "s.whatsapp.net" #self.methodInterface = MethodInterface(authenticatedSocketConnection.getId()) #self.signalInterface = SignalInterface(authenticatedSocketConnection.getId()) self.readerThread = None self.methodInterface = LibMethodInterface() self.signalInterface = LibSignalInterface() self.readerThread = ReaderThread() self.readerThread.setSignalInterface(self.signalInterface) self.bindMethods()
class YowsupConnectionManager: def __init__(self): Debugger.attach(self) self.currKeyId = 1 self.iqId = 0 self.verbose = True self.state = 0 self.lock = threading.Lock() self.autoPong = True self.domain = "s.whatsapp.net" #self.methodInterface = MethodInterface(authenticatedSocketConnection.getId()) #self.signalInterface = SignalInterface(authenticatedSocketConnection.getId()) self.readerThread = None self.methodInterface = LibMethodInterface() self.signalInterface = LibSignalInterface() self.readerThread = ReaderThread() self.readerThread.setSignalInterface(self.signalInterface) self.bindMethods() def setInterfaces(self, signalInterface, methodInterface): self.methodInterface = methodInterface self.signalInterface = signalInterface self.readerThread.setSignalInterface(self.signalInterface) self.bindMethods() def getSignalsInterface(self): return self.signalInterface def getMethodsInterface(self): return self.methodInterface def setAutoPong(self, autoPong): self.autoPong = self.readerThread.autoPong = autoPong def startReader(self): if self.readerThread.isAlive(): self._d("Reader already started") return 0 self._d("starting reader") try: self.readerThread.start() self._d("started") except RuntimeError: self._d("Reader already started before") self.readerThread.sendDisconnected() return 0 return 1 def block(self): self.readerThread.join() def bindMethods(self): self.methodInterface.registerCallback("getVersion", lambda: Constants.v) self.methodInterface.registerCallback("message_send",self.sendText) self.methodInterface.registerCallback("message_imageSend",self.sendImage) self.methodInterface.registerCallback("message_audioSend",self.sendAudio) self.methodInterface.registerCallback("message_videoSend",self.sendVideo) self.methodInterface.registerCallback("message_locationSend",self.sendLocation) self.methodInterface.registerCallback("message_vcardSend",self.sendVCard) self.methodInterface.registerCallback("message_broadcast",self.sendBroadcast) self.methodInterface.registerCallback("message_ack",self.sendMessageReceipt) self.methodInterface.registerCallback("notification_ack", self.sendNotificationReceipt) self.methodInterface.registerCallback("clientconfig_send",self.sendClientConfig) self.methodInterface.registerCallback("delivered_ack",self.sendDeliveredReceiptAck) self.methodInterface.registerCallback("visible_ack",self.sendVisibleReceiptAck) self.methodInterface.registerCallback("ping",self.sendPing) self.methodInterface.registerCallback("pong",self.sendPong) self.methodInterface.registerCallback("typing_send",self.sendTyping) self.methodInterface.registerCallback("typing_paused",self.sendPaused) self.methodInterface.registerCallback("subject_ack",self.sendSubjectReceived) self.methodInterface.registerCallback("group_getGroups", self.sendGetGroups) self.methodInterface.registerCallback("group_getInfo",self.sendGetGroupInfo) self.methodInterface.registerCallback("group_create",self.sendCreateGroupChat) self.methodInterface.registerCallback("group_addParticipants",self.sendAddParticipants) self.methodInterface.registerCallback("group_removeParticipants",self.sendRemoveParticipants) self.methodInterface.registerCallback("group_end",self.sendEndGroupChat) self.methodInterface.registerCallback("group_setSubject",self.sendSetGroupSubject) self.methodInterface.registerCallback("group_setPicture", self.sendSetPicture) self.methodInterface.registerCallback("group_getPicture", self.sendGetPicture) self.methodInterface.registerCallback("group_getParticipants",self.sendGetParticipants) self.methodInterface.registerCallback("picture_get",self.sendGetPicture) self.methodInterface.registerCallback("picture_getIds",self.sendGetPictureIds) self.methodInterface.registerCallback("contact_getProfilePicture", self.sendGetPicture) self.methodInterface.registerCallback("status_update",self.sendChangeStatus) self.methodInterface.registerCallback("presence_request",self.getLastOnline) #self.methodInterface.registerCallback("presence_unsubscribe",self.sendUnsubscribe)#@@TODO implement method self.methodInterface.registerCallback("presence_subscribe",self.sendSubscribe) self.methodInterface.registerCallback("presence_sendAvailableForChat",self.sendAvailableForChat) self.methodInterface.registerCallback("presence_sendAvailable",self.sendAvailable) self.methodInterface.registerCallback("presence_sendUnavailable",self.sendUnavailable) self.methodInterface.registerCallback("profile_setPicture", self.sendSetProfilePicture) self.methodInterface.registerCallback("profile_getPicture", self.sendGetProfilePicture) self.methodInterface.registerCallback("profile_setStatus", self.sendChangeStatus) self.methodInterface.registerCallback("sync_sendSync", self.sendSync) self.methodInterface.registerCallback("disconnect", self.disconnect) self.methodInterface.registerCallback("ready", self.startReader) self.methodInterface.registerCallback("auth_login", self.auth ) #self.methodInterface.registerCallback("auth_login", self.auth) self.methodInterface.registerCallback("media_requestUpload", self.sendRequestUpload) def disconnect(self, reason=""): self._d("Disconnect sequence initiated") self._d("Sending term signal to reader thread") if self.readerThread.isAlive(): self.readerThread.terminate() self._d("Shutting down socket") self.socket.close() self._d("Waiting for readerThread to die") self.readerThread.join() self._d("Disconnected!") self._d(reason) self.state = 0 self.readerThread.sendDisconnected(reason) def getConnection(self): return self.socket def triggerEvent(self, eventName, stanza): if eventName in self.events and self.events[eventName] is not None: self.events[eventName](stanza) def bindEvent(self, eventName, callback): if eventName in self.events: self.events[eventName] = callback ########################################################## def _writeNode(self, node): if self.state == 2: try: self.out.write(node) return True except ConnectionClosedException: self._d("CONNECTION DOWN") #self.disconnect("closed") if self.readerThread.isAlive(): self.readerThread.terminate() self.readerThread.join() self.readerThread.sendDisconnected("closed") return False def onDisconnected(self): self._d("Setting state to 0") self.state = 0 def auth(self, username, password): self._d(">>>>>>>> AUTH CALLED") username = str(username) #password = str(password) #traceback.print_stack() self.lock.acquire() if self.state == 0 : if self.readerThread.isAlive(): raise Exception("TWO READER THREADS ON BOARD!!") self.readerThread = ReaderThread() self.readerThread.autoPong = self.autoPong self.readerThread.setSignalInterface(self.signalInterface) yAuth = YowsupAuth(ConnectionEngine()) try: self.state = 1 tokenData = Utilities.readToken() resource = tokenData["r"] if tokenData else Constants.tokenData["r"] connection = yAuth.authenticate(username, password, Constants.domain, resource) except socket.gaierror: self._d("DNS ERROR") self.readerThread.sendDisconnected("dns") #self.signalInterface.send("disconnected", ("dns",)) self.lock.release() self.state = 0 return 0 except socket.error: self._d("Socket error, connection timed out") self.readerThread.sendDisconnected("closed") #self.signalInterface.send("disconnected", ("closed",)) self.lock.release() self.state = 0 return 0 except ConnectionClosedException: self._d("Conn closed Exception") self.readerThread.sendDisconnected("closed") #self.signalInterface.send("disconnected", ("closed",)) self.lock.release() self.state = 0 return 0 if not connection: self.state = 0 self.signalInterface.send("auth_fail", (username, "invalid")) self.lock.release() return 0 self.state = 2 self.socket = connection self.jid = self.socket.jid #@@TODO REPLACE PROPERLY self.out = self.socket.writer self.readerThread.setSocket(self.socket) self.readerThread.disconnectedCallback = self.onDisconnected self.readerThread.onPing = self.sendPong self.readerThread.ping = self.sendPing self.signalInterface.send("auth_success", (username,)) self.lock.release() 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._writeNode(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._writeNode(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._writeNode(messageNode); def sendMessageReceipt(self, jid, msgId): self.sendReceipt(jid, "chat", msgId) def sendNotificationReceipt(self, jid, notificationId): self.sendReceipt(jid, "notification", notificationId) def sendReceipt(self,jid,mtype,mid): self._d("sending message received to "+jid+" - type:"+mtype+" - id:"+mid) receivedNode = ProtocolTreeNode("received",{"xmlns": "urn:xmpp:receipts"}) messageNode = ProtocolTreeNode("message",{"to":jid,"type":mtype,"id":mid},[receivedNode]); self._writeNode(messageNode); def sendDeliveredReceiptAck(self,to,msg_id): self._writeNode(self.getReceiptAck(to,msg_id,"delivered")); def sendVisibleReceiptAck(self,to,msg_id): self._writeNode(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.readerThread.requests[idx] = self.readerThread.parsePingResponse; pingNode = ProtocolTreeNode("ping",{"xmlns":"w:p"}); iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":self.domain},[pingNode]); self._writeNode(iqNode); return idx def sendPong(self,idx): iqNode = ProtocolTreeNode("iq",{"type":"result","to":self.domain,"id":idx}) self._writeNode(iqNode); def getLastOnline(self,jid): if len(jid.split('-')) == 2 or jid == "*****@*****.**": #SUPER CANCEL SUBSCRIBE TO GROUP AND SERVER return self.sendSubscribe(jid); self._d("presence request Initiated for %s"%(jid)) idx = self.makeId("last_") self.readerThread.requests[idx] = self.readerThread.parseLastOnline; query = ProtocolTreeNode("query",{"xmlns":"jabber:iq:last"}); iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":jid},[query]); self._writeNode(iqNode) def sendIq(self): node = ProtocolTreeNode("iq",{"to":"g.us","type":"get","id":str(int(time.time()))+"-0"},None,'expired'); self._writeNode(node); node = ProtocolTreeNode("iq",{"to":"s.whatsapp.net","type":"set","id":str(int(time.time()))+"-1"},None,'expired'); self._writeNode(node); def sendAvailableForChat(self, pushname): presenceNode = ProtocolTreeNode("presence",{"name":pushname}) self._writeNode(presenceNode); def sendAvailable(self): presenceNode = ProtocolTreeNode("presence",{"type":"available"}) self._writeNode(presenceNode); def sendUnavailable(self): presenceNode = ProtocolTreeNode("presence",{"type":"unavailable"}) self._writeNode(presenceNode); def sendSubscribe(self,to): presenceNode = ProtocolTreeNode("presence",{"type":"subscribe","to":to}); self._writeNode(presenceNode); def mediaNode(fn): def wrapped(self, *args): mediaType = fn(self, *args) url = args[1] name = args[2] size = args[3] mmNode = ProtocolTreeNode("media", {"xmlns":"urn:xmpp:whatsapp:mms","type":mediaType,"file":name,"size":size,"url":url},None, args[4:][0] if args[4:] else None); return mmNode return wrapped def sendMessage(fn): def wrapped(self, *args): node = fn(self, *args) jid = "broadcast" if type(args[0]) == list else args[0] messageNode = self.getMessageNode(jid, node) self._writeNode(messageNode); return messageNode.getAttributeValue("id") return wrapped def sendChangeStatus(self,status): self._d("updating status to: %s"%(status)) bodyNode = ProtocolTreeNode("body",None,None,status); messageNode = self.getMessageNode("s.us",bodyNode) self._writeNode(messageNode); return messageNode.getAttributeValue("id") @sendMessage def sendText(self,jid, content): return ProtocolTreeNode("body",None,None,content); @sendMessage @mediaNode def sendImage(self, jid, url, name, size, preview): return "image" @sendMessage @mediaNode def sendVideo(self, jid, url, name, size, preview): return "video" @sendMessage @mediaNode def sendAudio(self, jid, url, name, size): return "audio" @sendMessage def sendLocation(self, jid, latitude, longitude, preview): self._d("sending location (" + latitude + ":" + longitude + ")") return ProtocolTreeNode("media", {"xmlns":"urn:xmpp:whatsapp:mms","type":"location","latitude":latitude,"longitude":longitude},None,preview) @sendMessage def sendVCard(self, jid, data, name): cardNode = ProtocolTreeNode("vcard",{"name":name},None,data); return ProtocolTreeNode("media", {"xmlns":"urn:xmpp:whatsapp:mms","type":"vcard"},[cardNode]) @sendMessage def sendBroadcast(self, jids, content): broadcastNode = ProtocolTreeNode("broadcast", None, [ProtocolTreeNode("to", {"jid": jid}) for jid in jids]) messageNode = ProtocolTreeNode("body",None,None,content); return [broadcastNode, messageNode] 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._writeNode(iqNode); # gtype should be either "participating" or "owning" def sendGetGroups(self,gtype): self._d("getting groups %s"%(gtype)) idx = self.makeId("get_groups_") self.readerThread.requests[idx] = self.readerThread.parseGroups; queryNode = ProtocolTreeNode("list",{"xmlns":"w:g","type":gtype}) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":"g.us"},[queryNode]) self._writeNode(iqNode) def sendGetGroupInfo(self,jid): self._d("getting group info for %s"%(jid)) idx = self.makeId("get_g_info_") self.readerThread.requests[idx] = self.readerThread.parseGroupInfo; queryNode = ProtocolTreeNode("query",{"xmlns":"w:g"}) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":jid},[queryNode]) self._writeNode(iqNode) def sendCreateGroupChat(self,subject): self._d("creating group: %s"%(subject)) idx = self.makeId("create_group_") self.readerThread.requests[idx] = self.readerThread.parseGroupCreated; queryNode = ProtocolTreeNode("group",{"xmlns":"w:g","action":"create","subject":subject}) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":"g.us"},[queryNode]) self._writeNode(iqNode) def sendAddParticipants(self, gjid, participants): self._d("opening group: %s"%(gjid)) self._d("adding participants: %s"%(participants)) idx = self.makeId("add_group_participants_") self.readerThread.requests[idx] = self.readerThread.parseAddedParticipants; innerNodeChildren = [] for part in participants: innerNodeChildren.append( ProtocolTreeNode("participant",{"jid":part}) ) queryNode = ProtocolTreeNode("add",{"xmlns":"w:g"},innerNodeChildren) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":gjid},[queryNode]) self._writeNode(iqNode) def sendRemoveParticipants(self,gjid, participants): self._d("opening group: %s"%(gjid)) self._d("removing participants: %s"%(participants)) idx = self.makeId("remove_group_participants_") self.readerThread.requests[idx] = self.readerThread.parseRemovedParticipants; innerNodeChildren = [] for part in participants: innerNodeChildren.append( ProtocolTreeNode("participant",{"jid":part}) ) queryNode = ProtocolTreeNode("remove",{"xmlns":"w:g"},innerNodeChildren) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":gjid},[queryNode]) self._writeNode(iqNode) def sendEndGroupChat(self,gjid): self._d("removing group: %s"%(gjid)) idx = self.makeId("leave_group_") self.readerThread.requests[idx] = self.readerThread.parseGroupEnded; innerNodeChildren = [] innerNodeChildren.append( ProtocolTreeNode("group",{"id":gjid}) ) queryNode = ProtocolTreeNode("leave",{"xmlns":"w:g"},innerNodeChildren) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":"g.us"},[queryNode]) self._writeNode(iqNode) def sendSetGroupSubject(self,gjid,subject): #subject = subject.encode('utf-8') #self._d("setting group subject of " + gjid + " to " + subject) idx = self.makeId("set_group_subject_") self.readerThread.requests[idx] = self.readerThread.parseGroupSubject queryNode = ProtocolTreeNode("subject",{"xmlns":"w:g","value":subject}) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":gjid},[queryNode]); self._writeNode(iqNode) def sendGetParticipants(self,jid): idx = self.makeId("get_participants_") self.readerThread.requests[idx] = self.readerThread.parseParticipants listNode = ProtocolTreeNode("list",{"xmlns":"w:g"}) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":jid},[listNode]); self._writeNode(iqNode) def sendGetPicture(self,jid): self._d("GETTING PICTURE FROM " + jid) idx = self.makeId("get_picture_") #@@TODO, ?! self.readerThread.requests[idx] = self.readerThread.parseGetPicture listNode = ProtocolTreeNode("picture",{"xmlns":"w:profile:picture","type":"image"}) iqNode = ProtocolTreeNode("iq",{"id":idx,"to":jid,"type":"get"},[listNode]); self._writeNode(iqNode) def sendGetPictureIds(self,jids): idx = self.makeId("get_picture_ids_") self.readerThread.requests[idx] = self.readerThread.parseGetPictureIds innerNodeChildren = [] for jid in jids: innerNodeChildren.append( ProtocolTreeNode("user",{"jid": jid}) ) queryNode = ProtocolTreeNode("list",{"xmlns":"w:profile:picture"},innerNodeChildren) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get"},[queryNode]) self._writeNode(iqNode) def sendGetProfilePicture(self): return self.sendGetPicture(self.jid) def sendSetProfilePicture(self, filepath): return self.sendSetPicture(self.jid, filepath) def sendSetPicture(self, jid, imagePath): f = open(imagePath, 'rb') imageData = f.read() imageData = bytearray(imageData) f.close() idx = self.makeId("set_picture_") self.readerThread.requests[idx] = self.readerThread.parseSetPicture listNode = ProtocolTreeNode("picture",{"xmlns":"w:profile:picture","type":"image"}, None, imageData) iqNode = ProtocolTreeNode("iq",{"id":idx,"to":jid,"type":"set"},[listNode]) self._writeNode(iqNode) def sendRequestUpload(self, b64Hash, t, size, b64OrigHash = None): idx = self.makeId("upload_") self.readerThread.requests[idx] = lambda iqresnode: self.readerThread.parseRequestUpload(iqresnode, b64Hash) if type(size) is not str: size = str(size) attribs = {"xmlns":"w:m","hash":b64Hash, "type":t, "size":size} if b64OrigHash: attribs["orighash"] = b64OrigHash mediaNode = ProtocolTreeNode("media", attribs) iqNode = ProtocolTreeNode("iq",{"id":idx,"to":"s.whatsapp.net","type":"set"},[mediaNode]) self._writeNode(iqNode) def sendSync(self, contacts): idx = self.makeId("sendsync_") self.readerThread.requests[idx] = self.readerThread.parseSync users = [] for c in contacts: users.append(ProtocolTreeNode("user",None,None,'+' + c.replace('+', ''))) node = ProtocolTreeNode( "iq", { "type" : "get", "id" : idx }, [ ( ProtocolTreeNode( "sync", { "mode" : 'delta', "context" : 'background', "sid" : str((time.time() + 11644477200) * 10000000), "index" : '0', "request" : "all", "xmlns" : "urn:xmpp:whatsapp:sync" }, users, None) ), ] , None) self._writeNode(node) def getMessageNode(self, jid, 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; if requestNode is not None: messageChildren.append(requestNode); #System.currentTimeMillis() / 1000L + "-"+1 messageChildren.append(xNode) if type(child) == list: messageChildren.extend(child) else: messageChildren.append(child) msgId = str(int(time.time()))+"-"+ str(self.currKeyId) messageNode = ProtocolTreeNode("message",{"to":jid,"type":"chat","id":msgId},messageChildren) self.currKeyId += 1 return messageNode;
class YowsupConnectionManager: def __init__(self): Debugger.attach(self) self.currKeyId = 1 self.iqId = 0 self.verbose = True self.state = 0 self.lock = threading.Lock() self.autoPong = True self.domain = "s.whatsapp.net" #self.methodInterface = MethodInterface(authenticatedSocketConnection.getId()) #self.signalInterface = SignalInterface(authenticatedSocketConnection.getId()) self.readerThread = None self.methodInterface = LibMethodInterface() self.signalInterface = LibSignalInterface() self.readerThread = ReaderThread() self.readerThread.setSignalInterface(self.signalInterface) self.bindMethods() def setInterfaces(self, signalInterface, methodInterface): self.methodInterface = methodInterface self.signalInterface = signalInterface self.readerThread.setSignalInterface(self.signalInterface) self.bindMethods() def getSignalsInterface(self): return self.signalInterface def getMethodsInterface(self): return self.methodInterface def setAutoPong(self, autoPong): self.autoPong = self.readerThread.autoPong = autoPong def startReader(self): if self.readerThread.isAlive(): self._d("Reader already started") return 0 self._d("starting reader") try: self.readerThread.start() self._d("started") except RuntimeError: self._d("Reader already started before") self.readerThread.sendDisconnected() return 0 return 1 def block(self): self.readerThread.join() def bindMethods(self): self.methodInterface.registerCallback("getVersion", lambda: Constants.v) self.methodInterface.registerCallback("message_send",self.sendText) self.methodInterface.registerCallback("message_imageSend",self.sendImage) self.methodInterface.registerCallback("message_audioSend",self.sendAudio) self.methodInterface.registerCallback("message_videoSend",self.sendVideo) self.methodInterface.registerCallback("message_locationSend",self.sendLocation) self.methodInterface.registerCallback("message_vcardSend",self.sendVCard) self.methodInterface.registerCallback("message_broadcast",self.sendBroadcast) self.methodInterface.registerCallback("message_ack",self.sendMessageReceipt) self.methodInterface.registerCallback("notification_ack", self.sendNotificationReceipt) self.methodInterface.registerCallback("clientconfig_send",self.sendClientConfig) self.methodInterface.registerCallback("delivered_ack",self.sendDeliveredReceiptAck) self.methodInterface.registerCallback("visible_ack",self.sendVisibleReceiptAck) self.methodInterface.registerCallback("ping",self.sendPing) self.methodInterface.registerCallback("pong",self.sendPong) self.methodInterface.registerCallback("typing_send",self.sendTyping) self.methodInterface.registerCallback("typing_paused",self.sendPaused) self.methodInterface.registerCallback("subject_ack",self.sendSubjectReceived) self.methodInterface.registerCallback("group_getGroups", self.sendGetGroups) self.methodInterface.registerCallback("group_getInfo",self.sendGetGroupInfo) self.methodInterface.registerCallback("group_create",self.sendCreateGroupChat) self.methodInterface.registerCallback("group_addParticipants",self.sendAddParticipants) self.methodInterface.registerCallback("group_removeParticipants",self.sendRemoveParticipants) self.methodInterface.registerCallback("group_end",self.sendEndGroupChat) self.methodInterface.registerCallback("group_setSubject",self.sendSetGroupSubject) self.methodInterface.registerCallback("group_setPicture", self.sendSetPicture) self.methodInterface.registerCallback("group_getPicture", self.sendGetPicture) self.methodInterface.registerCallback("group_getParticipants",self.sendGetParticipants) self.methodInterface.registerCallback("picture_get",self.sendGetPicture) self.methodInterface.registerCallback("picture_getIds",self.sendGetPictureIds) self.methodInterface.registerCallback("contact_getProfilePicture", self.sendGetPicture) self.methodInterface.registerCallback("status_update",self.sendChangeStatus) self.methodInterface.registerCallback("presence_request",self.getLastOnline) #self.methodInterface.registerCallback("presence_unsubscribe",self.sendUnsubscribe)#@@TODO implement method self.methodInterface.registerCallback("presence_subscribe",self.sendSubscribe) self.methodInterface.registerCallback("presence_sendAvailableForChat",self.sendAvailableForChat) self.methodInterface.registerCallback("presence_sendAvailable",self.sendAvailable) self.methodInterface.registerCallback("presence_sendUnavailable",self.sendUnavailable) self.methodInterface.registerCallback("profile_setPicture", self.sendSetProfilePicture) self.methodInterface.registerCallback("profile_getPicture", self.sendGetProfilePicture) self.methodInterface.registerCallback("profile_setStatus", self.sendChangeStatus) self.methodInterface.registerCallback("disconnect", self.disconnect) self.methodInterface.registerCallback("ready", self.startReader) self.methodInterface.registerCallback("auth_login", self.auth ) #self.methodInterface.registerCallback("auth_login", self.auth) self.methodInterface.registerCallback("media_requestUpload", self.sendRequestUpload) def disconnect(self, reason=""): self._d("Disconnect sequence initiated") self._d("Sending term signal to reader thread") if self.readerThread.isAlive(): self.readerThread.terminate() self._d("Shutting down socket") self.socket.close() self._d("Waiting for readerThread to die") self.readerThread.join() self._d("Disconnected!") self._d(reason) self.state = 0 self.readerThread.sendDisconnected(reason) def getConnection(self): return self.socket def triggerEvent(self, eventName, stanza): if eventName in self.events and self.events[eventName] is not None: self.events[eventName](stanza) def bindEvent(self, eventName, callback): if eventName in self.events: self.events[eventName] = callback ########################################################## def _writeNode(self, node): if self.state == 2: try: self.out.write(node) return True except ConnectionClosedException: self._d("CONNECTION DOWN") #self.disconnect("closed") if self.readerThread.isAlive(): self.readerThread.terminate() self.readerThread.join() self.readerThread.sendDisconnected("closed") return False def onDisconnected(self): self._d("Setting state to 0") self.state = 0 def auth(self, username, password, mcc="000", mnc="000"): self._d(">>>>>>>> AUTH CALLED") username = str(username) #password = str(password) #traceback.print_stack() self.lock.acquire() if self.state == 0 : if self.readerThread.isAlive(): raise Exception("TWO READER THREADS ON BOARD!!") self.readerThread = ReaderThread() self.readerThread.autoPong = self.autoPong self.readerThread.setSignalInterface(self.signalInterface) yAuth = YowsupAuth(ConnectionEngine()) try: self.state = 1 connection = yAuth.authenticate(username, password, Constants.domain, Utilities.Resource, mcc, mnc) except socket.gaierror: self._d("DNS ERROR") self.readerThread.sendDisconnected("dns") #self.signalInterface.send("disconnected", ("dns",)) self.lock.release() self.state = 0 return 0 except socket.error: self._d("Socket error, connection timed out") self.readerThread.sendDisconnected("closed") #self.signalInterface.send("disconnected", ("closed",)) self.lock.release() self.state = 0 return 0 except ConnectionClosedException: self._d("Conn closed Exception") self.readerThread.sendDisconnected("closed") #self.signalInterface.send("disconnected", ("closed",)) self.lock.release() self.state = 0 return 0 if not connection: self.state = 0 self.signalInterface.send("auth_fail", (username, "invalid")) self.lock.release() return 0 self.state = 2 self.socket = connection self.jid = self.socket.jid #@@TODO REPLACE PROPERLY self.out = self.socket.writer self.readerThread.setSocket(self.socket) self.readerThread.disconnectedCallback = self.onDisconnected self.readerThread.onPing = self.sendPong self.readerThread.ping = self.sendPing self.signalInterface.send("auth_success", (username,)) self.lock.release() 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._writeNode(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._writeNode(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._writeNode(messageNode); def sendMessageReceipt(self, jid, msgId): self.sendReceipt(jid, "chat", msgId) def sendNotificationReceipt(self, jid, notificationId): self.sendReceipt(jid, "notification", notificationId) def sendReceipt(self,jid,mtype,mid): self._d("sending message received to "+jid+" - type:"+mtype+" - id:"+mid) receivedNode = ProtocolTreeNode("received",{"xmlns": "urn:xmpp:receipts"}) messageNode = ProtocolTreeNode("message",{"to":jid,"type":mtype,"id":mid},[receivedNode]); self._writeNode(messageNode); def sendDeliveredReceiptAck(self,to,msg_id): self._writeNode(self.getReceiptAck(to,msg_id,"delivered")); def sendVisibleReceiptAck(self,to,msg_id): self._writeNode(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.readerThread.requests[idx] = self.readerThread.parsePingResponse; pingNode = ProtocolTreeNode("ping",{"xmlns":"w:p"}); iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":self.domain},[pingNode]); self._writeNode(iqNode); return idx def sendPong(self,idx): iqNode = ProtocolTreeNode("iq",{"type":"result","to":self.domain,"id":idx}) self._writeNode(iqNode); def getLastOnline(self,jid): if len(jid.split('-')) == 2 or jid == "*****@*****.**": #SUPER CANCEL SUBSCRIBE TO GROUP AND SERVER return self.sendSubscribe(jid); self._d("presence request Initiated for %s"%(jid)) idx = self.makeId("last_") self.readerThread.requests[idx] = self.readerThread.parseLastOnline; query = ProtocolTreeNode("query",{"xmlns":"jabber:iq:last"}); iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":jid},[query]); self._writeNode(iqNode) def sendIq(self): node = ProtocolTreeNode("iq",{"to":"g.us","type":"get","id":str(int(time.time()))+"-0"},None,'expired'); self._writeNode(node); node = ProtocolTreeNode("iq",{"to":"s.whatsapp.net","type":"set","id":str(int(time.time()))+"-1"},None,'expired'); self._writeNode(node); def sendAvailableForChat(self, pushname): presenceNode = ProtocolTreeNode("presence",{"name":pushname}) self._writeNode(presenceNode); def sendAvailable(self): presenceNode = ProtocolTreeNode("presence",{"type":"available"}) self._writeNode(presenceNode); def sendUnavailable(self): presenceNode = ProtocolTreeNode("presence",{"type":"unavailable"}) self._writeNode(presenceNode); def sendSubscribe(self,to): presenceNode = ProtocolTreeNode("presence",{"type":"subscribe","to":to}); self._writeNode(presenceNode); def mediaNode(fn): def wrapped(self, *args): mediaType = fn(self, *args) url = args[1] name = args[2] size = args[3] mmNode = ProtocolTreeNode("media", {"xmlns":"urn:xmpp:whatsapp:mms","type":mediaType,"file":name,"size":size,"url":url},None, args[4:][0] if args[4:] else None); return mmNode return wrapped def sendMessage(fn): def wrapped(self, *args): node = fn(self, *args) jid = "broadcast" if type(args[0]) == list else args[0] messageNode = self.getMessageNode(jid, node) self._writeNode(messageNode); return messageNode.getAttributeValue("id") return wrapped def sendChangeStatus(self,status): self._d("updating status to: %s"%(status)) bodyNode = ProtocolTreeNode("body",None,None,status); messageNode = self.getMessageNode("s.us",bodyNode) self._writeNode(messageNode); return messageNode.getAttributeValue("id") @sendMessage def sendText(self,jid, content): return ProtocolTreeNode("body",None,None,content); @sendMessage @mediaNode def sendImage(self, jid, url, name, size, preview): return "image" @sendMessage @mediaNode def sendVideo(self, jid, url, name, size, preview): return "video" @sendMessage @mediaNode def sendAudio(self, jid, url, name, size): return "audio" @sendMessage def sendLocation(self, jid, latitude, longitude, preview): self._d("sending location (" + latitude + ":" + longitude + ")") return ProtocolTreeNode("media", {"xmlns":"urn:xmpp:whatsapp:mms","type":"location","latitude":latitude,"longitude":longitude},None,preview) @sendMessage def sendVCard(self, jid, data, name): cardNode = ProtocolTreeNode("vcard",{"name":name},None,data); return ProtocolTreeNode("media", {"xmlns":"urn:xmpp:whatsapp:mms","type":"vcard"},[cardNode]) @sendMessage def sendBroadcast(self, jids, content): broadcastNode = ProtocolTreeNode("broadcast", None, [ProtocolTreeNode("to", {"jid": jid}) for jid in jids]) messageNode = ProtocolTreeNode("body",None,None,content); return [broadcastNode, messageNode] 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._writeNode(iqNode); def sendGetGroups(self,gtype): self._d("getting groups %s"%(gtype)) idx = self.makeId("get_groups_") self.readerThread.requests[idx] = self.readerThread.parseGroups; queryNode = ProtocolTreeNode("list",{"xmlns":"w:g","type":gtype}) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":"g.us"},[queryNode]) self._writeNode(iqNode) def sendGetGroupInfo(self,jid): self._d("getting group info for %s"%(jid)) idx = self.makeId("get_g_info_") self.readerThread.requests[idx] = self.readerThread.parseGroupInfo; queryNode = ProtocolTreeNode("query",{"xmlns":"w:g"}) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":jid},[queryNode]) self._writeNode(iqNode) def sendCreateGroupChat(self,subject): self._d("creating group: %s"%(subject)) idx = self.makeId("create_group_") self.readerThread.requests[idx] = self.readerThread.parseGroupCreated; queryNode = ProtocolTreeNode("group",{"xmlns":"w:g","action":"create","subject":subject}) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":"g.us"},[queryNode]) self._writeNode(iqNode) def sendAddParticipants(self, gjid, participants): self._d("opening group: %s"%(gjid)) self._d("adding participants: %s"%(participants)) idx = self.makeId("add_group_participants_") self.readerThread.requests[idx] = self.readerThread.parseAddedParticipants; innerNodeChildren = [] for part in participants: innerNodeChildren.append( ProtocolTreeNode("participant",{"jid":part}) ) queryNode = ProtocolTreeNode("add",{"xmlns":"w:g"},innerNodeChildren) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":gjid},[queryNode]) self._writeNode(iqNode) def sendRemoveParticipants(self,gjid, participants): self._d("opening group: %s"%(gjid)) self._d("removing participants: %s"%(participants)) idx = self.makeId("remove_group_participants_") self.readerThread.requests[idx] = self.readerThread.parseRemovedParticipants; innerNodeChildren = [] for part in participants: innerNodeChildren.append( ProtocolTreeNode("participant",{"jid":part}) ) queryNode = ProtocolTreeNode("remove",{"xmlns":"w:g"},innerNodeChildren) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":gjid},[queryNode]) self._writeNode(iqNode) def sendEndGroupChat(self,gjid): self._d("removing group: %s"%(gjid)) idx = self.makeId("leave_group_") self.readerThread.requests[idx] = self.readerThread.parseGroupEnded; innerNodeChildren = [] innerNodeChildren.append( ProtocolTreeNode("group",{"id":gjid}) ) queryNode = ProtocolTreeNode("leave",{"xmlns":"w:g"},innerNodeChildren) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":"g.us"},[queryNode]) self._writeNode(iqNode) def sendSetGroupSubject(self,gjid,subject): #subject = subject.encode('utf-8') #self._d("setting group subject of " + gjid + " to " + subject) idx = self.makeId("set_group_subject_") self.readerThread.requests[idx] = self.readerThread.parseGroupSubject queryNode = ProtocolTreeNode("subject",{"xmlns":"w:g","value":subject}) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":gjid},[queryNode]); self._writeNode(iqNode) def sendGetParticipants(self,jid): idx = self.makeId("get_participants_") self.readerThread.requests[idx] = self.readerThread.parseParticipants listNode = ProtocolTreeNode("list",{"xmlns":"w:g"}) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":jid},[listNode]); self._writeNode(iqNode) def sendGetPicture(self,jid): self._d("GETTING PICTURE FROM " + jid) idx = self.makeId("get_picture_") #@@TODO, ?! self.readerThread.requests[idx] = self.readerThread.parseGetPicture listNode = ProtocolTreeNode("picture",{"xmlns":"w:profile:picture","type":"image"}) iqNode = ProtocolTreeNode("iq",{"id":idx,"to":jid,"type":"get"},[listNode]); self._writeNode(iqNode) def sendGetPictureIds(self,jids): idx = self.makeId("get_picture_ids_") self.readerThread.requests[idx] = self.readerThread.parseGetPictureIds innerNodeChildren = [] for jid in jids: innerNodeChildren.append( ProtocolTreeNode("user",{"jid": jid}) ) queryNode = ProtocolTreeNode("list",{"xmlns":"w:profile:picture"},innerNodeChildren) iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get"},[queryNode]) self._writeNode(iqNode) def sendGetProfilePicture(self): return self.sendGetPicture(self.jid) def sendSetProfilePicture(self, filepath): return self.sendSetPicture(self.jid, filepath) def sendSetPicture(self, jid, imagePath): f = open(imagePath, 'rb') imageData = f.read() imageData = bytearray(imageData) f.close() idx = self.makeId("set_picture_") self.readerThread.requests[idx] = self.readerThread.parseSetPicture listNode = ProtocolTreeNode("picture",{"xmlns":"w:profile:picture","type":"image"}, None, imageData) iqNode = ProtocolTreeNode("iq",{"id":idx,"to":jid,"type":"set"},[listNode]) self._writeNode(iqNode) def sendRequestUpload(self, b64Hash, t, size, b64OrigHash = None): idx = self.makeId("upload_") self.readerThread.requests[idx] = lambda iqresnode: self.readerThread.parseRequestUpload(iqresnode, b64Hash) if type(size) is not str: size = str(size) attribs = {"xmlns":"w:m","hash":b64Hash, "type":t, "size":size} if b64OrigHash: attribs["orighash"] = b64OrigHash mediaNode = ProtocolTreeNode("media", attribs) iqNode = ProtocolTreeNode("iq",{"id":idx,"to":"s.whatsapp.net","type":"set"},[mediaNode]) self._writeNode(iqNode) def getMessageNode(self, jid, 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; if requestNode is not None: messageChildren.append(requestNode); #System.currentTimeMillis() / 1000L + "-"+1 messageChildren.append(xNode) if type(child) == list: messageChildren.extend(child) else: messageChildren.append(child) msgId = str(int(time.time()))+"-"+ str(self.currKeyId) messageNode = ProtocolTreeNode("message",{"to":jid,"type":"chat","id":msgId},messageChildren) self.currKeyId += 1 return messageNode;