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 """
|
||||
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)
|
||||
|
||||
|
|
113
session.py
113
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"
|
||||
self.sendImage(message, ID, 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.sendTextMessage(room + '@g.us', message)
|
||||
else: # private msg
|
||||
buddy = sender
|
||||
# if message == "\\lastseen":
|
||||
|
@ -650,19 +667,7 @@ class Session(YowsupApp):
|
|||
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"
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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):
|
||||
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)
|
||||
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())
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue