From 9434b1db6f5a3f2fdc9e8ee3737dba27625685ce Mon Sep 17 00:00:00 2001 From: moyamo Date: Mon, 14 Dec 2015 20:14:20 +0200 Subject: [PATCH 1/3] Request contacts' statuses when user logs in --- buddy.py | 36 ++++++++++++++++++++++++++++-------- session.py | 18 ++++++------------ yowsupwrapper.py | 22 ++++++++++++++++++++++ 3 files changed, 56 insertions(+), 20 deletions(-) diff --git a/buddy.py b/buddy.py index 0823163..6c581bf 100644 --- a/buddy.py +++ b/buddy.py @@ -24,6 +24,7 @@ __email__ = "post@steffenvogel.de" from Spectrum2 import protocol_pb2 import logging +import time class Buddy(): @@ -74,6 +75,7 @@ class BuddyList(dict): # new = self.buddies.keys() # contacts = new contacts = self.keys() + contacts.remove('bot') if self.synced == False: self.session.sendSync(contacts, delta = False, interactive = True) @@ -93,11 +95,19 @@ class BuddyList(dict): # for number in contacts: buddy = self[number] - if number != 'bot': - self.backend.handleBuddyChanged(self.user, number, buddy.nick, - buddy.groups, protocol_pb2.STATUS_NONE, - iconHash = buddy.image_hash if buddy.image_hash is not None else "") - self.session.subscribePresence(number) + self.backend.handleBuddyChanged(self.user, number, buddy.nick, + buddy.groups, protocol_pb2.STATUS_NONE, + iconHash = buddy.image_hash if buddy.image_hash is not None else "") + self.session.subscribePresence(number) + self.logger.debug("%s is requesting statuses of: %s", self.user, contacts) + self.session.requestStatuses(contacts, success = self.onStatus) + + def onStatus(self, contacts): + self.logger.debug("%s received statuses of: %s", self.user, contacts) + for number, (status, time) in contacts.iteritems(): + buddy = self[number] + buddy.statusMsg = status + self.updateSpectrum(buddy) def load(self, buddies): @@ -113,21 +123,31 @@ class BuddyList(dict): else: self.session.sendSync([number], delta = True, interactive = True) self.session.subscribePresence(number) + self.session.requestStatuses(contacts, success = self.onStatus) buddy = Buddy(self.owner, number, nick, "", groups, image_hash) self[number] = buddy self.logger.debug("Roster add: %s", buddy) + self.updateSpectrum(buddy) + return buddy + + def updateSpectrum(self, buddy): if buddy.presence == 0: status = protocol_pb2.STATUS_NONE elif buddy.presence == 'unavailable': status = protocol_pb2.STATUS_AWAY else: status = protocol_pb2.STATUS_ONLINE - self.backend.handleBuddyChanged(self.user, number, buddy.nick, - buddy.groups, status, + + statusmsg = buddy.statusMsg + if buddy.lastseen != 0: + timestamp = time.localtime(buddy.lastseen) + statusmsg += time.strftime("\n Last seen: %a, %d %b %Y %H:%M:%S", timestamp) + + self.backend.handleBuddyChanged(self.user, buddy.number, buddy.nick, + buddy.groups, status, statusMessage = statusmsg, iconHash = buddy.image_hash if buddy.image_hash is not None else "") - return buddy def remove(self, number): try: diff --git a/session.py b/session.py index 6dfed66..d481bfe 100644 --- a/session.py +++ b/session.py @@ -30,7 +30,6 @@ from PIL import Image import sys import os -from yowsup.common.tools import TimeTools from yowsup.layers.protocol_media.mediauploader import MediaUploader from yowsup.layers.protocol_media.mediadownloader import MediaDownloader @@ -497,25 +496,20 @@ class Session(YowsupApp): buddy.presence = _type - timestamp = time.localtime(buddy.lastseen) - statusmsg = buddy.statusMsg + time.strftime("\n Last seen: %a, %d %b %Y %H:%M:%S", timestamp) - if _type == "unavailable": - self.onPresenceUnavailable(buddy, statusmsg) + self.onPresenceUnavailable(buddy) else: - self.onPresenceAvailable(buddy, statusmsg) + self.onPresenceAvailable(buddy) - def onPresenceAvailable(self, buddy, statusmsg): + def onPresenceAvailable(self, buddy): self.logger.info("Is available: %s", buddy) - self.backend.handleBuddyChanged(self.user, buddy.number, - buddy.nick, buddy.groups, protocol_pb2.STATUS_ONLINE, statusmsg, buddy.image_hash) + self.buddies.updateSpectrum(buddy) - def onPresenceUnavailable(self, buddy, statusmsg): + def onPresenceUnavailable(self, buddy): self.logger.info("Is unavailable: %s", buddy) - self.backend.handleBuddyChanged(self.user, buddy.number, - buddy.nick, buddy.groups, protocol_pb2.STATUS_AWAY, statusmsg, buddy.image_hash) + self.buddies.updateSpectrum(buddy) # spectrum RequestMethods def sendTypingStarted(self, buddy): diff --git a/yowsupwrapper.py b/yowsupwrapper.py index d7c3a79..9fdb84c 100644 --- a/yowsupwrapper.py +++ b/yowsupwrapper.py @@ -65,6 +65,7 @@ class YowsupApp(object): YowProfilesProtocolLayer, YowGroupsProtocolLayer, YowPresenceProtocolLayer)), + YowLoggerLayer, YowAxolotlLayer, YowCoderLayer, YowCryptLayer, @@ -291,6 +292,27 @@ class YowsupApp(object): context = GetSyncIqProtocolEntity.CONTEXT_INTERACTIVE if interactive else GetSyncIqProtocolEntity.CONTEXT_REGISTRATION iq = GetSyncIqProtocolEntity(contacts, mode, context) self.sendIq(iq) + + def requestStatuses(self, contacts, success = None, failure = None): + """ + Request the statuses of a number of users. + + Args: + - contacts: ([str]) the phone numbers of users whose statuses you + wish to request + - success: (func) called when request is successful + - failure: (func) called when request has failed + """ + iq = GetStatusesIqProtocolEntity([c + '@s.whatsapp.net' for c in contacts]) + def onSuccess(response, request): + self.logger.debug("Received Statuses %s", response) + s = {} + for k, v in response.statuses.iteritems(): + s[k.split('@')[0]] = v + success(s) + + self.sendIq(iq, onSuccess = onSuccess, onError = failure) + def requestLastSeen(self, phoneNumber, success = None, failure = None): """ From 40131a06eb1d8ae533de5d30b0873832f8050c30 Mon Sep 17 00:00:00 2001 From: moyamo Date: Thu, 17 Dec 2015 10:06:11 +0200 Subject: [PATCH 2/3] Fix undefined variable in buddy.py --- buddy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buddy.py b/buddy.py index 6c581bf..8e722e3 100644 --- a/buddy.py +++ b/buddy.py @@ -123,7 +123,7 @@ class BuddyList(dict): else: self.session.sendSync([number], delta = True, interactive = True) self.session.subscribePresence(number) - self.session.requestStatuses(contacts, success = self.onStatus) + self.session.requestStatuses([number], success = self.onStatus) buddy = Buddy(self.owner, number, nick, "", groups, image_hash) self[number] = buddy self.logger.debug("Roster add: %s", buddy) From 3c16f39479767d165aac8bf1c0ea050bf3a73cce Mon Sep 17 00:00:00 2001 From: moyamo Date: Fri, 18 Dec 2015 20:33:32 +0200 Subject: [PATCH 3/3] Send 'muc = true' to spectrum backend --- Spectrum2/backend.py | 14 ++++++++++++-- transwhat.py | 7 ++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Spectrum2/backend.py b/Spectrum2/backend.py index feb2e94..4504bb1 100644 --- a/Spectrum2/backend.py +++ b/Spectrum2/backend.py @@ -222,9 +222,19 @@ class SpectrumBackend: message = WRAP(d.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_FT_DATA); self.send(message) - def handleBackendConfig(self, section, key, value): + def handleBackendConfig(self, data): + """ + data is a dictionary, whose keys are sections and values are a list of + tuples of configuration key and configuration value. + """ c = protocol_pb2.BackendConfig() - c.config = "[%s]\n%s = %s\n" % (section, key, value) + config = [] + for section, rest in data.items(): + config.append('[%s]' % section) + for key, value in rest: + config.append('%s = %s' % (key, value)) + + c.config = '\n'.join(config) message = WRAP(c.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_BACKEND_CONFIG); self.send(message) diff --git a/transwhat.py b/transwhat.py index aa58ad9..935b185 100755 --- a/transwhat.py +++ b/transwhat.py @@ -76,7 +76,12 @@ io = IOChannel(args.host, args.port, handleTransportData, connectionClosed) plugin = WhatsAppBackend(io, args.j) -plugin.handleBackendConfig('features', 'send_buddies_on_login', 1) +plugin.handleBackendConfig({ + 'features': [ + ('send_buddies_on_login', 1), + ('muc', 'true'), + ], +}) while True: try: