Refactor Presence
- Remove option to hide self contacts for now. This makes the code less complicated. - Move as much code as possible into the presence module - Use nbxmpp properties
This commit is contained in:
parent
608607b721
commit
a289ad5f60
|
@ -268,7 +268,6 @@ class Config:
|
||||||
'check_idle_every_foo_seconds': [opt_int, 2, _('Choose interval between 2 checks of idleness.')],
|
'check_idle_every_foo_seconds': [opt_int, 2, _('Choose interval between 2 checks of idleness.')],
|
||||||
'uri_schemes': [opt_str, 'aaa:// aaas:// acap:// cap:// cid: crid:// data: dav: dict:// dns: fax: file:/ ftp:// geo: go: gopher:// h323: http:// https:// iax: icap:// im: imap:// info: ipp:// iris: iris.beep: iris.xpc: iris.xpcs: iris.lwz: ldap:// mid: modem: msrp:// msrps:// mtqp:// mupdate:// news: nfs:// nntp:// opaquelocktoken: pop:// pres: prospero:// rtsp:// service: shttp:// sip: sips: sms: snmp:// soap.beep:// soap.beeps:// tag: tel: telnet:// tftp:// thismessage:/ tip:// tv: urn:// vemmi:// xmlrpc.beep:// xmlrpc.beeps:// z39.50r:// z39.50s:// about: apt: cvs:// daap:// ed2k:// feed: fish:// git:// iax2: irc:// ircs:// ldaps:// magnet: mms:// rsync:// ssh:// svn:// sftp:// smb:// webcal:// aesgcm://', _('Valid uri schemes. Only schemes in this list will be accepted as "real" uri. (mailto and xmpp are handled separately)'), True],
|
'uri_schemes': [opt_str, 'aaa:// aaas:// acap:// cap:// cid: crid:// data: dav: dict:// dns: fax: file:/ ftp:// geo: go: gopher:// h323: http:// https:// iax: icap:// im: imap:// info: ipp:// iris: iris.beep: iris.xpc: iris.xpcs: iris.lwz: ldap:// mid: modem: msrp:// msrps:// mtqp:// mupdate:// news: nfs:// nntp:// opaquelocktoken: pop:// pres: prospero:// rtsp:// service: shttp:// sip: sips: sms: snmp:// soap.beep:// soap.beeps:// tag: tel: telnet:// tftp:// thismessage:/ tip:// tv: urn:// vemmi:// xmlrpc.beep:// xmlrpc.beeps:// z39.50r:// z39.50s:// about: apt: cvs:// daap:// ed2k:// feed: fish:// git:// iax2: irc:// ircs:// ldaps:// magnet: mms:// rsync:// ssh:// svn:// sftp:// smb:// webcal:// aesgcm://', _('Valid uri schemes. Only schemes in this list will be accepted as "real" uri. (mailto and xmpp are handled separately)'), True],
|
||||||
'shell_like_completion': [opt_bool, False, _('If true, completion in groupchats will be like a shell auto-completion')],
|
'shell_like_completion': [opt_bool, False, _('If true, completion in groupchats will be like a shell auto-completion')],
|
||||||
'show_self_contact': [opt_str, 'when_other_resource', _('When is self contact row displayed. Can be "always", "when_other_resource" or "never"'), True],
|
|
||||||
'audio_input_device': [opt_str, 'autoaudiosrc ! volume name=gajim_vol'],
|
'audio_input_device': [opt_str, 'autoaudiosrc ! volume name=gajim_vol'],
|
||||||
'audio_output_device': [opt_str, 'autoaudiosink'],
|
'audio_output_device': [opt_str, 'autoaudiosink'],
|
||||||
'video_input_device': [opt_str, 'autovideosrc'],
|
'video_input_device': [opt_str, 'autovideosrc'],
|
||||||
|
|
|
@ -67,136 +67,13 @@ class ConnectionHandlersBase:
|
||||||
# We decrypt GPG messages one after the other. Keep queue in mem
|
# We decrypt GPG messages one after the other. Keep queue in mem
|
||||||
self.gpg_messages_to_decrypt = []
|
self.gpg_messages_to_decrypt = []
|
||||||
|
|
||||||
app.ged.register_event_handler('presence-received', ged.CORE,
|
|
||||||
self._nec_presence_received)
|
|
||||||
app.ged.register_event_handler('gc-message-received', ged.CORE,
|
app.ged.register_event_handler('gc-message-received', ged.CORE,
|
||||||
self._nec_gc_message_received)
|
self._nec_gc_message_received)
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
app.ged.remove_event_handler('presence-received', ged.CORE,
|
|
||||||
self._nec_presence_received)
|
|
||||||
app.ged.remove_event_handler('gc-message-received', ged.CORE,
|
app.ged.remove_event_handler('gc-message-received', ged.CORE,
|
||||||
self._nec_gc_message_received)
|
self._nec_gc_message_received)
|
||||||
|
|
||||||
def _nec_presence_received(self, obj):
|
|
||||||
account = obj.conn.name
|
|
||||||
if account != self.name:
|
|
||||||
return
|
|
||||||
jid = obj.jid
|
|
||||||
resource = obj.resource or ''
|
|
||||||
|
|
||||||
statuss = ['offline', 'error', 'online', 'chat', 'away', 'xa', 'dnd',
|
|
||||||
'invisible']
|
|
||||||
obj.old_show = 0
|
|
||||||
obj.new_show = statuss.index(obj.show)
|
|
||||||
|
|
||||||
obj.contact_list = []
|
|
||||||
|
|
||||||
highest = app.contacts.get_contact_with_highest_priority(account, jid)
|
|
||||||
obj.was_highest = (highest and highest.resource == resource)
|
|
||||||
|
|
||||||
# Update contact
|
|
||||||
obj.contact_list = app.contacts.get_contacts(account, jid)
|
|
||||||
obj.contact = None
|
|
||||||
resources = []
|
|
||||||
for c in obj.contact_list:
|
|
||||||
resources.append(c.resource)
|
|
||||||
if c.resource == resource:
|
|
||||||
obj.contact = c
|
|
||||||
break
|
|
||||||
|
|
||||||
if obj.contact:
|
|
||||||
if obj.contact.show in statuss:
|
|
||||||
obj.old_show = statuss.index(obj.contact.show)
|
|
||||||
# nick changed
|
|
||||||
if obj.contact_nickname is not None and \
|
|
||||||
obj.contact.contact_name != obj.contact_nickname:
|
|
||||||
obj.contact.contact_name = obj.contact_nickname
|
|
||||||
obj.need_redraw = True
|
|
||||||
|
|
||||||
elif obj.old_show != obj.new_show or obj.contact.status != \
|
|
||||||
obj.status:
|
|
||||||
obj.need_redraw = True
|
|
||||||
else:
|
|
||||||
obj.contact = app.contacts.get_first_contact_from_jid(account,
|
|
||||||
jid)
|
|
||||||
if not obj.contact:
|
|
||||||
# Presence of another resource of our jid
|
|
||||||
# Create self contact and add to roster
|
|
||||||
if resource == obj.conn.server_resource:
|
|
||||||
return
|
|
||||||
# Ignore offline presence of unknown self resource
|
|
||||||
if obj.new_show < 2:
|
|
||||||
return
|
|
||||||
obj.contact = app.contacts.create_self_contact(jid=jid,
|
|
||||||
account=account, show=obj.show, status=obj.status,
|
|
||||||
priority=obj.prio, keyID=obj.keyID,
|
|
||||||
resource=obj.resource)
|
|
||||||
app.contacts.add_contact(account, obj.contact)
|
|
||||||
obj.contact_list.append(obj.contact)
|
|
||||||
elif obj.contact.show in statuss:
|
|
||||||
obj.old_show = statuss.index(obj.contact.show)
|
|
||||||
if (resources != [''] and (len(obj.contact_list) != 1 or \
|
|
||||||
obj.contact_list[0].show not in ('not in roster', 'offline'))) and \
|
|
||||||
not app.jid_is_transport(jid):
|
|
||||||
# Another resource of an existing contact connected
|
|
||||||
obj.old_show = 0
|
|
||||||
obj.contact = app.contacts.copy_contact(obj.contact)
|
|
||||||
obj.contact_list.append(obj.contact)
|
|
||||||
obj.contact.resource = resource
|
|
||||||
|
|
||||||
obj.need_redraw = True
|
|
||||||
obj.need_add_in_roster = True
|
|
||||||
|
|
||||||
if not app.jid_is_transport(jid) and len(obj.contact_list) == 1:
|
|
||||||
# It's not an agent
|
|
||||||
if obj.old_show == 0 and obj.new_show > 1:
|
|
||||||
if not jid in app.newly_added[account]:
|
|
||||||
app.newly_added[account].append(jid)
|
|
||||||
if jid in app.to_be_removed[account]:
|
|
||||||
app.to_be_removed[account].remove(jid)
|
|
||||||
elif obj.old_show > 1 and obj.new_show == 0 and \
|
|
||||||
obj.conn.connected > 1:
|
|
||||||
if not jid in app.to_be_removed[account]:
|
|
||||||
app.to_be_removed[account].append(jid)
|
|
||||||
if jid in app.newly_added[account]:
|
|
||||||
app.newly_added[account].remove(jid)
|
|
||||||
obj.need_redraw = True
|
|
||||||
|
|
||||||
obj.contact.show = obj.show
|
|
||||||
obj.contact.status = obj.status
|
|
||||||
obj.contact.priority = obj.prio
|
|
||||||
attached_keys = app.config.get_per('accounts', account,
|
|
||||||
'attached_gpg_keys').split()
|
|
||||||
if jid in attached_keys:
|
|
||||||
obj.contact.keyID = attached_keys[attached_keys.index(jid) + 1]
|
|
||||||
else:
|
|
||||||
# Do not override assigned key
|
|
||||||
obj.contact.keyID = obj.keyID
|
|
||||||
obj.contact.contact_nickname = obj.contact_nickname
|
|
||||||
obj.contact.idle_time = obj.idle_time
|
|
||||||
|
|
||||||
if app.jid_is_transport(jid):
|
|
||||||
return
|
|
||||||
|
|
||||||
# It isn't an agent
|
|
||||||
# (when contact signs out or has errors)
|
|
||||||
if obj.show in ('offline', 'error'):
|
|
||||||
# TODO: This causes problems when another
|
|
||||||
# resource signs off!
|
|
||||||
self.stop_all_active_file_transfers(obj.contact)
|
|
||||||
|
|
||||||
if app.config.get('log_contact_status_changes') and \
|
|
||||||
app.config.should_log(self.name, obj.jid):
|
|
||||||
show = app.logger.convert_show_values_to_db_api_values(obj.show)
|
|
||||||
if show is not None:
|
|
||||||
app.logger.insert_into_logs(self.name,
|
|
||||||
nbxmpp.JID(obj.jid).getStripped(),
|
|
||||||
time.time(),
|
|
||||||
KindConstant.STATUS,
|
|
||||||
message=obj.status,
|
|
||||||
show=show)
|
|
||||||
|
|
||||||
def _check_for_mam_compliance(self, room_jid, stanza_id):
|
def _check_for_mam_compliance(self, room_jid, stanza_id):
|
||||||
namespace = muc_caps_cache.get_mam_namespace(room_jid)
|
namespace = muc_caps_cache.get_mam_namespace(room_jid)
|
||||||
if stanza_id is None and namespace == nbxmpp.NS_MAM_2:
|
if stanza_id is None and namespace == nbxmpp.NS_MAM_2:
|
||||||
|
|
|
@ -144,105 +144,8 @@ class StreamConflictReceivedEvent(nec.NetworkIncomingEvent):
|
||||||
self.conn = self.base_event.conn
|
self.conn = self.base_event.conn
|
||||||
return True
|
return True
|
||||||
|
|
||||||
class PresenceHelperEvent:
|
class PresenceReceivedEvent(nec.NetworkIncomingEvent):
|
||||||
def _generate_show(self):
|
|
||||||
self.show = self.stanza.getShow()
|
|
||||||
if self.show not in ('chat', 'away', 'xa', 'dnd'):
|
|
||||||
self.show = '' # We ignore unknown show
|
|
||||||
if not self.ptype and not self.show:
|
|
||||||
self.show = 'online'
|
|
||||||
elif self.ptype == 'unavailable':
|
|
||||||
self.show = 'offline'
|
|
||||||
|
|
||||||
def _generate_ptype(self):
|
|
||||||
self.ptype = self.stanza.getType()
|
|
||||||
if self.ptype == 'available':
|
|
||||||
self.ptype = None
|
|
||||||
rfc_types = ('unavailable', 'error', 'subscribe', 'subscribed',
|
|
||||||
'unsubscribe', 'unsubscribed')
|
|
||||||
if self.ptype and not self.ptype in rfc_types:
|
|
||||||
self.ptype = None
|
|
||||||
|
|
||||||
class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent,
|
|
||||||
PresenceHelperEvent):
|
|
||||||
name = 'presence-received'
|
name = 'presence-received'
|
||||||
base_network_events = ['raw-pres-received']
|
|
||||||
|
|
||||||
def _generate_keyID(self, sig_tag):
|
|
||||||
self.keyID = ''
|
|
||||||
if sig_tag and self.conn.USE_GPG and self.ptype != 'error':
|
|
||||||
# error presences contain our own signature
|
|
||||||
# verify
|
|
||||||
sig_msg = sig_tag.getData()
|
|
||||||
self.keyID = self.conn.gpg.verify(self.status, sig_msg)
|
|
||||||
self.keyID = helpers.prepare_and_validate_gpg_keyID(self.conn.name,
|
|
||||||
self.jid,
|
|
||||||
self.keyID)
|
|
||||||
|
|
||||||
def _generate_prio(self):
|
|
||||||
self.prio = self.stanza.getPriority()
|
|
||||||
try:
|
|
||||||
self.prio = int(self.prio)
|
|
||||||
except Exception:
|
|
||||||
self.prio = 0
|
|
||||||
|
|
||||||
def generate(self):
|
|
||||||
self.conn = self.base_event.conn
|
|
||||||
self.stanza = self.base_event.stanza
|
|
||||||
|
|
||||||
self.need_add_in_roster = False
|
|
||||||
self.need_redraw = False
|
|
||||||
|
|
||||||
self.popup = False # Do we want to open chat window ?
|
|
||||||
|
|
||||||
if not self.conn or self.conn.connected < 2:
|
|
||||||
log.debug('account is no more connected')
|
|
||||||
return
|
|
||||||
|
|
||||||
self._generate_ptype()
|
|
||||||
try:
|
|
||||||
self.get_jid_resource()
|
|
||||||
except Exception:
|
|
||||||
log.warning('Invalid JID: %s, ignoring it', self.stanza.getFrom())
|
|
||||||
return
|
|
||||||
jid_list = app.contacts.get_jid_list(self.conn.name)
|
|
||||||
self.timestamp = None
|
|
||||||
self.get_id()
|
|
||||||
self.avatar_sha = None
|
|
||||||
# XEP-0172 User Nickname
|
|
||||||
self.user_nick = self.stanza.getTagData('nick') or ''
|
|
||||||
self.contact_nickname = None
|
|
||||||
self.transport_auto_auth = False
|
|
||||||
|
|
||||||
# XEP-0203
|
|
||||||
self.timestamp = parse_delay(self.stanza)
|
|
||||||
if self.timestamp is None:
|
|
||||||
self.timestamp = time_time()
|
|
||||||
|
|
||||||
# XEP-0319
|
|
||||||
self.idle_time = parse_idle(self.stanza)
|
|
||||||
|
|
||||||
sig_tag = self.stanza.getTag('x', namespace=nbxmpp.NS_SIGNED)
|
|
||||||
|
|
||||||
self.status = self.stanza.getStatus() or ''
|
|
||||||
self._generate_show()
|
|
||||||
self._generate_prio()
|
|
||||||
self._generate_keyID(sig_tag)
|
|
||||||
|
|
||||||
self.errcode = self.stanza.getErrorCode()
|
|
||||||
self.errmsg = self.stanza.getErrorMsg()
|
|
||||||
|
|
||||||
if self.ptype == 'error':
|
|
||||||
return
|
|
||||||
|
|
||||||
if not self.ptype or self.ptype == 'unavailable':
|
|
||||||
our_jid = app.get_jid_from_account(self.conn.name)
|
|
||||||
if self.jid == our_jid and self.resource == self.conn.server_resource:
|
|
||||||
# We got our own presence
|
|
||||||
app.nec.push_incoming_event(OurShowEvent(None, conn=self.conn,
|
|
||||||
show=self.show))
|
|
||||||
elif self.jid in jid_list or self.jid == our_jid:
|
|
||||||
return True
|
|
||||||
|
|
||||||
class ZeroconfPresenceReceivedEvent(nec.NetworkIncomingEvent):
|
class ZeroconfPresenceReceivedEvent(nec.NetworkIncomingEvent):
|
||||||
name = 'presence-received'
|
name = 'presence-received'
|
||||||
|
@ -254,16 +157,13 @@ class ZeroconfPresenceReceivedEvent(nec.NetworkIncomingEvent):
|
||||||
self.keyID = None
|
self.keyID = None
|
||||||
self.idle_time = None
|
self.idle_time = None
|
||||||
self.timestamp = 0
|
self.timestamp = 0
|
||||||
self.contact_nickname = None
|
|
||||||
self.avatar_sha = None
|
self.avatar_sha = None
|
||||||
self.need_add_in_roster = False
|
self.need_add_in_roster = False
|
||||||
self.need_redraw = False
|
|
||||||
if self.show == 'offline':
|
if self.show == 'offline':
|
||||||
self.ptype = 'unavailable'
|
self.ptype = 'unavailable'
|
||||||
else:
|
else:
|
||||||
self.ptype = None
|
self.ptype = None
|
||||||
self.user_nick = ''
|
self.user_nick = ''
|
||||||
self.transport_auto_auth = False
|
|
||||||
self.errcode = None
|
self.errcode = None
|
||||||
self.errmsg = ''
|
self.errmsg = ''
|
||||||
self.popup = False # Do we want to open chat window ?
|
self.popup = False # Do we want to open chat window ?
|
||||||
|
|
|
@ -368,6 +368,9 @@ class LegacyContactsAPI:
|
||||||
def get_contact(self, account, jid, resource=None):
|
def get_contact(self, account, jid, resource=None):
|
||||||
return self._accounts[account].contacts.get_contact(jid, resource=resource)
|
return self._accounts[account].contacts.get_contact(jid, resource=resource)
|
||||||
|
|
||||||
|
def get_contact_strict(self, account, jid, resource):
|
||||||
|
return self._accounts[account].contacts.get_contact_strict(jid, resource)
|
||||||
|
|
||||||
def get_avatar(self, account, *args, **kwargs):
|
def get_avatar(self, account, *args, **kwargs):
|
||||||
return self._accounts[account].contacts.get_avatar(*args, **kwargs)
|
return self._accounts[account].contacts.get_avatar(*args, **kwargs)
|
||||||
|
|
||||||
|
@ -553,7 +556,7 @@ class Contacts():
|
||||||
"""
|
"""
|
||||||
Return the list of contact instances for this jid
|
Return the list of contact instances for this jid
|
||||||
"""
|
"""
|
||||||
return self._contacts.get(jid, [])
|
return list(self._contacts.get(jid, []))
|
||||||
|
|
||||||
def get_contact(self, jid, resource=None):
|
def get_contact(self, jid, resource=None):
|
||||||
### WARNING ###
|
### WARNING ###
|
||||||
|
|
|
@ -15,13 +15,17 @@
|
||||||
# Presence handler
|
# Presence handler
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import time
|
||||||
|
|
||||||
import nbxmpp
|
import nbxmpp
|
||||||
|
from nbxmpp.structs import StanzaHandler
|
||||||
|
from nbxmpp.const import PresenceType
|
||||||
|
|
||||||
from gajim.common import app
|
from gajim.common import app
|
||||||
from gajim.common.i18n import _
|
from gajim.common.i18n import _
|
||||||
from gajim.common.nec import NetworkEvent
|
from gajim.common.nec import NetworkEvent
|
||||||
from gajim.common.modules.user_nickname import parse_nickname
|
from gajim.common.const import KindConstant
|
||||||
|
from gajim.common.helpers import prepare_and_validate_gpg_keyID
|
||||||
|
|
||||||
log = logging.getLogger('gajim.c.m.presence')
|
log = logging.getLogger('gajim.c.m.presence')
|
||||||
|
|
||||||
|
@ -32,11 +36,25 @@ class Presence:
|
||||||
self._account = con.name
|
self._account = con.name
|
||||||
|
|
||||||
self.handlers = [
|
self.handlers = [
|
||||||
('presence', self._presence_received),
|
StanzaHandler(name='presence',
|
||||||
('presence', self._subscribe_received, 'subscribe'),
|
callback=self._presence_received,
|
||||||
('presence', self._subscribed_received, 'subscribed'),
|
priority=50),
|
||||||
('presence', self._unsubscribe_received, 'unsubscribe'),
|
StanzaHandler(name='presence',
|
||||||
('presence', self._unsubscribed_received, 'unsubscribed'),
|
callback=self._subscribe_received,
|
||||||
|
typ='subscribe',
|
||||||
|
priority=49),
|
||||||
|
StanzaHandler(name='presence',
|
||||||
|
callback=self._subscribed_received,
|
||||||
|
typ='subscribed',
|
||||||
|
priority=49),
|
||||||
|
StanzaHandler(name='presence',
|
||||||
|
callback=self._unsubscribe_received,
|
||||||
|
typ='unsubscribe',
|
||||||
|
priority=49),
|
||||||
|
StanzaHandler(name='presence',
|
||||||
|
callback=self._unsubscribed_received,
|
||||||
|
typ='unsubscribed',
|
||||||
|
priority=49),
|
||||||
]
|
]
|
||||||
|
|
||||||
# keep the jids we auto added (transports contacts) to not send the
|
# keep the jids we auto added (transports contacts) to not send the
|
||||||
|
@ -46,32 +64,198 @@ class Presence:
|
||||||
# list of jid to auto-authorize
|
# list of jid to auto-authorize
|
||||||
self.jids_for_auto_auth = []
|
self.jids_for_auto_auth = []
|
||||||
|
|
||||||
def _presence_received(self, _con, stanza):
|
def _presence_received(self, _con, stanza, properties):
|
||||||
if stanza.getType() in ('subscribe', 'subscribed',
|
log.info('Received from %s', properties.jid)
|
||||||
'unsubscribe', 'unsubscribed'):
|
|
||||||
# Dont handle that here
|
|
||||||
return
|
|
||||||
|
|
||||||
log.info('Received from %s', stanza.getFrom())
|
if properties.type == PresenceType.ERROR:
|
||||||
if nbxmpp.isErrorNode(stanza):
|
log.info('Error: %s %s', properties.jid, properties.error)
|
||||||
log.info('Error:\n%s', stanza)
|
raise nbxmpp.NodeProcessed
|
||||||
|
|
||||||
|
if self._account == 'Local':
|
||||||
app.nec.push_incoming_event(
|
app.nec.push_incoming_event(
|
||||||
NetworkEvent('raw-pres-received',
|
NetworkEvent('raw-pres-received',
|
||||||
conn=self._con,
|
conn=self._con,
|
||||||
stanza=stanza))
|
stanza=stanza))
|
||||||
|
raise nbxmpp.NodeProcessed
|
||||||
|
|
||||||
|
if properties.is_self_presence:
|
||||||
|
app.nec.push_incoming_event(
|
||||||
|
NetworkEvent('our-show',
|
||||||
|
conn=self._con,
|
||||||
|
show=properties.show.value))
|
||||||
|
raise nbxmpp.NodeProcessed
|
||||||
|
|
||||||
|
contacts = app.contacts.get_jid_list(self._account)
|
||||||
|
if properties.jid.getBare() not in contacts and not properties.is_self_bare:
|
||||||
|
# Handle only presence from roster contacts
|
||||||
|
log.warning('Unkown presence received')
|
||||||
|
log.warning(stanza)
|
||||||
|
return
|
||||||
|
|
||||||
|
key_id = ''
|
||||||
|
if properties.signed is not None and self._con.USE_GPG:
|
||||||
|
key_id = self._con.gpg.verify(properties.status, properties.signed)
|
||||||
|
key_id = prepare_and_validate_gpg_keyID(
|
||||||
|
self._account, properties.jid.getBare(), key_id)
|
||||||
|
|
||||||
|
show = properties.show.value
|
||||||
|
if properties.type.is_unavailable:
|
||||||
|
show = 'offline'
|
||||||
|
|
||||||
|
event_attrs = {
|
||||||
|
'conn': self._con,
|
||||||
|
'stanza': stanza,
|
||||||
|
'keyID': key_id,
|
||||||
|
'prio': properties.priority,
|
||||||
|
'need_add_in_roster': False,
|
||||||
|
'popup': False,
|
||||||
|
'ptype': properties.type.value,
|
||||||
|
'jid': properties.jid.getBare(),
|
||||||
|
'resource': properties.jid.getResource(),
|
||||||
|
'id_': properties.id,
|
||||||
|
'fjid': str(properties.jid),
|
||||||
|
'timestamp': properties.timestamp,
|
||||||
|
'avatar_sha': properties.avatar_sha,
|
||||||
|
'user_nick': properties.nickname,
|
||||||
|
'idle_time': properties.idle_timestamp,
|
||||||
|
'show': show,
|
||||||
|
'new_show': show,
|
||||||
|
'old_show': 0,
|
||||||
|
'status': properties.status,
|
||||||
|
'contact_list': [],
|
||||||
|
'contact': None,
|
||||||
|
'need_add_in_roster': False,
|
||||||
|
}
|
||||||
|
|
||||||
|
event_ = NetworkEvent('presence-received', **event_attrs)
|
||||||
|
|
||||||
|
# TODO: Refactor
|
||||||
|
self._update_contact(event_, properties)
|
||||||
|
|
||||||
|
app.nec.push_incoming_event(event_)
|
||||||
|
|
||||||
|
raise nbxmpp.NodeProcessed
|
||||||
|
|
||||||
|
def _update_contact(self, event, properties):
|
||||||
|
jid = properties.jid.getBare()
|
||||||
|
resource = properties.jid.getResource()
|
||||||
|
|
||||||
|
status_strings = ['offline', 'error', 'online', 'chat', 'away',
|
||||||
|
'xa', 'dnd', 'invisible']
|
||||||
|
|
||||||
|
event.new_show = status_strings.index(event.show)
|
||||||
|
|
||||||
|
# Update contact
|
||||||
|
contact_list = app.contacts.get_contacts(self._account, jid)
|
||||||
|
if not contact_list:
|
||||||
|
log.warning('No contact found')
|
||||||
|
return
|
||||||
|
|
||||||
|
event.contact_list = contact_list
|
||||||
|
|
||||||
|
contact = app.contacts.get_contact_strict(self._account,
|
||||||
|
properties.jid.getBare(),
|
||||||
|
properties.jid.getResource())
|
||||||
|
if contact is None:
|
||||||
|
contact = app.contacts.get_first_contact_from_jid(self._account, jid)
|
||||||
|
if contact is None:
|
||||||
|
log.warning('First contact not found')
|
||||||
|
return
|
||||||
|
|
||||||
|
if self._is_resource_known(contact_list) and not app.jid_is_transport(jid):
|
||||||
|
# Another resource of an existing contact connected
|
||||||
|
# Add new contact
|
||||||
|
event.old_show = 0
|
||||||
|
contact = app.contacts.copy_contact(contact)
|
||||||
|
contact.resource = resource
|
||||||
|
app.contacts.add_contact(self._account, contact)
|
||||||
|
else:
|
||||||
|
# Convert the inital roster contact to a contact with resource
|
||||||
|
contact.resource = resource
|
||||||
|
event.old_show = status_strings.index(contact.show)
|
||||||
|
|
||||||
|
event.need_add_in_roster = True
|
||||||
|
|
||||||
|
elif contact.show in status_strings:
|
||||||
|
event.old_show = status_strings.index(contact.show)
|
||||||
|
|
||||||
|
# Update contact with presence data
|
||||||
|
contact.show = event.show
|
||||||
|
contact.status = properties.status
|
||||||
|
contact.priority = properties.priority
|
||||||
|
attached_keys = app.config.get_per('accounts', self._account,
|
||||||
|
'attached_gpg_keys').split()
|
||||||
|
if jid in attached_keys:
|
||||||
|
contact.keyID = attached_keys[attached_keys.index(jid) + 1]
|
||||||
|
else:
|
||||||
|
# Do not override assigned key
|
||||||
|
contact.keyID = event.keyID
|
||||||
|
contact.idle_time = properties.idle_timestamp
|
||||||
|
|
||||||
|
event.contact = contact
|
||||||
|
|
||||||
|
if not app.jid_is_transport(jid) and len(contact_list) == 1:
|
||||||
|
# It's not an agent
|
||||||
|
if event.old_show == 0 and event.new_show > 1:
|
||||||
|
if not jid in app.newly_added[self._account]:
|
||||||
|
app.newly_added[self._account].append(jid)
|
||||||
|
if jid in app.to_be_removed[self._account]:
|
||||||
|
app.to_be_removed[self._account].remove(jid)
|
||||||
|
elif event.old_show > 1 and event.new_show == 0 and \
|
||||||
|
self._con.connected > 1:
|
||||||
|
if not jid in app.to_be_removed[self._account]:
|
||||||
|
app.to_be_removed[self._account].append(jid)
|
||||||
|
if jid in app.newly_added[self._account]:
|
||||||
|
app.newly_added[self._account].remove(jid)
|
||||||
|
|
||||||
|
if app.jid_is_transport(jid):
|
||||||
|
return
|
||||||
|
|
||||||
|
if properties.type.is_unavailable:
|
||||||
|
# TODO: This causes problems when another
|
||||||
|
# resource signs off!
|
||||||
|
self._con.stop_all_active_file_transfers(contact)
|
||||||
|
self._log_presence(properties)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _is_resource_known(contact_list):
|
||||||
|
if len(contact_list) > 1:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if contact_list[0].resource == '':
|
||||||
|
return False
|
||||||
|
return contact_list[0].show not in ('not in roster', 'offline')
|
||||||
|
|
||||||
|
def _log_presence(self, properties):
|
||||||
|
if not app.config.get('log_contact_status_changes'):
|
||||||
|
return
|
||||||
|
if not app.config.should_log(self._account, properties.jid.getBare()):
|
||||||
|
return
|
||||||
|
|
||||||
|
# TODO: Refactor
|
||||||
|
if properties.type.is_unavailable:
|
||||||
|
show = 'offline'
|
||||||
|
else:
|
||||||
|
show = properties.show.value
|
||||||
|
|
||||||
|
app.logger.insert_into_logs(self._account,
|
||||||
|
properties.jid.getBare(),
|
||||||
|
time.time(),
|
||||||
|
KindConstant.STATUS,
|
||||||
|
message=properties.status,
|
||||||
|
show=show)
|
||||||
|
|
||||||
|
def _subscribe_received(self, _con, _stanza, properties):
|
||||||
|
jid = properties.jid.getBare()
|
||||||
|
fjid = str(properties.jid)
|
||||||
|
|
||||||
def _subscribe_received(self, _con, stanza):
|
|
||||||
from_ = stanza.getFrom()
|
|
||||||
jid = from_.getStripped()
|
|
||||||
fjid = str(from_)
|
|
||||||
status = stanza.getStatus()
|
|
||||||
is_transport = app.jid_is_transport(fjid)
|
is_transport = app.jid_is_transport(fjid)
|
||||||
auto_auth = app.config.get_per('accounts', self._account, 'autoauth')
|
auto_auth = app.config.get_per('accounts', self._account, 'autoauth')
|
||||||
user_nick = parse_nickname(stanza)
|
|
||||||
|
|
||||||
log.info('Received Subscribe: %s, transport: %s, auto_auth: %s, '
|
log.info('Received Subscribe: %s, transport: %s, '
|
||||||
'user_nick: %s', from_, is_transport, auto_auth, user_nick)
|
'auto_auth: %s, user_nick: %s',
|
||||||
|
properties.jid, is_transport, auto_auth, properties.nickname)
|
||||||
|
|
||||||
if is_transport and fjid in self._con.agent_registrations:
|
if is_transport and fjid in self._con.agent_registrations:
|
||||||
self._con.agent_registrations[fjid]['sub_received'] = True
|
self._con.agent_registrations[fjid]['sub_received'] = True
|
||||||
if not self._con.agent_registrations[fjid]['roster_push']:
|
if not self._con.agent_registrations[fjid]['roster_push']:
|
||||||
|
@ -81,8 +265,8 @@ class Presence:
|
||||||
if auto_auth or is_transport or jid in self.jids_for_auto_auth:
|
if auto_auth or is_transport or jid in self.jids_for_auto_auth:
|
||||||
self.send_presence(fjid, 'subscribed')
|
self.send_presence(fjid, 'subscribed')
|
||||||
|
|
||||||
if not status:
|
status = (properties.status or
|
||||||
status = _('I would like to add you to my roster.')
|
_('I would like to add you to my roster.'))
|
||||||
|
|
||||||
app.nec.push_incoming_event(NetworkEvent(
|
app.nec.push_incoming_event(NetworkEvent(
|
||||||
'subscribe-presence-received',
|
'subscribe-presence-received',
|
||||||
|
@ -90,16 +274,15 @@ class Presence:
|
||||||
jid=jid,
|
jid=jid,
|
||||||
fjid=fjid,
|
fjid=fjid,
|
||||||
status=status,
|
status=status,
|
||||||
user_nick=user_nick,
|
user_nick=properties.nickname,
|
||||||
is_transport=is_transport))
|
is_transport=is_transport))
|
||||||
|
|
||||||
raise nbxmpp.NodeProcessed
|
raise nbxmpp.NodeProcessed
|
||||||
|
|
||||||
def _subscribed_received(self, _con, stanza):
|
def _subscribed_received(self, _con, _stanza, properties):
|
||||||
from_ = stanza.getFrom()
|
jid = properties.jid.getBare()
|
||||||
jid = from_.getStripped()
|
resource = properties.jid.getResource()
|
||||||
resource = from_.getResource()
|
log.info('Received Subscribed: %s', properties.jid)
|
||||||
log.info('Received Subscribed: %s', from_)
|
|
||||||
if jid in self.automatically_added:
|
if jid in self.automatically_added:
|
||||||
self.automatically_added.remove(jid)
|
self.automatically_added.remove(jid)
|
||||||
raise nbxmpp.NodeProcessed
|
raise nbxmpp.NodeProcessed
|
||||||
|
@ -110,17 +293,15 @@ class Presence:
|
||||||
raise nbxmpp.NodeProcessed
|
raise nbxmpp.NodeProcessed
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _unsubscribe_received(_con, stanza):
|
def _unsubscribe_received(_con, _stanza, properties):
|
||||||
log.info('Received Unsubscribe: %s', stanza.getFrom())
|
log.info('Received Unsubscribe: %s', properties.jid)
|
||||||
raise nbxmpp.NodeProcessed
|
raise nbxmpp.NodeProcessed
|
||||||
|
|
||||||
def _unsubscribed_received(self, _con, stanza):
|
def _unsubscribed_received(self, _con, _stanza, properties):
|
||||||
from_ = stanza.getFrom()
|
log.info('Received Unsubscribed: %s', properties.jid)
|
||||||
jid = from_.getStripped()
|
|
||||||
log.info('Received Unsubscribed: %s', from_)
|
|
||||||
app.nec.push_incoming_event(NetworkEvent(
|
app.nec.push_incoming_event(NetworkEvent(
|
||||||
'unsubscribed-presence-received',
|
'unsubscribed-presence-received',
|
||||||
conn=self._con, jid=jid))
|
conn=self._con, jid=properties.jid.getBare()))
|
||||||
raise nbxmpp.NodeProcessed
|
raise nbxmpp.NodeProcessed
|
||||||
|
|
||||||
def subscribed(self, jid):
|
def subscribed(self, jid):
|
||||||
|
|
|
@ -152,7 +152,7 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
|
||||||
def _on_remove_service(self, jid):
|
def _on_remove_service(self, jid):
|
||||||
self.roster.delItem(jid)
|
self.roster.delItem(jid)
|
||||||
# 'NOTIFY' (account, (jid, status, status message, resource, priority,
|
# 'NOTIFY' (account, (jid, status, status message, resource, priority,
|
||||||
# keyID, timestamp, contact_nickname))
|
# keyID, timestamp))
|
||||||
app.nec.push_incoming_event(ZeroconfPresenceReceivedEvent(
|
app.nec.push_incoming_event(ZeroconfPresenceReceivedEvent(
|
||||||
None, conn=self, fjid=jid, show='offline', status=''))
|
None, conn=self, fjid=jid, show='offline', status=''))
|
||||||
|
|
||||||
|
|
|
@ -331,7 +331,7 @@ class Interface:
|
||||||
|
|
||||||
def handle_event_presence(self, obj):
|
def handle_event_presence(self, obj):
|
||||||
# 'NOTIFY' (account, (jid, status, status message, resource,
|
# 'NOTIFY' (account, (jid, status, status message, resource,
|
||||||
# priority, # keyID, timestamp, contact_nickname))
|
# priority, # keyID, timestamp))
|
||||||
#
|
#
|
||||||
# Contact changed show
|
# Contact changed show
|
||||||
account = obj.conn.name
|
account = obj.conn.name
|
||||||
|
|
|
@ -366,8 +366,7 @@ class GajimRemote(Server):
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
self.raise_signal(event, (obj.conn.name, [obj.jid, obj.show,
|
self.raise_signal(event, (obj.conn.name, [obj.jid, obj.show,
|
||||||
obj.status, obj.resource, obj.prio, obj.keyID, obj.timestamp,
|
obj.status, obj.resource, obj.prio, obj.keyID, obj.timestamp]))
|
||||||
obj.contact_nickname]))
|
|
||||||
|
|
||||||
def on_subscribe_presence_received(self, obj):
|
def on_subscribe_presence_received(self, obj):
|
||||||
self.raise_signal('Subscribe', (obj.conn.name, [obj.jid, obj.status,
|
self.raise_signal('Subscribe', (obj.conn.name, [obj.jid, obj.status,
|
||||||
|
|
|
@ -720,14 +720,7 @@ class RosterWindow:
|
||||||
return
|
return
|
||||||
|
|
||||||
if jid == app.get_jid_from_account(account):
|
if jid == app.get_jid_from_account(account):
|
||||||
show_self_contact = app.config.get('show_self_contact')
|
|
||||||
if show_self_contact == 'never':
|
|
||||||
return
|
|
||||||
if (contact.resource != app.connections[account].server_resource \
|
|
||||||
and show_self_contact == 'when_other_resource') or \
|
|
||||||
show_self_contact == 'always':
|
|
||||||
return self._add_self_contact(account)
|
return self._add_self_contact(account)
|
||||||
return
|
|
||||||
|
|
||||||
is_observer = contact.is_observer()
|
is_observer = contact.is_observer()
|
||||||
if is_observer:
|
if is_observer:
|
||||||
|
@ -1871,7 +1864,7 @@ class RosterWindow:
|
||||||
'contacts': {}}
|
'contacts': {}}
|
||||||
if account not in app.groups:
|
if account not in app.groups:
|
||||||
app.groups[account] = {}
|
app.groups[account] = {}
|
||||||
if app.config.get('show_self_contact') == 'always':
|
|
||||||
self_jid = app.get_jid_from_account(account)
|
self_jid = app.get_jid_from_account(account)
|
||||||
if app.connections[account].server_resource:
|
if app.connections[account].server_resource:
|
||||||
self_jid += '/' + app.connections[account].server_resource
|
self_jid += '/' + app.connections[account].server_resource
|
||||||
|
@ -2212,9 +2205,6 @@ class RosterWindow:
|
||||||
|
|
||||||
elif contact.jid == app.get_jid_from_account(account) and \
|
elif contact.jid == app.get_jid_from_account(account) and \
|
||||||
show in ('offline', 'error'):
|
show in ('offline', 'error'):
|
||||||
if app.config.get('show_self_contact') != 'never':
|
|
||||||
# SelfContact went offline. Remove him when last pending
|
|
||||||
# message was read
|
|
||||||
self.remove_contact(contact.jid, account, backend=True)
|
self.remove_contact(contact.jid, account, backend=True)
|
||||||
|
|
||||||
uf_show = helpers.get_uf_show(show)
|
uf_show = helpers.get_uf_show(show)
|
||||||
|
@ -2249,7 +2239,6 @@ class RosterWindow:
|
||||||
if account not in app.contacts.get_accounts():
|
if account not in app.contacts.get_accounts():
|
||||||
return
|
return
|
||||||
child_iterA = self._get_account_iter(account, self.model)
|
child_iterA = self._get_account_iter(account, self.model)
|
||||||
if app.config.get('show_self_contact') == 'always':
|
|
||||||
self_resource = app.connections[account].server_resource
|
self_resource = app.connections[account].server_resource
|
||||||
self_contact = app.contacts.get_contact(account,
|
self_contact = app.contacts.get_contact(account,
|
||||||
app.get_jid_from_account(account), resource=self_resource)
|
app.get_jid_from_account(account), resource=self_resource)
|
||||||
|
@ -2570,7 +2559,6 @@ class RosterWindow:
|
||||||
GLib.timeout_add_seconds(5, self.remove_to_be_removed,
|
GLib.timeout_add_seconds(5, self.remove_to_be_removed,
|
||||||
jid, account)
|
jid, account)
|
||||||
|
|
||||||
if obj.need_redraw:
|
|
||||||
self.draw_contact(jid, account)
|
self.draw_contact(jid, account)
|
||||||
|
|
||||||
if app.jid_is_transport(jid) and jid in jid_list:
|
if app.jid_is_transport(jid) and jid in jid_list:
|
||||||
|
@ -2579,7 +2567,7 @@ class RosterWindow:
|
||||||
self.draw_contact(jid, account)
|
self.draw_contact(jid, account)
|
||||||
self.draw_group(_('Transports'), account)
|
self.draw_group(_('Transports'), account)
|
||||||
|
|
||||||
if obj.contact and obj.need_redraw:
|
if obj.contact:
|
||||||
self.chg_contact_status(obj.contact, obj.show, obj.status, account)
|
self.chg_contact_status(obj.contact, obj.show, obj.status, account)
|
||||||
|
|
||||||
if obj.popup:
|
if obj.popup:
|
||||||
|
@ -2598,7 +2586,6 @@ class RosterWindow:
|
||||||
self.fire_up_unread_messages_events(obj.conn.name)
|
self.fire_up_unread_messages_events(obj.conn.name)
|
||||||
else:
|
else:
|
||||||
# add self contact
|
# add self contact
|
||||||
if app.config.get('show_self_contact') == 'always':
|
|
||||||
account = obj.conn.name
|
account = obj.conn.name
|
||||||
self_jid = app.get_jid_from_account(account)
|
self_jid = app.get_jid_from_account(account)
|
||||||
if self_jid not in app.contacts.get_jid_list(account):
|
if self_jid not in app.contacts.get_jid_list(account):
|
||||||
|
@ -2612,6 +2599,7 @@ class RosterWindow:
|
||||||
ask='none', resource=resource, avatar_sha=sha)
|
ask='none', resource=resource, avatar_sha=sha)
|
||||||
app.contacts.add_contact(account, contact)
|
app.contacts.add_contact(account, contact)
|
||||||
self.add_contact(self_jid, account)
|
self.add_contact(self_jid, account)
|
||||||
|
|
||||||
if app.config.get('remember_opened_chat_controls'):
|
if app.config.get('remember_opened_chat_controls'):
|
||||||
account = obj.conn.name
|
account = obj.conn.name
|
||||||
controls = app.config.get_per(
|
controls = app.config.get_per(
|
||||||
|
|
Loading…
Reference in New Issue