Refactor VCard code into own modules
This commit is contained in:
parent
71a82b5c3e
commit
8b800f4646
|
@ -397,6 +397,9 @@ def account_is_connected(account):
|
|||
else:
|
||||
return False
|
||||
|
||||
def is_invisible(account):
|
||||
return SHOW_LIST[connections[account].connected] == 'invisible'
|
||||
|
||||
def account_is_disconnected(account):
|
||||
return not account_is_connected(account)
|
||||
|
||||
|
|
|
@ -71,6 +71,8 @@ from gajim.common.modules.annotations import Annotations
|
|||
from gajim.common.modules.roster_item_exchange import RosterItemExchange
|
||||
from gajim.common.modules.last_activity import LastActivity
|
||||
from gajim.common.modules.http_auth import HTTPAuth
|
||||
from gajim.common.modules.vcard_temp import VCardTemp
|
||||
from gajim.common.modules.vcard_avatars import VCardAvatars
|
||||
from gajim.common.connection_handlers import *
|
||||
from gajim.common.contacts import GC_Contact
|
||||
from gajim.gtkgui_helpers import get_action
|
||||
|
@ -666,6 +668,8 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
self.register_module('RosterItemExchange', RosterItemExchange, self)
|
||||
self.register_module('LastActivity', LastActivity, self)
|
||||
self.register_module('HTTPAuth', HTTPAuth, self)
|
||||
self.register_module('VCardTemp', VCardTemp, self)
|
||||
self.register_module('VCardAvatars', VCardAvatars, self)
|
||||
|
||||
app.ged.register_event_handler('privacy-list-received', ged.CORE,
|
||||
self._nec_privacy_list_received)
|
||||
|
@ -756,7 +760,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
self.connected = 0
|
||||
self.time_to_reconnect = None
|
||||
self.privacy_rules_supported = False
|
||||
self.avatar_presence_sent = False
|
||||
self.get_module('VCardAvatars').avatar_advertised = False
|
||||
if on_purpose:
|
||||
self.sm = Smacks(self)
|
||||
if self.connection:
|
||||
|
@ -1768,7 +1772,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
show='invisible'))
|
||||
if initial:
|
||||
# ask our VCard
|
||||
self.request_vcard(self._on_own_avatar_received)
|
||||
self.get_module('VCardTemp').request_vcard()
|
||||
|
||||
# Get bookmarks from private namespace
|
||||
self.get_bookmarks()
|
||||
|
|
|
@ -283,388 +283,6 @@ class ConnectionDisco:
|
|||
app.nec.push_incoming_event(AgentInfoReceivedEvent(None, conn=self,
|
||||
stanza=iq_obj))
|
||||
|
||||
class ConnectionVcard:
|
||||
def __init__(self):
|
||||
self.own_vcard = None
|
||||
self.room_jids = []
|
||||
self.avatar_presence_sent = False
|
||||
self._requested_shas = {}
|
||||
|
||||
app.ged.register_event_handler('presence-received', ged.GUI2,
|
||||
self._vcard_presence_received)
|
||||
app.ged.register_event_handler('gc-presence-received', ged.GUI2,
|
||||
self._vcard_gc_presence_received)
|
||||
app.ged.register_event_handler('room-avatar-received', ged.GUI2,
|
||||
self._vcard_presence_received)
|
||||
|
||||
def _vcard_presence_received(self, obj):
|
||||
if obj.conn.name != self.name:
|
||||
return
|
||||
|
||||
if obj.avatar_sha is None:
|
||||
# No Avatar is advertised
|
||||
return
|
||||
|
||||
room_avatar = False
|
||||
if isinstance(obj, RoomAvatarReceivedEvent):
|
||||
room_avatar = True
|
||||
|
||||
if self.get_own_jid().bareMatch(obj.jid):
|
||||
app.log('avatar').info('Update (vCard): %s %s',
|
||||
obj.jid, obj.avatar_sha)
|
||||
current_sha = app.config.get_per(
|
||||
'accounts', self.name, 'avatar_sha')
|
||||
if obj.avatar_sha != current_sha:
|
||||
app.log('avatar').info(
|
||||
'Request (vCard): %s', obj.jid)
|
||||
self.request_vcard(self._on_own_avatar_received)
|
||||
else:
|
||||
app.log('avatar').info(
|
||||
'Avatar already known (vCard): %s %s',
|
||||
obj.jid, obj.avatar_sha)
|
||||
return
|
||||
|
||||
if obj.avatar_sha == '':
|
||||
# Empty <photo/> tag, means no avatar is advertised
|
||||
app.log('avatar').info(
|
||||
'%s has no avatar published (vCard)', obj.jid)
|
||||
|
||||
# Remove avatar
|
||||
app.log('avatar').debug('Remove: %s', obj.jid)
|
||||
app.contacts.set_avatar(self.name, obj.jid, None)
|
||||
own_jid = self.get_own_jid().getStripped()
|
||||
if not room_avatar:
|
||||
app.logger.set_avatar_sha(own_jid, obj.jid, None)
|
||||
app.interface.update_avatar(
|
||||
self.name, obj.jid, room_avatar=room_avatar)
|
||||
else:
|
||||
app.log('avatar').info(
|
||||
'Update (vCard): %s %s', obj.jid, obj.avatar_sha)
|
||||
current_sha = app.contacts.get_avatar_sha(self.name, obj.jid)
|
||||
|
||||
if obj.avatar_sha == current_sha:
|
||||
app.log('avatar').info(
|
||||
'Avatar already known (vCard): %s %s',
|
||||
obj.jid, obj.avatar_sha)
|
||||
return
|
||||
|
||||
if room_avatar:
|
||||
# We dont save the room avatar hash in our DB, so check
|
||||
# if we previously downloaded it
|
||||
if app.interface.avatar_exists(obj.avatar_sha):
|
||||
app.contacts.set_avatar(self.name, obj.jid, obj.avatar_sha)
|
||||
app.interface.update_avatar(
|
||||
self.name, obj.jid, room_avatar=room_avatar)
|
||||
elif obj.jid not in self._requested_shas:
|
||||
app.log('avatar').info(
|
||||
'Request (vCard): %s', obj.jid)
|
||||
self._requested_shas[obj.jid] = obj.avatar_sha
|
||||
self.request_vcard(self._on_room_avatar_received, obj.jid)
|
||||
return
|
||||
|
||||
if obj.jid not in self._requested_shas:
|
||||
app.log('avatar').info(
|
||||
'Request (vCard): %s', obj.jid)
|
||||
self._requested_shas[obj.jid] = obj.avatar_sha
|
||||
self.request_vcard(self._on_avatar_received, obj.jid)
|
||||
|
||||
|
||||
def _vcard_gc_presence_received(self, obj):
|
||||
if obj.conn.name != self.name:
|
||||
return
|
||||
|
||||
server = app.get_server_from_jid(obj.room_jid)
|
||||
if server.startswith('irc') or obj.avatar_sha is None:
|
||||
return
|
||||
|
||||
if obj.show == 'offline':
|
||||
return
|
||||
|
||||
gc_contact = app.contacts.get_gc_contact(
|
||||
self.name, obj.room_jid, obj.nick)
|
||||
|
||||
if gc_contact is None:
|
||||
app.log('avatar').error('no gc contact found: %s', obj.nick)
|
||||
return
|
||||
|
||||
if obj.avatar_sha == '':
|
||||
# Empty <photo/> tag, means no avatar is advertised, remove avatar
|
||||
app.log('avatar').info(
|
||||
'%s has no avatar published (vCard)', obj.nick)
|
||||
app.log('avatar').debug('Remove: %s', obj.nick)
|
||||
gc_contact.avatar_sha = None
|
||||
app.interface.update_avatar(contact=gc_contact)
|
||||
else:
|
||||
app.log('avatar').info(
|
||||
'Update (vCard): %s %s', obj.nick, obj.avatar_sha)
|
||||
path = os.path.join(configpaths.get('AVATAR'), obj.avatar_sha)
|
||||
if not os.path.isfile(path):
|
||||
if obj.fjid not in self._requested_shas:
|
||||
app.log('avatar').info(
|
||||
'Request (vCard): %s', obj.nick)
|
||||
self._requested_shas[obj.fjid] = obj.avatar_sha
|
||||
obj.conn.request_vcard(
|
||||
self._on_avatar_received, obj.fjid, room=True)
|
||||
return
|
||||
|
||||
if gc_contact.avatar_sha != obj.avatar_sha:
|
||||
app.log('avatar').info(
|
||||
'%s changed his Avatar (vCard): %s',
|
||||
obj.nick, obj.avatar_sha)
|
||||
gc_contact.avatar_sha = obj.avatar_sha
|
||||
app.interface.update_avatar(contact=gc_contact)
|
||||
else:
|
||||
app.log('avatar').info(
|
||||
'Avatar already known (vCard): %s', obj.nick)
|
||||
|
||||
def send_avatar_presence(self):
|
||||
show = helpers.get_xmpp_show(app.SHOW_LIST[self.connected])
|
||||
p = nbxmpp.Presence(typ=None, priority=self.priority,
|
||||
show=show, status=self.status)
|
||||
p = self.add_sha(p)
|
||||
self.connection.send(p)
|
||||
app.interface.update_avatar(self.name, self.get_own_jid().getStripped())
|
||||
|
||||
def _node_to_dict(self, node):
|
||||
dict_ = {}
|
||||
for info in node.getChildren():
|
||||
name = info.getName()
|
||||
if name in ('ADR', 'TEL', 'EMAIL'): # we can have several
|
||||
dict_.setdefault(name, [])
|
||||
entry = {}
|
||||
for c in info.getChildren():
|
||||
entry[c.getName()] = c.getData()
|
||||
dict_[name].append(entry)
|
||||
elif info.getChildren() == []:
|
||||
dict_[name] = info.getData()
|
||||
else:
|
||||
dict_[name] = {}
|
||||
for c in info.getChildren():
|
||||
dict_[name][c.getName()] = c.getData()
|
||||
return dict_
|
||||
|
||||
def request_vcard(self, callback, jid=None, room=False):
|
||||
"""
|
||||
Request the VCARD
|
||||
"""
|
||||
if not self.connection or self.connected < 2:
|
||||
return
|
||||
|
||||
if room:
|
||||
room_jid = app.get_room_from_fjid(jid)
|
||||
if room_jid not in self.room_jids:
|
||||
self.room_jids.append(room_jid)
|
||||
|
||||
iq = nbxmpp.Iq(typ='get')
|
||||
if jid:
|
||||
iq.setTo(jid)
|
||||
iq.setQuery('vCard').setNamespace(nbxmpp.NS_VCARD)
|
||||
|
||||
self.connection.SendAndCallForResponse(
|
||||
iq, self._parse_vcard, {'callback': callback})
|
||||
|
||||
def send_vcard(self, vcard, sha):
|
||||
if not self.connection or self.connected < 2:
|
||||
return
|
||||
iq = nbxmpp.Iq(typ='set')
|
||||
iq2 = iq.setTag(nbxmpp.NS_VCARD + ' vCard')
|
||||
for i in vcard:
|
||||
if i == 'jid':
|
||||
continue
|
||||
if isinstance(vcard[i], dict):
|
||||
iq3 = iq2.addChild(i)
|
||||
for j in vcard[i]:
|
||||
iq3.addChild(j).setData(vcard[i][j])
|
||||
elif isinstance(vcard[i], list):
|
||||
for j in vcard[i]:
|
||||
iq3 = iq2.addChild(i)
|
||||
for k in j:
|
||||
iq3.addChild(k).setData(j[k])
|
||||
else:
|
||||
iq2.addChild(i).setData(vcard[i])
|
||||
|
||||
self.connection.SendAndCallForResponse(
|
||||
iq, self._avatar_publish_result, {'sha': sha})
|
||||
|
||||
def upload_room_avatar(self, room_jid, data):
|
||||
iq = nbxmpp.Iq(typ='set', to=room_jid)
|
||||
vcard = iq.addChild('vCard', namespace=nbxmpp.NS_VCARD)
|
||||
photo = vcard.addChild('PHOTO')
|
||||
photo.addChild('TYPE', payload='image/png')
|
||||
photo.addChild('BINVAL', payload=data)
|
||||
|
||||
self.connection.SendAndCallForResponse(
|
||||
iq, self._upload_room_avatar_result)
|
||||
|
||||
def _upload_room_avatar_result(self, stanza):
|
||||
if not nbxmpp.isResultNode(stanza):
|
||||
reason = stanza.getErrorMsg() or stanza.getError()
|
||||
app.nec.push_incoming_event(InformationEvent(
|
||||
None, dialog_name='avatar-upload-error', args=reason))
|
||||
|
||||
def _avatar_publish_result(self, con, stanza, sha):
|
||||
if stanza.getType() == 'result':
|
||||
current_sha = app.config.get_per(
|
||||
'accounts', self.name, 'avatar_sha')
|
||||
if (current_sha != sha and
|
||||
app.SHOW_LIST[self.connected] != 'invisible'):
|
||||
if not self.connection or self.connected < 2:
|
||||
return
|
||||
app.config.set_per(
|
||||
'accounts', self.name, 'avatar_sha', sha or '')
|
||||
own_jid = self.get_own_jid().getStripped()
|
||||
app.contacts.set_avatar(self.name, own_jid, sha)
|
||||
self.send_avatar_presence()
|
||||
app.log('avatar').info('%s: Published: %s', self.name, sha)
|
||||
app.nec.push_incoming_event(
|
||||
VcardPublishedEvent(None, conn=self))
|
||||
|
||||
elif stanza.getType() == 'error':
|
||||
app.nec.push_incoming_event(
|
||||
VcardNotPublishedEvent(None, conn=self))
|
||||
|
||||
def _get_vcard_photo(self, vcard, jid):
|
||||
try:
|
||||
photo = vcard['PHOTO']['BINVAL']
|
||||
except (KeyError, AttributeError, TypeError):
|
||||
avatar_sha = None
|
||||
photo_decoded = None
|
||||
else:
|
||||
if photo == '':
|
||||
avatar_sha = None
|
||||
photo_decoded = None
|
||||
else:
|
||||
try:
|
||||
photo_decoded = base64.b64decode(photo.encode('utf-8'))
|
||||
except binascii.Error as error:
|
||||
app.log('avatar').warning('Invalid avatar for %s: %s',
|
||||
jid, error)
|
||||
return None, None
|
||||
avatar_sha = hashlib.sha1(photo_decoded).hexdigest()
|
||||
|
||||
return avatar_sha, photo_decoded
|
||||
|
||||
def _parse_vcard(self, con, stanza, callback):
|
||||
frm_jid = stanza.getFrom()
|
||||
room = False
|
||||
if frm_jid is None:
|
||||
frm_jid = self.get_own_jid()
|
||||
elif frm_jid.getStripped() in self.room_jids:
|
||||
room = True
|
||||
|
||||
resource = frm_jid.getResource()
|
||||
jid = frm_jid.getStripped()
|
||||
|
||||
stanza_error = stanza.getError()
|
||||
if stanza_error in ('service-unavailable', 'item-not-found',
|
||||
'not-allowed'):
|
||||
app.log('avatar').info('vCard not available: %s %s',
|
||||
frm_jid, stanza_error)
|
||||
callback(jid, resource, room, {})
|
||||
return
|
||||
|
||||
vcard_node = stanza.getTag('vCard', namespace=nbxmpp.NS_VCARD)
|
||||
if vcard_node is None:
|
||||
app.log('avatar').info('vCard not available: %s', frm_jid)
|
||||
app.log('avatar').debug(stanza)
|
||||
return
|
||||
vcard = self._node_to_dict(vcard_node)
|
||||
|
||||
if self.get_own_jid().bareMatch(jid):
|
||||
if 'NICKNAME' in vcard:
|
||||
app.nicks[self.name] = vcard['NICKNAME']
|
||||
elif 'FN' in vcard:
|
||||
app.nicks[self.name] = vcard['FN']
|
||||
|
||||
app.nec.push_incoming_event(
|
||||
VcardReceivedEvent(None, conn=self, vcard_dict=vcard))
|
||||
|
||||
callback(jid, resource, room, vcard)
|
||||
|
||||
def _on_own_avatar_received(self, jid, resource, room, vcard):
|
||||
|
||||
avatar_sha, photo_decoded = self._get_vcard_photo(vcard, jid)
|
||||
|
||||
app.log('avatar').info(
|
||||
'Received own (vCard): %s', avatar_sha)
|
||||
|
||||
self.own_vcard = vcard
|
||||
if avatar_sha is None:
|
||||
app.log('avatar').info('No avatar found (vCard)')
|
||||
app.config.set_per('accounts', self.name, 'avatar_sha', '')
|
||||
self.send_avatar_presence()
|
||||
return
|
||||
|
||||
current_sha = app.config.get_per('accounts', self.name, 'avatar_sha')
|
||||
if current_sha == avatar_sha:
|
||||
path = os.path.join(configpaths.get('AVATAR'), current_sha)
|
||||
if not os.path.isfile(path):
|
||||
app.log('avatar').info(
|
||||
'Caching (vCard): %s', current_sha)
|
||||
app.interface.save_avatar(photo_decoded)
|
||||
if self.avatar_presence_sent:
|
||||
app.log('avatar').debug('Avatar already advertised')
|
||||
return
|
||||
else:
|
||||
app.interface.save_avatar(photo_decoded)
|
||||
|
||||
app.config.set_per('accounts', self.name, 'avatar_sha', avatar_sha)
|
||||
if app.SHOW_LIST[self.connected] == 'invisible':
|
||||
app.log('avatar').info(
|
||||
'We are invisible, not publishing avatar')
|
||||
return
|
||||
|
||||
self.send_avatar_presence()
|
||||
self.avatar_presence_sent = True
|
||||
|
||||
def _on_room_avatar_received(self, jid, resource, room, vcard):
|
||||
avatar_sha, photo_decoded = self._get_vcard_photo(vcard, jid)
|
||||
expected_avatar_sha = self._requested_shas[jid]
|
||||
if expected_avatar_sha != avatar_sha:
|
||||
app.log('avatar').warning(
|
||||
'Avatar mismatch (vCard): %s %s', jid, avatar_sha)
|
||||
return
|
||||
|
||||
app.interface.save_avatar(photo_decoded)
|
||||
self._requested_shas.pop(jid)
|
||||
|
||||
app.log('avatar').info('Received (vCard): %s %s', jid, avatar_sha)
|
||||
app.contacts.set_avatar(self.name, jid, avatar_sha)
|
||||
app.interface.update_avatar(self.name, jid, room_avatar=True)
|
||||
|
||||
def _on_avatar_received(self, jid, resource, room, vcard):
|
||||
"""
|
||||
Called when we receive a vCard Parse the vCard and trigger Events
|
||||
"""
|
||||
request_jid = jid
|
||||
if room:
|
||||
request_jid = '%s/%s' % (jid, resource)
|
||||
|
||||
avatar_sha, photo_decoded = self._get_vcard_photo(vcard, request_jid)
|
||||
expected_avatar_sha = self._requested_shas[request_jid]
|
||||
if expected_avatar_sha != avatar_sha:
|
||||
app.log('avatar').warning(
|
||||
'Avatar mismatch (vCard): %s %s', request_jid, avatar_sha)
|
||||
return
|
||||
|
||||
app.interface.save_avatar(photo_decoded)
|
||||
self._requested_shas.pop(request_jid)
|
||||
|
||||
# Received vCard from a contact
|
||||
if room:
|
||||
app.log('avatar').info(
|
||||
'Received (vCard): %s %s', resource, avatar_sha)
|
||||
contact = app.contacts.get_gc_contact(self.name, jid, resource)
|
||||
if contact is not None:
|
||||
contact.avatar_sha = avatar_sha
|
||||
app.interface.update_avatar(contact=contact)
|
||||
else:
|
||||
app.log('avatar').info('Received (vCard): %s %s', jid, avatar_sha)
|
||||
own_jid = self.get_own_jid().getStripped()
|
||||
app.logger.set_avatar_sha(own_jid, jid, avatar_sha)
|
||||
app.contacts.set_avatar(self.name, jid, avatar_sha)
|
||||
app.interface.update_avatar(self.name, jid)
|
||||
|
||||
|
||||
class ConnectionPEP(object):
|
||||
|
||||
|
@ -1296,13 +914,12 @@ class ConnectionHandlersBase:
|
|||
return sess
|
||||
|
||||
class ConnectionHandlers(ConnectionArchive313,
|
||||
ConnectionVcard, ConnectionSocks5Bytestream, ConnectionDisco,
|
||||
ConnectionSocks5Bytestream, ConnectionDisco,
|
||||
ConnectionCommands, ConnectionPubSub, ConnectionPEP, ConnectionCaps,
|
||||
ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream,
|
||||
ConnectionHTTPUpload):
|
||||
def __init__(self):
|
||||
ConnectionArchive313.__init__(self)
|
||||
ConnectionVcard.__init__(self)
|
||||
ConnectionSocks5Bytestream.__init__(self)
|
||||
ConnectionIBBytestream.__init__(self)
|
||||
ConnectionCommands.__init__(self)
|
||||
|
@ -1398,11 +1015,7 @@ ConnectionHTTPUpload):
|
|||
app.ged.remove_event_handler('blocking', ged.CORE, self._nec_blocking)
|
||||
|
||||
def add_sha(self, p, send_caps=True):
|
||||
c = p.setTag('x', namespace=nbxmpp.NS_VCARD_UPDATE)
|
||||
sha = app.config.get_per('accounts', self.name, 'avatar_sha')
|
||||
app.log('avatar').info(
|
||||
'%s: Send avatar presence: %s', self.name, sha or 'empty')
|
||||
c.setTagData('photo', sha)
|
||||
p = self.get_module('VCardAvatars').add_update_node(p)
|
||||
if send_caps:
|
||||
return self._add_caps(p)
|
||||
return p
|
||||
|
@ -1925,7 +1538,7 @@ ConnectionHTTPUpload):
|
|||
show=show))
|
||||
if self.vcard_supported:
|
||||
# ask our VCard
|
||||
self.request_vcard(self._on_own_avatar_received)
|
||||
self.get_module('VCardTemp').request_vcard()
|
||||
|
||||
# Get bookmarks from private namespace
|
||||
self.get_bookmarks()
|
||||
|
|
|
@ -550,16 +550,6 @@ PresenceHelperEvent):
|
|||
tim = helpers.datetime_tuple(time_str)
|
||||
self.idle_time = timegm(tim)
|
||||
|
||||
# Check if presence is from the room itself, used when the room
|
||||
# sends a avatar hash
|
||||
contact = app.contacts.get_groupchat_contact(self.conn.name, self.fjid)
|
||||
if contact:
|
||||
app.nec.push_incoming_event(
|
||||
RoomAvatarReceivedEvent(
|
||||
None, conn=self.conn, stanza=self.stanza,
|
||||
contact=contact, jid=self.jid))
|
||||
return
|
||||
|
||||
xtags = self.stanza.getTags('x')
|
||||
for x in xtags:
|
||||
namespace = x.getNamespace()
|
||||
|
@ -567,9 +557,6 @@ PresenceHelperEvent):
|
|||
self.is_gc = True
|
||||
elif namespace == nbxmpp.NS_SIGNED:
|
||||
sig_tag = x
|
||||
elif namespace == nbxmpp.NS_VCARD_UPDATE:
|
||||
self.avatar_sha = x.getTagData('photo')
|
||||
self.contact_nickname = x.getTagData('nickname')
|
||||
elif namespace == nbxmpp.NS_DELAY and not self.timestamp:
|
||||
# XEP-0091
|
||||
self._generate_timestamp(self.stanza.timestamp)
|
||||
|
@ -1770,14 +1757,6 @@ class ConnectionTypeEvent(nec.NetworkIncomingEvent):
|
|||
name = 'connection-type'
|
||||
base_network_events = []
|
||||
|
||||
class VcardPublishedEvent(nec.NetworkIncomingEvent):
|
||||
name = 'vcard-published'
|
||||
base_network_events = []
|
||||
|
||||
class VcardNotPublishedEvent(nec.NetworkIncomingEvent):
|
||||
name = 'vcard-not-published'
|
||||
base_network_events = []
|
||||
|
||||
class StanzaReceivedEvent(nec.NetworkIncomingEvent):
|
||||
name = 'stanza-received'
|
||||
base_network_events = []
|
||||
|
@ -1967,13 +1946,6 @@ class NonAnonymousServerErrorEvent(nec.NetworkIncomingEvent):
|
|||
name = 'non-anonymous-server-error'
|
||||
base_network_events = []
|
||||
|
||||
class VcardReceivedEvent(nec.NetworkIncomingEvent):
|
||||
name = 'vcard-received'
|
||||
base_network_events = []
|
||||
|
||||
def generate(self):
|
||||
return True
|
||||
|
||||
class UpdateGCAvatarEvent(nec.NetworkIncomingEvent):
|
||||
name = 'update-gc-avatar'
|
||||
base_network_events = []
|
||||
|
@ -1995,19 +1967,6 @@ class UpdateRoomAvatarEvent(nec.NetworkIncomingEvent):
|
|||
def generate(self):
|
||||
return True
|
||||
|
||||
class RoomAvatarReceivedEvent(nec.NetworkIncomingEvent):
|
||||
name = 'room-avatar-received'
|
||||
base_network_events = []
|
||||
|
||||
def generate(self):
|
||||
vcard = self.stanza.getTag('x', namespace=nbxmpp.NS_VCARD_UPDATE)
|
||||
if vcard is None:
|
||||
app.log('avatar').info(
|
||||
'%s has no avatar published (vCard)', self.jid)
|
||||
return
|
||||
self.avatar_sha = vcard.getTagData('photo')
|
||||
return True
|
||||
|
||||
class PEPConfigReceivedEvent(nec.NetworkIncomingEvent):
|
||||
name = 'pep-config-received'
|
||||
base_network_events = []
|
||||
|
|
|
@ -113,6 +113,12 @@ class IdleState(IntEnum):
|
|||
AWAY = 2
|
||||
AWAKE = 3
|
||||
|
||||
@unique
|
||||
class RequestAvatar(IntEnum):
|
||||
SELF = 0
|
||||
ROOM = 1
|
||||
USER = 2
|
||||
|
||||
SSLError = {
|
||||
2: _("Unable to get issuer certificate"),
|
||||
3: _("Unable to get certificate CRL"),
|
||||
|
|
|
@ -1398,15 +1398,7 @@ def get_subscription_request_msg(account=None):
|
|||
s = _('I would like to add you to my contact list.')
|
||||
if account:
|
||||
s = _('Hello, I am $name.') + ' ' + s
|
||||
our_jid = app.get_jid_from_account(account)
|
||||
vcard = app.connections[account].own_vcard
|
||||
name = ''
|
||||
if vcard:
|
||||
if 'N' in vcard:
|
||||
if 'GIVEN' in vcard['N'] and 'FAMILY' in vcard['N']:
|
||||
name = vcard['N']['GIVEN'] + ' ' + vcard['N']['FAMILY']
|
||||
if not name and 'FN' in vcard:
|
||||
name = vcard['FN']
|
||||
name = app.connections[account].get_module('VCardTemp').get_vard_name()
|
||||
nick = app.nicks[account]
|
||||
if name and nick:
|
||||
name += ' (%s)' % nick
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
# This file is part of Gajim.
|
||||
#
|
||||
# Gajim is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published
|
||||
# by the Free Software Foundation; version 3 only.
|
||||
#
|
||||
# Gajim is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# XEP-0153: vCard-Based Avatars
|
||||
|
||||
import os
|
||||
import logging
|
||||
|
||||
import nbxmpp
|
||||
|
||||
from gajim.common import app
|
||||
from gajim.common import helpers
|
||||
from gajim.common import configpaths
|
||||
from gajim.common.const import RequestAvatar
|
||||
|
||||
log = logging.getLogger('gajim.c.m.vcard.avatars')
|
||||
|
||||
|
||||
class VCardAvatars:
|
||||
def __init__(self, con):
|
||||
self._con = con
|
||||
self._account = con.name
|
||||
self._requested_shas = []
|
||||
|
||||
self.handlers = [
|
||||
('presence', self._presence_received, '', nbxmpp.NS_VCARD_UPDATE),
|
||||
]
|
||||
|
||||
self.avatar_advertised = False
|
||||
|
||||
def _presence_received(self, con, stanza):
|
||||
update = stanza.getTag('x', namespace=nbxmpp.NS_VCARD_UPDATE)
|
||||
if update is None:
|
||||
return
|
||||
|
||||
jid = stanza.getFrom()
|
||||
|
||||
avatar_sha = update.getTagData('photo')
|
||||
if avatar_sha is None:
|
||||
log.info('%s is not ready to promote an avatar', jid)
|
||||
# Empty update element, ignore
|
||||
return
|
||||
|
||||
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)
|
||||
return
|
||||
|
||||
# Check if presence is from a MUC service
|
||||
contact = app.contacts.get_groupchat_contact(self._account, str(jid))
|
||||
if contact is not None:
|
||||
self._update_received(jid, avatar_sha)
|
||||
elif stanza.getTag('x', namespace=nbxmpp.NS_MUC_USER):
|
||||
show = stanza.getShow()
|
||||
type_ = stanza.getType()
|
||||
self._gc_update_received(jid, avatar_sha, show, type_)
|
||||
else:
|
||||
self._update_received(jid, avatar_sha)
|
||||
|
||||
def _self_update_received(self, jid, avatar_sha):
|
||||
jid = jid.getStripped()
|
||||
full_jid = jid
|
||||
if avatar_sha == '':
|
||||
# Empty <photo/> tag, means no avatar is advertised
|
||||
log.info('%s has no avatar published', full_jid)
|
||||
return
|
||||
|
||||
log.info('Update: %s %s', jid, avatar_sha)
|
||||
current_sha = app.config.get_per(
|
||||
'accounts', self._account, 'avatar_sha')
|
||||
|
||||
if avatar_sha != current_sha:
|
||||
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)
|
||||
|
||||
def _update_received(self, jid, avatar_sha, room=False):
|
||||
jid = jid.getStripped()
|
||||
full_jid = jid
|
||||
if avatar_sha == '':
|
||||
# Empty <photo/> tag, means no avatar is advertised
|
||||
log.info('%s has no avatar published', full_jid)
|
||||
|
||||
# Remove avatar
|
||||
log.debug('Remove: %s', jid)
|
||||
app.contacts.set_avatar(self._account, jid, None)
|
||||
acc_jid = self._con.get_own_jid().getStripped()
|
||||
if not room:
|
||||
app.logger.set_avatar_sha(acc_jid, jid, None)
|
||||
app.interface.update_avatar(
|
||||
self._account, jid, room_avatar=room)
|
||||
else:
|
||||
log.info('Update: %s %s', full_jid, avatar_sha)
|
||||
current_sha = app.contacts.get_avatar_sha(self._account, jid)
|
||||
|
||||
if avatar_sha == current_sha:
|
||||
log.info('Avatar already known: %s %s', jid, avatar_sha)
|
||||
return
|
||||
|
||||
if room:
|
||||
# We dont save the room avatar hash in our DB, so check
|
||||
# if we previously downloaded it
|
||||
if app.interface.avatar_exists(avatar_sha):
|
||||
app.contacts.set_avatar(self._account, jid, avatar_sha)
|
||||
app.interface.update_avatar(
|
||||
self._account, jid, room_avatar=room)
|
||||
return
|
||||
|
||||
if avatar_sha not in self._requested_shas:
|
||||
self._requested_shas.append(avatar_sha)
|
||||
if room:
|
||||
self._con.get_module('VCardTemp').request_vcard(
|
||||
RequestAvatar.ROOM, jid, sha=avatar_sha)
|
||||
else:
|
||||
self._con.get_module('VCardTemp').request_vcard(
|
||||
RequestAvatar.USER, jid, sha=avatar_sha)
|
||||
|
||||
def _gc_update_received(self, jid, avatar_sha, show, type_):
|
||||
if show == 'offline' or type_ == 'unavailable':
|
||||
return
|
||||
|
||||
nick = jid.getResource()
|
||||
|
||||
gc_contact = app.contacts.get_gc_contact(
|
||||
self._account, jid.getStripped(), nick)
|
||||
|
||||
if gc_contact is None:
|
||||
log.error('no gc contact found: %s', nick)
|
||||
return
|
||||
|
||||
if avatar_sha == '':
|
||||
# Empty <photo/> tag, means no avatar is advertised, remove avatar
|
||||
log.info('%s has no avatar published', nick)
|
||||
log.debug('Remove: %s', nick)
|
||||
gc_contact.avatar_sha = None
|
||||
app.interface.update_avatar(contact=gc_contact)
|
||||
else:
|
||||
log.info('Update: %s %s', nick, avatar_sha)
|
||||
path = os.path.join(configpaths.get('AVATAR'), avatar_sha)
|
||||
if not os.path.isfile(path):
|
||||
if avatar_sha not in self._requested_shas:
|
||||
app.log('avatar').info('Request: %s', nick)
|
||||
self._requested_shas.append(avatar_sha)
|
||||
self._con.get_module('VCardTemp').request_vcard(
|
||||
RequestAvatar.USER, str(jid),
|
||||
room=True, sha=avatar_sha)
|
||||
return
|
||||
|
||||
if gc_contact.avatar_sha != avatar_sha:
|
||||
log.info('%s changed his Avatar: %s', nick, avatar_sha)
|
||||
gc_contact.avatar_sha = avatar_sha
|
||||
app.interface.update_avatar(contact=gc_contact)
|
||||
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
|
||||
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.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)
|
||||
if self._con.get_module('VCardTemp').own_vcard_received:
|
||||
sha = app.config.get_per('accounts', self._account, 'avatar_sha')
|
||||
own_jid = self._con.get_own_jid()
|
||||
log.info('Send avatar presence to: %s %s',
|
||||
node.getTo() or own_jid, sha or 'no sha advertised')
|
||||
update.setTagData('photo', sha)
|
||||
return node
|
|
@ -0,0 +1,308 @@
|
|||
# This file is part of Gajim.
|
||||
#
|
||||
# Gajim is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published
|
||||
# by the Free Software Foundation; version 3 only.
|
||||
#
|
||||
# Gajim is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# XEP-0054: vcard-temp
|
||||
|
||||
import os
|
||||
import hashlib
|
||||
import binascii
|
||||
import base64
|
||||
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
|
||||
|
||||
log = logging.getLogger('gajim.c.m.vcard')
|
||||
|
||||
|
||||
class VCardTemp:
|
||||
def __init__(self, con):
|
||||
self._con = con
|
||||
self._account = con.name
|
||||
|
||||
self.handlers = []
|
||||
|
||||
self._own_vcard = None
|
||||
self.own_vcard_received = False
|
||||
self.room_jids = []
|
||||
|
||||
def _node_to_dict(self, node):
|
||||
dict_ = {}
|
||||
for info in node.getChildren():
|
||||
name = info.getName()
|
||||
if name in ('ADR', 'TEL', 'EMAIL'): # we can have several
|
||||
dict_.setdefault(name, [])
|
||||
entry = {}
|
||||
for c in info.getChildren():
|
||||
entry[c.getName()] = c.getData()
|
||||
dict_[name].append(entry)
|
||||
elif info.getChildren() == []:
|
||||
dict_[name] = info.getData()
|
||||
else:
|
||||
dict_[name] = {}
|
||||
for c in info.getChildren():
|
||||
dict_[name][c.getName()] = c.getData()
|
||||
return dict_
|
||||
|
||||
def request_vcard(self, callback=RequestAvatar.SELF, jid=None,
|
||||
room=False, sha=None):
|
||||
if not app.account_is_connected(self._account):
|
||||
return
|
||||
|
||||
if isinstance(callback, RequestAvatar):
|
||||
if callback == RequestAvatar.SELF:
|
||||
callback = self._on_own_avatar_received
|
||||
elif callback == RequestAvatar.ROOM:
|
||||
callback = self._on_room_avatar_received
|
||||
elif callback == RequestAvatar.USER:
|
||||
callback = self._on_avatar_received
|
||||
|
||||
if room:
|
||||
room_jid = app.get_room_from_fjid(jid)
|
||||
if room_jid not in self.room_jids:
|
||||
self.room_jids.append(room_jid)
|
||||
|
||||
iq = nbxmpp.Iq(typ='get')
|
||||
if jid:
|
||||
iq.setTo(jid)
|
||||
iq.setQuery('vCard').setNamespace(nbxmpp.NS_VCARD)
|
||||
|
||||
own_jid = self._con.get_own_jid().getStripped()
|
||||
log.info('Request: %s, expected sha: %s', jid or own_jid, sha)
|
||||
|
||||
self._con.connection.SendAndCallForResponse(
|
||||
iq, self._parse_vcard, {'callback': callback, 'expected_sha': sha})
|
||||
|
||||
def send_vcard(self, vcard, sha):
|
||||
if not app.account_is_connected(self._account):
|
||||
return
|
||||
|
||||
iq = nbxmpp.Iq(typ='set')
|
||||
iq2 = iq.setTag(nbxmpp.NS_VCARD + ' vCard')
|
||||
for i in vcard:
|
||||
if i == 'jid':
|
||||
continue
|
||||
if isinstance(vcard[i], dict):
|
||||
iq3 = iq2.addChild(i)
|
||||
for j in vcard[i]:
|
||||
iq3.addChild(j).setData(vcard[i][j])
|
||||
elif isinstance(vcard[i], list):
|
||||
for j in vcard[i]:
|
||||
iq3 = iq2.addChild(i)
|
||||
for k in j:
|
||||
iq3.addChild(k).setData(j[k])
|
||||
else:
|
||||
iq2.addChild(i).setData(vcard[i])
|
||||
|
||||
log.info('Upload avatar: %s %s', self._account, sha)
|
||||
|
||||
self._con.connection.SendAndCallForResponse(
|
||||
iq, self._avatar_publish_result, {'sha': sha})
|
||||
|
||||
def upload_room_avatar(self, room_jid, data):
|
||||
iq = nbxmpp.Iq(typ='set', to=room_jid)
|
||||
vcard = iq.addChild('vCard', namespace=nbxmpp.NS_VCARD)
|
||||
photo = vcard.addChild('PHOTO')
|
||||
photo.addChild('TYPE', payload='image/png')
|
||||
photo.addChild('BINVAL', payload=data)
|
||||
|
||||
log.info('Upload avatar: %s %s', room_jid)
|
||||
self._con.connection.SendAndCallForResponse(
|
||||
iq, self._upload_room_avatar_result)
|
||||
|
||||
def _upload_room_avatar_result(self, stanza):
|
||||
if not nbxmpp.isResultNode(stanza):
|
||||
reason = stanza.getErrorMsg() or stanza.getError()
|
||||
app.nec.push_incoming_event(InformationEvent(
|
||||
None, dialog_name='avatar-upload-error', args=reason))
|
||||
|
||||
def _avatar_publish_result(self, con, stanza, sha):
|
||||
if stanza.getType() == 'result':
|
||||
current_sha = app.config.get_per(
|
||||
'accounts', self._account, 'avatar_sha')
|
||||
if (current_sha != sha and not app.is_invisible(self._account)):
|
||||
if not app.account_is_connected(self._account):
|
||||
return
|
||||
app.config.set_per(
|
||||
'accounts', self._account, 'avatar_sha', sha or '')
|
||||
own_jid = self._con.get_own_jid().getStripped()
|
||||
app.contacts.set_avatar(self._account, own_jid, sha)
|
||||
self._con.get_module('VCardAvatars').send_avatar_presence(
|
||||
force=True)
|
||||
log.info('%s: Published: %s', self._account, sha)
|
||||
app.nec.push_incoming_event(
|
||||
VcardPublishedEvent(None, conn=self._con))
|
||||
|
||||
elif stanza.getType() == 'error':
|
||||
app.nec.push_incoming_event(
|
||||
VcardNotPublishedEvent(None, conn=self._con))
|
||||
|
||||
def _get_vcard_photo(self, vcard, jid):
|
||||
try:
|
||||
photo = vcard['PHOTO']['BINVAL']
|
||||
except (KeyError, AttributeError, TypeError):
|
||||
avatar_sha = None
|
||||
photo_decoded = None
|
||||
else:
|
||||
if photo == '':
|
||||
avatar_sha = None
|
||||
photo_decoded = None
|
||||
else:
|
||||
try:
|
||||
photo_decoded = base64.b64decode(photo.encode('utf-8'))
|
||||
except binascii.Error as error:
|
||||
log.warning('Invalid avatar for %s: %s', jid, error)
|
||||
return None, None
|
||||
avatar_sha = hashlib.sha1(photo_decoded).hexdigest()
|
||||
|
||||
return avatar_sha, photo_decoded
|
||||
|
||||
def _parse_vcard(self, con, stanza, callback, expected_sha):
|
||||
frm_jid = stanza.getFrom()
|
||||
room = False
|
||||
if frm_jid is None:
|
||||
frm_jid = self._con.get_own_jid()
|
||||
elif frm_jid.getStripped() in self.room_jids:
|
||||
room = True
|
||||
|
||||
resource = frm_jid.getResource()
|
||||
jid = frm_jid.getStripped()
|
||||
|
||||
stanza_error = stanza.getError()
|
||||
if stanza_error in ('service-unavailable', 'item-not-found',
|
||||
'not-allowed'):
|
||||
log.info('vCard not available: %s %s', frm_jid, stanza_error)
|
||||
callback(jid, resource, room, {}, expected_sha)
|
||||
return
|
||||
|
||||
vcard_node = stanza.getTag('vCard', namespace=nbxmpp.NS_VCARD)
|
||||
if vcard_node is None:
|
||||
log.info('vCard not available: %s', frm_jid)
|
||||
log.debug(stanza)
|
||||
return
|
||||
vcard = self._node_to_dict(vcard_node)
|
||||
|
||||
if self._con.get_own_jid().bareMatch(jid):
|
||||
if 'NICKNAME' in vcard:
|
||||
app.nicks[self._account] = vcard['NICKNAME']
|
||||
elif 'FN' in vcard:
|
||||
app.nicks[self._account] = vcard['FN']
|
||||
|
||||
app.nec.push_incoming_event(
|
||||
VcardReceivedEvent(None, conn=self._con, vcard_dict=vcard))
|
||||
|
||||
callback(jid, resource, room, vcard, expected_sha)
|
||||
|
||||
def _on_own_avatar_received(self, jid, resource, room, vcard, *args):
|
||||
avatar_sha, photo_decoded = self._get_vcard_photo(vcard, jid)
|
||||
|
||||
log.info('Received own vcard, avatar sha is: %s', avatar_sha)
|
||||
|
||||
self._own_vcard = vcard
|
||||
self.own_vcard_received = True
|
||||
if avatar_sha is None:
|
||||
log.info('No avatar found')
|
||||
app.config.set_per('accounts', self._account, 'avatar_sha', '')
|
||||
self._con.get_module('VCardAvatars').send_avatar_presence(force=True)
|
||||
return
|
||||
|
||||
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.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)
|
||||
|
||||
def _on_room_avatar_received(self, jid, resource, room, vcard,
|
||||
expected_sha):
|
||||
avatar_sha, photo_decoded = self._get_vcard_photo(vcard, jid)
|
||||
if expected_sha != avatar_sha:
|
||||
log.warning('Avatar mismatch: %s %s', jid, avatar_sha)
|
||||
return
|
||||
|
||||
app.interface.save_avatar(photo_decoded)
|
||||
|
||||
log.info('Received: %s %s', jid, avatar_sha)
|
||||
app.contacts.set_avatar(self._account, jid, avatar_sha)
|
||||
app.interface.update_avatar(self._account, jid, room_avatar=True)
|
||||
|
||||
def _on_avatar_received(self, jid, resource, room, vcard, expected_sha):
|
||||
request_jid = jid
|
||||
if room:
|
||||
request_jid = '%s/%s' % (jid, resource)
|
||||
|
||||
avatar_sha, photo_decoded = self._get_vcard_photo(vcard, request_jid)
|
||||
if expected_sha != avatar_sha:
|
||||
log.warning('Received: avatar mismatch: %s %s',
|
||||
request_jid, avatar_sha)
|
||||
return
|
||||
|
||||
app.interface.save_avatar(photo_decoded)
|
||||
|
||||
# Received vCard from a contact
|
||||
if room:
|
||||
log.info('Received: %s %s', resource, avatar_sha)
|
||||
contact = app.contacts.get_gc_contact(self._account, jid, resource)
|
||||
if contact is not None:
|
||||
contact.avatar_sha = avatar_sha
|
||||
app.interface.update_avatar(contact=contact)
|
||||
else:
|
||||
log.info('Received: %s %s', jid, avatar_sha)
|
||||
own_jid = self._con.get_own_jid().getStripped()
|
||||
app.logger.set_avatar_sha(own_jid, jid, avatar_sha)
|
||||
app.contacts.set_avatar(self._account, jid, avatar_sha)
|
||||
app.interface.update_avatar(self._account, jid)
|
||||
|
||||
def get_vard_name(self):
|
||||
name = ''
|
||||
vcard = self._own_vcard
|
||||
if not vcard:
|
||||
return name
|
||||
|
||||
if 'N' in vcard:
|
||||
if 'GIVEN' in vcard['N'] and 'FAMILY' in vcard['N']:
|
||||
name = vcard['N']['GIVEN'] + ' ' + vcard['N']['FAMILY']
|
||||
if not name and 'FN' in vcard:
|
||||
name = vcard['FN']
|
||||
return name
|
||||
|
||||
|
||||
class VcardPublishedEvent(NetworkIncomingEvent):
|
||||
name = 'vcard-published'
|
||||
base_network_events = []
|
||||
|
||||
|
||||
class VcardNotPublishedEvent(NetworkIncomingEvent):
|
||||
name = 'vcard-not-published'
|
||||
base_network_events = []
|
||||
|
||||
|
||||
class VcardReceivedEvent(NetworkIncomingEvent):
|
||||
name = 'vcard-received'
|
||||
base_network_events = []
|
|
@ -40,19 +40,13 @@ AGENT_REMOVED = 'agent_removed'
|
|||
|
||||
from gajim.common import connection_handlers
|
||||
|
||||
class ConnectionVcard(connection_handlers.ConnectionVcard):
|
||||
class ConnectionVcard:
|
||||
def add_sha(self, p, *args):
|
||||
return p
|
||||
|
||||
def add_caps(self, p):
|
||||
return p
|
||||
|
||||
def request_vcard(self, *args):
|
||||
pass
|
||||
|
||||
def send_vcard(self, *args):
|
||||
pass
|
||||
|
||||
|
||||
class ConnectionHandlersZeroconf(ConnectionVcard,
|
||||
ConnectionSocks5BytestreamZeroconf, ConnectionCommands,
|
||||
|
|
|
@ -762,8 +762,8 @@ class GroupchatControl(ChatControlBase):
|
|||
|
||||
publish = app.interface.get_avatar(sha, publish=True)
|
||||
avatar = base64.b64encode(publish).decode('utf-8')
|
||||
|
||||
app.connections[self.account].upload_room_avatar(
|
||||
con = app.connections[self.account]
|
||||
con.get_module('VCardTemp').upload_room_avatar(
|
||||
self.room_jid, avatar)
|
||||
|
||||
AvatarChooserDialog(_on_accept,
|
||||
|
|
|
@ -77,7 +77,7 @@ class ProfileWindow:
|
|||
self._nec_vcard_not_published)
|
||||
self.window.show_all()
|
||||
self.xml.get_object('ok_button').grab_focus()
|
||||
app.connections[account].request_vcard(
|
||||
app.connections[account].get_module('VCardTemp').request_vcard(
|
||||
self._nec_vcard_received, self.jid)
|
||||
|
||||
def on_information_notebook_switch_page(self, widget, page, page_num):
|
||||
|
@ -261,7 +261,7 @@ class ProfileWindow:
|
|||
self.progressbar.set_fraction(0)
|
||||
self.update_progressbar_timeout_id = None
|
||||
|
||||
def _nec_vcard_received(self, jid, resource, room, vcard_):
|
||||
def _nec_vcard_received(self, jid, resource, room, vcard_, *args):
|
||||
self.set_values(vcard_)
|
||||
|
||||
def add_to_vcard(self, vcard_, entry, txt):
|
||||
|
@ -339,7 +339,8 @@ class ProfileWindow:
|
|||
app.connections[self.account].retract_nickname()
|
||||
nick = app.config.get_per('accounts', self.account, 'name')
|
||||
app.nicks[self.account] = nick
|
||||
app.connections[self.account].send_vcard(vcard_, sha)
|
||||
app.connections[self.account].get_module('VCardTemp').send_vcard(
|
||||
vcard_, sha)
|
||||
self.message_id = self.statusbar.push(self.context_id,
|
||||
_('Sending profile…'))
|
||||
self.progressbar.show()
|
||||
|
|
|
@ -840,10 +840,12 @@ class SignalObject(dbus.service.Object):
|
|||
if avatar_mime_type:
|
||||
vcard['PHOTO']['TYPE'] = avatar_mime_type
|
||||
if account:
|
||||
app.connections[account].send_vcard(vcard, sha)
|
||||
app.connections[account].get_module('VCardTemp').send_vcard(
|
||||
vcard, sha)
|
||||
else:
|
||||
for acc in app.connections:
|
||||
app.connections[acc].send_vcard(vcard, sha)
|
||||
app.connections[acc].get_module('VCardTemp').send_vcard(
|
||||
vcard, sha)
|
||||
|
||||
@dbus.service.method(INTERFACE, in_signature='ssss', out_signature='')
|
||||
def join_room(self, room_jid, nick, password, account):
|
||||
|
|
|
@ -268,7 +268,7 @@ class VcardWindow:
|
|||
widget.set_text('')
|
||||
self.xml.get_object('DESC_textview').get_buffer().set_text('')
|
||||
|
||||
def _nec_vcard_received(self, jid, resource, room, vcard):
|
||||
def _nec_vcard_received(self, jid, resource, room, vcard, *args):
|
||||
self.clear_values()
|
||||
self._set_values(vcard, jid)
|
||||
|
||||
|
@ -477,10 +477,13 @@ class VcardWindow:
|
|||
self.fill_status_label()
|
||||
|
||||
if self.gc_contact:
|
||||
con.request_vcard(self._nec_vcard_received,
|
||||
self.gc_contact.get_full_jid(), room=True)
|
||||
con.get_module('VCardTemp').request_vcard(
|
||||
self._nec_vcard_received,
|
||||
self.gc_contact.get_full_jid(),
|
||||
room=True)
|
||||
else:
|
||||
con.request_vcard(self._nec_vcard_received, self.contact.jid)
|
||||
con.get_module('VCardTemp').request_vcard(
|
||||
self._nec_vcard_received, self.contact.jid)
|
||||
|
||||
def on_close_button_clicked(self, widget):
|
||||
self.window.destroy()
|
||||
|
|
|
@ -47,9 +47,6 @@ class MockConnection(Mock, ConnectionHandlers):
|
|||
|
||||
app.connections[account] = self
|
||||
|
||||
def request_vcard(self, *args):
|
||||
pass
|
||||
|
||||
class MockWindow(Mock):
|
||||
def __init__(self, *args):
|
||||
Mock.__init__(self, *args)
|
||||
|
|
Loading…
Reference in New Issue