Allow multiple pictures to be sent in a short period of time
Picture data was stored in the session object. This means that if you send multiple pictures within a short period of time the last picture would overwrite the data of the other pictures. This would cause pictures to be lost. Now picture data is stored in closures
This commit is contained in:
parent
4273153d84
commit
df305b8491
|
@ -71,7 +71,7 @@ class Deferred(object):
|
||||||
""" Calls when func(*args, **kwargs) when deferred gets a value """
|
""" Calls when func(*args, **kwargs) when deferred gets a value """
|
||||||
def helper(*args2, **kwargs2):
|
def helper(*args2, **kwargs2):
|
||||||
func(*args, **kwargs)
|
func(*args, **kwargs)
|
||||||
self.then(helper)
|
return self.then(helper)
|
||||||
|
|
||||||
def __getattr__(self, method_name):
|
def __getattr__(self, method_name):
|
||||||
return getattr(Then(self), method_name)
|
return getattr(Then(self), method_name)
|
||||||
|
@ -130,7 +130,7 @@ def call(func, *args, **kwargs):
|
||||||
def restfunc2(*arg2, **kwarg2):
|
def restfunc2(*arg2, **kwarg2):
|
||||||
apply_deferred = partial(normalfunc, *arg2, **kwarg2)
|
apply_deferred = partial(normalfunc, *arg2, **kwarg2)
|
||||||
return call(apply_deferred, **dict(items[i + 1:]))
|
return call(apply_deferred, **dict(items[i + 1:]))
|
||||||
return c.then(restfunc2)
|
return v.then(restfunc2)
|
||||||
# No items deferred
|
# No items deferred
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
|
|
121
session.py
121
session.py
|
@ -570,16 +570,46 @@ class Session(YowsupApp):
|
||||||
self.logger.info("Stopped typing: %s to %s", self.legacyName, buddy)
|
self.logger.info("Stopped typing: %s to %s", self.legacyName, buddy)
|
||||||
self.sendTyping(buddy, False)
|
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=""):
|
def sendMessageToWA(self, sender, message, ID, xhtml=""):
|
||||||
self.logger.info("Message sent from %s to %s: %s (xhtml=%s)",
|
self.logger.info("Message sent from %s to %s: %s (xhtml=%s)",
|
||||||
self.legacyName, sender, message, xhtml)
|
self.legacyName, sender, message, xhtml)
|
||||||
|
|
||||||
message = message.encode("utf-8")
|
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":
|
if sender == "bot":
|
||||||
self.bot.parse(message)
|
self.bot.parse(message)
|
||||||
|
@ -616,24 +646,11 @@ class Session(YowsupApp):
|
||||||
self.logger.error('Group not found: %s', room)
|
self.logger.error('Group not found: %s', room)
|
||||||
|
|
||||||
if (".jpg" in message.lower()) or (".webp" in message.lower()):
|
if (".jpg" in message.lower()) or (".webp" in message.lower()):
|
||||||
if (".jpg" in message.lower()):
|
self.sendImage(message, ID, room + '@g.us')
|
||||||
self.imgType = "jpg"
|
elif "geo:" in message.lower():
|
||||||
if (".webp" in message.lower()):
|
self._sendLocation(room + "@g.us", message, ID)
|
||||||
self.imgType = "webp"
|
else:
|
||||||
self.imgMsgId = ID
|
self.sendTextMessage(room + '@g.us', message)
|
||||||
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)
|
|
||||||
else: # private msg
|
else: # private msg
|
||||||
buddy = sender
|
buddy = sender
|
||||||
# if message == "\\lastseen":
|
# if message == "\\lastseen":
|
||||||
|
@ -649,20 +666,8 @@ class Session(YowsupApp):
|
||||||
#self.call("contact_getProfilePicture", (buddy + "@s.whatsapp.net",))
|
#self.call("contact_getProfilePicture", (buddy + "@s.whatsapp.net",))
|
||||||
self.requestVCard(buddy)
|
self.requestVCard(buddy)
|
||||||
else:
|
else:
|
||||||
if (".jpg" in message.lower()) or (".webp" in message.lower()):
|
if (".jpg" in message.lower()) or (".webp" in message.lower()):
|
||||||
#waId = self.call("message_imageSend", (buddy + "@s.whatsapp.net", message, None, 0, None))
|
self.sendImage(message, ID, buddy + "@s.whatsapp.net")
|
||||||
#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"
|
|
||||||
elif "geo:" in message.lower():
|
elif "geo:" in message.lower():
|
||||||
self._sendLocation(buddy + "@s.whatsapp.net", message, ID)
|
self._sendLocation(buddy + "@s.whatsapp.net", message, ID)
|
||||||
else:
|
else:
|
||||||
|
@ -804,48 +809,6 @@ class Session(YowsupApp):
|
||||||
def requestVCard(self, buddy, ID=None):
|
def requestVCard(self, buddy, ID=None):
|
||||||
self.buddies.requestVCard(buddy, ID)
|
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):
|
def createThumb(self, size=100, raw=False):
|
||||||
img = Image.open(self.imgPath)
|
img = Image.open(self.imgPath)
|
||||||
width, height = img.size
|
width, height = img.size
|
||||||
|
|
|
@ -121,6 +121,9 @@ class WhatsAppBackend(SpectrumBackend):
|
||||||
self.logger.debug("handleVCardUpdatedRequest(user=%s, nickname=%s)", user, nickname)
|
self.logger.debug("handleVCardUpdatedRequest(user=%s, nickname=%s)", user, nickname)
|
||||||
self.sessions[user].setProfilePicture(photo)
|
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):
|
def relogin(self, user, legacyName, password, extra):
|
||||||
"""
|
"""
|
||||||
Used to re-initialize the session object. Used when finished with
|
Used to re-initialize the session object. Used when finished with
|
||||||
|
@ -137,10 +140,6 @@ class WhatsAppBackend(SpectrumBackend):
|
||||||
self.sessions[user].login(password)
|
self.sessions[user].login(password)
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
def handleBuddyBlockToggled(self, user, buddy, blocked):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def handleAttentionRequest(self, user, buddy, message):
|
def handleAttentionRequest(self, user, buddy, message):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ from yowsup.layers.protocol_privacy.protocolentities import *
|
||||||
from yowsup.layers.protocol_receipts.protocolentities import *
|
from yowsup.layers.protocol_receipts.protocolentities import *
|
||||||
from yowsup.layers.protocol_iq.protocolentities import *
|
from yowsup.layers.protocol_iq.protocolentities import *
|
||||||
from yowsup.layers.protocol_media.mediauploader import MediaUploader
|
from yowsup.layers.protocol_media.mediauploader import MediaUploader
|
||||||
|
from yowsup.layers.protocol_media.mediadownloader import MediaDownloader
|
||||||
|
|
||||||
|
|
||||||
# Registration
|
# Registration
|
||||||
|
@ -136,6 +137,10 @@ class YowsupApp(object):
|
||||||
receipt = OutgoingReceiptProtocolEntity(_id, _from, read, participant)
|
receipt = OutgoingReceiptProtocolEntity(_id, _from, read, participant)
|
||||||
self.sendEntity(receipt)
|
self.sendEntity(receipt)
|
||||||
|
|
||||||
|
def downloadMedia(self, url, onSuccess = None, onFailure = None):
|
||||||
|
downloader = MediaDownloader(onSuccess, onFailure)
|
||||||
|
downloader.download(url)
|
||||||
|
|
||||||
def sendTextMessage(self, to, message):
|
def sendTextMessage(self, to, message):
|
||||||
"""
|
"""
|
||||||
Sends a text message
|
Sends a text message
|
||||||
|
@ -153,26 +158,27 @@ class YowsupApp(object):
|
||||||
self.sendEntity(messageEntity)
|
self.sendEntity(messageEntity)
|
||||||
return messageEntity.getId()
|
return messageEntity.getId()
|
||||||
|
|
||||||
def image_send(self, jid, path, caption = None):
|
def sendImage(self, jid, path, caption = None, onSuccess = None, onFailure = None):
|
||||||
entity = RequestUploadIqProtocolEntity(RequestUploadIqProtocolEntity.MEDIA_TYPE_IMAGE, filePath=path)
|
entity = RequestUploadIqProtocolEntity(RequestUploadIqProtocolEntity.MEDIA_TYPE_IMAGE, filePath=path)
|
||||||
successFn = lambda successEntity, originalEntity: self.onRequestUploadResult(jid, path, successEntity, originalEntity, caption)
|
successFn = lambda successEntity, originalEntity: self.onRequestUploadResult(jid, path, successEntity, originalEntity, caption, onSuccess, onFailure)
|
||||||
errorFn = lambda errorEntity, originalEntity: self.onRequestUploadError(jid, path, errorEntity, originalEntity)
|
errorFn = lambda errorEntity, originalEntity: self.onRequestUploadError(jid, path, errorEntity, originalEntity)
|
||||||
|
|
||||||
self.sendIq(entity, successFn, errorFn)
|
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:
|
if requestUploadIqProtocolEntity.mediaType == RequestUploadIqProtocolEntity.MEDIA_TYPE_AUDIO:
|
||||||
doSendFn = self._doSendAudio
|
doSendFn = self.doSendAudio
|
||||||
else:
|
else:
|
||||||
doSendFn = self._doSendImage
|
doSendFn = self.doSendImage
|
||||||
|
|
||||||
if resultRequestUploadIqProtocolEntity.isDuplicate():
|
if resultRequestUploadIqProtocolEntity.isDuplicate():
|
||||||
doSendFn(filePath, resultRequestUploadIqProtocolEntity.getUrl(), jid,
|
doSendFn(filePath, resultRequestUploadIqProtocolEntity.getUrl(), jid,
|
||||||
resultRequestUploadIqProtocolEntity.getIp(), caption)
|
resultRequestUploadIqProtocolEntity.getIp(), caption)
|
||||||
else:
|
else:
|
||||||
successFn = lambda filePath, jid, url: doSendFn(filePath, url, jid, resultRequestUploadIqProtocolEntity.getIp(), caption)
|
successFn = lambda filePath, jid, url: doSendFn(filePath, url, jid, resultRequestUploadIqProtocolEntity.getIp(), caption, onSuccess, onFailure)
|
||||||
mediaUploader = MediaUploader(jid, self.legacyName, filePath,
|
ownNumber = self.stack.getLayerInterface(YowAuthenticationProtocolLayer).getUsername(full=False)
|
||||||
|
mediaUploader = MediaUploader(jid, ownNumber, filePath,
|
||||||
resultRequestUploadIqProtocolEntity.getUrl(),
|
resultRequestUploadIqProtocolEntity.getUrl(),
|
||||||
resultRequestUploadIqProtocolEntity.getResumeOffset(),
|
resultRequestUploadIqProtocolEntity.getResumeOffset(),
|
||||||
successFn, self.onUploadError, self.onUploadProgress, async=False)
|
successFn, self.onUploadError, self.onUploadProgress, async=False)
|
||||||
|
@ -190,17 +196,21 @@ class YowsupApp(object):
|
||||||
#sys.stdout.flush()
|
#sys.stdout.flush()
|
||||||
pass
|
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)
|
entity = ImageDownloadableMediaMessageProtocolEntity.fromFilePath(filePath, url, ip, to, caption = caption)
|
||||||
self.sendEntity(entity)
|
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()
|
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)
|
entity = AudioDownloadableMediaMessageProtocolEntity.fromFilePath(filePath, url, ip, to)
|
||||||
self.sendEntity(entity)
|
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()
|
return entity.getId()
|
||||||
|
|
||||||
|
|
||||||
|
@ -310,7 +320,6 @@ class YowsupApp(object):
|
||||||
- success: (func) - Callback; Takes three arguments: existing numbers,
|
- success: (func) - Callback; Takes three arguments: existing numbers,
|
||||||
non-existing numbers, invalid numbers.
|
non-existing numbers, invalid numbers.
|
||||||
"""
|
"""
|
||||||
# TODO: Implement callbacks
|
|
||||||
mode = GetSyncIqProtocolEntity.MODE_DELTA if delta else GetSyncIqProtocolEntity.MODE_FULL
|
mode = GetSyncIqProtocolEntity.MODE_DELTA if delta else GetSyncIqProtocolEntity.MODE_FULL
|
||||||
context = GetSyncIqProtocolEntity.CONTEXT_INTERACTIVE if interactive else GetSyncIqProtocolEntity.CONTEXT_REGISTRATION
|
context = GetSyncIqProtocolEntity.CONTEXT_INTERACTIVE if interactive else GetSyncIqProtocolEntity.CONTEXT_REGISTRATION
|
||||||
# International contacts must be preceded by a plus. Other numbers are
|
# International contacts must be preceded by a plus. Other numbers are
|
||||||
|
|
Loading…
Reference in a new issue