Refactor roster item exchange code into own module

This commit is contained in:
Philipp Hörist 2018-06-25 22:43:09 +02:00
parent f382ce2a6c
commit b74706afcf
5 changed files with 133 additions and 90 deletions

View File

@ -68,6 +68,7 @@ from gajim.common.modules.software_version import SoftwareVersion
from gajim.common.modules.ping import Ping
from gajim.common.modules.search import Search
from gajim.common.modules.annotations import Annotations
from gajim.common.modules.roster_item_exchange import RosterItemExchange
from gajim.common.connection_handlers import *
from gajim.common.contacts import GC_Contact
from gajim.gtkgui_helpers import get_action
@ -660,6 +661,7 @@ class Connection(CommonConnection, ConnectionHandlers):
self.register_module('Ping', Ping, self)
self.register_module('Search', Search, self)
self.register_module('Annotations', Annotations, self)
self.register_module('RosterItemExchange', RosterItemExchange, self)
app.ged.register_event_handler('privacy-list-received', ged.CORE,
self._nec_privacy_list_received)
@ -2046,32 +2048,6 @@ class Connection(CommonConnection, ConnectionHandlers):
else:
self.log_message(obj, obj.jid)
def send_contacts(self, contacts, fjid, type_='message'):
"""
Send contacts with RosterX (Xep-0144)
"""
if not app.account_is_connected(self.name):
return
if type_ == 'message':
if len(contacts) == 1:
msg = _('Sent contact: "%(jid)s" (%(name)s)') % {
'jid': contacts[0].get_full_jid(),
'name': contacts[0].get_shown_name()}
else:
msg = _('Sent contacts:')
for contact in contacts:
msg += '\n "%s" (%s)' % (contact.get_full_jid(),
contact.get_shown_name())
stanza = nbxmpp.Message(to=app.get_jid_without_resource(fjid),
body=msg)
elif type_ == 'iq':
stanza = nbxmpp.Iq(to=fjid, typ='set')
x = stanza.addChild(name='x', namespace=nbxmpp.NS_ROSTERX)
for contact in contacts:
x.addChild(name='item', attrs={'action': 'add', 'jid': contact.jid,
'name': contact.get_shown_name()})
self.connection.send(stanza)
def send_stanza(self, stanza):
"""
Send a stanza untouched

View File

@ -1663,15 +1663,6 @@ ConnectionHTTPUpload):
iq_obj.addChild(node=err)
self.connection.send(iq_obj)
def _rosterItemExchangeCB(self, con, msg):
"""
XEP-0144 Roster Item Echange
"""
log.debug('rosterItemExchangeCB')
app.nec.push_incoming_event(RosterItemExchangeEvent(None, conn=self,
stanza=msg))
raise nbxmpp.NodeProcessed
def _messageCB(self, con, msg):
"""
Called when we receive a message
@ -2075,8 +2066,6 @@ ConnectionHTTPUpload):
con.RegisterHandler('message', self._pubsubEventCB, makefirst=True)
con.RegisterHandler('iq', self._rosterSetCB, 'set', nbxmpp.NS_ROSTER)
con.RegisterHandler('iq', self._siSetCB, 'set', nbxmpp.NS_SI)
con.RegisterHandler('iq', self._rosterItemExchangeCB, 'set',
nbxmpp.NS_ROSTERX)
con.RegisterHandler('iq', self._siErrorCB, 'error', nbxmpp.NS_SI)
con.RegisterHandler('iq', self._siResultCB, 'result', nbxmpp.NS_SI)
con.RegisterHandler('iq', self._discoGetCB, 'get', nbxmpp.NS_DISCO)

View File

@ -193,51 +193,6 @@ class HttpAuthReceivedEvent(nec.NetworkIncomingEvent):
self.msg = self.stanza.getTagData('body')
return True
class RosterItemExchangeEvent(nec.NetworkIncomingEvent, HelperEvent):
name = 'roster-item-exchange-received'
base_network_events = []
def generate(self):
self.get_id()
self.get_jid_resource()
self.exchange_items_list = {}
items_list = self.stanza.getTag('x').getChildren()
if not items_list:
return
self.action = items_list[0].getAttr('action')
if self.action is None:
self.action = 'add'
for item in self.stanza.getTag('x', namespace=nbxmpp.NS_ROSTERX).\
getChildren():
try:
jid = helpers.parse_jid(item.getAttr('jid'))
except helpers.InvalidFormat:
log.warning('Invalid JID: %s, ignoring it' % item.getAttr('jid'))
continue
name = item.getAttr('name')
contact = app.contacts.get_contact(self.conn.name, jid)
groups = []
same_groups = True
for group in item.getTags('group'):
groups.append(group.getData())
# check that all suggested groups are in the groups we have for
# this contact
if not contact or group not in contact.groups:
same_groups = False
if contact:
# check that all groups we have for this contact are in the
# suggested groups
for group in contact.groups:
if group not in groups:
same_groups = False
if contact.sub in ('both', 'to') and same_groups:
continue
self.exchange_items_list[jid] = []
self.exchange_items_list[jid].append(name)
self.exchange_items_list[jid].append(groups)
if self.exchange_items_list:
return True
class LastRequestEvent(nec.NetworkIncomingEvent):
name = 'last-request-received'
base_network_events = []
@ -1103,8 +1058,8 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
# check if the message is a roster item exchange (XEP-0144)
if self.stanza.getTag('x', namespace=nbxmpp.NS_ROSTERX):
app.nec.push_incoming_event(RosterItemExchangeEvent(None,
conn=self.conn, stanza=self.stanza))
self.conn.get_module('RosterItemExchange').received_item(
self.conn, self.stanza)
return
# check if the message is a XEP-0070 confirmation request

