Add receiveing of images, videos and sound files

When a whatsapp buddy sends an image, video or sound to the spectrum
user, the spectrum user will receive a URL that links to the media.

FileTranfer in spectrum is not working, apparently. Thus media cannot be
sent yet.
This commit is contained in:
moyamo 2015-09-05 22:05:34 +02:00
parent a6971ad889
commit 4c365e3f81
4 changed files with 163 additions and 28 deletions

View file

@ -204,7 +204,7 @@ class SpectrumBackend:
def handleFTData(self, ftID, data): def handleFTData(self, ftID, data):
d = protocol_pb2.FileTransferData() d = protocol_pb2.FileTransferData()
d.ftid = ftID d.ftID = ftID
d.data = data d.data = data
message = WRAP(d.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_FT_DATA); message = WRAP(d.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_FT_DATA);

View file

@ -204,26 +204,69 @@ class Session(YowsupApp):
) )
# Called by superclass # Called by superclass
def onMessage(self, messageEntity): def onTextMessage(self, _id, _from, to, notify, timestamp, participant, offline, retry, body):
self.logger.debug(str(messageEntity)) self.logger.debug('received TextMessage' +
buddy = messageEntity.getFrom().split('@')[0] ' '.join(map(str, [
messageContent = utils.softToUni(messageEntity.getBody()) _id, _from, to, notify, timestamp,
timestamp = messageEntity.getTimestamp() participant, offline, retry, body
]))
)
buddy = _from.split('@')[0]
messageContent = utils.softToUni(body)
self.sendReceipt(_id, _from, None, participant)
self.logger.info("Message received from %s to %s: %s (at ts=%s)",
buddy, self.legacyName, messageContent, timestamp)
self.sendMessageToXMPP(buddy, messageContent, timestamp)
# isBroadcast always returns false, I'm not sure how to get a broadcast
# message.
#if messageEntity.isBroadcast():
# self.logger.info("Broadcast received from %s to %s: %s (at ts=%s)",\
# buddy, self.legacyName, messageContent, timestamp)
# messageContent = "[Broadcast] " + messageContent
self.sendReceipt(messageEntity.getId(), messageEntity.getFrom(), None, # Called by superclass
messageEntity.getParticipant()) def onImage(self, image):
self.logger.debug('Received image message %s', str(image))
buddy = image._from.split('@')[0]
message = image.url + ' ' + image.caption
self.sendMessageToXMPP(buddy, message, image.timestamp)
self.sendReceipt(image._id, image._from, None, image.participant)
if messageEntity.isBroadcast(): # Called by superclass
self.logger.info("Broadcast received from %s to %s: %s (at ts=%s)",\ def onAudio(self, audio):
buddy, self.legacyName, messageContent, timestamp) self.logger.debug('Received audio message %s', str(audio))
messageContent = "[Broadcast] " + messageContent buddy = audio._from.split('@')[0]
else: message = audio.url
self.logger.info("Message received from %s to %s: %s (at ts=%s)", self.sendMessageToXMPP(buddy, message, audio.timestamp)
buddy, self.legacyName, messageContent, timestamp) self.sendReceipt(audio._id, audio._from, None, audio.participant)
self.sendMessageToXMPP(buddy, messageContent, timestamp)
# if receiptRequested: self.call("message_ack", (jid, messageId)) # Called by superclass
def onVideo(self, video):
self.logger.debug('Received video message %s', str(video))
buddy = video._from.split('@')[0]
message = video.url
self.sendMessageToXMPP(buddy, message, video.timestamp)
self.sendReceipt(video._id, video._from, None, video.participant)
# Called by superclass
def onVCard(self, _id, _from, name, card_data, to, notify, timestamp, participant):
self.logger.debug('received VCard' +
' '.join(map(str, [
_id, _from, name, card_data, to, notify, timestamp, participant
]))
)
buddy = _from.split("@")[0]
self.sendMessageToXMPP(buddy, "Received VCard (not implemented yet)")
self.sendMessageToXMPP(buddy, card_data)
self.transferFile(buddy, str(name), card_data)
self.sendReceipt(_id, _from, None, participant)
def transferFile(self, buddy, name, data):
# Not working
self.logger.debug('transfering file %s', name)
self.backend.handleFTStart(self.user, buddy, name, len(data))
self.backend.handleFTData(0, data)
self.backend.handleFTFinish(self.user, buddy, name, len(data), 0)
# Called by superclass # Called by superclass
def onContactTyping(self, buddy): def onContactTyping(self, buddy):
@ -408,11 +451,6 @@ class Session(YowsupApp):
self.sendMessageToXMPP(buddy, utils.shorten(url)) self.sendMessageToXMPP(buddy, utils.shorten(url))
if receiptRequested: self.call("message_ack", (jid, messageId)) if receiptRequested: self.call("message_ack", (jid, messageId))
def onVcardReceived(self, messageId, jid, name, data, receiptRequested, isBroadcast): # TODO
buddy = jid.split("@")[0]
self.logger.info("VCard received from %s", buddy)
self.sendMessageToXMPP(buddy, "Received VCard (not implemented yet)")
if receiptRequested: self.call("message_ack", (jid, messageId))
def onGroupGotInfo(self, gjid, owner, subject, subjectOwner, subjectTimestamp, creationTimestamp): def onGroupGotInfo(self, gjid, owner, subject, subjectOwner, subjectTimestamp, creationTimestamp):
room = gjid.split("@")[0] room = gjid.split("@")[0]
@ -471,7 +509,7 @@ class Session(YowsupApp):
room = gjid.split("@")[0] room = gjid.split("@")[0]
buddy = jid.split("@")[0] buddy = jid.split("@")[0]
logger.info("Added % to room %s", buddy, room) self.logger.info("Added %s to room %s", buddy, room)
self.backend.handleParticipantChanged(self.user, buddy, room, protocol_pb2.PARTICIPANT_FLAG_NONE, protocol_pb2.STATUS_ONLINE) self.backend.handleParticipantChanged(self.user, buddy, room, protocol_pb2.PARTICIPANT_FLAG_NONE, protocol_pb2.STATUS_ONLINE)
if receiptRequested: self.call("notification_ack", (gjid, messageId)) if receiptRequested: self.call("notification_ack", (gjid, messageId))

