Commit cef5b04d authored by Philipp Hörist's avatar Philipp Hörist

Refactor UserAvatar

- Simplify modules because nbxmpp handles more stuff
parent 15dc059b
Pipeline #3017 passed with stages
in 3 minutes and 29 seconds
......@@ -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 _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)
def send(self, data):
# Not implemented yet
return
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):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment