Refactor UserAvatar

- Simplify modules because nbxmpp handles more stuff
This commit is contained in:
Philipp Hörist 2019-02-03 00:08:28 +01:00
parent 15dc059bf3
commit cef5b04d82
1 changed files with 39 additions and 106 deletions

View File

@ -15,134 +15,67 @@
# XEP-0084: User Avatar
import logging
import base64
import binascii
import nbxmpp
from gajim.common import app
from gajim.common.const import PEPEventType
from gajim.common.exceptions import StanzaMalformed
from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData
from gajim.common.modules.base import BaseModule
from gajim.common.modules.util import event_node
log = logging.getLogger('gajim.c.m.user_avatar')
class UserAvatarData(AbstractPEPData):
class UserAvatar(BaseModule):
type_ = PEPEventType.AVATAR
_nbxmpp_extends = 'UserAvatar'
_nbxmpp_methods = [
'request_avatar'
]
def __init__(self, con):
BaseModule.__init__(self, con)
self._register_pubsub_handler(self._avatar_metadata_received)
class UserAvatar(AbstractPEPModule):
@event_node(nbxmpp.NS_AVATAR_METADATA)
def _avatar_metadata_received(self, _con, _stanza, properties):
data = properties.pubsub_event.data
empty = properties.pubsub_event.empty
jid = str(properties.jid)
own_jid = self._con.get_own_jid().getBare()
name = 'user-avatar'
namespace = 'urn:xmpp:avatar:metadata'
pep_class = UserAvatarData
store_publish = False
_log = log
def get_pubsub_avatar(self, jid, item_id):
log.info('Request: %s %s', jid, item_id)
self._con.get_module('PubSub').send_pb_retrieve(
jid, 'urn:xmpp:avatar:data', item_id, self._avatar_received)
def _validate_avatar_node(self, stanza):
jid = stanza.getFrom()
if jid is None:
jid = self._con.get_own_jid().getStripped()
else:
jid = jid.getStripped()
if nbxmpp.isErrorNode(stanza):
raise StanzaMalformed(stanza.getErrorMsg())
pubsub_node = stanza.getTag('pubsub')
if pubsub_node is None:
raise StanzaMalformed('No pubsub node', stanza)
items_node = pubsub_node.getTag('items')
if items_node is None:
raise StanzaMalformed('No items node', stanza)
if items_node.getAttr('node') != 'urn:xmpp:avatar:data':
raise StanzaMalformed('Wrong namespace', stanza)
item = items_node.getTag('item')
if item is None:
raise StanzaMalformed('No item node', stanza)
sha = item.getAttr('id')
data_tag = item.getTag('data', namespace='urn:xmpp:avatar:data')
if sha is None or data_tag is None:
raise StanzaMalformed('No id attr or data node found', stanza)
data = data_tag.getData()
if data is None:
raise StanzaMalformed('Data node empty', stanza)
data = base64.b64decode(data.encode('utf-8'))
return jid, sha, data
def _avatar_received(self, _con, stanza):
try:
jid, sha, data = self._validate_avatar_node(stanza)
except (StanzaMalformed, binascii.Error) as error:
log.warning('Error: %s %s', stanza.getFrom(), error)
return
log.info('Received Avatar: %s %s', jid, sha)
app.interface.save_avatar(data)
if self._con.get_own_jid().bareMatch(jid):
app.config.set_per('accounts', self._account, 'avatar_sha', sha)
else:
own_jid = self._con.get_own_jid().getStripped()
app.logger.set_avatar_sha(own_jid, jid, sha)
app.contacts.set_avatar(self._account, jid, sha)
app.interface.update_avatar(self._account, jid)
def _extract_info(self, item):
metadata = item.getTag('metadata', namespace=self.namespace)
if metadata is None:
raise StanzaMalformed('No metadata node')
info = metadata.getTags('info', one=True)
if not info:
return None
avatar = info.getAttrs()
return avatar or None
def _notification_received(self, jid, user_pep):
avatar = user_pep.data
own_jid = self._con.get_own_jid()
if avatar is None:
if empty:
# Remove avatar
log.info('Remove: %s', jid)
app.contacts.set_avatar(self._account, str(jid), None)
app.logger.set_avatar_sha(own_jid.getStripped(), str(jid), None)
app.interface.update_avatar(self._account, str(jid))
app.contacts.set_avatar(self._account, jid, None)
app.logger.set_avatar_sha(own_jid, jid, None)
app.interface.update_avatar(self._account, jid)
else:
if own_jid.bareMatch(jid):
if properties.is_self_message:
sha = app.config.get_per(
'accounts', self._account, 'avatar_sha')
else:
sha = app.contacts.get_avatar_sha(self._account, str(jid))
sha = app.contacts.get_avatar_sha(self._account, jid)
if sha == avatar['id']:
log.info('Avatar already known: %s %s',
jid, avatar['id'])
if sha == data.id:
log.info('Avatar already known: %s %s', jid, data.id)
return
self.get_pubsub_avatar(jid, avatar['id'])
def _build_node(self, data):
raise NotImplementedError
log.info('Request: %s %s', jid, data.id)
self._nbxmpp('UserAvatar').request_avatar(
jid, data.id, callback=self._avatar_received)
def send(self, data):
# Not implemented yet
return
def _avatar_received(self, result):
log.info('Received Avatar: %s %s', result.jid, result.sha)
app.interface.save_avatar(result.data)
if self._con.get_own_jid().bareMatch(result.jid):
app.config.set_per('accounts', self._account, 'avatar_sha', result.sha)
else:
own_jid = self._con.get_own_jid().getBare()
app.logger.set_avatar_sha(own_jid, str(result.jid), result.sha)
app.contacts.set_avatar(self._account, str(result.jid), result.sha)
app.interface.update_avatar(self._account, str(result.jid))
def get_instance(*args, **kwargs):