View file

@ -64,6 +64,9 @@ class WhatsAppBackend(SpectrumBackend):
# a buddy, one to the bare jid and one to /bot. This causes duplicate # a buddy, one to the bare jid and one to /bot. This causes duplicate
# messages. Since it is unlikely a user wants to send the same message # messages. Since it is unlikely a user wants to send the same message
# twice, we should just ignore the second message # twice, we should just ignore the second message
#
# TODO Proper fix, this work around drops all duplicate messages even
# intentional ones.
usersMessage = self.lastMessage[user] usersMessage = self.lastMessage[user]
if buddy not in usersMessage or usersMessage[buddy] != message: if buddy not in usersMessage or usersMessage[buddy] != message:
self.sessions[user].sendMessageToWA(buddy, message) self.sessions[user].sendMessageToWA(buddy, message)
@ -115,7 +118,8 @@ class WhatsAppBackend(SpectrumBackend):
pass pass
def handleFTStartRequest(self, user, buddy, fileName, size, ftID): def handleFTStartRequest(self, user, buddy, fileName, size, ftID):
pass self.logger.debug('File send request %s, for user %s, from %s, size: %s',
fileName, user, buddy, size)
def handleFTFinishRequest(self, user, buddy, fileName, size, ftID): def handleFTFinishRequest(self, user, buddy, fileName, size, ftID):
pass pass

View file

