Philipp Hörist pushed to branch master at gajim / gajim
Commits: c68f4f10 by Philipp Hörist at 2018-09-01T16:06:21Z Send all presence through the presence module
- - - - - be6c2d4f by Philipp Hörist at 2018-09-01T18:40:20Z 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
- - - - -
11 changed files:
- gajim/common/config.py - gajim/common/connection.py - gajim/common/connection_handlers.py - gajim/common/connection_handlers_events.py - gajim/common/modules/discovery.py - gajim/common/modules/muc.py - gajim/common/modules/presence.py - gajim/common/modules/user_avatar.py - gajim/common/modules/vcard_avatars.py - gajim/common/modules/vcard_temp.py - gajim/gtk/server_info.py
Changes:
===================================== gajim/common/config.py ===================================== --- a/gajim/common/config.py +++ b/gajim/common/config.py @@ -241,7 +241,6 @@ class Config: 'roster_window_skip_taskbar': [opt_bool, False, _('Don't show roster in the system taskbar.')], 'use_urgency_hint': [opt_bool, True, _('If true, make the window flash (the default behaviour in most Window Managers) when holding pending events.')], 'notification_timeout': [opt_int, 5], - 'send_sha_in_gc_presence': [opt_bool, True, _('Jabberd1.4 does not like sha info when one join a password protected group chat. Turn this option to False to stop sending sha info in group chat presences.')], 'one_message_window': [opt_str, 'always', #always, never, peracct, pertype should not be translated _('Controls the window where new messages are placed.\n'always' - All messages are sent to a single window.\n'always_with_roster' - Like 'always' but the messages are in a single window along with the roster.\n'never' - All messages get their own window.\n'peracct' - Messages for each account are sent to a specific window.\n'pertype' - Each message type (e.g. chats vs. groupchats) is sent to a specific window.')],
===================================== gajim/common/connection.py ===================================== --- a/gajim/common/connection.py +++ b/gajim/common/connection.py @@ -38,7 +38,6 @@ import socket import operator import string import time -import hmac import hashlib import json import logging @@ -60,12 +59,10 @@ from gajim.common import helpers from gajim.common import app from gajim.common import gpg from gajim.common import passwords -from gajim.common import i18n from gajim.common import idle from gajim.common.connection_handlers import * from gajim.common.contacts import GC_Contact from gajim.common import modules -from gajim.gtkgui_helpers import get_action
log = logging.getLogger('gajim.c.connection') @@ -117,6 +114,7 @@ class CommonConnection:
self.roster_supported = True self.addressing_supported = False + self.avatar_conversion = False
self.muc_jid = {} # jid of muc server for each transport type self._stun_servers = [] # STUN servers of our jabber server @@ -474,10 +472,11 @@ class CommonConnection: if self.connection: app.nec.push_incoming_event(BeforeChangeShowEvent(None, conn=self, show=show, message=msg)) - p = nbxmpp.Presence(typ = 'unavailable') - p = self.add_sha(p, False) - if msg: - p.setStatus(msg) + + p = self.get_module('Presence').get_presence( + typ='unavailable', + status=msg, + caps=False)
self.connection.RegisterDisconnectHandler(self._on_disconnected) self.connection.send(p, now=True) @@ -542,7 +541,6 @@ class Connection(CommonConnection, ConnectionHandlers): # server {'icq': ['icq.server.com', 'icq2.server.com'], }
self.streamError = '' - self.secret_hmac = str(random.random())[2:].encode('utf-8') self.removing_account = False
# We only request POSH once @@ -1351,9 +1349,6 @@ class Connection(CommonConnection, ConnectionHandlers): self.on_connect_auth = None # END connect
- def add_lang(self, stanza): - stanza.setAttr('xml:lang', i18n.LANG) - def send_keepalive(self): # nothing received for the last foo seconds if self.connection: @@ -1372,15 +1367,15 @@ class Connection(CommonConnection, ConnectionHandlers): # offline presence first as it's required by XEP-0126 if self.connected > 1 and self.get_module('PrivacyLists').supported: self.on_purpose = True - p = nbxmpp.Presence(typ='unavailable') - p = self.add_sha(p, False) - if msg: - p.setStatus(msg) + self.remove_all_transfers() - self.connection.send(p) + self.get_module('Presence').send_presence( + typ='unavailable', + status=msg, + caps=False)
# try to set the privacy rule - iq = self.get_module('PrivacyLists').set_invisible_rule( + self.get_module('PrivacyLists').set_invisible_rule( callback=self._continue_invisible, msg=msg, signed=signed, @@ -1394,19 +1389,19 @@ class Connection(CommonConnection, ConnectionHandlers): self.connected = app.SHOW_LIST.index('invisible') self.status = msg priority = app.get_priority(self.name, 'invisible') - p = nbxmpp.Presence(priority=priority) - p = self.add_sha(p, True) - if msg: - p.setStatus(msg) - if signed: - p.setTag(nbxmpp.NS_SIGNED + ' x').setData(signed) - self.connection.send(p) + + self.get_module('Presence').send_presence( + priority=priority, + status=msg, + sign=signed) + self.priority = priority app.nec.push_incoming_event(OurShowEvent(None, conn=self, show='invisible')) if initial: - # ask our VCard - self.get_module('VCardTemp').request_vcard() + if not self.avatar_conversion: + # ask our VCard + self.get_module('VCardTemp').request_vcard()
# Get bookmarks self.get_module('Bookmarks').get_bookmarks() @@ -1486,20 +1481,21 @@ class Connection(CommonConnection, ConnectionHandlers): if not msg: msg = '' if show == 'offline': - p = nbxmpp.Presence(typ='unavailable', to=jid) - p = self.add_sha(p, False) - if msg: - p.setStatus(msg) + self.get_module('Presence').send_presence( + jid, + 'unavailable', + caps=False, + status=msg) + else: signed = self.get_signed_presence(msg) priority = app.get_priority(self.name, sshow) - p = nbxmpp.Presence(typ=None, priority=priority, show=sshow, to=jid) - p = self.add_sha(p) - if msg: - p.setStatus(msg) - if signed: - p.setTag(nbxmpp.NS_SIGNED + ' x').setData(signed) - self.connection.send(p) + self.get_module('Presence').send_presence( + jid, + priority=priority, + show=sshow, + status=msg, + sign=signed)
def _change_to_invisible(self, msg): signed = self.get_signed_presence(msg) @@ -1512,18 +1508,16 @@ class Connection(CommonConnection, ConnectionHandlers): def _update_status(self, show, msg, idle_time=None): xmpp_show = helpers.get_xmpp_show(show) priority = app.get_priority(self.name, xmpp_show) - p = nbxmpp.Presence(typ=None, priority=priority, show=xmpp_show) - p = self.add_sha(p) - if msg: - p.setStatus(msg) signed = self.get_signed_presence(msg) - if signed: - p.setTag(nbxmpp.NS_SIGNED + ' x').setData(signed) - if idle_time: - idle_node = p.setTag('idle', namespace=nbxmpp.NS_IDLE) - idle_node.setAttr('since', idle_time) + + self.get_module('Presence').send_presence( + priority=priority, + show=xmpp_show, + status=msg, + sign=signed, + idle_time=idle_time) + if self.connection: - self.connection.send(p) self.priority = priority app.nec.push_incoming_event(OurShowEvent(None, conn=self, show=show)) @@ -1654,9 +1648,12 @@ class Connection(CommonConnection, ConnectionHandlers): if not app.account_is_connected(self.name): return show = helpers.get_xmpp_show(app.SHOW_LIST[self.connected]) - p = nbxmpp.Presence(to=agent, typ=ptype, show=show) - p = self.add_sha(p, ptype != 'unavailable') - self.connection.send(p) + + self.get_module('Presence').send_presence( + agent, + ptype, + show=show, + caps=ptype != 'unavailable')
def send_captcha(self, jid, form_node): if not app.account_is_connected(self.name): @@ -1697,56 +1694,19 @@ class Connection(CommonConnection, ConnectionHandlers): password, change_nick, rejoin))
def _join_gc(self, nick, show, room_jid, password, change_nick, rejoin): - # Check time first in the FAST table - last_date = app.logger.get_room_last_message_time( - self.name, room_jid) - if not last_date: - last_date = 0 - - p = nbxmpp.Presence(to='%s/%s' % (room_jid, nick), - show=show, status=self.status) - h = hmac.new(self.secret_hmac, room_jid.encode('utf-8'), hashlib.md5).\ - hexdigest()[:6] - id_ = self.connection.getAnID() - id_ = 'gajim_muc_' + id_ + '_' + h - p.setID(id_) - if app.config.get('send_sha_in_gc_presence'): - p = self.add_sha(p) - self.add_lang(p) if change_nick: - self.connection.send(p) - return - - t = p.setTag(nbxmpp.NS_MUC + ' x') - if muc_caps_cache.has_mam(room_jid): - # The room is MAM capable dont get MUC History - t.setTag('history', {'maxchars': '0'}) + self.get_module('Presence').send_presence( + '%s/%s' % (room_jid, nick), + show=show, + status=self.status) else: - # Request MUC History (not MAM) - tags = {} - timeout = app.config.get_per('rooms', room_jid, - 'muc_restore_timeout') - if timeout is None or timeout == -2: - timeout = app.config.get('muc_restore_timeout') - if last_date == 0 and timeout >= 0: - last_date = time.time() - timeout * 60 - elif not rejoin and timeout >= 0: - last_date = max(last_date, time.time() - timeout * 60) - last_date = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime( - last_date)) - tags['since'] = last_date - - nb = app.config.get_per('rooms', room_jid, 'muc_restore_lines') - if nb is None or nb == -2: - nb = app.config.get('muc_restore_lines') - if nb >= 0: - tags['maxstanzas'] = nb - if tags: - t.setTag('history', tags) - - if password: - t.setTagData('password', password) - self.connection.send(p) + self.get_module('MUC').send_muc_join_presence( + '%s/%s' % (room_jid, nick), + show=show, + status=self.status, + room_jid=room_jid, + password=password, + rejoin=rejoin)
def _nec_gc_message_outgoing(self, obj): if obj.account != self.name: @@ -1809,26 +1769,20 @@ class Connection(CommonConnection, ConnectionHandlers): if show == 'offline': ptype = 'unavailable' xmpp_show = helpers.get_xmpp_show(show) - p = nbxmpp.Presence(to='%s/%s' % (jid, nick), typ=ptype, - show=xmpp_show, status=status) - h = hmac.new(self.secret_hmac, jid.encode('utf-8'), hashlib.md5).\ - hexdigest()[:6] - id_ = self.connection.getAnID() - id_ = 'gajim_muc_' + id_ + '_' + h - p.setID(id_) - if app.config.get('send_sha_in_gc_presence') and show != 'offline': - p = self.add_sha(p, ptype != 'unavailable') - self.add_lang(p) - if auto: - if app.is_installed('IDLE') and app.config.get('autoaway'): - idle_sec = idle.Monitor.get_idle_sec() - idle_time = time.strftime('%Y-%m-%dT%H:%M:%SZ', - time.gmtime(time.time() - idle_sec)) - idle_node = p.setTag('idle', namespace=nbxmpp.NS_IDLE) - idle_node.setAttr('since', idle_time) - # send instantly so when we go offline, status is sent to gc before we - # disconnect from jabber server - self.connection.send(p) + + idle_time = None + if auto and app.is_installed('IDLE') and app.config.get('autoaway'): + idle_sec = idle.Monitor.get_idle_sec() + idle_time = time.strftime('%Y-%m-%dT%H:%M:%SZ', + time.gmtime(time.time() - idle_sec)) + + self.get_module('Presence').send_presence( + '%s/%s' % (jid, nick), + typ=ptype, + show=xmpp_show, + status=status, + caps=ptype != 'unavailable', + idle_time=idle_time)
def get_password(self, callback, type_): if app.config.get_per('accounts', self.name, 'anonymous_auth') and \
===================================== gajim/common/connection_handlers.py ===================================== --- a/gajim/common/connection_handlers.py +++ b/gajim/common/connection_handlers.py @@ -422,20 +422,6 @@ class ConnectionHandlers(ConnectionSocks5Bytestream, app.ged.remove_event_handler('agent-removed', ged.CORE, self._nec_agent_removed)
- def add_sha(self, p, send_caps=True): - p = self.get_module('VCardAvatars').add_update_node(p) - if send_caps: - return self._add_caps(p) - return p - - def _add_caps(self, p): - ''' advertise our capabilities in presence stanza (xep-0115)''' - c = p.setTag('c', namespace=nbxmpp.NS_CAPS) - c.setAttr('hash', 'sha-1') - c.setAttr('node', 'http://gajim.org') - c.setAttr('ver', app.caps_hash[self.name]) - return p - def _ErrorCB(self, con, iq_obj): log.debug('ErrorCB') app.nec.push_incoming_event(IqErrorReceivedEvent(None, conn=self, @@ -582,21 +568,21 @@ class ConnectionHandlers(ConnectionSocks5Bytestream, if show not in ['offline', 'online', 'chat', 'away', 'xa', 'dnd']: return priority = app.get_priority(self.name, sshow) - p = nbxmpp.Presence(typ=None, priority=priority, show=sshow) - if msg: - p.setStatus(msg) - if signed: - p.setTag(nbxmpp.NS_SIGNED + ' x').setData(signed) - p = self.add_sha(p) + + self.get_module('Presence').send_presence( + priority=priority, + show=sshow, + status=msg, + sign=signed)
if self.connection: - self.connection.send(p) self.priority = priority app.nec.push_incoming_event(OurShowEvent(None, conn=self, show=show))
- # ask our VCard - self.get_module('VCardTemp').request_vcard() + if not self.avatar_conversion: + # ask our VCard + self.get_module('VCardTemp').request_vcard()
# Get bookmarks self.get_module('Bookmarks').get_bookmarks()
===================================== gajim/common/connection_handlers_events.py ===================================== --- a/gajim/common/connection_handlers_events.py +++ b/gajim/common/connection_handlers_events.py @@ -288,7 +288,7 @@ PresenceHelperEvent): xtags = self.stanza.getTags('x') for x in xtags: namespace = x.getNamespace() - if namespace == nbxmpp.NS_MUC_USER: + if namespace in (nbxmpp.NS_MUC_USER, nbxmpp.NS_MUC): self.is_gc = True elif namespace == nbxmpp.NS_SIGNED: sig_tag = x @@ -296,14 +296,6 @@ PresenceHelperEvent): # XEP-0091 self._generate_timestamp(self.stanza.timestamp)
- if not self.is_gc and self.id_ and self.id_.startswith('gajim_muc_') \ - and self.ptype == 'error': - # Error presences may not include sent stanza, so we don't detect - # it's a muc presence. So detect it by ID - h = hmac.new(self.conn.secret_hmac, self.jid.encode('utf-8'), - hashlib.md5).hexdigest()[:6] - if self.id_.split('_')[-1] == h: - self.is_gc = True self.status = self.stanza.getStatus() or '' self._generate_show() self._generate_prio()
===================================== gajim/common/modules/discovery.py ===================================== --- a/gajim/common/modules/discovery.py +++ b/gajim/common/modules/discovery.py @@ -178,6 +178,10 @@ class Discovery: self._con.get_module('PEP').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): # Calling this method starts the connect_maschine() server = self._con.get_own_jid().getDomain()
===================================== gajim/common/modules/muc.py ===================================== --- a/gajim/common/modules/muc.py +++ b/gajim/common/modules/muc.py @@ -15,6 +15,7 @@ # XEP-0045: Multi-User Chat # XEP-0249: Direct MUC Invitations
+import time import logging
import nbxmpp @@ -23,6 +24,7 @@ from gajim.common import i18n from gajim.common.modules import dataforms from gajim.common import app from gajim.common import helpers +from gajim.common.caps_cache import muc_caps_cache from gajim.common.nec import NetworkIncomingEvent
log = logging.getLogger('gajim.c.m.muc') @@ -50,6 +52,56 @@ class MUC: self._con.muc_jid['jabber'] = from_ raise nbxmpp.NodeProcessed
+ def send_muc_join_presence(self, *args, room_jid=None, password=None, + rejoin=False, **kwargs): + if not app.account_is_connected(self._account): + return + presence = self._con.get_module('Presence').get_presence( + *args, **kwargs) + + if room_jid is not None: + self._add_history_query(presence, room_jid, rejoin) + + if password is not None: + presence.setTagData('password', password) + + log.debug('Send MUC join presence:\n%s', presence) + + self._con.connection.send(presence) + + def _add_history_query(self, presence, room_jid, rejoin): + last_date = app.logger.get_room_last_message_time( + self._account, room_jid) + if not last_date: + last_date = 0 + + history = presence.setTag(nbxmpp.NS_MUC + ' x') + if muc_caps_cache.has_mam(room_jid): + # The room is MAM capable dont get MUC History + history.setTag('history', {'maxchars': '0'}) + else: + # Request MUC History (not MAM) + tags = {} + timeout = app.config.get_per('rooms', room_jid, + 'muc_restore_timeout') + if timeout is None or timeout == -2: + timeout = app.config.get('muc_restore_timeout') + if last_date == 0 and timeout >= 0: + last_date = time.time() - timeout * 60 + elif not rejoin and timeout >= 0: + last_date = max(last_date, time.time() - timeout * 60) + last_date = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime( + last_date)) + tags['since'] = last_date + + nb = app.config.get_per('rooms', room_jid, 'muc_restore_lines') + if nb is None or nb == -2: + nb = app.config.get('muc_restore_lines') + if nb >= 0: + tags['maxstanzas'] = nb + if tags: + history.setTag('history', tags) + def set_subject(self, room_jid, subject): if not app.account_is_connected(self._account): return
===================================== gajim/common/modules/presence.py ===================================== --- a/gajim/common/modules/presence.py +++ b/gajim/common/modules/presence.py @@ -75,9 +75,7 @@ class Presence: raise nbxmpp.NodeProcessed
if auto_auth or is_transport or jid in self.jids_for_auto_auth: - presence = nbxmpp.Presence(fjid, 'subscribed') - presence = self._add_sha(presence) - self._con.connection.send(presence) + self.send_presence(fjid, 'subscribed')
if not status: status = _('I would like to add you to my roster.') @@ -124,17 +122,13 @@ class Presence: if not app.account_is_connected(self._account): return log.info('Subscribed: %s', jid) - presence = nbxmpp.Presence(jid, 'subscribed') - presence = self._add_sha(presence) - self._con.connection.send(presence) + self.send_presence(jid, 'subscribed')
def unsubscribed(self, jid): if not app.account_is_connected(self._account): return log.info('Unsubscribed: %s', jid) - presence = nbxmpp.Presence(jid, 'unsubscribed') - presence = self._add_sha(presence) - self._con.connection.send(presence) + self.send_presence(jid, 'unsubscribed')
def unsubscribe(self, jid, remove_auth=True): if not app.account_is_connected(self._account): @@ -150,7 +144,7 @@ class Presence: self._con.getRoster().Unsubscribe(jid) self._con.getRoster().setItem(jid)
- def subscribe(self, jid, msg='', name='', groups=None, + def subscribe(self, jid, msg=None, name='', groups=None, auto_auth=False, user_nick=''): if not app.account_is_connected(self._account): return @@ -172,29 +166,43 @@ class Presence: item.addChild('group').setData(group) self._con.connection.send(iq)
- presence = nbxmpp.Presence(jid, 'subscribe') - if user_nick: - nick = presence.setTag('nick', namespace=nbxmpp.NS_NICK) - nick.setData(user_nick) - presence = self._add_sha(presence) - if msg: - presence.setStatus(msg) - self._con.connection.send(presence) + self.send_presence(jid, 'subscribe', msg)
- def _add_sha(self, presence, send_caps=True): - vcard = self._con.get_module('VCardAvatars') - presence = vcard.add_update_node(presence) - if send_caps: - return self._add_caps(presence) - return presence + def get_presence(self, to=None, typ=None, priority=None, + show=None, status=None, nick=None, caps=True, + sign=None, idle_time=None): + presence = nbxmpp.Presence(to, typ, priority, show, status) + if nick is not None: + nick_tag = presence.setTag('nick', namespace=nbxmpp.NS_NICK) + nick_tag.setData(nick) + + if sign: + presence.setTag(nbxmpp.NS_SIGNED + ' x').setData(sign) + + if idle_time is not None: + idle_node = presence.setTag('idle', namespace=nbxmpp.NS_IDLE) + idle_node.setAttr('since', idle_time) + + 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: + attrs = {'hash': 'sha-1', + 'node': 'http://gajim.org', + 'ver': app.caps_hash[self._account]} + presence.setTag('c', namespace=nbxmpp.NS_CAPS, attrs=attrs)
- def _add_caps(self, presence): - c = presence.setTag('c', namespace=nbxmpp.NS_CAPS) - c.setAttr('hash', 'sha-1') - c.setAttr('node', 'http://gajim.org') - c.setAttr('ver', app.caps_hash[self._account]) return presence
+ def send_presence(self, *args, **kwargs): + if not app.account_is_connected(self._account): + return + presence = self.get_presence(*args, **kwargs) + log.debug('Send presence:\n%s', presence) + self._con.connection.send(presence) +
def parse_show(stanza): show = stanza.getShow()
===================================== gajim/common/modules/user_avatar.py ===================================== --- a/gajim/common/modules/user_avatar.py +++ b/gajim/common/modules/user_avatar.py @@ -107,8 +107,8 @@ class UserAvatar(AbstractPEPModule): 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.contacts.set_avatar(self._account, jid, sha) app.interface.update_avatar(self._account, jid)
def _extract_info(self, item):
===================================== gajim/common/modules/vcard_avatars.py ===================================== --- a/gajim/common/modules/vcard_avatars.py +++ b/gajim/common/modules/vcard_avatars.py @@ -16,6 +16,7 @@
import os import logging +from pathlib import Path
import nbxmpp
@@ -38,6 +39,16 @@ class VCardAvatars: ]
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): 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() == jid: - # Reflection of our own presence - return - self._self_update_received(jid, avatar_sha) + # Initial presence reflection + if self._con.avatar_conversion: + # 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
# Check if presence is from a MUC service @@ -76,6 +92,9 @@ class VCardAvatars: if avatar_sha == '': # Empty <photo/> tag, means no avatar is advertised 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
log.info('Update: %s %s', jid, avatar_sha) @@ -83,8 +102,16 @@ class VCardAvatars: 'accounts', self._account, 'avatar_sha')
if avatar_sha != current_sha: - log.info('Request : %s', jid) - self._con.get_module('VCardTemp').request_vcard(RequestAvatar.SELF) + path = Path(configpaths.get('AVATAR')) / avatar_sha + 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: log.info('Avatar already known: %s %s', jid, avatar_sha) @@ -168,18 +195,25 @@ class VCardAvatars: else: log.info('Avatar already known: %s', nick)
- def send_avatar_presence(self, force=False): - if self.avatar_advertised and not force: - log.debug('Avatar already advertised') - return + def send_avatar_presence(self, force=False, after_publish=False): + if self._con.avatar_conversion: + if not after_publish: + # 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]) - pres = nbxmpp.Presence(typ=None, priority=self._con.priority, - show=show, status=self._con.status) - pres = self._con.add_sha(pres) - self._con.connection.send(pres) + + self._con.get_module('Presence').send_presence( + priority=self._con.priority, + show=show, + status=self._con.status) + self.avatar_advertised = True - app.interface.update_avatar(self._account, - self._con.get_own_jid().getStripped())
def add_update_node(self, node): update = node.setTag('x', namespace=nbxmpp.NS_VCARD_UPDATE) @@ -189,7 +223,6 @@ class VCardAvatars: log.info('Send avatar presence to: %s %s', node.getTo() or own_jid, sha or 'no sha advertised') update.setTagData('photo', sha) - return node
def get_instance(*args, **kwargs):
===================================== gajim/common/modules/vcard_temp.py ===================================== --- a/gajim/common/modules/vcard_temp.py +++ b/gajim/common/modules/vcard_temp.py @@ -14,7 +14,6 @@
# XEP-0054: vcard-temp
-import os import hashlib import binascii import base64 @@ -23,7 +22,6 @@ import logging import nbxmpp
from gajim.common import app -from gajim.common import configpaths from gajim.common.const import RequestAvatar from gajim.common.nec import NetworkIncomingEvent from gajim.common.connection_handlers_events import InformationEvent @@ -156,8 +154,10 @@ class VCardTemp: 'accounts', self._account, 'avatar_sha', sha or '') own_jid = self._con.get_own_jid().getStripped() 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( - force=True) + after_publish=True) log.info('%s: Published: %s', self._account, sha) app.nec.push_incoming_event( VcardPublishedEvent(None, conn=self._con)) @@ -231,28 +231,28 @@ class VCardTemp:
self._own_vcard = vcard self.own_vcard_received = True + if avatar_sha is None: + # No avatar found in vcard log.info('No avatar found') 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) 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: - 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() else: 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) - 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) + app.interface.update_avatar(self._account, jid)
def _on_room_avatar_received(self, jid, resource, room, vcard, expected_sha):
===================================== gajim/gtk/server_info.py ===================================== --- a/gajim/gtk/server_info.py +++ b/gajim/gtk/server_info.py @@ -177,7 +177,10 @@ class ServerInfoDialog(Gtk.Dialog): mam_enabled), Feature('XEP-0363: HTTP File Upload', 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): self.info_listbox.add(ServerInfoItem(info))
View it on GitLab: https://dev.gajim.org/gajim/gajim/compare/7d723d7b9846c0226b4c0d3b068e08b772...