diff --git a/deferred.py b/deferred.py index 5ab3d02..e270c5d 100644 --- a/deferred.py +++ b/deferred.py @@ -71,7 +71,7 @@ class Deferred(object): """ Calls when func(*args, **kwargs) when deferred gets a value """ def helper(*args2, **kwargs2): func(*args, **kwargs) - self.then(helper) + return self.then(helper) def __getattr__(self, method_name): return getattr(Then(self), method_name) @@ -130,7 +130,7 @@ def call(func, *args, **kwargs): def restfunc2(*arg2, **kwarg2): apply_deferred = partial(normalfunc, *arg2, **kwarg2) return call(apply_deferred, **dict(items[i + 1:])) - return c.then(restfunc2) + return v.then(restfunc2) # No items deferred return func(*args, **kwargs) diff --git a/session.py b/session.py index 853c642..f1f6c34 100644 --- a/session.py +++ b/session.py @@ -570,16 +570,46 @@ class Session(YowsupApp): self.logger.info("Stopped typing: %s to %s", self.legacyName, buddy) self.sendTyping(buddy, False) + def sendImage(self, message, ID, to): + if (".jpg" in message.lower()): + imgType = "jpg" + if (".webp" in message.lower()): + imgType = "webp" + + success = deferred.Deferred() + error = deferred.Deferred() + self.downloadMedia(message, success.run, error.run) + + # Success + path = success.arg(0) + call(self.logger.info, "Success: Image downloaded to %s", path) + pathWithExt = path.then(lambda p: p + "." + imgType) + call(os.rename, path, pathWithExt) + pathJpg = path.then(lambda p: p + ".jpg") + if imgType != "jpg": + im = call(Image.open, pathWithExt) + call(im.save, pathJpg) + call(os.remove, pathWithExt) + call(self.logger.info, "Sending image to %s", to) + waId = deferred.Deferred() + call(super(Session, self).sendImage, to, pathJpg, onSuccess = waId.run) + call(self.setWaId, ID, waId) + waId.when(call, os.remove, pathJpg) + waId.when(self.logger.info, "Image sent") + + # Error + error.when(self.logger.info, "Download Error. Sending message as is.") + waId = error.when(self.sendTextMessage, to, message) + call(self.setWaId, ID, waId) + + def setWaId(self, XmppId, waId): + self.msgIDs[waId] = MsgIDs(XmppId, waId) + def sendMessageToWA(self, sender, message, ID, xhtml=""): self.logger.info("Message sent from %s to %s: %s (xhtml=%s)", self.legacyName, sender, message, xhtml) message = message.encode("utf-8") - # FIXME: Fragile, should pass this in to onDlerror - self.dlerror_message = message - self.dlerror_sender = sender - self.dlerror_ID = ID - # End Fragile if sender == "bot": self.bot.parse(message) @@ -616,24 +646,11 @@ class Session(YowsupApp): self.logger.error('Group not found: %s', room) if (".jpg" in message.lower()) or (".webp" in message.lower()): - if (".jpg" in message.lower()): - self.imgType = "jpg" - if (".webp" in message.lower()): - self.imgType = "webp" - self.imgMsgId = ID - self.imgBuddy = room + "@g.us" - - - downloader = MediaDownloader(self.onDlsuccess, self.onDlerror) - downloader.download(message) - #self.imgMsgId = ID - #self.imgBuddy = room + "@g.us" - elif "geo:" in message.lower(): - self._sendLocation(room + "@g.us", message, ID) - - else: - - self.sendTextMessage(self._lengthenGroupId(room) + '@g.us', message) + self.sendImage(message, ID, room + '@g.us') + elif "geo:" in message.lower(): + self._sendLocation(room + "@g.us", message, ID) + else: + self.sendTextMessage(room + '@g.us', message) else: # private msg buddy = sender # if message == "\\lastseen": @@ -649,20 +666,8 @@ class Session(YowsupApp): #self.call("contact_getProfilePicture", (buddy + "@s.whatsapp.net",)) self.requestVCard(buddy) else: - if (".jpg" in message.lower()) or (".webp" in message.lower()): - #waId = self.call("message_imageSend", (buddy + "@s.whatsapp.net", message, None, 0, None)) - #waId = self.call("message_send", (buddy + "@s.whatsapp.net", message)) - if (".jpg" in message.lower()): - self.imgType = "jpg" - if (".webp" in message.lower()): - self.imgType = "webp" - self.imgMsgId = ID - self.imgBuddy = buddy + "@s.whatsapp.net" - - downloader = MediaDownloader(self.onDlsuccess, self.onDlerror) - downloader.download(message) - #self.imgMsgId = ID - #self.imgBuddy = buddy + "@s.whatsapp.net" + if (".jpg" in message.lower()) or (".webp" in message.lower()): + self.sendImage(message, ID, buddy + "@s.whatsapp.net") elif "geo:" in message.lower(): self._sendLocation(buddy + "@s.whatsapp.net", message, ID) else: @@ -804,48 +809,6 @@ class Session(YowsupApp): def requestVCard(self, buddy, ID=None): self.buddies.requestVCard(buddy, ID) - def onDlsuccess(self, path): - self.logger.info("Success: Image downloaded to %s", path) - os.rename(path, path+"."+self.imgType) - if self.imgType != "jpg": - im = Image.open(path+"."+self.imgType) - im.save(path+".jpg") - self.imgPath = path+".jpg" - statinfo = os.stat(self.imgPath) - name=os.path.basename(self.imgPath) - self.logger.info("Buddy %s",self.imgBuddy) - self.image_send(self.imgBuddy, self.imgPath) - - #self.logger.info("Sending picture %s of size %s with name %s",self.imgPath, statinfo.st_size, name) - #mtype = "image" - - #sha1 = hashlib.sha256() - #fp = open(self.imgPath, 'rb') - #try: - # sha1.update(fp.read()) - # hsh = base64.b64encode(sha1.digest()) - # self.call("media_requestUpload", (hsh, mtype, os.path.getsize(self.imgPath))) - #finally: - # fp.close() - - - def onDlerror(self): - self.logger.info("Download Error. Sending message as is.") - waId = self.sendTextMessage(self.dlerror_sender + '@s.whatsapp.net', self.dlerror_message) - self.msgIDs[waId] = MsgIDs(self.dlerror_ID, waId) - - - def _doSendImage(self, filePath, url, to, ip = None, caption = None): - waId = self.doSendImage(filePath, url, to, ip, caption) - self.msgIDs[waId] = MsgIDs(self.imgMsgId, waId) - - def _doSendAudio(self, filePath, url, to, ip = None, caption = None): - waId = self.doSendAudio(filePath, url, to, ip, caption) - self.msgIDs[waId] = MsgIDs(self.imgMsgId, waId) - - - - def createThumb(self, size=100, raw=False): img = Image.open(self.imgPath) width, height = img.size diff --git a/whatsappbackend.py b/whatsappbackend.py index 1c908f5..691dc73 100644 --- a/whatsappbackend.py +++ b/whatsappbackend.py @@ -121,6 +121,9 @@ class WhatsAppBackend(SpectrumBackend): self.logger.debug("handleVCardUpdatedRequest(user=%s, nickname=%s)", user, nickname) self.sessions[user].setProfilePicture(photo) + def handleBuddyBlockToggled(self, user, buddy, blocked): + self.logger.debug("handleBuddyBlockedToggled(user=%s, buddy=%s, blocked=%s)", user, buddy, blocked) + def relogin(self, user, legacyName, password, extra): """ Used to re-initialize the session object. Used when finished with @@ -137,10 +140,6 @@ class WhatsAppBackend(SpectrumBackend): self.sessions[user].login(password) # TODO - def handleBuddyBlockToggled(self, user, buddy, blocked): - pass - - def handleAttentionRequest(self, user, buddy, message): pass diff --git a/yowsupwrapper.py b/yowsupwrapper.py index 1cef653..f5bece2 100644 --- a/yowsupwrapper.py +++ b/yowsupwrapper.py @@ -43,6 +43,7 @@ from yowsup.layers.protocol_privacy.protocolentities import * from yowsup.layers.protocol_receipts.protocolentities import * from yowsup.layers.protocol_iq.protocolentities import * from yowsup.layers.protocol_media.mediauploader import MediaUploader +from yowsup.layers.protocol_media.mediadownloader import MediaDownloader # Registration @@ -136,6 +137,10 @@ class YowsupApp(object): receipt = OutgoingReceiptProtocolEntity(_id, _from, read, participant) self.sendEntity(receipt) + def downloadMedia(self, url, onSuccess = None, onFailure = None): + downloader = MediaDownloader(onSuccess, onFailure) + downloader.download(url) + def sendTextMessage(self, to, message): """ Sends a text message @@ -153,26 +158,27 @@ class YowsupApp(object): self.sendEntity(messageEntity) return messageEntity.getId() - def image_send(self, jid, path, caption = None): - entity = RequestUploadIqProtocolEntity(RequestUploadIqProtocolEntity.MEDIA_TYPE_IMAGE, filePath=path) - successFn = lambda successEntity, originalEntity: self.onRequestUploadResult(jid, path, successEntity, originalEntity, caption) + def sendImage(self, jid, path, caption = None, onSuccess = None, onFailure = None): + entity = RequestUploadIqProtocolEntity(RequestUploadIqProtocolEntity.MEDIA_TYPE_IMAGE, filePath=path) + successFn = lambda successEntity, originalEntity: self.onRequestUploadResult(jid, path, successEntity, originalEntity, caption, onSuccess, onFailure) errorFn = lambda errorEntity, originalEntity: self.onRequestUploadError(jid, path, errorEntity, originalEntity) self.sendIq(entity, successFn, errorFn) - def onRequestUploadResult(self, jid, filePath, resultRequestUploadIqProtocolEntity, requestUploadIqProtocolEntity, caption = None): + def onRequestUploadResult(self, jid, filePath, resultRequestUploadIqProtocolEntity, requestUploadIqProtocolEntity, caption = None, onSuccess=None, onFailure=None): if requestUploadIqProtocolEntity.mediaType == RequestUploadIqProtocolEntity.MEDIA_TYPE_AUDIO: - doSendFn = self._doSendAudio + doSendFn = self.doSendAudio else: - doSendFn = self._doSendImage + doSendFn = self.doSendImage if resultRequestUploadIqProtocolEntity.isDuplicate(): doSendFn(filePath, resultRequestUploadIqProtocolEntity.getUrl(), jid, resultRequestUploadIqProtocolEntity.getIp(), caption) else: - successFn = lambda filePath, jid, url: doSendFn(filePath, url, jid, resultRequestUploadIqProtocolEntity.getIp(), caption) - mediaUploader = MediaUploader(jid, self.legacyName, filePath, + successFn = lambda filePath, jid, url: doSendFn(filePath, url, jid, resultRequestUploadIqProtocolEntity.getIp(), caption, onSuccess, onFailure) + ownNumber = self.stack.getLayerInterface(YowAuthenticationProtocolLayer).getUsername(full=False) + mediaUploader = MediaUploader(jid, ownNumber, filePath, resultRequestUploadIqProtocolEntity.getUrl(), resultRequestUploadIqProtocolEntity.getResumeOffset(), successFn, self.onUploadError, self.onUploadProgress, async=False) @@ -190,17 +196,21 @@ class YowsupApp(object): #sys.stdout.flush() pass - def doSendImage(self, filePath, url, to, ip = None, caption = None): + def doSendImage(self, filePath, url, to, ip = None, caption = None, onSuccess = None, onFailure = None): entity = ImageDownloadableMediaMessageProtocolEntity.fromFilePath(filePath, url, ip, to, caption = caption) self.sendEntity(entity) - #self.msgIDs[entity.getId()] = MsgIDs(self.imgMsgId, entity.getId()) + #self.msgIDs[entity.getId()] = MsgIDs(self.imgMsgId, entity.getId()) + if onSuccess is not None: + onSuccess(entity.getId()) return entity.getId() - def doSendAudio(self, filePath, url, to, ip = None, caption = None): + def doSendAudio(self, filePath, url, to, ip = None, caption = None, onSuccess = None, onFailure = None): entity = AudioDownloadableMediaMessageProtocolEntity.fromFilePath(filePath, url, ip, to) self.sendEntity(entity) #self.msgIDs[entity.getId()] = MsgIDs(self.imgMsgId, entity.getId()) + if onSuccess is not None: + onSuccess(entity.getId()) return entity.getId() @@ -310,7 +320,6 @@ class YowsupApp(object): - success: (func) - Callback; Takes three arguments: existing numbers, non-existing numbers, invalid numbers. """ - # TODO: Implement callbacks mode = GetSyncIqProtocolEntity.MODE_DELTA if delta else GetSyncIqProtocolEntity.MODE_FULL context = GetSyncIqProtocolEntity.CONTEXT_INTERACTIVE if interactive else GetSyncIqProtocolEntity.CONTEXT_REGISTRATION # International contacts must be preceded by a plus. Other numbers are