@ -30,7 +30,8 @@ from yowsup.layers.protocol_calls import YowCallsProtocolLayer
# ProtocolEntities # ProtocolEntities
from yowsup.layers.protocol_presence.protocolentities import * from yowsup.layers.protocol_presence.protocolentities import *
from yowsup.layers.protocol_messages.protocolentities import TextMessageProtocolEntity from yowsup.layers.protocol_messages.protocolentities import *
from yowsup.layers.protocol_media.protocolentities import *
from yowsup.layers.protocol_chatstate.protocolentities import * from yowsup.layers.protocol_chatstate.protocolentities import *
from yowsup.layers.protocol_acks.protocolentities import * from yowsup.layers.protocol_acks.protocolentities import *
from yowsup.layers.protocol_receipts.protocolentities import * from yowsup.layers.protocol_receipts.protocolentities import *
@ -110,8 +111,8 @@ class YowsupApp(object):
Args: Args:
- _id: id of message received - _id: id of message received
- _from - _from: jid of person who sent the message
- read: ('read' or something else) - read: ('read' or None) None is just delivered, 'read' is read
- participant - participant
""" """
receipt = OutgoingReceiptProtocolEntity(_id, _from, read, participant) receipt = OutgoingReceiptProtocolEntity(_id, _from, read, participant)
@ -304,6 +305,67 @@ class YowsupApp(object):
""" """
pass pass
def onTextMessage(self, _id, _from, to, notify, timestamp, participant, offline, retry, body):
"""
Called when text message is received
Args:
- _id:
- _from: (str) jid of of sender
- to:
- notify: (str) human readable name of _from (e.g. John Smith)
- timestamp:
- participant:
- offline:
- retry:
- body: The content of the message
"""
pass
def onImage(self, entity):
"""
Called when image message is received
Args:
- entity: ImageDownloadableMediaMessageProtocolEntity
"""
pass
def onAudio(self, entity):
"""
Called when audio message is received
Args:
- entity: AudioDownloadableMediaMessageProtocolEntity
"""
pass
def onVideo(self, entity):
"""
Called when video message is received
Args:
- entity: VideoDownloadableMediaMessageProtocolEntity
"""
pass
def onVCard(self, _id, _from, name, card_data, to, notify, timestamp, participant):
"""
Called when VCard message is received
Args:
- _id: (str) id of entity
- _from:
- name:
- card_data:
- to:
- notify:
- timestamp:
- participant:
"""
pass
def sendEntity(self, entity): def sendEntity(self, entity):
"""Sends an entity down the stack (as if YowsupAppLayer called toLower)""" """Sends an entity down the stack (as if YowsupAppLayer called toLower)"""
self.stack.broadcastEvent(YowLayerEvent(YowsupAppLayer.TO_LOWER_EVENT, self.stack.broadcastEvent(YowLayerEvent(YowsupAppLayer.TO_LOWER_EVENT,
@ -392,7 +454,38 @@ class YowsupAppLayer(YowInterfaceLayer):
@ProtocolEntityCallback('message') @ProtocolEntityCallback('message')
def onMessageReceived(self, entity): def onMessageReceived(self, entity):
self.caller.onMessage(entity) if entity.getType() == MessageProtocolEntity.MESSAGE_TYPE_TEXT:
self.caller.onTextMessage(
entity._id,
entity._from,
entity.to,
entity.notify,
entity.timestamp,
entity.participant,
entity.offline,
entity.retry,
entity.body
)
elif entity.getType() == MessageProtocolEntity.MESSAGE_TYPE_MEDIA:
if isinstance(entity, ImageDownloadableMediaMessageProtocolEntity):
# There is just way too many fields to pass them into the
# function
self.caller.onImage(entity)
elif isinstance(entity, AudioDownloadableMediaMessageProtocolEntity):
self.caller.onAudio(entity)
elif isinstance(entity, VideoDownloadableMediaMessageProtocolEntity):
self.caller.onVideo(entity)
elif isinstance(entity, VCardMediaMessageProtocolEntity):
self.caller.onVCard(
entity._id,
entity._from,
entity.name,
entity.card_data,
entity.to,
entity.notify,
entity.timestamp,
entity.participant
)
@ProtocolEntityCallback('presence') @ProtocolEntityCallback('presence')
def onPresenceReceived(self, presence): def onPresenceReceived(self, presence):