diff --git a/session.py b/session.py index 7883305..a459c49 100644 --- a/session.py +++ b/session.py @@ -211,11 +211,11 @@ class Session(YowsupApp): else: self.onPresenceUnavailable(number) def sendReadReceipts(self, buddy): - for _id, _from, participant in self.recvMsgIDs: + for _id, _from, participant, t in self.recvMsgIDs: if _from.split('@')[0] == buddy: - self.sendReceipt(_id, _from, 'read', participant) - self.recvMsgIDs.remove((_id, _from, participant)) - self.logger.debug("Send read receipt to %s (ID: %s)" % (_from, _id)) + self.sendReceipt(_id, _from, 'read', participant, t) + self.recvMsgIDs.remove((_id, _from, participant, t)) + self.logger.debug("Send read receipt to %s (ID: %s)", _from, _id) # Called by superclass def onAuthSuccess(self, status, kind, creation, @@ -280,19 +280,13 @@ class Session(YowsupApp): # Called by superclass def onTextMessage(self, _id, _from, to, notify, timestamp, participant, offline, retry, body): - - self.logger.debug('received TextMessage' + - ' '.join(map(str, [ - _id, _from, to, notify, timestamp, - participant, offline, retry, body.encode("utf-8") - ])) - ) buddy = _from.split('@')[0] messageContent = utils.softToUni(body) - self.sendReceipt(_id, _from, None, participant) - self.recvMsgIDs.append((_id, _from, participant)) + self.sendReceipt(_id, _from, None, participant, timestamp) + self.recvMsgIDs.append((_id, _from, participant, timestamp)) self.logger.info("Message received from %s to %s: %s (at ts=%s)" % (buddy, self.legacyName, messageContent, timestamp)) + if participant is not None: # Group message or broadcast partname = participant.split('@')[0] if _from.split('@')[1] == 'broadcast': # Broadcast message @@ -313,27 +307,36 @@ class Session(YowsupApp): participant = image.participant if image.caption is None: image.caption = '' - - # Add to message data for descrypt - iv, cipherKey = image.getDecryptData(); - ivHexString = "".join("{:02x}".format(ord(c)) for c in iv) - cipherKeyHexString = "".join("{:02x}".format(ord(c)) for c in cipherKey) - message = image.url + ';' + ivHexString + ';' + cipherKeyHexString + + if image.isEncrypted(): + self.logger.debug('Received encrypted image message') + if self.backend.specConf is not None and self.backend.specConf.__getitem__("service.web_directory") is not None and self.backend.specConf.__getitem__("service.web_url") is not None : + ipath = "/" + str(image.timestamp) + image.getExtension() + + with open(self.backend.specConf.__getitem__("service.web_directory") + ipath,"wb") as f: + f.write(image.getMediaContent()) + url = self.backend.specConf.__getitem__("service.web_url") + ipath + else: + self.logger.warn('Received encrypted image: web storage not set in config!') + url = image.url + + else: + url = image.url if participant is not None: # Group message partname = participant.split('@')[0] if image._from.split('@')[1] == 'broadcast': # Broadcast message self.sendMessageToXMPP(partname, self.broadcast_prefix, image.timestamp) - self.sendMessageToXMPP(partname, image.url, image.timestamp) + self.sendMessageToXMPP(partname, url, image.timestamp) self.sendMessageToXMPP(partname, image.caption, image.timestamp) else: # Group message - self.sendGroupMessageToXMPP(buddy, partname, image.url, image.timestamp) + self.sendGroupMessageToXMPP(buddy, partname, url, image.timestamp) self.sendGroupMessageToXMPP(buddy, partname, image.caption, image.timestamp) else: - self.sendMessageToXMPP(buddy, image.url, image.timestamp) + self.sendMessageToXMPP(buddy, url, image.timestamp) self.sendMessageToXMPP(buddy, image.caption, image.timestamp) - self.sendReceipt(image._id, image._from, None, image.participant) - self.recvMsgIDs.append((image._id, image._from, image.participant)) + self.sendReceipt(image._id, image._from, None, image.participant, image.timestamp) + self.recvMsgIDs.append((image._id, image._from, image.participant, image.timestamp)) # Called by superclass @@ -351,8 +354,8 @@ class Session(YowsupApp): self.sendGroupMessageToXMPP(buddy, partname, message, audio.timestamp) else: self.sendMessageToXMPP(buddy, message, audio.timestamp) - self.sendReceipt(audio._id, audio._from, None, audio.participant) - self.recvMsgIDs.append((audio._id, audio._from, audio.participant)) + self.sendReceipt(audio._id, audio._from, None, audio.participant, audio.timestamp) + self.recvMsgIDs.append((audio._id, audio._from, audio.participant, audio.timestamp)) # Called by superclass @@ -371,8 +374,8 @@ class Session(YowsupApp): self.sendGroupMessageToXMPP(buddy, partname, message, video.timestamp) else: self.sendMessageToXMPP(buddy, message, video.timestamp) - self.sendReceipt(video._id, video._from, None, video.participant) - self.recvMsgIDs.append((video._id, video._from, video.participant)) + self.sendReceipt(video._id, video._from, None, video.participant, video.timestamp) + self.recvMsgIDs.append((video._id, video._from, video.participant, video.timestamp)) def onLocation(self, location): @@ -400,8 +403,8 @@ class Session(YowsupApp): if url is not None: self.sendMessageToXMPP(buddy, url, location.timestamp) self.sendMessageToXMPP(buddy, latlong, location.timestamp) - self.sendReceipt(location._id, location._from, None, location.participant) - self.recvMsgIDs.append((loaction._id, location._from, location.participant)) + self.sendReceipt(location._id, location._from, None, location.participant, location.timestamp) + self.recvMsgIDs.append((location._id, location._from, location.participant, location.timestamp)) @@ -423,8 +426,8 @@ class Session(YowsupApp): self.sendMessageToXMPP(buddy, message, timestamp) # self.sendMessageToXMPP(buddy, card_data) #self.transferFile(buddy, str(name), card_data) - self.sendReceipt(_id, _from, None, participant) - self.recvMsgIDs.append((_id, _from, participant)) + self.sendReceipt(_id, _from, None, participant, timestamp) + self.recvMsgIDs.append((_id, _from, participant, timestamp)) def transferFile(self, buddy, name, data): diff --git a/transwhat.py b/transwhat.py index 8186a93..929727d 100644 --- a/transwhat.py +++ b/transwhat.py @@ -40,7 +40,7 @@ import threadutils sys.path.insert(0, os.getcwd()) from Spectrum2.iochannel import IOChannel - +from config import SpectrumConfig from whatsappbackend import WhatsAppBackend from yowsup.common import YowConstants from yowsup.stacks import YowStack @@ -69,6 +69,11 @@ logging.basicConfig( level = logging.DEBUG if args.debug else logging.INFO ) +if args.config is not None: + specConf = SpectrumConfig(args.config) +else: + specConf = None + # Handler def handleTransportData(data): try: @@ -89,7 +94,7 @@ def connectionClosed(): # Main io = IOChannel(args.host, args.port, handleTransportData, connectionClosed) -plugin = WhatsAppBackend(io, args.j) +plugin = WhatsAppBackend(io, args.j, specConf) plugin.handleBackendConfig({ 'features': [ diff --git a/whatsappbackend.py b/whatsappbackend.py index e0cdc99..6230d94 100644 --- a/whatsappbackend.py +++ b/whatsappbackend.py @@ -36,10 +36,11 @@ import logging class WhatsAppBackend(SpectrumBackend): - def __init__(self, io, spectrum_jid): + def __init__(self, io, spectrum_jid, specConf): SpectrumBackend.__init__(self) self.logger = logging.getLogger(self.__class__.__name__) self.io = io + self.specConf = specConf self.sessions = { } self.spectrum_jid = spectrum_jid # Used to prevent duplicate messages diff --git a/yowsupwrapper.py b/yowsupwrapper.py index 348f3c5..8b64301 100644 --- a/yowsupwrapper.py +++ b/yowsupwrapper.py @@ -133,7 +133,7 @@ class YowsupApp(object): """ self.stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_DISCONNECT)) - def sendReceipt(self, _id, _from, read, participant): + def sendReceipt(self, _id, _from, read, participant, t): """ Send a receipt (delivered: double-tick, read: blue-ticks) @@ -142,8 +142,10 @@ class YowsupApp(object): - _from: jid of person who sent the message - read: ('read' or None) None is just delivered, 'read' is read - participant + - t: The time the original message was sent. """ - receipt = OutgoingReceiptProtocolEntity(_id, _from, read, participant) + self.logger.debug(u'Sending receipt to whatsapp: %s', [_id, _from, read, participant, t]) + receipt = OutgoingReceiptProtocolEntity(_id, _from, read, participant, t=t) self.sendEntity(receipt) def downloadMedia(self, url, onSuccess = None, onFailure = None): @@ -183,9 +185,27 @@ class YowsupApp(object): if resultRequestUploadIqProtocolEntity.isDuplicate(): doSendFn(filePath, resultRequestUploadIqProtocolEntity.getUrl(), jid, - resultRequestUploadIqProtocolEntity.getIp(), caption) + resultRequestUploadIqProtocolEntity.getIp(), caption, onSuccess, onFailure) else: - successFn = lambda filePath, jid, url: doSendFn(filePath, url, jid, resultRequestUploadIqProtocolEntity.getIp(), caption, onSuccess, onFailure) + successFn = lambda filePath, jid, url: doSendFn(filePath, url.encode('ascii','ignore'), 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) + mediaUploader.start() + + def onRequestUploadError(self, jid, path, errorRequestUploadIqProtocolEntity, requestUploadIqProtocolEntity): + self.logger.error("Request upload for file %s for %s failed" % (path, jid)) + + def onUploadError(self, filePath, jid, url): + #logger.error("Upload file %s to %s for %s failed!" % (filePath, url, jid)) + self.logger.error("Upload Error!") + + def onUploadProgress(self, filePath, jid, url, progress): + #sys.stdout.write("%s => %s, %d%% \r" % (os.path.basename(filePath), jid, progress)) + #sys.stdout.flush() + pass ownNumber = self.stack.getLayerInterface(YowAuthenticationProtocolLayer).getUsername(full=False)