View File

@ -0,0 +1,122 @@
# 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-0144: Roster Item Exchange
import logging
import nbxmpp
from gajim.common import app
from gajim.common import helpers
from gajim.common.nec import NetworkIncomingEvent
log = logging.getLogger('gajim.c.m.roster_item_exchange')
class RosterItemExchange:
def __init__(self, con):
self._con = con
self._account = con.name
self.handlers = [
('iq', self.received_item, 'set', nbxmpp.NS_ROSTERX)
]
def received_item(self, con, stanza):
# stanza can be a message or a iq
log.info('Received roster items from %s', stanza.getFrom())
exchange_items_list = {}
items_list = stanza.getTag(
'x', namespace=nbxmpp.NS_ROSTERX).getChildren()
if items_list is None:
return
action = items_list[0].getAttr('action')
if not action:
action = 'add'
for item in items_list:
try:
jid = helpers.parse_jid(item.getAttr('jid'))
except helpers.InvalidFormat:
log.warning('Invalid JID: %s, ignoring it',
item.getAttr('jid'))
continue
name = item.getAttr('name')
contact = app.contacts.get_contact(self._account, jid)
groups = []
same_groups = True
for group in item.getTags('group'):
groups.append(group.getData())
# check that all suggested groups are in the groups we have for
# this contact
if not contact or group not in contact.groups:
same_groups = False
if contact:
# check that all groups we have for this contact are in the
# suggested groups
for group in contact.groups:
if group not in groups:
same_groups = False
if contact.sub in ('both', 'to') and same_groups:
continue
exchange_items_list[jid] = [name, groups]
if not exchange_items_list:
return
log.info('Items: %s', exchange_items_list)
app.nec.push_incoming_event(RosterItemExchangeEvent(
None, conn=self._con,
fjid=str(stanza.getFrom()),
exchange_items_list=exchange_items_list,
action=action))
if stanza.name == 'iq':
raise nbxmpp.NodeProcessed
def send_contacts(self, contacts, fjid, type_='message'):
if not app.account_is_connected(self._account):
return
if type_ == 'message':
if len(contacts) == 1:
msg = _('Sent contact: "%(jid)s" (%(name)s)') % {
'jid': contacts[0].get_full_jid(),
'name': contacts[0].get_shown_name()}
else:
msg = _('Sent contacts:')
for contact in contacts:
msg += '\n "%s" (%s)' % (contact.get_full_jid(),
contact.get_shown_name())
stanza = nbxmpp.Message(to=app.get_jid_without_resource(fjid),
body=msg)
elif type_ == 'iq':
stanza = nbxmpp.Iq(to=fjid, typ='set')
x = stanza.addChild(name='x', namespace=nbxmpp.NS_ROSTERX)
for contact in contacts:
name = contact.get_shown_name()
x.addChild(name='item', attrs={'action': 'add',
'jid': contact.jid,
'name': name})
log.info('Send contact: %s %s', contact.jid, name)
self._con.connection.send(stanza)
class RosterItemExchangeEvent(NetworkIncomingEvent):
name = 'roster-item-exchange-received'
base_network_events = []

View File

@ -4117,13 +4117,14 @@ class RosterWindow:
self.dragging = False
def on_drop_rosterx(self, widget, account_source, c_source, account_dest,
c_dest, was_big_brother, context, etime):
c_dest, was_big_brother, context, etime):
type_ = 'message'
if c_dest.show not in ('offline', 'error') and c_dest.supports(
NS_ROSTERX):
if (c_dest.show not in ('offline', 'error') and
c_dest.supports(NS_ROSTERX)):
type_ = 'iq'
app.connections[account_dest].send_contacts([c_source],
c_dest.get_full_jid(), type_=type_)
con = app.connections[account_dest]
con.get_module('RosterItemExchange').send_contacts(
[c_source], c_dest.get_full_jid(), type_=type_)
def on_drop_in_contact(self, widget, account_source, c_source, account_dest,
c_dest, was_big_brother, context, etime):
@ -4534,7 +4535,7 @@ class RosterWindow:
menu.attach_to_widget(self.tree, None)
menu.connect('selection-done', gtkgui_helpers.destroy_widget)
menu.show_all()
menu.popup(None, None, None, None, 1, etime)
menu.popup_at_pointer(None)
################################################################################
### Everything about images and icons....