Add XEP-0398 optimizations

- If the server implements XEP-0398 we dont need to add the avatar sha
anymore, the server adds it for us.
- It also means we dont have to query our own avatar from vcard at start
because the server tells us the avatar sha that is published with the inital
presence reflection
This commit is contained in:
Philipp Hörist 2018-09-01 20:34:56 +02:00 committed by Philipp Hörist
parent d4d29f8309
commit 3e73ee93e1
8 changed files with 77 additions and 32 deletions

View File

@ -114,6 +114,7 @@ class CommonConnection:
self.roster_supported = True self.roster_supported = True
self.addressing_supported = False self.addressing_supported = False
self.avatar_conversion = False
self.muc_jid = {} # jid of muc server for each transport type self.muc_jid = {} # jid of muc server for each transport type
self._stun_servers = [] # STUN servers of our jabber server self._stun_servers = [] # STUN servers of our jabber server
@ -1398,8 +1399,9 @@ class Connection(CommonConnection, ConnectionHandlers):
app.nec.push_incoming_event(OurShowEvent(None, conn=self, app.nec.push_incoming_event(OurShowEvent(None, conn=self,
show='invisible')) show='invisible'))
if initial: if initial:
# ask our VCard if not self.avatar_conversion:
self.get_module('VCardTemp').request_vcard() # ask our VCard
self.get_module('VCardTemp').request_vcard()
# Get bookmarks # Get bookmarks
self.get_module('Bookmarks').get_bookmarks() self.get_module('Bookmarks').get_bookmarks()

View File

