[Git][gajim/gajim][master] Refactor Pubsub/Bookmarks/UserAvatar into own modules
Philipp Hörist
gitlab at dev.gajim.org
Sun Jul 1 22:36:49 CEST 2018
Philipp Hörist pushed to branch master at gajim / gajim
Commits:
2ca0ca38 by Philipp Hörist at 2018-07-01T22:35:56+02:00
Refactor Pubsub/Bookmarks/UserAvatar into own modules
- - - - -
17 changed files:
- gajim/common/connection.py
- gajim/common/connection_handlers.py
- gajim/common/connection_handlers_events.py
- gajim/common/const.py
- + gajim/common/modules/bookmarks.py
- + gajim/common/modules/pubsub.py
- + gajim/common/modules/user_avatar.py
- gajim/common/pep.py
- − gajim/common/pubsub.py
- gajim/config.py
- gajim/dialogs.py
- gajim/disco.py
- gajim/groupchat_control.py
- gajim/groups.py
- gajim/gui_interface.py
- gajim/gui_menu_builder.py
- gajim/roster_window.py
Changes:
=====================================
gajim/common/connection.py
=====================================
--- a/gajim/common/connection.py
+++ b/gajim/common/connection.py
@@ -73,6 +73,9 @@ 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.modules.pubsub import PubSub
+from gajim.common.modules.bookmarks import Bookmarks
+from gajim.common.modules.user_avatar import UserAvatar
from gajim.common.connection_handlers import *
from gajim.common.contacts import GC_Contact
from gajim.gtkgui_helpers import get_action
@@ -113,7 +116,6 @@ class CommonConnection:
self.old_show = ''
self.priority = app.get_priority(name, 'offline')
self.time_to_reconnect = None
- self.bookmarks = []
self.blocked_list = []
self.blocked_contacts = []
@@ -491,18 +493,6 @@ class CommonConnection:
def account_changed(self, new_name):
self.name = new_name
- def get_bookmarks(self):
- """
- To be implemented by derived classes
- """
- raise NotImplementedError
-
- def store_bookmarks(self):
- """
- To be implemented by derived classes
- """
- raise NotImplementedError
-
def get_metacontacts(self):
"""
To be implemented by derived classes
@@ -670,6 +660,9 @@ class Connection(CommonConnection, ConnectionHandlers):
self.register_module('HTTPAuth', HTTPAuth, self)
self.register_module('VCardTemp', VCardTemp, self)
self.register_module('VCardAvatars', VCardAvatars, self)
+ self.register_module('PubSub', PubSub, self)
+ self.register_module('Bookmarks', Bookmarks, self)
+ self.register_module('UserAvatar', UserAvatar, self)
app.ged.register_event_handler('privacy-list-received', ged.CORE,
self._nec_privacy_list_received)
@@ -1774,8 +1767,8 @@ class Connection(CommonConnection, ConnectionHandlers):
# ask our VCard
self.get_module('VCardTemp').request_vcard()
- # Get bookmarks from private namespace
- self.get_bookmarks()
+ # Get bookmarks
+ self.get_module('Bookmarks').get_bookmarks()
# Get annotations
self.get_module('Annotations').get_annotations()
@@ -1916,8 +1909,7 @@ class Connection(CommonConnection, ConnectionHandlers):
self.pubsub_publish_options_supported = True
else:
# Remove stored bookmarks accessible to everyone.
- self.send_pb_purge(our_jid, 'storage:bookmarks')
- self.send_pb_delete(our_jid, 'storage:bookmarks')
+ self.get_module('Bookmarks').purge_pubsub_bookmarks()
if obj.fjid == hostname:
if nbxmpp.NS_SECLABEL in obj.features:
@@ -2255,99 +2247,6 @@ class Connection(CommonConnection, ConnectionHandlers):
return True
return False
- def _request_bookmarks_xml(self):
- if not app.account_is_connected(self.name):
- return
- iq = nbxmpp.Iq(typ='get')
- iq2 = iq.addChild(name='query', namespace=nbxmpp.NS_PRIVATE)
- iq2.addChild(name='storage', namespace='storage:bookmarks')
- self.connection.send(iq)
- app.log('bookmarks').info('Request Bookmarks (PrivateStorage)')
-
- def _check_bookmarks_received(self):
- if not self.bookmarks:
- self._request_bookmarks_xml()
-
- def get_bookmarks(self, storage_type=None):
- """
- Get Bookmarks from storage or PubSub if supported as described in XEP
- 0048
-
- storage_type can be set to xml to force request to xml storage
- """
- if not app.account_is_connected(self.name):
- return
-
- if storage_type != 'xml':
- if self.pep_supported and self.pubsub_publish_options_supported:
- self.send_pb_retrieve('', 'storage:bookmarks')
- app.log('bookmarks').info('Request Bookmarks (PubSub)')
- # some server (ejabberd) are so slow to answer that we
- # request via XML if we don't get answer in the next 30 seconds
- app.idlequeue.set_alarm(self._check_bookmarks_received, 30)
- return
-
- self._request_bookmarks_xml()
-
- def get_bookmarks_storage_node(self):
- NS_GAJIM_BM = 'xmpp:gajim.org/bookmarks'
- storage_node = nbxmpp.Node(
- tag='storage', attrs={'xmlns': 'storage:bookmarks'})
- for bm in self.bookmarks:
- conf_node = storage_node.addChild(name="conference")
- conf_node.setAttr('jid', bm['jid'])
- conf_node.setAttr('autojoin', bm['autojoin'])
- conf_node.setAttr('name', bm['name'])
- conf_node.setTag(
- 'minimize', namespace=NS_GAJIM_BM).setData(bm['minimize'])
- # Only add optional elements if not empty
- # Note: need to handle both None and '' as empty
- # thus shouldn't use "is not None"
- if bm.get('nick', None):
- conf_node.setTagData('nick', bm['nick'])
- if bm.get('password', None):
- conf_node.setTagData('password', bm['password'])
- if bm.get('print_status', None):
- conf_node.setTag(
- 'print_status',
- namespace=NS_GAJIM_BM).setData(bm['print_status'])
- return storage_node
-
- @staticmethod
- def get_bookmark_publish_options():
- options = nbxmpp.Node(nbxmpp.NS_DATA + ' x',
- attrs={'type': 'submit'})
- f = options.addChild('field',
- attrs={'var': 'FORM_TYPE', 'type': 'hidden'})
- f.setTagData('value', nbxmpp.NS_PUBSUB_PUBLISH_OPTIONS)
- f = options.addChild('field', attrs={'var': 'pubsub#access_model'})
- f.setTagData('value', 'whitelist')
- return options
-
- def store_bookmarks(self, storage_type=None):
- """
- Send bookmarks to the storage namespace or PubSub if supported
-
- storage_type can be set to 'pubsub' or 'xml' so store in only one method
- else it will be stored on both
- """
- if not app.account_is_connected(self.name):
- return
-
- storage_node = self.get_bookmarks_storage_node()
-
- if storage_type != 'xml':
- if self.pep_supported and self.pubsub_publish_options_supported:
- self.send_pb_publish(
- '', 'storage:bookmarks', storage_node, 'current',
- options=self.get_bookmark_publish_options())
- app.log('bookmarks').info('Bookmarks published (PubSub)')
-
- if storage_type != 'pubsub':
- iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVATE, payload=storage_node)
- self.connection.send(iq)
- app.log('bookmarks').info('Bookmarks published (PrivateStorage)')
-
def get_roster_delimiter(self):
"""
Get roster group delimiter from storage as described in XEP 0083
@@ -2614,11 +2513,7 @@ class Connection(CommonConnection, ConnectionHandlers):
destroy.setAttr('jid', jid)
self.connection.send(iq)
i = 0
- for bm in self.bookmarks:
- if bm['jid'] == room_jid:
- del self.bookmarks[i]
- break
- i += 1
+ self.get_module('Bookmarks').bookmarks.pop(jid, None)
self.store_bookmarks()
def send_gc_status(self, nick, jid, show, status, auto=False):
=====================================
gajim/common/connection_handlers.py
=====================================
--- a/gajim/common/connection_handlers.py
+++ b/gajim/common/connection_handlers.py
@@ -50,7 +50,6 @@ from gajim.common import jingle_xtls
from gajim.common import configpaths
from gajim.common.caps_cache import muc_caps_cache
from gajim.common.commands import ConnectionCommands
-from gajim.common.pubsub import ConnectionPubSub
from gajim.common.protocol.caps import ConnectionCaps
from gajim.common.protocol.bytestream import ConnectionSocks5Bytestream
from gajim.common.protocol.bytestream import ConnectionIBBytestream
@@ -339,15 +338,15 @@ class ConnectionPEP(object):
if message:
i = item.addChild('text')
i.addData(message)
- self._pubsub_connection.send_pb_publish('', nbxmpp.NS_ACTIVITY, item,
- '0')
+ self.get_module('PubSub').send_pb_publish(
+ '', nbxmpp.NS_ACTIVITY, item, '0')
def retract_activity(self):
if not self.pep_supported:
return
self.send_activity(None)
# not all client support new XEP, so we still retract
- self._pubsub_connection.send_pb_retract('', nbxmpp.NS_ACTIVITY, '0')
+ self.get_module('PubSub').send_pb_retract('', nbxmpp.NS_ACTIVITY, '0')
def send_mood(self, mood, message=None):
if self.connected == 1:
@@ -363,14 +362,14 @@ class ConnectionPEP(object):
if message:
i = item.addChild('text')
i.addData(message)
- self._pubsub_connection.send_pb_publish('', nbxmpp.NS_MOOD, item, '0')
+ self.get_module('PubSub').send_pb_publish('', nbxmpp.NS_MOOD, item, '0')
def retract_mood(self):
if not self.pep_supported:
return
self.send_mood(None)
# not all client support new XEP, so we still retract
- self._pubsub_connection.send_pb_retract('', nbxmpp.NS_MOOD, '0')
+ self.get_module('PubSub').send_pb_retract('', nbxmpp.NS_MOOD, '0')
def send_tune(self, artist='', title='', source='', track=0, length=0,
items=None):
@@ -399,14 +398,14 @@ class ConnectionPEP(object):
i.addData(length)
if items:
item.addChild(payload=items)
- self._pubsub_connection.send_pb_publish('', nbxmpp.NS_TUNE, item, '0')
+ self.get_module('PubSub').send_pb_publish('', nbxmpp.NS_TUNE, item, '0')
def retract_tune(self):
if not self.pep_supported:
return
self.send_tune(None)
# not all client support new XEP, so we still retract
- self._pubsub_connection.send_pb_retract('', nbxmpp.NS_TUNE, '0')
+ self.get_module('PubSub').send_pb_retract('', nbxmpp.NS_TUNE, '0')
def send_nickname(self, nick):
if self.connected == 1:
@@ -418,13 +417,13 @@ class ConnectionPEP(object):
return
item = nbxmpp.Node('nick', {'xmlns': nbxmpp.NS_NICK})
item.addData(nick)
- self._pubsub_connection.send_pb_publish('', nbxmpp.NS_NICK, item, '0')
+ self.get_module('PubSub').send_pb_publish('', nbxmpp.NS_NICK, item, '0')
def retract_nickname(self):
if not self.pep_supported:
return
- self._pubsub_connection.send_pb_retract('', nbxmpp.NS_NICK, '0')
+ self.get_module('PubSub').send_pb_retract('', nbxmpp.NS_NICK, '0')
def send_location(self, info):
if self.connected == 1:
@@ -439,14 +438,14 @@ class ConnectionPEP(object):
if info.get(field, None):
i = item.addChild(field)
i.addData(info[field])
- self._pubsub_connection.send_pb_publish('', nbxmpp.NS_LOCATION, item, '0')
+ self.get_module('PubSub').send_pb_publish('', nbxmpp.NS_LOCATION, item, '0')
def retract_location(self):
if not self.pep_supported:
return
self.send_location({})
# not all client support new XEP, so we still retract
- self._pubsub_connection.send_pb_retract('', nbxmpp.NS_LOCATION, '0')
+ self.get_module('PubSub').send_pb_retract('', nbxmpp.NS_LOCATION, '0')
# basic connection handlers used here and in zeroconf
class ConnectionHandlersBase:
@@ -915,7 +914,7 @@ class ConnectionHandlersBase:
class ConnectionHandlers(ConnectionArchive313,
ConnectionSocks5Bytestream, ConnectionDisco,
-ConnectionCommands, ConnectionPubSub, ConnectionPEP, ConnectionCaps,
+ConnectionCommands, ConnectionPEP, ConnectionCaps,
ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream,
ConnectionHTTPUpload):
def __init__(self):
@@ -923,7 +922,6 @@ ConnectionHTTPUpload):
ConnectionSocks5Bytestream.__init__(self)
ConnectionIBBytestream.__init__(self)
ConnectionCommands.__init__(self)
- ConnectionPubSub.__init__(self)
ConnectionPEP.__init__(self, account=self.name, dispatcher=self,
pubsub_connection=self)
ConnectionHTTPUpload.__init__(self)
@@ -949,8 +947,6 @@ ConnectionHTTPUpload):
self.privacy_default_list = None
- app.nec.register_incoming_event(PrivateStorageBookmarksReceivedEvent)
- app.nec.register_incoming_event(BookmarksReceivedEvent)
app.nec.register_incoming_event(StreamConflictReceivedEvent)
app.nec.register_incoming_event(StreamOtherHostReceivedEvent)
app.nec.register_incoming_event(MessageReceivedEvent)
@@ -961,8 +957,6 @@ ConnectionHTTPUpload):
app.ged.register_event_handler('roster-set-received',
ged.CORE, self._nec_roster_set_received)
- app.ged.register_event_handler('private-storage-bookmarks-received',
- ged.CORE, self._nec_private_storate_bookmarks_received)
app.ged.register_event_handler('roster-received', ged.CORE,
self._nec_roster_received)
app.ged.register_event_handler('iq-error-received', ged.CORE,
@@ -988,12 +982,9 @@ ConnectionHTTPUpload):
ConnectionHandlersBase.cleanup(self)
ConnectionCaps.cleanup(self)
ConnectionArchive313.cleanup(self)
- ConnectionPubSub.cleanup(self)
ConnectionHTTPUpload.cleanup(self)
app.ged.remove_event_handler('roster-set-received',
ged.CORE, self._nec_roster_set_received)
- app.ged.remove_event_handler('private-storage-bookmarks-received',
- ged.CORE, self._nec_private_storate_bookmarks_received)
app.ged.remove_event_handler('roster-received', ged.CORE,
self._nec_roster_received)
app.ged.remove_event_handler('iq-error-received', ged.CORE,
@@ -1144,28 +1135,6 @@ ConnectionHTTPUpload):
conn=self, stanza=obj.stanza))
return True
- def _nec_private_storate_bookmarks_received(self, obj):
- if obj.conn.name != self.name:
- return
- app.log('bookmarks').info('Received Bookmarks (PrivateStorage)')
- resend_to_pubsub = False
- bm_jids = [b['jid'] for b in self.bookmarks]
- for bm in obj.bookmarks:
- if bm['jid'] not in bm_jids:
- self.bookmarks.append(bm)
- # We got a bookmark that was not in pubsub
- resend_to_pubsub = True
- if resend_to_pubsub:
- self.store_bookmarks('pubsub')
-
- def _PrivateCB(self, con, iq_obj):
- """
- Private Data (XEP 048 and 049)
- """
- log.debug('PrivateCB')
- app.nec.push_incoming_event(PrivateStorageReceivedEvent(None,
- conn=self, stanza=iq_obj))
-
def _SecLabelCB(self, con, iq_obj):
"""
Security Label callback, used for catalogues.
@@ -1540,8 +1509,8 @@ ConnectionHTTPUpload):
# ask our VCard
self.get_module('VCardTemp').request_vcard()
- # Get bookmarks from private namespace
- self.get_bookmarks()
+ # Get bookmarks
+ self.get_module('Bookmarks').get_bookmarks()
# Get annotations from private namespace
self.get_module('Annotations').get_annotations()
@@ -1645,7 +1614,6 @@ ConnectionHTTPUpload):
nbxmpp.NS_MUC_OWNER)
con.RegisterHandler('iq', self._MucAdminCB, 'result',
nbxmpp.NS_MUC_ADMIN)
- con.RegisterHandler('iq', self._PrivateCB, 'result', nbxmpp.NS_PRIVATE)
con.RegisterHandler('iq', self._SecLabelCB, 'result',
nbxmpp.NS_SECLABEL_CATALOG)
con.RegisterHandler('iq', self._CommandExecuteCB, 'set',
@@ -1657,8 +1625,6 @@ ConnectionHTTPUpload):
con.RegisterHandler('iq', self._PrivacySetCB, 'set', nbxmpp.NS_PRIVACY)
con.RegisterHandler('iq', self._ArchiveCB, ns=nbxmpp.NS_MAM_1)
con.RegisterHandler('iq', self._ArchiveCB, ns=nbxmpp.NS_MAM_2)
- con.RegisterHandler('iq', self._PubSubCB, 'result')
- con.RegisterHandler('iq', self._PubSubErrorCB, 'error')
con.RegisterHandler('iq', self._JingleCB, 'result')
con.RegisterHandler('iq', self._JingleCB, 'error')
con.RegisterHandler('iq', self._JingleCB, 'set', nbxmpp.NS_JINGLE)
=====================================
gajim/common/connection_handlers_events.py
=====================================
--- a/gajim/common/connection_handlers_events.py
+++ b/gajim/common/connection_handlers_events.py
@@ -309,118 +309,6 @@ class MucAdminReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
self.users_dict[jid]['reason'] = reason
return True
-class PrivateStorageReceivedEvent(nec.NetworkIncomingEvent):
- name = 'private-storage-received'
- base_network_events = []
-
- def generate(self):
- query = self.stanza.getTag('query')
- self.storage_node = query.getTag('storage')
- if self.storage_node:
- self.namespace = self.storage_node.getNamespace()
- return True
-
-
-class BookmarksHelper:
- def parse_bookmarks(self):
- self.bookmarks = []
- NS_GAJIM_BM = 'xmpp:gajim.org/bookmarks'
- confs = self.storage_node.getTags('conference')
- for conf in confs:
- autojoin_val = conf.getAttr('autojoin')
- if not autojoin_val: # not there (it's optional)
- autojoin_val = False
- minimize_val = conf.getTag('minimize', namespace=NS_GAJIM_BM)
- if not minimize_val: # not there, try old Gajim behaviour
- minimize_val = conf.getAttr('minimize')
- if not minimize_val: # not there (it's optional)
- minimize_val = False
- else:
- minimize_val = minimize_val.getData()
-
- print_status = conf.getTag('print_status', namespace=NS_GAJIM_BM)
- if not print_status: # not there, try old Gajim behaviour
- print_status = conf.getTagData('print_status')
- if not print_status: # not there, try old Gajim behaviour
- print_status = conf.getTagData('show_status')
- else:
- print_status = print_status.getData()
-
- try:
- jid = helpers.parse_jid(conf.getAttr('jid'))
- except helpers.InvalidFormat:
- log.warning('Invalid JID: %s, ignoring it'
- % conf.getAttr('jid'))
- continue
-
- bm = {'name': conf.getAttr('name'),
- 'jid': jid,
- 'autojoin': autojoin_val,
- 'minimize': minimize_val,
- 'password': conf.getTagData('password'),
- 'nick': conf.getTagData('nick'),
- 'print_status': print_status}
-
- bm_jids = [b['jid'] for b in self.bookmarks]
- if bm['jid'] not in bm_jids:
- self.bookmarks.append(bm)
-
-class PrivateStorageBookmarksReceivedEvent(nec.NetworkIncomingEvent,
-BookmarksHelper):
- name = 'private-storage-bookmarks-received'
- base_network_events = ['private-storage-received']
-
- def generate(self):
- self.conn = self.base_event.conn
- self.storage_node = self.base_event.storage_node
- if self.base_event.namespace != nbxmpp.NS_BOOKMARKS:
- return
- self.parse_bookmarks()
- return True
-
-class BookmarksReceivedEvent(nec.NetworkIncomingEvent):
- name = 'bookmarks-received'
- base_network_events = ['private-storage-bookmarks-received',
- 'pubsub-bookmarks-received']
-
- def generate(self):
- self.conn = self.base_event.conn
- self.bookmarks = self.base_event.bookmarks
- return True
-
-class PubsubReceivedEvent(nec.NetworkIncomingEvent):
- name = 'pubsub-received'
- base_network_events = []
-
- def generate(self):
- self.jid = self.stanza.getFrom()
- self.pubsub_node = self.stanza.getTag('pubsub')
- if not self.pubsub_node:
- return
- self.items_node = self.pubsub_node.getTag('items')
- if not self.items_node:
- return
- return True
-
-class PubsubBookmarksReceivedEvent(nec.NetworkIncomingEvent, BookmarksHelper):
- name = 'pubsub-bookmarks-received'
- base_network_events = ['pubsub-received']
-
- def generate(self):
- self.conn = self.base_event.conn
- self.item_node = self.base_event.items_node.getTag('item')
- if not self.item_node:
- return
- children = self.item_node.getChildren()
- if not children:
- return
- self.storage_node = children[0]
- ns = self.storage_node.getNamespace()
- if ns != nbxmpp.NS_BOOKMARKS:
- return
- self.parse_bookmarks()
- return True
-
class IqErrorReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
name = 'iq-error-received'
base_network_events = []
=====================================
gajim/common/const.py
=====================================
--- a/gajim/common/const.py
+++ b/gajim/common/const.py
@@ -119,6 +119,11 @@ class RequestAvatar(IntEnum):
ROOM = 1
USER = 2
+ at unique
+class BookmarkStorageType(IntEnum):
+ PRIVATE = 0
+ PUBSUB = 1
+
SSLError = {
2: _("Unable to get issuer certificate"),
3: _("Unable to get certificate CRL"),
=====================================
gajim/common/modules/bookmarks.py
=====================================
--- /dev/null
+++ b/gajim/common/modules/bookmarks.py
@@ -0,0 +1,294 @@
+# 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-0048: Bookmarks
+
+import logging
+
+import nbxmpp
+
+from gajim.common import app
+from gajim.common import helpers
+from gajim.common.const import BookmarkStorageType
+from gajim.common.nec import NetworkIncomingEvent
+
+log = logging.getLogger('gajim.c.m.bookmarks')
+
+
+class Bookmarks:
+ def __init__(self, con):
+ self._con = con
+ self._account = con.name
+ self.bookmarks = {}
+
+ self.handlers = []
+
+ def _pubsub_support(self):
+ return (self._con.pep_supported and
+ self._con.pubsub_publish_options_supported)
+
+ def get_bookmarks(self, storage_type=None):
+ if not app.account_is_connected(self._account):
+ return
+
+ if storage_type in (None, BookmarkStorageType.PUBSUB):
+ if self._pubsub_support():
+ self._request_pubsub_bookmarks()
+ else:
+ # Fallback, request private storage
+ self._request_private_bookmarks()
+ else:
+ log.info('Request Bookmarks (PrivateStorage)')
+ self._request_private_bookmarks()
+
+ def _request_pubsub_bookmarks(self):
+ log.info('Request Bookmarks (PubSub)')
+ self._con.get_module('PubSub').send_pb_retrieve(
+ '', 'storage:bookmarks',
+ cb=self._pubsub_bookmarks_received)
+
+ def _pubsub_bookmarks_received(self, conn, stanza):
+ if not nbxmpp.isResultNode(stanza):
+ log.info('No pubsub bookmarks: %s', stanza.getError())
+ # Fallback, request private storage
+ self._request_private_bookmarks()
+ return
+
+ log.info('Received Bookmarks (PubSub)')
+ self._parse_bookmarks(stanza)
+ self._request_private_bookmarks()
+
+ def _request_private_bookmarks(self):
+ if not app.account_is_connected(self._account):
+ return
+
+ iq = nbxmpp.Iq(typ='get')
+ query = iq.addChild(name='query', namespace=nbxmpp.NS_PRIVATE)
+ query.addChild(name='storage', namespace='storage:bookmarks')
+ log.info('Request Bookmarks (PrivateStorage)')
+ self._con.connection.SendAndCallForResponse(
+ iq, self._private_bookmarks_received)
+
+ def _private_bookmarks_received(self, stanza):
+ if not nbxmpp.isResultNode(stanza):
+ log.info('No private bookmarks: %s', stanza.getError())
+ else:
+ log.info('Received Bookmarks (PrivateStorage)')
+ merged = self._parse_bookmarks(stanza, check_merge=True)
+ if merged:
+ log.info('Merge PrivateStorage with PubSub')
+ self.store_bookmarks(BookmarkStorageType.PUBSUB)
+ self.auto_join_bookmarks()
+ app.nec.push_incoming_event(BookmarksReceivedEvent(
+ None, account=self._account))
+
+ @staticmethod
+ def _get_storage_node(stanza):
+ node = stanza.getTag('pubsub', namespace=nbxmpp.NS_PUBSUB)
+ if node is None:
+ node = stanza.getTag('event', namespace=nbxmpp.NS_PUBSUB_EVENT)
+ if node is None:
+ # Private Storage
+ query = stanza.getQuery()
+ if query is None:
+ return
+ storage = query.getTag('storage',
+ namespace=nbxmpp.NS_BOOKMARKS)
+ if storage is None:
+ return
+ return storage
+
+ items_node = node.getTag('items')
+ if items_node is None:
+ return
+ if items_node.getAttr('node') != nbxmpp.NS_BOOKMARKS:
+ return
+
+ item_node = items_node.getTag('item')
+ if item_node is None:
+ return
+
+ storage = item_node.getTag('storage', namespace=nbxmpp.NS_BOOKMARKS)
+ if storage is None:
+ return
+ return storage
+
+ def _parse_bookmarks(self, stanza, check_merge=False):
+ merged = False
+ storage = self._get_storage_node(stanza)
+ if storage is None:
+ return
+
+ NS_GAJIM_BM = 'xmpp:gajim.org/bookmarks'
+ confs = storage.getTags('conference')
+ for conf in confs:
+ autojoin_val = conf.getAttr('autojoin')
+ if not autojoin_val: # not there (it's optional)
+ autojoin_val = False
+ minimize_val = conf.getTag('minimize', namespace=NS_GAJIM_BM)
+ if not minimize_val: # not there, try old Gajim behaviour
+ minimize_val = conf.getAttr('minimize')
+ if not minimize_val: # not there (it's optional)
+ minimize_val = False
+ else:
+ minimize_val = minimize_val.getData()
+
+ print_status = conf.getTag('print_status', namespace=NS_GAJIM_BM)
+ if not print_status: # not there, try old Gajim behaviour
+ print_status = conf.getTagData('print_status')
+ if not print_status: # not there, try old Gajim behaviour
+ print_status = conf.getTagData('show_status')
+ else:
+ print_status = print_status.getData()
+
+ try:
+ jid = helpers.parse_jid(conf.getAttr('jid'))
+ except helpers.InvalidFormat:
+ log.warning('Invalid JID: %s, ignoring it'
+ % conf.getAttr('jid'))
+ continue
+
+ if check_merge:
+ if jid not in self.bookmarks:
+ merged = True
+
+ log.debug('Found Bookmark: %s', jid)
+ self.bookmarks[jid] = {
+ 'name': conf.getAttr('name'),
+ 'autojoin': autojoin_val,
+ 'minimize': minimize_val,
+ 'password': conf.getTagData('password'),
+ 'nick': conf.getTagData('nick'),
+ 'print_status': print_status}
+
+ return merged
+
+ def _build_storage_node(self):
+ NS_GAJIM_BM = 'xmpp:gajim.org/bookmarks'
+ storage_node = nbxmpp.Node(
+ tag='storage', attrs={'xmlns': 'storage:bookmarks'})
+ for jid, bm in self.bookmarks.items():
+ conf_node = storage_node.addChild(name="conference")
+ conf_node.setAttr('jid', jid)
+ conf_node.setAttr('autojoin', bm['autojoin'])
+ conf_node.setAttr('name', bm['name'])
+ conf_node.setTag(
+ 'minimize', namespace=NS_GAJIM_BM).setData(bm['minimize'])
+ # Only add optional elements if not empty
+ # Note: need to handle both None and '' as empty
+ # thus shouldn't use "is not None"
+ if bm.get('nick', None):
+ conf_node.setTagData('nick', bm['nick'])
+ if bm.get('password', None):
+ conf_node.setTagData('password', bm['password'])
+ if bm.get('print_status', None):
+ conf_node.setTag(
+ 'print_status',
+ namespace=NS_GAJIM_BM).setData(bm['print_status'])
+ return storage_node
+
+ @staticmethod
+ def get_bookmark_publish_options():
+ options = nbxmpp.Node(nbxmpp.NS_DATA + ' x',
+ attrs={'type': 'submit'})
+ f = options.addChild('field',
+ attrs={'var': 'FORM_TYPE', 'type': 'hidden'})
+ f.setTagData('value', nbxmpp.NS_PUBSUB_PUBLISH_OPTIONS)
+ f = options.addChild('field', attrs={'var': 'pubsub#access_model'})
+ f.setTagData('value', 'whitelist')
+ return options
+
+ def store_bookmarks(self, storage_type=None):
+ if not app.account_is_connected(self._account):
+ return
+
+ storage_node = self._build_storage_node()
+
+ if storage_type is None:
+ if self._pubsub_support():
+ self._pubsub_store(storage_node)
+ else:
+ self._private_store(storage_node)
+ elif storage_type == BookmarkStorageType.PUBSUB:
+ if self._pubsub_support():
+ self._pubsub_store(storage_node)
+ elif storage_type == BookmarkStorageType.PRIVATE:
+ self._private_store(storage_node)
+
+ def _pubsub_store(self, storage_node):
+ self._con.get_module('PubSub').send_pb_publish(
+ '', 'storage:bookmarks', storage_node, 'current',
+ options=self.get_bookmark_publish_options(),
+ cb=self._pubsub_store_result)
+ log.info('Publish Bookmarks (PubSub)')
+
+ def _private_store(self, storage_node):
+ iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVATE, payload=storage_node)
+ log.info('Publish Bookmarks (PrivateStorage)')
+ self._con.connection.SendAndCallForResponse(
+ iq, self._private_store_result)
+
+ def _pubsub_store_result(self, conn, stanza):
+ if not nbxmpp.isResultNode(stanza):
+ log.error('Error: %s', stanza.getError())
+ return
+
+ def _private_store_result(self, stanza):
+ if not nbxmpp.isResultNode(stanza):
+ log.error('Error: %s', stanza.getError())
+ return
+
+ def auto_join_bookmarks(self):
+ if app.is_invisible(self._account):
+ return
+ for jid, bm in self.bookmarks.items():
+ if bm['autojoin'] in ('1', 'true'):
+ # Only join non-opened groupchats. Opened one are already
+ # auto-joined on re-connection
+ if jid not in app.gc_connected[self._account]:
+ # we are not already connected
+ minimize = bm['minimize'] in ('1', 'true')
+ app.interface.join_gc_room(
+ self._account, jid, bm['nick'],
+ bm['password'], minimize=minimize)
+
+ def add_bookmark(self, name, jid, autojoin,
+ minimize, password, nick):
+ self.bookmarks[jid] = {
+ 'name': name,
+ 'autojoin': autojoin,
+ 'minimize': minimize,
+ 'password': password,
+ 'nick': nick}
+
+ self.store_bookmarks()
+ app.nec.push_incoming_event(BookmarksReceivedEvent(
+ None, account=self._account))
+
+ def get_name_from_bookmark(self, jid):
+ try:
+ return self.bookmarks[jid]['name']
+ except KeyError:
+ return jid.split('@')[0]
+
+ def purge_pubsub_bookmarks(self):
+ log.info('Purge/Delete Bookmarks on PubSub, '
+ 'because publish options are not available')
+ self._con.get_module('PubSub').send_pb_purge('', 'storage:bookmarks')
+ self._con.get_module('PubSub').send_pb_delete('', 'storage:bookmarks')
+
+
+class BookmarksReceivedEvent(NetworkIncomingEvent):
+ name = 'bookmarks-received'
+ base_network_events = []
=====================================
gajim/common/modules/pubsub.py
=====================================
--- /dev/null
+++ b/gajim/common/modules/pubsub.py
@@ -0,0 +1,217 @@
+# Copyright (C) 2006 Tomasz Melcer <liori AT exroot.org>
+# Copyright (C) 2006-2014 Yann Leboulanger <asterix AT lagaule.org>
+# Copyright (C) 2007 Jean-Marie Traissard <jim AT lapin.org>
+# Copyright (C) 2008 Stephan Erb <steve-e AT h3c.de>
+# Copyright (C) 2018 Philipp Hörist <philipp AT hoerist.com>
+#
+# 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-0060: Publish-Subscribe
+
+import logging
+
+import nbxmpp
+
+from gajim.common import app
+
+log = logging.getLogger('gajim.c.m.pubsub')
+
+
+class PubSub:
+ def __init__(self, con):
+ self._con = con
+ self._account = con.name
+
+ self.handlers = []
+
+ def send_pb_subscription_query(self, jid, cb, **kwargs):
+ if not app.account_is_connected(self._account):
+ return
+
+ query = nbxmpp.Iq('get', to=jid)
+ pb = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
+ pb.addChild('subscriptions')
+
+ self._con.connection.SendAndCallForResponse(query, cb, kwargs)
+
+ def send_pb_subscribe(self, jid, node, cb, **kwargs):
+ if not app.account_is_connected(self._account):
+ return
+
+ our_jid = app.get_jid_from_account(self._account)
+ query = nbxmpp.Iq('set', to=jid)
+ pb = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
+ pb.addChild('subscribe', {'node': node, 'jid': our_jid})
+
+ self._con.connection.SendAndCallForResponse(query, cb, kwargs)
+
+ def send_pb_unsubscribe(self, jid, node, cb, **kwargs):
+ if not app.account_is_connected(self._account):
+ return
+
+ our_jid = app.get_jid_from_account(self._account)
+ query = nbxmpp.Iq('set', to=jid)
+ pb = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
+ pb.addChild('unsubscribe', {'node': node, 'jid': our_jid})
+
+ self._con.connection.SendAndCallForResponse(query, cb, kwargs)
+
+ def send_pb_publish(self, jid, node, item,
+ id_=None, options=None, cb=None, **kwargs):
+ if not app.account_is_connected(self._account):
+ return
+
+ if cb is None:
+ cb = self._default_callback
+
+ query = nbxmpp.Iq('set', to=jid)
+ e = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
+ p = e.addChild('publish', {'node': node})
+ attrs = {}
+ if id_:
+ attrs = {'id': id_}
+ p.addChild('item', attrs, [item])
+ if options:
+ p = e.addChild('publish-options')
+ p.addChild(node=options)
+
+ self._con.connection.SendAndCallForResponse(query, cb, kwargs)
+
+ @staticmethod
+ def get_pb_retrieve_iq(jid, node, item_id=None):
+ """
+ Get IQ to query items from a node
+ """
+ query = nbxmpp.Iq('get', to=jid)
+ r = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
+ r = r.addChild('items', {'node': node})
+ if item_id is not None:
+ r.addChild('item', {'id': item_id})
+ return query
+
+ def send_pb_retrieve(self, jid, node, item_id=None, cb=None, **kwargs):
+ """
+ Get items from a node
+ """
+ if not app.account_is_connected(self._account):
+ return
+
+ if cb is None:
+ cb = self._default_callback
+
+ query = self.get_pb_retrieve_iq(jid, node, item_id)
+
+ self._con.connection.SendAndCallForResponse(query, cb, kwargs)
+
+ def send_pb_retract(self, jid, node, id_, cb=None, **kwargs):
+ """
+ Delete item from a node
+ """
+ if not app.account_is_connected(self._account):
+ return
+
+ if cb is None:
+ cb = self._default_callback
+
+ query = nbxmpp.Iq('set', to=jid)
+ r = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
+ r = r.addChild('retract', {'node': node, 'notify': '1'})
+ r = r.addChild('item', {'id': id_})
+
+ self._con.connection.SendAndCallForResponse(query, cb, kwargs)
+
+ def send_pb_purge(self, jid, node, cb=None, **kwargs):
+ """
+ Purge node: Remove all items
+ """
+ if not app.account_is_connected(self._account):
+ return
+
+ if cb is None:
+ cb = self._default_callback
+
+ query = nbxmpp.Iq('set', to=jid)
+ d = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER)
+ d = d.addChild('purge', {'node': node})
+
+ self._con.connection.SendAndCallForResponse(query, cb, kwargs)
+
+ def send_pb_delete(self, jid, node, on_ok=None, on_fail=None):
+ """
+ Delete node
+ """
+ if not app.account_is_connected(self._account):
+ return
+ query = nbxmpp.Iq('set', to=jid)
+ d = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER)
+ d = d.addChild('delete', {'node': node})
+
+ def response(con, resp, jid, node):
+ if resp.getType() == 'result' and on_ok:
+ on_ok(jid, node)
+ elif on_fail:
+ msg = resp.getErrorMsg()
+ on_fail(jid, node, msg)
+
+ self._con.connection.SendAndCallForResponse(
+ query, response, {'jid': jid, 'node': node})
+
+ def send_pb_create(self, jid, node, cb,
+ configure=False, configure_form=None):
+ """
+ Create a new node
+ """
+ if not app.account_is_connected(self._account):
+ return
+ query = nbxmpp.Iq('set', to=jid)
+ c = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
+ c = c.addChild('create', {'node': node})
+ if configure:
+ conf = c.addChild('configure')
+ if configure_form is not None:
+ conf.addChild(node=configure_form)
+
+ self._con.connection.SendAndCallForResponse(query, cb)
+
+ def send_pb_configure(self, jid, node, form, cb=None):
+ if not app.account_is_connected(self._account):
+ return
+
+ if cb is None:
+ cb = self._default_callback
+
+ query = nbxmpp.Iq('set', to=jid)
+ c = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER)
+ c = c.addChild('configure', {'node': node})
+ c.addChild(node=form)
+
+ self._con.connection.SendAndCallForResponse(query, cb)
+
+ def request_pb_configuration(self, jid, node, cb=None):
+ if not app.account_is_connected(self._account):
+ return
+
+ if cb is None:
+ cb = self._default_callback
+
+ query = nbxmpp.Iq('get', to=jid)
+ e = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER)
+ e = e.addChild('configure', {'node': node})
+
+ self._con.connection.SendAndCallForResponse(query, cb)
+
+ def _default_callback(self, conn, stanza, *args, **kwargs):
+ if not nbxmpp.isResultNode(stanza):
+ log.warning('Error: %s', stanza.getError())
=====================================
gajim/common/modules/user_avatar.py
=====================================
--- /dev/null
+++ b/gajim/common/modules/user_avatar.py
@@ -0,0 +1,96 @@
+# 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-0084: User Avatar
+
+import logging
+import base64
+import binascii
+
+import nbxmpp
+
+from gajim.common import app
+from gajim.common.exceptions import StanzaMalformed
+
+log = logging.getLogger('gajim.c.m.user_avatar')
+
+
+class UserAvatar:
+ def __init__(self, con):
+ self._con = con
+ self._account = con.name
+
+ self.handlers = []
+
+ def get_pubsub_avatar(self, jid, item_id):
+ log.info('Request: %s %s', jid, item_id)
+ self._con.get_module('PubSub').send_pb_retrieve(
+ jid, 'urn:xmpp:avatar:data', item_id, self._avatar_received)
+
+ def _validate_avatar_node(self, stanza):
+ jid = stanza.getFrom()
+ if jid is None:
+ jid = self._con.get_own_jid().getStripped()
+ else:
+ jid = jid.getStripped()
+
+ if nbxmpp.isErrorNode(stanza):
+ raise StanzaMalformed(stanza.getErrorMsg())
+
+ pubsub_node = stanza.getTag('pubsub')
+ if pubsub_node is None:
+ raise StanzaMalformed('No pubsub node', stanza)
+
+ items_node = pubsub_node.getTag('items')
+ if items_node is None:
+ raise StanzaMalformed('No items node', stanza)
+
+ if items_node.getAttr('node') != 'urn:xmpp:avatar:data':
+ raise StanzaMalformed('Wrong namespace', stanza)
+
+ item = items_node.getTag('item')
+ if item is None:
+ raise StanzaMalformed('No item node', stanza)
+
+ sha = item.getAttr('id')
+ data_tag = item.getTag('data', namespace='urn:xmpp:avatar:data')
+ if sha is None or data_tag is None:
+ raise StanzaMalformed('No id attr or data node found', stanza)
+
+ data = data_tag.getData()
+ if data is None:
+ raise StanzaMalformed('Data node empty', stanza)
+
+ data = base64.b64decode(data.encode('utf-8'))
+
+ return jid, sha, data
+
+ def _avatar_received(self, conn, stanza):
+ try:
+ jid, sha, data = self._validate_avatar_node(stanza)
+ except (StanzaMalformed, binascii.Error) as error:
+ log.warning('Error: %s %s', stanza.getFrom(), error)
+ return
+
+ log.info('Received: %s %s', jid, sha)
+ app.interface.save_avatar(data)
+
+ if self._con.get_own_jid().bareMatch(jid):
+ app.config.set_per('accounts', self._account, 'avatar_sha', sha)
+ else:
+ own_jid = self._con.get_own_jid().getStripped()
+ app.logger.set_avatar_sha(own_jid, jid, sha)
+ app.contacts.set_avatar(self._account, jid, sha)
+
+ app.interface.update_avatar(self._account, jid)
=====================================
gajim/common/pep.py
=====================================
--- a/gajim/common/pep.py
+++ b/gajim/common/pep.py
@@ -485,7 +485,8 @@ class AvatarNotificationPEP(AbstractPEP):
for item in items.getTags('item'):
metadata = item.getTag('metadata')
if metadata is None:
- app.log('avatar').warning('Invalid avatar stanza:\n%s', items)
+ app.log('c.m.user_avatar').warning(
+ 'Invalid avatar stanza:\n%s', items)
break
info = item.getTag('metadata').getTag('info')
if info is not None:
@@ -498,23 +499,22 @@ class AvatarNotificationPEP(AbstractPEP):
con = app.connections[account]
if self.avatar is None:
# Remove avatar
- app.log('avatar').info('Remove (Pubsub): %s', jid)
+ app.log('c.m.user_avatar').info('Remove: %s', jid)
app.contacts.set_avatar(account, jid, None)
own_jid = con.get_own_jid().getStripped()
app.logger.set_avatar_sha(own_jid, jid, None)
app.interface.update_avatar(account, jid)
else:
sha = app.contacts.get_avatar_sha(account, jid)
- app.log('avatar').info(
- 'Update (Pubsub): %s %s', jid, self.avatar['id'])
+ app.log('c.m.user_avatar').info(
+ 'Update: %s %s', jid, self.avatar['id'])
if sha == self.avatar['id']:
- app.log('avatar').info(
- 'Avatar already known (Pubsub): %s %s',
+ app.log('c.m.user_avatar').info(
+ 'Avatar already known: %s %s',
jid, self.avatar['id'])
return
- app.log('avatar').info('Request (Pubsub): %s', jid)
- con.get_pubsub_avatar(jid, 'urn:xmpp:avatar:data',
- self.avatar['id'])
+ con.get_module('UserAvatar').get_pubsub_avatar(
+ jid, self.avatar['id'])
SUPPORTED_PERSONAL_USER_EVENTS = [
=====================================
gajim/common/pubsub.py deleted
=====================================
--- a/gajim/common/pubsub.py
+++ /dev/null
@@ -1,306 +0,0 @@
-# -*- coding:utf-8 -*-
-## src/common/pubsub.py
-##
-## Copyright (C) 2006 Tomasz Melcer <liori AT exroot.org>
-## Copyright (C) 2006-2014 Yann Leboulanger <asterix AT lagaule.org>
-## Copyright (C) 2007 Jean-Marie Traissard <jim AT lapin.org>
-## Copyright (C) 2008 Stephan Erb <steve-e AT h3c.de>
-##
-## 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/>.
-##
-
-import base64
-import binascii
-
-import nbxmpp
-from gajim.common import app
-#TODO: Doesn't work
-#from common.connection_handlers import PEP_CONFIG
-PEP_CONFIG = 'pep_config'
-from gajim.common import ged
-from gajim.common.connection_handlers_events import PubsubReceivedEvent
-from gajim.common.connection_handlers_events import PubsubBookmarksReceivedEvent
-from gajim.common.exceptions import StanzaMalformed
-
-import logging
-log = logging.getLogger('gajim.c.pubsub')
-
-class ConnectionPubSub:
- def __init__(self):
- self.__callbacks = {}
- app.nec.register_incoming_event(PubsubBookmarksReceivedEvent)
- app.ged.register_event_handler('pubsub-bookmarks-received',
- ged.CORE, self._nec_pubsub_bookmarks_received)
-
- def cleanup(self):
- app.ged.remove_event_handler('pubsub-bookmarks-received',
- ged.CORE, self._nec_pubsub_bookmarks_received)
-
- def send_pb_subscription_query(self, jid, cb, *args, **kwargs):
- if not self.connection or self.connected < 2:
- return
- query = nbxmpp.Iq('get', to=jid)
- pb = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
- pb.addChild('subscriptions')
-
- id_ = self.connection.send(query)
-
- self.__callbacks[id_] = (cb, args, kwargs)
-
- def send_pb_subscribe(self, jid, node, cb, *args, **kwargs):
- if not self.connection or self.connected < 2:
- return
- our_jid = app.get_jid_from_account(self.name)
- query = nbxmpp.Iq('set', to=jid)
- pb = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
- pb.addChild('subscribe', {'node': node, 'jid': our_jid})
-
- id_ = self.connection.send(query)
-
- self.__callbacks[id_] = (cb, args, kwargs)
-
- def send_pb_unsubscribe(self, jid, node, cb, *args, **kwargs):
- if not self.connection or self.connected < 2:
- return
- our_jid = app.get_jid_from_account(self.name)
- query = nbxmpp.Iq('set', to=jid)
- pb = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
- pb.addChild('unsubscribe', {'node': node, 'jid': our_jid})
-
- id_ = self.connection.send(query)
-
- self.__callbacks[id_] = (cb, args, kwargs)
-
- def send_pb_publish(self, jid, node, item, id_=None, options=None):
- """
- Publish item to a node
- """
- if not self.connection or self.connected < 2:
- return
- query = nbxmpp.Iq('set', to=jid)
- e = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
- p = e.addChild('publish', {'node': node})
- attrs = {}
- if id_:
- attrs = {'id': id_}
- p.addChild('item', attrs, [item])
- if options:
- p = e.addChild('publish-options')
- p.addChild(node=options)
-
- self.connection.send(query)
-
- @staticmethod
- def get_pb_retrieve_iq(jid, node, item_id=None):
- """
- Get IQ to query items from a node
- """
- query = nbxmpp.Iq('get', to=jid)
- r = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
- r = r.addChild('items', {'node': node})
- if item_id is not None:
- r.addChild('item', {'id': item_id})
- return query
-
- def send_pb_retrieve(self, jid, node, item_id=None, cb=None, *args, **kwargs):
- """
- Get items from a node
- """
- if not self.connection or self.connected < 2:
- return
- query = self.get_pb_retrieve_iq(jid, node, item_id)
- id_ = self.connection.send(query)
-
- if cb:
- self.__callbacks[id_] = (cb, args, kwargs)
-
- def get_pubsub_avatar(self, jid, node, item_id):
- query = self.get_pb_retrieve_iq(jid, node, item_id)
- self.connection.SendAndCallForResponse(
- query, self._nec_pubsub_avatar_received, {'jid': jid})
-
- def send_pb_retract(self, jid, node, id_):
- """
- Delete item from a node
- """
- if not self.connection or self.connected < 2:
- return
- query = nbxmpp.Iq('set', to=jid)
- r = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
- r = r.addChild('retract', {'node': node, 'notify': '1'})
- r = r.addChild('item', {'id': id_})
-
- self.connection.send(query)
-
- def send_pb_purge(self, jid, node):
- """
- Purge node: Remove all items
- """
- if not self.connection or self.connected < 2:
- return
- query = nbxmpp.Iq('set', to=jid)
- d = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER)
- d = d.addChild('purge', {'node': node})
-
- self.connection.send(query)
-
- def send_pb_delete(self, jid, node, on_ok=None, on_fail=None):
- """
- Delete node
- """
- if not self.connection or self.connected < 2:
- return
- query = nbxmpp.Iq('set', to=jid)
- d = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER)
- d = d.addChild('delete', {'node': node})
-
- def response(con, resp, jid, node):
- if resp.getType() == 'result' and on_ok:
- on_ok(jid, node)
- elif on_fail:
- msg = resp.getErrorMsg()
- on_fail(jid, node, msg)
-
- self.connection.SendAndCallForResponse(query, response, {'jid': jid,
- 'node': node})
-
- def send_pb_create(self, jid, node, configure=False, configure_form=None):
- """
- Create a new node
- """
- if not self.connection or self.connected < 2:
- return
- query = nbxmpp.Iq('set', to=jid)
- c = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
- c = c.addChild('create', {'node': node})
- if configure:
- conf = c.addChild('configure')
- if configure_form is not None:
- conf.addChild(node=configure_form)
-
- self.connection.send(query)
-
- def send_pb_configure(self, jid, node, form):
- if not self.connection or self.connected < 2:
- return
- query = nbxmpp.Iq('set', to=jid)
- c = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER)
- c = c.addChild('configure', {'node': node})
- c.addChild(node=form)
-
- self.connection.send(query)
-
- def _PubSubCB(self, conn, stanza):
- log.debug('_PubsubCB')
- try:
- cb, args, kwargs = self.__callbacks.pop(stanza.getID())
- cb(conn, stanza, *args, **kwargs)
- except Exception:
- pass
- app.nec.push_incoming_event(PubsubReceivedEvent(None,
- conn=self, stanza=stanza))
-
- def _nec_pubsub_bookmarks_received(self, obj):
- if obj.conn.name != self.name:
- return
- app.log('bookmarks').info('Received Bookmarks (PubSub)')
- bm_jids = [b['jid'] for b in self.bookmarks]
- for bm in obj.bookmarks:
- if bm['jid'] not in bm_jids:
- self.bookmarks.append(bm)
- # We got bookmarks from pubsub, now get those from xml to merge them
- self.get_bookmarks(storage_type='xml')
-
- def _validate_avatar_node(self, stanza):
- jid = stanza.getFrom()
- if jid is None:
- jid = self.get_own_jid().getStripped()
- else:
- jid = jid.getStripped()
-
- if nbxmpp.isErrorNode(stanza):
- raise StanzaMalformed(stanza.getErrorMsg())
-
- pubsub_node = stanza.getTag('pubsub')
- if pubsub_node is None:
- raise StanzaMalformed('No pubsub node', stanza)
-
- items_node = pubsub_node.getTag('items')
- if items_node is None:
- raise StanzaMalformed('No items node', stanza)
-
- if items_node.getAttr('node') != 'urn:xmpp:avatar:data':
- raise StanzaMalformed('Wrong namespace', stanza)
-
- item = items_node.getTag('item')
- if item is None:
- raise StanzaMalformed('No item node', stanza)
-
- sha = item.getAttr('id')
- data_tag = item.getTag('data', namespace='urn:xmpp:avatar:data')
- if sha is None or data_tag is None:
- raise StanzaMalformed('No id attr or data node found', stanza)
-
- data = data_tag.getData()
- if data is None:
- raise StanzaMalformed('Data node empty', stanza)
-
- data = base64.b64decode(data.encode('utf-8'))
-
- return jid, sha, data
-
- def _nec_pubsub_avatar_received(self, conn, stanza, jid):
- try:
- jid, sha, data = self._validate_avatar_node(stanza)
- except (StanzaMalformed, binascii.Error) as error:
- app.log('avatar').warning(
- 'Error loading Avatar (Pubsub): %s %s', jid, error)
- return
-
- app.log('avatar').info(
- 'Received Avatar (Pubsub): %s %s', jid, sha)
- app.interface.save_avatar(data)
-
- if self.get_own_jid().bareMatch(jid):
- app.config.set_per('accounts', self.name, 'avatar_sha', sha)
- else:
- own_jid = self.get_own_jid().getStripped()
- app.logger.set_avatar_sha(own_jid, jid, sha)
- app.contacts.set_avatar(self.name, jid, sha)
-
- app.interface.update_avatar(self.name, jid)
-
- def _PubSubErrorCB(self, conn, stanza):
- log.debug('_PubsubErrorCB')
- pubsub = stanza.getTag('pubsub')
- if not pubsub:
- return
- items = pubsub.getTag('items')
- if not items:
- return
- if items.getAttr('node') == 'storage:bookmarks':
- # Receiving bookmarks from pubsub failed, so take them from xml
- self.get_bookmarks(storage_type='xml')
-
- def request_pb_configuration(self, jid, node):
- if not self.connection or self.connected < 2:
- return
- query = nbxmpp.Iq('get', to=jid)
- e = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER)
- e = e.addChild('configure', {'node': node})
- id_ = self.connection.getAnID()
- query.setID(id_)
- self.awaiting_answers[id_] = (PEP_CONFIG,)
- self.connection.send(query)
=====================================
gajim/config.py
=====================================
--- a/gajim/config.py
+++ b/gajim/config.py
@@ -1900,11 +1900,13 @@ class ManageBookmarksWindow:
iter_ = self.treestore.append(None, [None, account, None, None,
None, None, None, None])
- for bookmark in app.connections[account].bookmarks:
+ con = app.connections[account]
+ bookmarks = con.get_module('Bookmarks').bookmarks
+ for jid, bookmark in bookmarks.items():
if not bookmark['name']:
# No name was given for this bookmark.
# Use the first part of JID instead...
- name = bookmark['jid'].split("@")[0]
+ name = jid.split("@")[0]
bookmark['name'] = name
# make '1', '0', 'true', 'false' (or other) to True/False
@@ -1920,7 +1922,7 @@ class ManageBookmarksWindow:
self.treestore.append(iter_, [
account,
bookmark['name'],
- bookmark['jid'],
+ jid,
autojoin,
minimize,
bookmark['password'],
@@ -2047,15 +2049,17 @@ class ManageBookmarksWindow:
Parse the treestore data into our new bookmarks array, then send the new
bookmarks to the server.
"""
+
(model, iter_) = self.selection.get_selected()
if iter_ and model.iter_parent(iter_):
- #bookmark selected, check it
+ # bookmark selected, check it
if not self.check_valid_bookmark():
return
for account in self.treestore:
acct = account[1]
- app.connections[acct].bookmarks = []
+ con = app.connections[acct]
+ con.get_module('Bookmarks').bookmarks = {}
for bm in account.iterchildren():
# Convert True/False/None to '1' or '0'
@@ -2067,13 +2071,17 @@ class ManageBookmarksWindow:
nick = bm[6]
# create the bookmark-dict
- bmdict = { 'name': name, 'jid': jid, 'autojoin': autojoin,
- 'minimize': minimize, 'password': pw, 'nick': nick,
+ bmdict = {
+ 'name': name,
+ 'autojoin': autojoin,
+ 'minimize': minimize,
+ 'password': pw,
+ 'nick': nick,
'print_status': bm[7]}
- app.connections[acct].bookmarks.append(bmdict)
+ con.get_module('Bookmarks').bookmarks[jid] = bmdict
- app.connections[acct].store_bookmarks()
+ con.get_module('Bookmarks').store_bookmarks()
gui_menu_builder.build_bookmark_menu(acct)
self.window.destroy()
@@ -2900,8 +2908,10 @@ class ManagePEPServicesWindow:
model, iter_ = selection.get_selected()
node = model[iter_][0]
our_jid = app.get_jid_from_account(self.account)
- app.connections[self.account].send_pb_delete(our_jid, node,
- on_ok=self.node_removed, on_fail=self.node_not_removed)
+ con = app.connections[self.account]
+ con.get_module('PubSub').send_pb_delete(our_jid, node,
+ on_ok=self.node_removed,
+ on_fail=self.node_not_removed)
def on_configure_button_clicked(self, widget):
selection = self.treeview.get_selection()
@@ -2910,13 +2920,15 @@ class ManagePEPServicesWindow:
model, iter_ = selection.get_selected()
node = model[iter_][0]
our_jid = app.get_jid_from_account(self.account)
- app.connections[self.account].request_pb_configuration(our_jid, node)
+ con = app.connections[self.account]
+ con.get_module('PubSub').request_pb_configuration(our_jid, node)
def _nec_pep_config_received(self, obj):
def on_ok(form, node):
form.type_ = 'submit'
our_jid = app.get_jid_from_account(self.account)
- app.connections[self.account].send_pb_configure(our_jid, node, form)
+ con = app.connections[self.account]
+ con.get_module('PubSub').send_pb_configure(our_jid, node, form)
window = dialogs.DataFormWindow(obj.form, (on_ok, obj.node))
title = _('Configure %s') % obj.node
window.set_title(title)
=====================================
gajim/dialogs.py
=====================================
--- a/gajim/dialogs.py
+++ b/gajim/dialogs.py
@@ -2520,7 +2520,8 @@ class JoinGroupchatWindow(Gtk.ApplicationWindow):
self.autojoin_switch.set_sensitive(switch.get_active())
def _add_bookmark(self, account, nickname, password):
- if not app.connections[account].private_storage_supported:
+ con = app.connections[account]
+ if not con.private_storage_supported:
return
add_bookmark = self.bookmark_switch.get_active()
@@ -2531,8 +2532,8 @@ class JoinGroupchatWindow(Gtk.ApplicationWindow):
# Add as bookmark, with autojoin and not minimized
name = app.get_nick_from_jid(self.room_jid)
- app.interface.add_gc_bookmark(
- account, name, self.room_jid, autojoin, 1, password, nickname)
+ con.get_module('Bookmarks').add_bookmark(
+ name, self.room_jid, autojoin, 1, password, nickname)
def _on_destroy(self, *args):
if self.minimal_mode == 0:
@@ -2784,10 +2785,11 @@ class StartChatDialog(Gtk.ApplicationWindow):
show_account = len(self.accounts) > 1
for account in self.accounts:
self.new_groupchat_rows[account] = None
- bookmarks = app.connections[account].bookmarks
+ con = app.connections[account]
+ bookmarks = con.get_module('Bookmarks').bookmarks
groupchats = {}
- for bookmark in bookmarks:
- groupchats[bookmark['jid']] = bookmark['name']
+ for jid, bookmark in bookmarks.items():
+ groupchats[jid] = bookmark['name']
for jid in app.contacts.get_gc_list(account):
if jid in groupchats:
=====================================
gajim/disco.py
=====================================
--- a/gajim/disco.py
+++ b/gajim/disco.py
@@ -1757,29 +1757,29 @@ class MucBrowser(AgentBrowser):
self.join_button = None
def on_bookmark_button_clicked(self, *args):
+ con = app.connections[self.account]
model, iter = self.window.services_treeview.get_selection().get_selected()
if not iter:
return
name = app.config.get_per('accounts', self.account, 'name')
room_jid = model[iter][0]
bm = {
- 'name': room_jid.split('@')[0],
- 'jid': room_jid,
- 'autojoin': '0',
- 'minimize': '0',
- 'password': '',
- 'nick': name
+ 'name': room_jid.split('@')[0],
+ 'autojoin': '0',
+ 'minimize': '0',
+ 'password': '',
+ 'nick': name
}
- for bookmark in app.connections[self.account].bookmarks:
- if bookmark['jid'] == bm['jid']:
- dialogs.ErrorDialog( _('Bookmark already set'),
- _('Group Chat "%s" is already in your bookmarks.') % bm['jid'],
+ if room_jid in con.get_module('Bookmarks').bookmarks:
+ dialogs.ErrorDialog(
+ _('Bookmark already set'),
+ _('Group Chat "%s" is already in your bookmarks.') % room_jid,
transient_for=self.window.window)
- return
+ return
- app.connections[self.account].bookmarks.append(bm)
- app.connections[self.account].store_bookmarks()
+ con.get_module('Bookmarks').bookmarks[room_jid] = bm
+ con.get_module('Bookmarks').store_bookmarks()
gui_menu_builder.build_bookmark_menu(self.account)
@@ -1951,8 +1951,9 @@ class DiscussionGroupsBrowser(AgentBrowser):
self.subscribe_button = None
self.unsubscribe_button = None
- app.connections[account].send_pb_subscription_query(jid,
- self._on_pep_subscriptions)
+ con = app.connections[account]
+ con.get_module('PubSub').send_pb_subscription_query(
+ jid, self._on_pep_subscriptions)
def _create_treemodel(self):
"""
@@ -2122,10 +2123,11 @@ class DiscussionGroupsBrowser(AgentBrowser):
model, iter_ = self.window.services_treeview.get_selection().get_selected()
if iter_ is None: return
- groupnode = model.get_value(iter_, 1) # 1 = groupnode
+ node = model.get_value(iter_, 1) # 1 = groupnode
- app.connections[self.account].send_pb_subscribe(self.jid, groupnode,
- self._on_pep_subscribe, groupnode)
+ con = app.connections[self.account]
+ con.get_module('PubSub').send_pb_subscribe(
+ self.jid, node, self._on_pep_subscribe, groupnode=node)
def on_unsubscribe_button_clicked(self, widget):
"""
@@ -2134,10 +2136,11 @@ class DiscussionGroupsBrowser(AgentBrowser):
model, iter_ = self.window.services_treeview.get_selection().get_selected()
if iter_ is None: return
- groupnode = model.get_value(iter_, 1) # 1 = groupnode
+ node = model.get_value(iter_, 1) # 1 = groupnode
- app.connections[self.account].send_pb_unsubscribe(self.jid, groupnode,
- self._on_pep_unsubscribe, groupnode)
+ con = app.connections[self.account]
+ con.get_module('PubSub').send_pb_unsubscribe(
+ self.jid, node, self._on_pep_unsubscribe, groupnode=node)
def _on_pep_subscriptions(self, conn, request):
"""
@@ -2168,8 +2171,6 @@ class DiscussionGroupsBrowser(AgentBrowser):
# we now know subscriptions, update button states
self.update_actions()
- raise nbxmpp.NodeProcessed
-
def _on_pep_subscribe(self, conn, request, groupnode):
"""
We have just subscribed to a node. Update UI
@@ -2184,8 +2185,6 @@ class DiscussionGroupsBrowser(AgentBrowser):
self.update_actions()
- raise nbxmpp.NodeProcessed
-
def _on_pep_unsubscribe(self, conn, request, groupnode):
"""
We have just unsubscribed from a node. Update UI
@@ -2200,7 +2199,5 @@ class DiscussionGroupsBrowser(AgentBrowser):
self.update_actions()
- raise nbxmpp.NodeProcessed
-
# Fill the global agent type info dictionary
_agent_type_info = _gen_agent_type_info()
=====================================
gajim/groupchat_control.py
=====================================
--- a/gajim/groupchat_control.py
+++ b/gajim/groupchat_control.py
@@ -348,13 +348,10 @@ class GroupchatControl(ChatControlBase):
self.room_jid = self.contact.jid
self.nick = nick
self.new_nick = ''
- self.name = ''
- for bm in app.connections[self.account].bookmarks:
- if bm['jid'] == self.room_jid:
- self.name = bm['name']
- break
- if not self.name:
- self.name = self.room_jid.split('@')[0]
+
+ bm_module = app.connections[self.account].get_module('Bookmarks')
+ self.name = bm_module.get_name_from_bookmark(self.room_jid)
+
self.contact.name = self.name
self.widget_set_visible(self.xml.get_object('banner_eventbox'),
@@ -589,13 +586,9 @@ class GroupchatControl(ChatControlBase):
# Bookmarks
con = app.connections[self.account]
bookmark_support = con.bookmarks_available()
- not_bookmarked = True
- for bm in con.bookmarks:
- if bm['jid'] == self.room_jid:
- not_bookmarked = False
- break
+ bookmarked = self.room_jid in con.get_module('Bookmarks').bookmarks
win.lookup_action('bookmark-' + self.control_id).set_enabled(
- online and bookmark_support and not_bookmarked)
+ online and bookmark_support and not bookmarked)
# Request Voice
role = self.get_role(self.nick)
@@ -712,9 +705,10 @@ class GroupchatControl(ChatControlBase):
Bookmark the room, without autojoin and not minimized
"""
password = app.gc_passwords.get(self.room_jid, '')
- app.interface.add_gc_bookmark(
- self.account, self.name, self.room_jid,
- '0', '0', password, self.nick)
+ con = app.connections[self.account]
+ con.get_module('Bookmarks').add_bookmark(
+ self.name, self.room_jid,
+ '1', '1', password, self.nick)
self.update_actions()
def _on_request_voice(self, action, param):
=====================================
gajim/groups.py
=====================================
--- a/gajim/groups.py
+++ b/gajim/groups.py
@@ -67,7 +67,9 @@ class GroupsPostWindow:
item.addChild('content', {}, [buf.get_text(buf.get_start_iter(), buf.get_end_iter(), True)])
# publish it to node
- app.connections[self.account].send_pb_publish(self.servicejid, self.groupid, item, '0')
+ con = app.connections[self.account]
+ con.get_module('PubSub').send_pb_publish(
+ self.servicejid, self.groupid, item, '0')
# close the window
self.window.destroy()
=====================================
gajim/gui_interface.py
=====================================
--- a/gajim/gui_interface.py
+++ b/gajim/gui_interface.py
@@ -824,17 +824,7 @@ class Interface:
self.instances[account]['sub_request'][obj.jid].destroy()
def handle_event_bookmarks(self, obj):
- # ('BOOKMARKS', account, [{name,jid,autojoin,password,nick}, {}])
- # We received a bookmark item from the server (JEP48)
- # Auto join GC windows if necessary
-
- gui_menu_builder.build_bookmark_menu(obj.conn.name)
- invisible_show = app.SHOW_LIST.index('invisible')
- # do not autojoin if we are invisible
- if obj.conn.connected == invisible_show:
- return
-
- GLib.idle_add(self.auto_join_bookmarks, obj.conn.name)
+ gui_menu_builder.build_bookmark_menu(obj.account)
def handle_event_file_send_error(self, account, array):
jid = array[0]
@@ -1728,7 +1718,6 @@ class Interface:
if isinstance(ctrl, ChatControlBase):
ctrl.scroll_to_end()
-
def join_gc_minimal(self, account, room_jid, password=None,
transient_for=None):
if account is not None:
@@ -1738,9 +1727,10 @@ class Interface:
app.interface.join_gc_room(account, room_jid, '', '')
return
- for bookmark in app.connections[account].bookmarks:
- if bookmark['jid'] != room_jid:
- continue
+ con = app.connections[account]
+ bookmarks = con.get_module('Bookmarks').bookmarks
+ bookmark = bookmarks.get(room_jid, None)
+ if bookmark is not None:
app.interface.join_gc_room(
account, room_jid, bookmark['nick'], bookmark['password'])
return
@@ -2469,51 +2459,6 @@ class Interface:
return False
return True
- def auto_join_bookmarks(self, account):
- """
- Autojoin bookmarked GCs that have 'auto join' on for this account
- """
- for bm in app.connections[account].bookmarks:
- if bm['autojoin'] in ('1', 'true'):
- jid = bm['jid']
- # Only join non-opened groupchats. Opened one are already
- # auto-joined on re-connection
- if not jid in app.gc_connected[account]:
- # we are not already connected
- minimize = bm['minimize'] in ('1', 'true')
- self.join_gc_room(account, jid, bm['nick'],
- bm['password'], minimize = minimize)
-
- def add_gc_bookmark(self, account, name, jid, autojoin, minimize, password,
- nick):
- """
- Add a bookmark for this account, sorted in bookmark list
- """
- bm = {
- 'name': name,
- 'jid': jid,
- 'autojoin': autojoin,
- 'minimize': minimize,
- 'password': password,
- 'nick': nick
- }
- place_found = False
- index = 0
- # check for duplicate entry and respect alpha order
- for bookmark in app.connections[account].bookmarks:
- if bookmark['jid'] == bm['jid']:
- return
- if bookmark['name'] > bm['name']:
- place_found = True
- break
- index += 1
- if place_found:
- app.connections[account].bookmarks.insert(index, bm)
- else:
- app.connections[account].bookmarks.append(bm)
- app.connections[account].store_bookmarks()
- gui_menu_builder.build_bookmark_menu(account)
-
# does JID exist only within a groupchat?
def is_pm_contact(self, fjid, account):
bare_jid = app.get_jid_without_resource(fjid)
=====================================
gajim/gui_menu_builder.py
=====================================
--- a/gajim/gui_menu_builder.py
+++ b/gajim/gui_menu_builder.py
@@ -172,14 +172,15 @@ show_bookmarked=False, force_resource=False):
rooms2 = [] # a list of (room_jid, account) tuple
r_jids = [] # list of room jids
for account in connected_accounts:
- for room in app.connections[account].bookmarks:
- r_jid = room['jid']
- if r_jid in r_jids:
+ con = app.connections[account]
+ boomarks = con.get_module('Bookmarks').bookmarks
+ for jid, bookmark in boomarks.items():
+ if jid in r_jids:
continue
- if r_jid not in app.gc_connected[account] or not \
- app.gc_connected[account][r_jid]:
- rooms2.append((r_jid, account))
- r_jids.append(r_jid)
+ if jid not in app.gc_connected[account] or not \
+ app.gc_connected[account][jid]:
+ rooms2.append((jid, account))
+ r_jids.append(jid)
if not rooms2:
return
@@ -675,7 +676,9 @@ def get_groupchat_menu(control_id):
def get_bookmarks_menu(account, rebuild=False):
- if not app.connections[account].bookmarks:
+ con = app.connections[account]
+ boomarks = con.get_module('Bookmarks').bookmarks
+ if not boomarks:
return None
menu = Gio.Menu()
@@ -688,12 +691,12 @@ def get_bookmarks_menu(account, rebuild=False):
# Build Bookmarks
section = Gio.Menu()
- for bookmark in app.connections[account].bookmarks:
+ for jid, bookmark in boomarks.items():
name = bookmark['name']
if not name:
# No name was given for this bookmark.
# Use the first part of JID instead...
- name = bookmark['jid'].split("@")[0]
+ name = jid.split("@")[0]
# Shorten long names
name = (name[:42] + '..') if len(name) > 42 else name
@@ -703,7 +706,7 @@ def get_bookmarks_menu(account, rebuild=False):
# Create Variant Dict
dict_ = {'account': GLib.Variant('s', account),
- 'jid': GLib.Variant('s', bookmark['jid'])}
+ 'jid': GLib.Variant('s', jid)}
if bookmark['nick']:
dict_['nick'] = GLib.Variant('s', bookmark['nick'])
if bookmark['password']:
=====================================
gajim/roster_window.py
=====================================
--- a/gajim/roster_window.py
+++ b/gajim/roster_window.py
@@ -2154,7 +2154,8 @@ class RosterWindow:
auto=auto)
if was_invisible and status != 'offline':
# We come back from invisible, join bookmarks
- app.interface.auto_join_bookmarks(account)
+ con = app.connections[account]
+ con.get_module('Bookmarks').auto_join_bookmarks()
def chg_contact_status(self, contact, show, status, account):
@@ -2712,9 +2713,9 @@ class RosterWindow:
### FIXME: order callbacks in itself...
################################################################################
- def on_bookmark_menuitem_activate(self, widget, account, bookmark):
- app.interface.join_gc_room(account, bookmark['jid'], bookmark['nick'],
- bookmark['password'])
+ def on_bookmark_menuitem_activate(self, widget, account, jid, bookmark):
+ app.interface.join_gc_room(
+ account, jid, bookmark['nick'], bookmark['password'])
def on_info(self, widget, contact, account):
"""
@@ -5439,16 +5440,17 @@ class RosterWindow:
gc_sub_menu.append(item)
# User has at least one bookmark.
- if app.connections[account].bookmarks:
+ con = app.connections[account]
+ if con.get_module('Bookmarks').bookmarks:
item = Gtk.SeparatorMenuItem.new()
gc_sub_menu.append(item)
- for bookmark in app.connections[account].bookmarks:
+ for jid, bookmark in con.get_module('Bookmarks').bookmarks.items():
name = bookmark['name']
if not name:
# No name was given for this bookmark.
# Use the first part of JID instead...
- name = bookmark['jid'].split("@")[0]
+ name = jid.split("@")[0]
# Shorten long names
name = (name[:42] + '..') if len(name) > 42 else name
@@ -5456,8 +5458,9 @@ class RosterWindow:
# Do not use underline.
item = Gtk.MenuItem.new_with_label(name)
item.set_use_underline(False)
- item.connect('activate', self.on_bookmark_menuitem_activate,
- account, bookmark)
+ item.connect(
+ 'activate', self.on_bookmark_menuitem_activate,
+ account, jid, bookmark)
gc_sub_menu.append(item)
def show_appropriate_context_menu(self, event, iters):
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/2ca0ca38a59d5c944ff697d20cb373ce3945d2cd
--
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/2ca0ca38a59d5c944ff697d20cb373ce3945d2cd
You're receiving this email because of your account on dev.gajim.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.gajim.org/pipermail/commits/attachments/20180701/0b391208/attachment-0001.html>
More information about the Commits
mailing list