transpub/transWhat/buddy.py

214 lines
6.4 KiB
Python
Raw Normal View History

2013-06-28 17:46:25 +00:00
from Spectrum2 import protocol_pb2
import logging
import time
import base64
2019-04-25 20:12:39 +00:00
import hashlib
import deferred
from deferred import call
2013-06-28 17:46:25 +00:00
2019-04-25 20:12:39 +00:00
def sha1hash(data):
hashlib.sha1(data).hexdigest()
2013-06-28 17:46:25 +00:00
class Buddy():
2015-12-01 19:33:02 +00:00
def __init__(self, owner, number, nick, statusMsg, groups, image_hash):
2013-06-28 17:46:25 +00:00
self.nick = nick
self.owner = owner
2016-04-12 12:53:15 +00:00
self.number = "%s" % number
2013-06-28 17:46:25 +00:00
self.groups = groups
self.image_hash = image_hash if image_hash is not None else ""
self.statusMsg = u""
2015-11-10 16:04:20 +00:00
self.lastseen = 0
self.presence = 0
def update(self, nick, groups, image_hash):
2013-06-28 17:46:25 +00:00
self.nick = nick
self.groups = groups
if image_hash is not None:
self.image_hash = image_hash
2013-06-28 17:46:25 +00:00
def __str__(self):
# we must return str here
return str("%s (nick=%s)") % (self.number, self.nick)
2013-06-28 17:46:25 +00:00
class BuddyList(dict):
2015-12-01 21:21:38 +00:00
def __init__(self, owner, backend, user, session):
2015-12-01 19:33:02 +00:00
self.owner = owner
2015-12-01 19:54:58 +00:00
self.backend = backend
2015-12-01 21:21:38 +00:00
self.session = session
2015-12-01 19:54:58 +00:00
self.user = user
self.logger = logging.getLogger(self.__class__.__name__)
def _load(self, buddies):
2015-12-01 19:33:02 +00:00
for buddy in buddies:
number = buddy.buddyName
nick = buddy.alias
2016-04-09 22:21:58 +00:00
statusMsg = buddy.statusMessage
2015-12-01 19:33:02 +00:00
groups = [g for g in buddy.group]
image_hash = buddy.iconHash
self[number] = Buddy(self.owner, number, nick, statusMsg,
groups, image_hash)
self.logger.debug("Update roster")
2015-12-01 19:54:58 +00:00
contacts = self.keys()
contacts.remove('bot')
2015-12-01 19:54:58 +00:00
self.session.sendSync(contacts, delta=False, interactive=True,
success=self.onSync)
2015-12-01 19:54:58 +00:00
2016-04-09 22:21:58 +00:00
self.logger.debug("Roster add: %s" % list(contacts))
2015-12-01 19:54:58 +00:00
2015-12-01 21:21:38 +00:00
for number in contacts:
buddy = self[number]
self.updateSpectrum(buddy)
def onSync(self, existing, nonexisting, invalid):
"""We should only presence subscribe to existing numbers"""
for number in existing:
self.session.subscribePresence(number)
2016-04-09 22:21:58 +00:00
self.logger.debug("%s is requesting statuses of: %s" % (self.user, existing))
self.session.requestStatuses(existing, success = self.onStatus)
2016-04-09 22:21:58 +00:00
self.logger.debug("Removing nonexisting buddies %s" % nonexisting)
for number in nonexisting:
self.remove(number)
try: del self[number]
except KeyError: self.logger.warn("non-existing buddy really didn't exist: %s" % number)
2016-04-09 22:21:58 +00:00
self.logger.debug("Removing invalid buddies %s" % invalid)
for number in invalid:
self.remove(number)
try: del self[number]
except KeyError: self.logger.warn("non-existing buddy really didn't exist: %s" % number)
def onStatus(self, contacts):
2016-04-09 22:21:58 +00:00
self.logger.debug("%s received statuses of: %s" % (self.user, contacts))
for number, (status, time) in contacts.iteritems():
try: buddy = self[number]
except KeyError: self.logger.warn("received status of buddy not in list: %s" % number)
if status is None:
buddy.statusMsg = ""
else:
buddy.statusMsg = status
self.updateSpectrum(buddy)
2015-12-01 19:54:58 +00:00
def load(self, buddies):
if self.session.loggedIn:
self._load(buddies)
else:
self.session.loginQueue.append(lambda: self._load(buddies))
def update(self, number, nick, groups, image_hash):
2013-06-28 17:46:25 +00:00
if number in self:
buddy = self[number]
buddy.update(nick, groups, image_hash)
2013-06-28 17:46:25 +00:00
else:
buddy = Buddy(self.owner, number, nick, "", groups, image_hash)
2015-12-01 21:21:38 +00:00
self[number] = buddy
2016-04-09 22:21:58 +00:00
self.logger.debug("Roster add: %s" % buddy)
self.session.sendSync([number], delta = True, interactive = True)
self.session.subscribePresence(number)
self.session.requestStatuses([number], success = self.onStatus)
if image_hash == "" or image_hash is None:
self.requestVCard(number)
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
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)
iconHash = buddy.image_hash if buddy.image_hash is not None else ""
2016-04-09 22:21:58 +00:00
self.logger.debug("Updating buddy %s (%s) in %s, image_hash = %s" %
(buddy.nick, buddy.number, buddy.groups, iconHash))
self.logger.debug("Status Message: %s" % statusmsg)
self.backend.handleBuddyChanged(self.user, buddy.number, buddy.nick,
buddy.groups, status, statusMessage=statusmsg, iconHash=iconHash)
2013-06-28 17:46:25 +00:00
def remove(self, number):
try:
buddy = self[number]
2015-12-01 21:21:38 +00:00
del self[number]
self.backend.handleBuddyChanged(self.user, number, "", [],
2015-12-01 19:54:58 +00:00
protocol_pb2.STATUS_NONE)
self.backend.handleBuddyRemoved(self.user, number)
2015-12-01 21:21:38 +00:00
self.session.unsubscribePresence(number)
2017-02-11 20:51:57 +00:00
# TODO Sync remove
return buddy
except KeyError:
return None
def requestVCard(self, buddy, ID=None):
2016-02-10 23:46:53 +00:00
if "/" in buddy:
room, nick = buddy.split("/")
group = self.session.groups[room]
buddynr = None
for othernumber, othernick in group.participants.iteritems():
if othernick == nick:
buddynr = othernumber
break
if buddynr is None:
return
else:
buddynr = buddy
if buddynr == self.user or buddynr == self.user.split('@')[0]:
buddynr = self.session.legacyName
# Get profile picture
2016-04-09 22:21:58 +00:00
self.logger.debug('Requesting profile picture of %s' % buddynr)
response = deferred.Deferred()
2016-01-07 21:04:20 +00:00
# Error probably means image doesn't exist
error = deferred.Deferred()
2016-02-10 23:46:53 +00:00
self.session.requestProfilePicture(buddynr, onSuccess=response.run,
2016-01-07 21:04:20 +00:00
onFailure=error.run)
response = response.arg(0)
pictureData = response.pictureData()
# Send VCard
if ID != None:
2016-04-09 22:21:58 +00:00
call(self.logger.debug, 'Sending VCard (%s) with image id %s: %s' %
(ID, response.pictureId(), pictureData.then(base64.b64encode)))
call(self.backend.handleVCard, self.user, ID, buddy, "", "",
pictureData)
2016-01-07 21:04:20 +00:00
# If error
2016-04-09 22:21:58 +00:00
error.when(self.logger.debug, 'Sending VCard (%s) without image' % ID)
2016-01-07 21:04:20 +00:00
error.when(self.backend.handleVCard, self.user, ID, buddy, "", "", "")
# Send image hash
2016-02-10 23:46:53 +00:00
if not buddynr == self.session.legacyName:
try:
2016-02-10 23:46:53 +00:00
obuddy = self[buddynr]
nick = obuddy.nick
groups = obuddy.groups
except KeyError:
nick = ""
groups = []
2019-04-25 20:12:39 +00:00
image_hash = pictureData.then(sha1hash)
2016-04-09 22:21:58 +00:00
call(self.logger.debug, 'Image hash is %s' % image_hash)
2016-02-10 23:46:53 +00:00
call(self.update, buddynr, nick, groups, image_hash)
2016-01-07 21:04:20 +00:00
# No image
error.when(self.logger.debug, 'No image')
2016-02-10 23:46:53 +00:00
error.when(self.update, buddynr, nick, groups, '')
def refresh(self, number):
self.session.unsubscribePresence(number)
self.session.subscribePresence(number)
self.requestVCard(number)
self.session.requestStatuses([number], success = self.onStatus)