@ -580,8 +580,9 @@ class ConnectionHandlers(ConnectionSocks5Bytestream,
app.nec.push_incoming_event(OurShowEvent(None, conn=self, app.nec.push_incoming_event(OurShowEvent(None, conn=self,
show=show)) show=show))
# ask our VCard if not self.avatar_conversion:
self.get_module('VCardTemp').request_vcard() # ask our VCard
self.get_module('VCardTemp').request_vcard()
# Get bookmarks # Get bookmarks
self.get_module('Bookmarks').get_bookmarks() self.get_module('Bookmarks').get_bookmarks()

View File

@ -178,6 +178,10 @@ class Discovery:
self._con.get_module('PEP').pass_disco(from_, *args) self._con.get_module('PEP').pass_disco(from_, *args)
self._con.get_module('PubSub').pass_disco(from_, *args) self._con.get_module('PubSub').pass_disco(from_, *args)
identities, features, data, node = args
if 'urn:xmpp:pep-vcard-conversion:0' in features:
self._con.avatar_conversion = True
def discover_server_info(self): def discover_server_info(self):
# Calling this method starts the connect_maschine() # Calling this method starts the connect_maschine()
server = self._con.get_own_jid().getDomain() server = self._con.get_own_jid().getDomain()

View File

@ -183,7 +183,10 @@ class Presence:
idle_node = presence.setTag('idle', namespace=nbxmpp.NS_IDLE) idle_node = presence.setTag('idle', namespace=nbxmpp.NS_IDLE)
idle_node.setAttr('since', idle_time) idle_node.setAttr('since', idle_time)
self._con.get_module('VCardAvatars').add_update_node(presence) if not self._con.avatar_conversion:
# XEP-0398 not supported by server so
# we add the avatar sha to our presence
self._con.get_module('VCardAvatars').add_update_node(presence)
if caps: if caps:
attrs = {'hash': 'sha-1', attrs = {'hash': 'sha-1',

View File

@ -107,8 +107,8 @@ class UserAvatar(AbstractPEPModule):
else: else:
own_jid = self._con.get_own_jid().getStripped() own_jid = self._con.get_own_jid().getStripped()
app.logger.set_avatar_sha(own_jid, jid, sha) app.logger.set_avatar_sha(own_jid, jid, sha)
app.contacts.set_avatar(self._account, jid, sha)
app.contacts.set_avatar(self._account, jid, sha)
app.interface.update_avatar(self._account, jid) app.interface.update_avatar(self._account, jid)
def _extract_info(self, item): def _extract_info(self, item):

View File

@ -16,6 +16,7 @@
import os import os
import logging import logging
from pathlib import Path
import nbxmpp import nbxmpp
@ -38,6 +39,16 @@ class VCardAvatars:
] ]
self.avatar_advertised = False self.avatar_advertised = False
self._find_own_avatar()
def _find_own_avatar(self):
sha = app.config.get_per('accounts', self._account, 'avatar_sha')
if not sha:
return
path = Path(configpaths.get('AVATAR')) / sha
if not path.exists():
log.info('Missing own avatar, reset sha')
app.config.set_per('accounts', self._account, 'avatar_sha', '')
def _presence_received(self, con, stanza): def _presence_received(self, con, stanza):
update = stanza.getTag('x', namespace=nbxmpp.NS_VCARD_UPDATE) update = stanza.getTag('x', namespace=nbxmpp.NS_VCARD_UPDATE)
@ -54,9 +65,14 @@ class VCardAvatars:
if self._con.get_own_jid().bareMatch(jid): if self._con.get_own_jid().bareMatch(jid):
if self._con.get_own_jid() == jid: if self._con.get_own_jid() == jid:
# Reflection of our own presence # Initial presence reflection
return if self._con.avatar_conversion:
self._self_update_received(jid, avatar_sha) # XEP-0398: Tells us the current avatar sha on the
# inital presence reflection
self._self_update_received(jid, avatar_sha)
else:
# Presence from another resource of ours
self._self_update_received(jid, avatar_sha)
return return
# Check if presence is from a MUC service # Check if presence is from a MUC service
@ -76,6 +92,9 @@ class VCardAvatars:
if avatar_sha == '': if avatar_sha == '':
# Empty <photo/> tag, means no avatar is advertised # Empty <photo/> tag, means no avatar is advertised
log.info('%s has no avatar published', full_jid) log.info('%s has no avatar published', full_jid)
app.config.set_per('accounts', self._account, 'avatar_sha', '')
app.contacts.set_avatar(self._account, jid, None)
app.interface.update_avatar(self._account, jid)
return return
log.info('Update: %s %s', jid, avatar_sha) log.info('Update: %s %s', jid, avatar_sha)
@ -83,8 +102,16 @@ class VCardAvatars:
'accounts', self._account, 'avatar_sha') 'accounts', self._account, 'avatar_sha')
if avatar_sha != current_sha: if avatar_sha != current_sha:
log.info('Request : %s', jid) path = Path(configpaths.get('AVATAR')) / avatar_sha
self._con.get_module('VCardTemp').request_vcard(RequestAvatar.SELF) if path.exists():
app.config.set_per(
'accounts', self._account, 'avatar_sha', avatar_sha)
app.contacts.set_avatar(self._account, jid, avatar_sha)
app.interface.update_avatar(self._account, jid)
else:
log.info('Request : %s', jid)
self._con.get_module('VCardTemp').request_vcard(
RequestAvatar.SELF)
else: else:
log.info('Avatar already known: %s %s', log.info('Avatar already known: %s %s',
jid, avatar_sha) jid, avatar_sha)
@ -168,10 +195,17 @@ class VCardAvatars:
else: else:
log.info('Avatar already known: %s', nick) log.info('Avatar already known: %s', nick)
def send_avatar_presence(self, force=False): def send_avatar_presence(self, force=False, after_publish=False):
if self.avatar_advertised and not force: if self._con.avatar_conversion:
log.debug('Avatar already advertised') if not after_publish:
return # XEP-0398: We only resend presence after we publish a
# new avatar
return
else:
if self.avatar_advertised and not force:
log.debug('Avatar already advertised')
return
show = helpers.get_xmpp_show(app.SHOW_LIST[self._con.connected]) show = helpers.get_xmpp_show(app.SHOW_LIST[self._con.connected])
self._con.get_module('Presence').send_presence( self._con.get_module('Presence').send_presence(
@ -180,8 +214,6 @@ class VCardAvatars:
status=self._con.status) status=self._con.status)
self.avatar_advertised = True self.avatar_advertised = True
app.interface.update_avatar(self._account,
self._con.get_own_jid().getStripped())
def add_update_node(self, node): def add_update_node(self, node):
update = node.setTag('x', namespace=nbxmpp.NS_VCARD_UPDATE) update = node.setTag('x', namespace=nbxmpp.NS_VCARD_UPDATE)

View File

