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 # XEP-0084: User Avatar
import logging import logging
import base64
import binascii
import nbxmpp import nbxmpp
from gajim.common import app from gajim.common import app
from gajim.common.const import PEPEventType from gajim.common.modules.base import BaseModule
from gajim.common.exceptions import StanzaMalformed from gajim.common.modules.util import event_node
from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData
log = logging.getLogger('gajim.c.m.user_avatar') 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' if empty:
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:
# Remove avatar # Remove avatar
log.info('Remove: %s', jid) log.info('Remove: %s', jid)
app.contacts.set_avatar(self._account, str(jid), None) app.contacts.set_avatar(self._account, jid, None)
app.logger.set_avatar_sha(own_jid.getStripped(), str(jid), None) app.logger.set_avatar_sha(own_jid, jid, None)
app.interface.update_avatar(self._account, str(jid)) app.interface.update_avatar(self._account, jid)
else: else:
if own_jid.bareMatch(jid): if properties.is_self_message:
sha = app.config.get_per( sha = app.config.get_per(
'accounts', self._account, 'avatar_sha') 'accounts', self._account, 'avatar_sha')
else: else:
sha = app.contacts.get_avatar_sha(self._account, str(jid)) sha = app.contacts.get_avatar_sha(self._account, jid)
if sha == avatar['id']: if sha == data.id:
log.info('Avatar already known: %s %s', log.info('Avatar already known: %s %s', jid, data.id)
jid, avatar['id'])
return return
self.get_pubsub_avatar(jid, avatar['id'])
def _build_node(self, data): log.info('Request: %s %s', jid, data.id)
raise NotImplementedError self._nbxmpp('UserAvatar').request_avatar(
jid, data.id, callback=self._avatar_received)
def send(self, data): def _avatar_received(self, result):
# Not implemented yet log.info('Received Avatar: %s %s', result.jid, result.sha)
return 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): def get_instance(*args, **kwargs):