Refactor roster item exchange code into own module
This commit is contained in:
parent
f382ce2a6c
commit
b74706afcf
|
@ -68,6 +68,7 @@ from gajim.common.modules.software_version import SoftwareVersion
|
||||||
from gajim.common.modules.ping import Ping
|
from gajim.common.modules.ping import Ping
|
||||||
from gajim.common.modules.search import Search
|
from gajim.common.modules.search import Search
|
||||||
from gajim.common.modules.annotations import Annotations
|
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.connection_handlers import *
|
||||||
from gajim.common.contacts import GC_Contact
|
from gajim.common.contacts import GC_Contact
|
||||||
from gajim.gtkgui_helpers import get_action
|
from gajim.gtkgui_helpers import get_action
|
||||||
|
@ -660,6 +661,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
self.register_module('Ping', Ping, self)
|
self.register_module('Ping', Ping, self)
|
||||||
self.register_module('Search', Search, self)
|
self.register_module('Search', Search, self)
|
||||||
self.register_module('Annotations', Annotations, self)
|
self.register_module('Annotations', Annotations, self)
|
||||||
|
self.register_module('RosterItemExchange', RosterItemExchange, self)
|
||||||
|
|
||||||
app.ged.register_event_handler('privacy-list-received', ged.CORE,
|
app.ged.register_event_handler('privacy-list-received', ged.CORE,
|
||||||
self._nec_privacy_list_received)
|
self._nec_privacy_list_received)
|
||||||
|
@ -2046,32 +2048,6 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
else:
|
else:
|
||||||
self.log_message(obj, obj.jid)
|
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):
|
def send_stanza(self, stanza):
|
||||||
"""
|
"""
|
||||||
Send a stanza untouched
|
Send a stanza untouched
|
||||||
|
|
|
@ -1663,15 +1663,6 @@ ConnectionHTTPUpload):
|
||||||
iq_obj.addChild(node=err)
|
iq_obj.addChild(node=err)
|
||||||
self.connection.send(iq_obj)
|
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):
|
def _messageCB(self, con, msg):
|
||||||
"""
|
"""
|
||||||
Called when we receive a message
|
Called when we receive a message
|
||||||
|
@ -2075,8 +2066,6 @@ ConnectionHTTPUpload):
|
||||||
con.RegisterHandler('message', self._pubsubEventCB, makefirst=True)
|
con.RegisterHandler('message', self._pubsubEventCB, makefirst=True)
|
||||||
con.RegisterHandler('iq', self._rosterSetCB, 'set', nbxmpp.NS_ROSTER)
|
con.RegisterHandler('iq', self._rosterSetCB, 'set', nbxmpp.NS_ROSTER)
|
||||||
con.RegisterHandler('iq', self._siSetCB, 'set', nbxmpp.NS_SI)
|
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._siErrorCB, 'error', nbxmpp.NS_SI)
|
||||||
con.RegisterHandler('iq', self._siResultCB, 'result', nbxmpp.NS_SI)
|
con.RegisterHandler('iq', self._siResultCB, 'result', nbxmpp.NS_SI)
|
||||||
con.RegisterHandler('iq', self._discoGetCB, 'get', nbxmpp.NS_DISCO)
|
con.RegisterHandler('iq', self._discoGetCB, 'get', nbxmpp.NS_DISCO)
|
||||||
|
|
|
@ -193,51 +193,6 @@ class HttpAuthReceivedEvent(nec.NetworkIncomingEvent):
|
||||||
self.msg = self.stanza.getTagData('body')
|
self.msg = self.stanza.getTagData('body')
|
||||||
return True
|
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):
|
class LastRequestEvent(nec.NetworkIncomingEvent):
|
||||||
name = 'last-request-received'
|
name = 'last-request-received'
|
||||||
base_network_events = []
|
base_network_events = []
|
||||||
|
@ -1103,8 +1058,8 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
|
||||||
|
|
||||||
# check if the message is a roster item exchange (XEP-0144)
|
# check if the message is a roster item exchange (XEP-0144)
|
||||||
if self.stanza.getTag('x', namespace=nbxmpp.NS_ROSTERX):
|
if self.stanza.getTag('x', namespace=nbxmpp.NS_ROSTERX):
|
||||||
app.nec.push_incoming_event(RosterItemExchangeEvent(None,
|
self.conn.get_module('RosterItemExchange').received_item(
|
||||||
conn=self.conn, stanza=self.stanza))
|
self.conn, self.stanza)
|
||||||
return
|
return
|
||||||
|
|
||||||
# check if the message is a XEP-0070 confirmation request
|
# check if the message is a XEP-0070 confirmation request
|
||||||
|
|
|
@ -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 = []
|
|
@ -4119,11 +4119,12 @@ class RosterWindow:
|
||||||
def on_drop_rosterx(self, widget, account_source, c_source, account_dest,
|
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'
|
type_ = 'message'
|
||||||
if c_dest.show not in ('offline', 'error') and c_dest.supports(
|
if (c_dest.show not in ('offline', 'error') and
|
||||||
NS_ROSTERX):
|
c_dest.supports(NS_ROSTERX)):
|
||||||
type_ = 'iq'
|
type_ = 'iq'
|
||||||
app.connections[account_dest].send_contacts([c_source],
|
con = app.connections[account_dest]
|
||||||
c_dest.get_full_jid(), type_=type_)
|
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,
|
def on_drop_in_contact(self, widget, account_source, c_source, account_dest,
|
||||||
c_dest, was_big_brother, context, etime):
|
c_dest, was_big_brother, context, etime):
|
||||||
|
@ -4534,7 +4535,7 @@ class RosterWindow:
|
||||||
menu.attach_to_widget(self.tree, None)
|
menu.attach_to_widget(self.tree, None)
|
||||||
menu.connect('selection-done', gtkgui_helpers.destroy_widget)
|
menu.connect('selection-done', gtkgui_helpers.destroy_widget)
|
||||||
menu.show_all()
|
menu.show_all()
|
||||||
menu.popup(None, None, None, None, 1, etime)
|
menu.popup_at_pointer(None)
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
### Everything about images and icons....
|
### Everything about images and icons....
|
||||||
|
|
Loading…
Reference in New Issue