@ -14,7 +14,6 @@
# XEP-0054: vcard-temp # XEP-0054: vcard-temp
import os
import hashlib import hashlib
import binascii import binascii
import base64 import base64
@ -23,7 +22,6 @@ import logging
import nbxmpp import nbxmpp
from gajim.common import app from gajim.common import app
from gajim.common import configpaths
from gajim.common.const import RequestAvatar from gajim.common.const import RequestAvatar
from gajim.common.nec import NetworkIncomingEvent from gajim.common.nec import NetworkIncomingEvent
from gajim.common.connection_handlers_events import InformationEvent from gajim.common.connection_handlers_events import InformationEvent
@ -156,8 +154,10 @@ class VCardTemp:
'accounts', self._account, 'avatar_sha', sha or '') 'accounts', self._account, 'avatar_sha', sha or '')
own_jid = self._con.get_own_jid().getStripped() own_jid = self._con.get_own_jid().getStripped()
app.contacts.set_avatar(self._account, own_jid, sha) app.contacts.set_avatar(self._account, own_jid, sha)
app.interface.update_avatar(
self._account, self._con.get_own_jid().getStripped())
self._con.get_module('VCardAvatars').send_avatar_presence( self._con.get_module('VCardAvatars').send_avatar_presence(
force=True) after_publish=True)
log.info('%s: Published: %s', self._account, sha) log.info('%s: Published: %s', self._account, sha)
app.nec.push_incoming_event( app.nec.push_incoming_event(
VcardPublishedEvent(None, conn=self._con)) VcardPublishedEvent(None, conn=self._con))
@ -231,28 +231,28 @@ class VCardTemp:
self._own_vcard = vcard self._own_vcard = vcard
self.own_vcard_received = True self.own_vcard_received = True
if avatar_sha is None: if avatar_sha is None:
# No avatar found in vcard
log.info('No avatar found') log.info('No avatar found')
app.config.set_per('accounts', self._account, 'avatar_sha', '') app.config.set_per('accounts', self._account, 'avatar_sha', '')
app.contacts.set_avatar(self._account, jid, avatar_sha)
self._con.get_module('VCardAvatars').send_avatar_presence(force=True) self._con.get_module('VCardAvatars').send_avatar_presence(force=True)
return return
current_sha = app.config.get_per('accounts', self._account, 'avatar_sha') # Avatar found in vcard
current_sha = app.config.get_per(
'accounts', self._account, 'avatar_sha')
if current_sha == avatar_sha: if current_sha == avatar_sha:
path = os.path.join(configpaths.get('AVATAR'), current_sha)
if not os.path.isfile(path):
log.info('Caching: %s', current_sha)
app.interface.save_avatar(photo_decoded)
self._con.get_module('VCardAvatars').send_avatar_presence() self._con.get_module('VCardAvatars').send_avatar_presence()
else: else:
app.interface.save_avatar(photo_decoded) app.interface.save_avatar(photo_decoded)
app.contacts.set_avatar(self._account, jid, avatar_sha)
app.config.set_per(
'accounts', self._account, 'avatar_sha', avatar_sha)
self._con.get_module('VCardAvatars').send_avatar_presence(force=True)
app.config.set_per('accounts', self._account, 'avatar_sha', avatar_sha) app.interface.update_avatar(self._account, jid)
if app.is_invisible(self._account):
log.info('We are invisible, not advertising avatar')
return
self._con.get_module('VCardAvatars').send_avatar_presence(force=True)
def _on_room_avatar_received(self, jid, resource, room, vcard, def _on_room_avatar_received(self, jid, resource, room, vcard,
expected_sha): expected_sha):

View File

@ -177,7 +177,10 @@ class ServerInfoDialog(Gtk.Dialog):
mam_enabled), mam_enabled),
Feature('XEP-0363: HTTP File Upload', Feature('XEP-0363: HTTP File Upload',
con.get_module('HTTPUpload').available, con.get_module('HTTPUpload').available,
con.get_module('HTTPUpload').httpupload_namespace, None)] con.get_module('HTTPUpload').httpupload_namespace, None),
Feature('XEP-0398: Avatar Conversion',
con.avatar_conversion, '', None)
]
def add_info(self, info): def add_info(self, info):
self.info_listbox.add(ServerInfoItem(info)) self.info_listbox.add(ServerInfoItem(info))