Add connect_maschine()
Add method that sequentially works the steps we have to do before sending first presence - Move Delimiter into own module - Move Metacontacts into own module
This commit is contained in:
parent
db77fa1ace
commit
5a6f03dea4
|
@ -415,7 +415,9 @@ def account_is_zeroconf(account):
|
|||
return connections[account].is_zeroconf
|
||||
|
||||
def account_supports_private_storage(account):
|
||||
return connections[account].private_storage_supported
|
||||
# If Delimiter module is not available we can assume
|
||||
# Private Storage is not available
|
||||
return connections[account].get_module('Delimiter').available
|
||||
|
||||
def account_is_connected(account):
|
||||
if account not in connections:
|
||||
|
|
|
@ -115,7 +115,6 @@ class CommonConnection:
|
|||
# the fake jid
|
||||
self.groupchat_jids = {} # {ID : groupchat_jid}
|
||||
|
||||
self.private_storage_supported = False
|
||||
self.roster_supported = True
|
||||
self.addressing_supported = False
|
||||
|
||||
|
@ -124,7 +123,8 @@ class CommonConnection:
|
|||
|
||||
self.awaiting_cids = {} # Used for XEP-0231
|
||||
|
||||
self.nested_group_delimiter = '::'
|
||||
# Tracks the calls of the connect_maschine() method
|
||||
self._connect_maschine_calls = 0
|
||||
|
||||
self.get_config_values_or_default()
|
||||
|
||||
|
@ -412,12 +412,6 @@ class CommonConnection:
|
|||
def account_changed(self, new_name):
|
||||
self.name = new_name
|
||||
|
||||
def get_metacontacts(self):
|
||||
"""
|
||||
To be implemented by derived classes
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def send_agent_status(self, agent, ptype):
|
||||
"""
|
||||
To be implemented by derived classes
|
||||
|
@ -546,8 +540,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
self.retrycount = 0
|
||||
self.available_transports = {} # list of available transports on this
|
||||
# server {'icq': ['icq.server.com', 'icq2.server.com'], }
|
||||
self.private_storage_supported = True
|
||||
self.privacy_rules_requested = False
|
||||
|
||||
self.streamError = ''
|
||||
self.secret_hmac = str(random.random())[2:].encode('utf-8')
|
||||
self.removing_account = False
|
||||
|
@ -644,7 +637,6 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
self.on_purpose = on_purpose
|
||||
self.connected = 0
|
||||
self.time_to_reconnect = None
|
||||
self.get_module('PrivacyLists').supported = False
|
||||
self.get_module('VCardAvatars').avatar_advertised = False
|
||||
if on_purpose:
|
||||
self.sm = Smacks(self)
|
||||
|
@ -1427,6 +1419,9 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
# Get annotations
|
||||
self.get_module('Annotations').get_annotations()
|
||||
|
||||
# Blocking
|
||||
self.get_module('Blocking').get_blocking_list()
|
||||
|
||||
# Inform GUI we just signed in
|
||||
app.nec.push_incoming_event(SignedInEvent(None, conn=self))
|
||||
|
||||
|
@ -1455,60 +1450,39 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
self.pingalives, self.get_module('Ping').send_keepalive_ping)
|
||||
self.connection.onreceive(None)
|
||||
|
||||
self.privacy_rules_requested = False
|
||||
|
||||
# If we are not resuming, we ask for discovery info
|
||||
# and archiving preferences
|
||||
if not self.sm.supports_sm or (not self.sm.resuming and self.sm.enabled):
|
||||
our_server = app.config.get_per('accounts', self.name, 'hostname')
|
||||
self.get_module('Discovery').discover_account_info()
|
||||
# This starts the connect_maschine
|
||||
self.get_module('Discovery').discover_server_info()
|
||||
else:
|
||||
self.request_roster(resume=True)
|
||||
self.get_module('Discovery').discover_account_info()
|
||||
|
||||
self.sm.resuming = False # back to previous state
|
||||
# Discover Stun server(s)
|
||||
if self._proxy is None:
|
||||
hostname = app.config.get_per('accounts', self.name, 'hostname')
|
||||
app.resolver.resolve('_stun._udp.' + helpers.idn_to_ascii(hostname),
|
||||
app.resolver.resolve(
|
||||
'_stun._udp.' + helpers.idn_to_ascii(hostname),
|
||||
self._on_stun_resolved)
|
||||
|
||||
def _on_stun_resolved(self, host, result_array):
|
||||
if len(result_array) != 0:
|
||||
self._stun_servers = self._hosts = [i for i in result_array]
|
||||
|
||||
def _continue_connection_request_privacy(self):
|
||||
if self.get_module('PrivacyLists').supported:
|
||||
if not self.privacy_rules_requested:
|
||||
self.privacy_rules_requested = True
|
||||
self.get_module('PrivacyLists').get_privacy_lists(
|
||||
self._received_privacy)
|
||||
else:
|
||||
# Privacy lists not supported
|
||||
log.info('Privacy Lists not supported')
|
||||
self._received_privacy(False)
|
||||
|
||||
def _received_privacy(self, result):
|
||||
if not result:
|
||||
if (self.continue_connect_info and
|
||||
self.continue_connect_info[0] == 'invisible'):
|
||||
# Trying to login as invisible but privacy list not
|
||||
# supported
|
||||
self.disconnect(on_purpose=True)
|
||||
app.nec.push_incoming_event(OurShowEvent(
|
||||
None, conn=self, show='offline'))
|
||||
app.nec.push_incoming_event(InformationEvent(
|
||||
None, dialog_name='invisibility-not-supported',
|
||||
args=self.name))
|
||||
return
|
||||
|
||||
self.get_module('Blocking').get_blocking_list()
|
||||
|
||||
# Ask metacontacts before roster
|
||||
self.get_metacontacts()
|
||||
@helpers.call_counter
|
||||
def connect_maschine(self, restart=False):
|
||||
log.info('Connect maschine state: %s', self._connect_maschine_calls)
|
||||
if self._connect_maschine_calls == 1:
|
||||
self.get_module('MetaContacts').get_metacontacts()
|
||||
elif self._connect_maschine_calls == 2:
|
||||
self.get_module('Delimiter').get_roster_delimiter()
|
||||
elif self._connect_maschine_calls == 3:
|
||||
self.get_module('Roster').request_roster()
|
||||
elif self._connect_maschine_calls == 4:
|
||||
self.send_first_presence()
|
||||
|
||||
def send_custom_status(self, show, msg, jid):
|
||||
if not show in app.SHOW_LIST:
|
||||
if show not in app.SHOW_LIST:
|
||||
return -1
|
||||
if not app.account_is_connected(self.name):
|
||||
return
|
||||
|
@ -1677,85 +1651,9 @@ class Connection(CommonConnection, ConnectionHandlers):
|
|||
query.setTagData('prompt', prompt)
|
||||
self.connection.SendAndCallForResponse(iq, _on_prompt_result)
|
||||
|
||||
def bookmarks_available(self):
|
||||
if self.private_storage_supported:
|
||||
return True
|
||||
if self.get_module('PubSub').publish_options:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_roster_delimiter(self):
|
||||
"""
|
||||
Get roster group delimiter from storage as described in XEP 0083
|
||||
"""
|
||||
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='roster', namespace='roster:delimiter')
|
||||
id_ = self.connection.getAnID()
|
||||
iq.setID(id_)
|
||||
self.awaiting_answers[id_] = (DELIMITER_ARRIVED, )
|
||||
self.connection.send(iq)
|
||||
|
||||
def set_roster_delimiter(self, delimiter='::'):
|
||||
"""
|
||||
Set roster group delimiter to the storage namespace
|
||||
"""
|
||||
if not app.account_is_connected(self.name):
|
||||
return
|
||||
iq = nbxmpp.Iq(typ='set')
|
||||
iq2 = iq.addChild(name='query', namespace=nbxmpp.NS_PRIVATE)
|
||||
iq3 = iq2.addChild(name='roster', namespace='roster:delimiter')
|
||||
iq3.setData(delimiter)
|
||||
|
||||
self.connection.send(iq)
|
||||
|
||||
def get_metacontacts(self):
|
||||
"""
|
||||
Get metacontacts list from storage as described in XEP 0049
|
||||
"""
|
||||
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:metacontacts')
|
||||
id_ = self.connection.getAnID()
|
||||
iq.setID(id_)
|
||||
self.awaiting_answers[id_] = (METACONTACTS_ARRIVED, )
|
||||
self.connection.send(iq)
|
||||
|
||||
def store_metacontacts(self, tags_list):
|
||||
"""
|
||||
Send meta contacts to the storage namespace
|
||||
"""
|
||||
if not app.account_is_connected(self.name):
|
||||
return
|
||||
iq = nbxmpp.Iq(typ='set')
|
||||
iq2 = iq.addChild(name='query', namespace=nbxmpp.NS_PRIVATE)
|
||||
iq3 = iq2.addChild(name='storage', namespace='storage:metacontacts')
|
||||
for tag in tags_list:
|
||||
for data in tags_list[tag]:
|
||||
jid = data['jid']
|
||||
dict_ = {'jid': jid, 'tag': tag}
|
||||
if 'order' in data:
|
||||
dict_['order'] = data['order']
|
||||
iq3.addChild(name='meta', attrs=dict_)
|
||||
self.connection.send(iq)
|
||||
|
||||
def getRoster(self):
|
||||
return self.get_module('Roster')
|
||||
|
||||
def request_roster(self, resume=False):
|
||||
version = None
|
||||
features = self.connection.Dispatcher.Stream.features
|
||||
if features and features.getTag('ver', namespace=nbxmpp.NS_ROSTER_VER):
|
||||
version = app.config.get_per(
|
||||
'accounts', self.name, 'roster_version')
|
||||
|
||||
if not resume:
|
||||
self.get_module('Roster').request_roster(version)
|
||||
|
||||
def send_agent_status(self, agent, ptype):
|
||||
if not app.account_is_connected(self.name):
|
||||
return
|
||||
|
|
|
@ -53,10 +53,6 @@ log = logging.getLogger('gajim.c.connection_handlers')
|
|||
|
||||
# kind of events we can wait for an answer
|
||||
AGENT_REMOVED = 'agent_removed'
|
||||
METACONTACTS_ARRIVED = 'metacontacts_arrived'
|
||||
ROSTER_ARRIVED = 'roster_arrived'
|
||||
DELIMITER_ARRIVED = 'delimiter_arrived'
|
||||
PRIVACY_ARRIVED = 'privacy_arrived'
|
||||
|
||||
|
||||
class ConnectionDisco:
|
||||
|
@ -518,35 +514,6 @@ class ConnectionHandlers(ConnectionSocks5Bytestream, ConnectionDisco,
|
|||
app.nec.push_incoming_event(AgentRemovedEvent(None, conn=self,
|
||||
agent=jid))
|
||||
del self.awaiting_answers[id_]
|
||||
elif self.awaiting_answers[id_][0] == METACONTACTS_ARRIVED:
|
||||
if not self.connection:
|
||||
return
|
||||
if iq_obj.getType() == 'result':
|
||||
app.nec.push_incoming_event(MetacontactsReceivedEvent(None,
|
||||
conn=self, stanza=iq_obj))
|
||||
else:
|
||||
if iq_obj.getErrorCode() not in ('403', '406', '404'):
|
||||
self.private_storage_supported = False
|
||||
self.get_roster_delimiter()
|
||||
del self.awaiting_answers[id_]
|
||||
elif self.awaiting_answers[id_][0] == DELIMITER_ARRIVED:
|
||||
del self.awaiting_answers[id_]
|
||||
if not self.connection:
|
||||
return
|
||||
if iq_obj.getType() == 'result':
|
||||
query = iq_obj.getTag('query')
|
||||
if not query:
|
||||
return
|
||||
delimiter = query.getTagData('roster')
|
||||
if delimiter:
|
||||
self.nested_group_delimiter = delimiter
|
||||
else:
|
||||
self.set_roster_delimiter('::')
|
||||
else:
|
||||
self.private_storage_supported = False
|
||||
|
||||
# We can now continue connection by requesting the roster
|
||||
self.request_roster()
|
||||
|
||||
def _dispatch_gc_msg_with_captcha(self, stanza, msg_obj):
|
||||
msg_obj.stanza = stanza
|
||||
|
|
|
@ -852,37 +852,6 @@ class UpdateRoomAvatarEvent(nec.NetworkIncomingEvent):
|
|||
def generate(self):
|
||||
return True
|
||||
|
||||
class MetacontactsReceivedEvent(nec.NetworkIncomingEvent):
|
||||
name = 'metacontacts-received'
|
||||
base_network_events = []
|
||||
|
||||
def generate(self):
|
||||
# Metacontact tags
|
||||
# http://www.xmpp.org/extensions/xep-0209.html
|
||||
self.meta_list = {}
|
||||
query = self.stanza.getTag('query')
|
||||
storage = query.getTag('storage')
|
||||
metas = storage.getTags('meta')
|
||||
for meta in metas:
|
||||
try:
|
||||
jid = helpers.parse_jid(meta.getAttr('jid'))
|
||||
except helpers.InvalidFormat:
|
||||
continue
|
||||
tag = meta.getAttr('tag')
|
||||
data = {'jid': jid}
|
||||
order = meta.getAttr('order')
|
||||
try:
|
||||
order = int(order)
|
||||
except Exception:
|
||||
order = 0
|
||||
if order is not None:
|
||||
data['order'] = order
|
||||
if tag in self.meta_list:
|
||||
self.meta_list[tag].append(data)
|
||||
else:
|
||||
self.meta_list[tag] = [data]
|
||||
return True
|
||||
|
||||
class ZeroconfNameConflictEvent(nec.NetworkIncomingEvent):
|
||||
name = 'zeroconf-name-conflict'
|
||||
base_network_events = []
|
||||
|
|
|
@ -732,7 +732,8 @@ class MetacontactManager():
|
|||
self._metacontacts_tags[brother_account][tag] = [{'jid': brother_jid,
|
||||
'tag': tag}]
|
||||
if brother_account != account:
|
||||
common.app.connections[brother_account].store_metacontacts(
|
||||
con = common.app.connections[brother_account]
|
||||
con.get_module('MetaContacts').store_metacontacts(
|
||||
self._metacontacts_tags[brother_account])
|
||||
# be sure jid has no other tag
|
||||
old_tag = self._get_metacontacts_tag(account, jid)
|
||||
|
@ -748,11 +749,12 @@ class MetacontactManager():
|
|||
else:
|
||||
self._metacontacts_tags[account][tag].append({'jid': jid,
|
||||
'tag': tag})
|
||||
common.app.connections[account].store_metacontacts(
|
||||
con = common.app.connections[account]
|
||||
con.get_module('MetaContacts').store_metacontacts(
|
||||
self._metacontacts_tags[account])
|
||||
|
||||
def remove_metacontact(self, account, jid):
|
||||
if not account in self._metacontacts_tags:
|
||||
if account not in self._metacontacts_tags:
|
||||
return
|
||||
|
||||
found = None
|
||||
|
@ -763,7 +765,8 @@ class MetacontactManager():
|
|||
break
|
||||
if found:
|
||||
self._metacontacts_tags[account][tag].remove(found)
|
||||
common.app.connections[account].store_metacontacts(
|
||||
con = common.app.connections[account]
|
||||
con.get_module('MetaContacts').store_metacontacts(
|
||||
self._metacontacts_tags[account])
|
||||
break
|
||||
|
||||
|
|
|
@ -1508,3 +1508,11 @@ def get_emoticon_theme_path(theme):
|
|||
emoticons_user_path = os.path.join(configpaths.get('MY_EMOTS'), theme)
|
||||
if os.path.exists(emoticons_user_path):
|
||||
return emoticons_user_path
|
||||
|
||||
def call_counter(func):
|
||||
def helper(self, restart=False):
|
||||
if restart:
|
||||
self._connect_maschine_calls = 0
|
||||
self._connect_maschine_calls += 1
|
||||
return func(self, restart=False)
|
||||
return helper
|
||||
|
|
|
@ -43,7 +43,7 @@ class ModuleMock:
|
|||
def __init__(self, name):
|
||||
self._name = name
|
||||
|
||||
# HTTPUpload
|
||||
# HTTPUpload, ..
|
||||
self.available = False
|
||||
|
||||
# Blocking
|
||||
|
@ -54,6 +54,9 @@ class ModuleMock:
|
|||
self.blocked_groups = []
|
||||
self.blocked_all = False
|
||||
|
||||
# Delimiter
|
||||
self.delimiter = '::'
|
||||
|
||||
# Bookmarks
|
||||
self.bookmarks = {}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ class Bookmarks:
|
|||
self._con = con
|
||||
self._account = con.name
|
||||
self.bookmarks = {}
|
||||
self.available = False
|
||||
|
||||
self.handlers = []
|
||||
|
||||
|
@ -65,6 +66,7 @@ class Bookmarks:
|
|||
self._request_private_bookmarks()
|
||||
return
|
||||
|
||||
self.available = True
|
||||
log.info('Received Bookmarks (PubSub)')
|
||||
self._parse_bookmarks(stanza)
|
||||
self._request_private_bookmarks()
|
||||
|
@ -84,6 +86,7 @@ class Bookmarks:
|
|||
if not nbxmpp.isResultNode(stanza):
|
||||
log.info('No private bookmarks: %s', stanza.getError())
|
||||
else:
|
||||
self.available = True
|
||||
log.info('Received Bookmarks (PrivateStorage)')
|
||||
merged = self._parse_bookmarks(stanza, check_merge=True)
|
||||
if merged and self._pubsub_support():
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
# 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-0083: Nested Roster Groups
|
||||
|
||||
import logging
|
||||
|
||||
import nbxmpp
|
||||
|
||||
log = logging.getLogger('gajim.c.m.delimiter')
|
||||
|
||||
|
||||
class Delimiter:
|
||||
def __init__(self, con):
|
||||
self._con = con
|
||||
self._account = con.name
|
||||
self.available = False
|
||||
|
||||
self.delimiter = '::'
|
||||
|
||||
self.handlers = []
|
||||
|
||||
def get_roster_delimiter(self):
|
||||
log.info('Request')
|
||||
node = nbxmpp.Node('storage', attrs={'xmlns': 'roster:delimiter'})
|
||||
iq = nbxmpp.Iq('get', nbxmpp.NS_PRIVATE, payload=node)
|
||||
|
||||
self._con.connection.SendAndCallForResponse(
|
||||
iq, self._delimiter_received)
|
||||
|
||||
def _delimiter_received(self, stanza):
|
||||
if not nbxmpp.isResultNode(stanza):
|
||||
log.info('Request error: %s', stanza.getError())
|
||||
else:
|
||||
delimiter = stanza.getQuery().getTagData('roster')
|
||||
self.available = True
|
||||
log.info('Delimiter received: %s', delimiter)
|
||||
if delimiter:
|
||||
self.delimiter = delimiter
|
||||
else:
|
||||
self.set_roster_delimiter()
|
||||
|
||||
self._con.connect_maschine()
|
||||
|
||||
def set_roster_delimiter(self):
|
||||
log.info('Set delimiter')
|
||||
iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVATE)
|
||||
roster = iq.getQuery().addChild('roster', namespace='roster:delimiter')
|
||||
roster.setData('::')
|
||||
|
||||
self._con.connection.SendAndCallForResponse(
|
||||
iq, self._set_delimiter_response)
|
||||
|
||||
def _set_delimiter_response(self, stanza):
|
||||
if not nbxmpp.isResultNode(stanza):
|
||||
log.info('Store error: %s', stanza.getError())
|
||||
|
||||
|
||||
def get_instance(*args, **kwargs):
|
||||
return Delimiter(*args, **kwargs), 'Delimiter'
|
|
@ -199,7 +199,7 @@ class Discovery:
|
|||
if nbxmpp.NS_ADDRESS in features:
|
||||
self._con.addressing_supported = True
|
||||
|
||||
self._con._continue_connection_request_privacy()
|
||||
self._con.connect_maschine()
|
||||
|
||||
def _parse_transports(self, from_, identities, features, data, node):
|
||||
for identity in identities:
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
# 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-0209: Metacontacts
|
||||
|
||||
import logging
|
||||
|
||||
import nbxmpp
|
||||
|
||||
from gajim.common import app
|
||||
from gajim.common import helpers
|
||||
from gajim.common.nec import NetworkEvent
|
||||
|
||||
log = logging.getLogger('gajim.c.m.metacontacts')
|
||||
|
||||
|
||||
class MetaContacts:
|
||||
def __init__(self, con):
|
||||
self._con = con
|
||||
self._account = con.name
|
||||
self.available = False
|
||||
|
||||
self.handlers = []
|
||||
|
||||
def get_metacontacts(self):
|
||||
log.info('Request')
|
||||
node = nbxmpp.Node('storage', attrs={'xmlns': 'storage:metacontacts'})
|
||||
iq = nbxmpp.Iq('get', nbxmpp.NS_PRIVATE, payload=node)
|
||||
|
||||
self._con.connection.SendAndCallForResponse(
|
||||
iq, self._metacontacts_received)
|
||||
|
||||
def _metacontacts_received(self, stanza):
|
||||
if not nbxmpp.isResultNode(stanza):
|
||||
log.info('Request error: %s', stanza.getError())
|
||||
else:
|
||||
self.available = True
|
||||
meta_list = self._parse_metacontacts(stanza)
|
||||
|
||||
log.info('Received: %s', meta_list)
|
||||
|
||||
app.nec.push_incoming_event(NetworkEvent(
|
||||
'metacontacts-received', conn=self._con, meta_list=meta_list))
|
||||
|
||||
self._con.connect_maschine()
|
||||
|
||||
@staticmethod
|
||||
def _parse_metacontacts(stanza):
|
||||
meta_list = {}
|
||||
query = stanza.getQuery()
|
||||
storage = query.getTag('storage')
|
||||
metas = storage.getTags('meta')
|
||||
for meta in metas:
|
||||
try:
|
||||
jid = helpers.parse_jid(meta.getAttr('jid'))
|
||||
except helpers.InvalidFormat:
|
||||
continue
|
||||
tag = meta.getAttr('tag')
|
||||
data = {'jid': jid}
|
||||
order = meta.getAttr('order')
|
||||
try:
|
||||
order = int(order)
|
||||
except Exception:
|
||||
order = 0
|
||||
if order is not None:
|
||||
data['order'] = order
|
||||
if tag in meta_list:
|
||||
meta_list[tag].append(data)
|
||||
else:
|
||||
meta_list[tag] = [data]
|
||||
return meta_list
|
||||
|
||||
def store_metacontacts(self, tags_list):
|
||||
if not app.account_is_connected(self._account):
|
||||
return
|
||||
iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVATE)
|
||||
meta = iq.getQuery().addChild('storage',
|
||||
namespace='storage:metacontacts')
|
||||
for tag in tags_list:
|
||||
for data in tags_list[tag]:
|
||||
jid = data['jid']
|
||||
dict_ = {'jid': jid, 'tag': tag}
|
||||
if 'order' in data:
|
||||
dict_['order'] = data['order']
|
||||
meta.addChild(name='meta', attrs=dict_)
|
||||
log.info('Store: %s', tags_list)
|
||||
self._con.connection.SendAndCallForResponse(
|
||||
iq, self._store_response_received)
|
||||
|
||||
def _store_response_received(self, stanza):
|
||||
if not nbxmpp.isResultNode(stanza):
|
||||
log.info('Store error: %s', stanza.getError())
|
||||
|
||||
|
||||
def get_instance(*args, **kwargs):
|
||||
return MetaContacts(*args, **kwargs), 'MetaContacts'
|
|
@ -24,10 +24,6 @@ from gajim.common.nec import NetworkEvent
|
|||
|
||||
log = logging.getLogger('gajim.c.m.roster')
|
||||
|
||||
|
||||
# TODO: Error IQs
|
||||
# What if roster not supported on server -> error
|
||||
|
||||
RosterItem = namedtuple('RosterItem', 'jid data')
|
||||
|
||||
|
||||
|
@ -65,7 +61,13 @@ class Roster:
|
|||
app.config.set_per(
|
||||
'accounts', self._account, 'roster_version', '')
|
||||
|
||||
def request_roster(self, version):
|
||||
def request_roster(self):
|
||||
version = None
|
||||
features = self._con.connection.Dispatcher.Stream.features
|
||||
if features and features.getTag('ver', namespace=nbxmpp.NS_ROSTER_VER):
|
||||
version = app.config.get_per(
|
||||
'accounts', self._account, 'roster_version')
|
||||
|
||||
log.info('Requested from server')
|
||||
iq = nbxmpp.Iq('get', nbxmpp.NS_ROSTER)
|
||||
if version is not None:
|
||||
|
@ -77,8 +79,7 @@ class Roster:
|
|||
def _roster_received(self, stanza):
|
||||
if not nbxmpp.isResultNode(stanza):
|
||||
log.warning('Unable to retrive roster: %s', stanza.getError())
|
||||
return
|
||||
|
||||
else:
|
||||
log.info('Received Roster')
|
||||
received_from_server = False
|
||||
if stanza.getTag('query') is not None:
|
||||
|
@ -97,7 +98,7 @@ class Roster:
|
|||
roster=self._data.copy(),
|
||||
received_from_server=received_from_server))
|
||||
|
||||
self._con.send_first_presence()
|
||||
self._con.connect_maschine()
|
||||
|
||||
def _roster_push_received(self, con, stanza):
|
||||
log.info('Push received')
|
||||
|
|
|
@ -183,11 +183,3 @@ connection_handlers.ConnectionJingle):
|
|||
|
||||
app.nec.push_incoming_event(
|
||||
DecryptedMessageReceivedEvent(None, **vars(event)))
|
||||
|
||||
def store_metacontacts(self, tags):
|
||||
"""
|
||||
Fake empty method
|
||||
"""
|
||||
# serverside metacontacts are not supported with zeroconf
|
||||
# (there is no server)
|
||||
pass
|
||||
|
|
|
@ -592,7 +592,7 @@ class GroupchatControl(ChatControlBase):
|
|||
|
||||
# Bookmarks
|
||||
con = app.connections[self.account]
|
||||
bookmark_support = con.bookmarks_available()
|
||||
bookmark_support = con.get_module('Bookmarks').available
|
||||
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)
|
||||
|
|
|
@ -111,7 +111,8 @@ class JoinGroupchatWindow(Gtk.ApplicationWindow):
|
|||
|
||||
# Set bookmark switch sensitive if server supports bookmarks
|
||||
acc = self.account_combo.get_active_id()
|
||||
if not app.connections[acc].private_storage_supported:
|
||||
con = app.connections[acc]
|
||||
if not con.get_module('Bookmarks').available:
|
||||
self.bookmark_switch.set_sensitive(False)
|
||||
self.autojoin_switch.set_sensitive(False)
|
||||
|
||||
|
@ -256,8 +257,6 @@ class JoinGroupchatWindow(Gtk.ApplicationWindow):
|
|||
|
||||
def _add_bookmark(self, account, nickname, password):
|
||||
con = app.connections[account]
|
||||
if not con.private_storage_supported:
|
||||
return
|
||||
|
||||
add_bookmark = self.bookmark_switch.get_active()
|
||||
if not add_bookmark:
|
||||
|
|
|
@ -343,7 +343,7 @@ class RosterWindow:
|
|||
account_group = 'MERGED'
|
||||
else:
|
||||
account_group = account
|
||||
delimiter = app.connections[account].nested_group_delimiter
|
||||
delimiter = app.connections[account].get_module('Delimiter').delimiter
|
||||
group_splited = group.split(delimiter)
|
||||
parent_group = delimiter.join(group_splited[:-1])
|
||||
if len(group_splited) > 1 and parent_group in self._iters[account_group]['groups']:
|
||||
|
@ -1347,7 +1347,7 @@ class RosterWindow:
|
|||
self.draw_parent_contact(jid, account)
|
||||
|
||||
if visible:
|
||||
delimiter = app.connections[account].nested_group_delimiter
|
||||
delimiter = app.connections[account].get_module('Delimiter').delimiter
|
||||
for group in contact.get_shown_groups():
|
||||
group_splited = group.split(delimiter)
|
||||
i = 1
|
||||
|
@ -1600,7 +1600,7 @@ class RosterWindow:
|
|||
return
|
||||
if account not in app.connections:
|
||||
return
|
||||
delimiter = app.connections[account].nested_group_delimiter
|
||||
delimiter = app.connections[account].get_module('Delimiter').delimiter
|
||||
group_splited = group.split(delimiter)
|
||||
i = 1
|
||||
while i < len(group_splited) + 1:
|
||||
|
@ -4159,9 +4159,10 @@ class RosterWindow:
|
|||
|
||||
def on_drop_in_contact(self, widget, account_source, c_source, account_dest,
|
||||
c_dest, was_big_brother, context, etime):
|
||||
|
||||
if not app.connections[account_source].private_storage_supported or \
|
||||
not app.connections[account_dest].private_storage_supported:
|
||||
con_source = app.connections[account_source]
|
||||
con_dest = app.connections[account_dest]
|
||||
if (not con_source.get_module('MetaContacts').available or
|
||||
not con_dest.get_module('MetaContacts').available):
|
||||
WarningDialog(_('Metacontacts storage not supported by '
|
||||
'your server'),
|
||||
_('Your server does not support storing metacontacts '
|
||||
|
@ -4433,7 +4434,7 @@ class RosterWindow:
|
|||
# drop on another account
|
||||
return
|
||||
grp_source = model[iter_source][Column.JID]
|
||||
delimiter = app.connections[account_source].nested_group_delimiter
|
||||
delimiter = app.connections[account_source].get_module('Delimiter').delimiter
|
||||
grp_source_list = grp_source.split(delimiter)
|
||||
new_grp = None
|
||||
if type_dest == 'account':
|
||||
|
|
|
@ -221,8 +221,6 @@ class StatusIcon:
|
|||
if connected_accounts < 1:
|
||||
item.set_sensitive(False)
|
||||
|
||||
connected_accounts_with_private_storage = 0
|
||||
|
||||
item = Gtk.SeparatorMenuItem.new()
|
||||
sub_menu.append(item)
|
||||
|
||||
|
@ -271,8 +269,6 @@ class StatusIcon:
|
|||
for account in app.connections:
|
||||
if app.account_is_connected(account) and \
|
||||
not app.config.get_per('accounts', account, 'is_zeroconf'):
|
||||
if app.connections[account].private_storage_supported:
|
||||
connected_accounts_with_private_storage += 1
|
||||
|
||||
# for single message
|
||||
single_message_menuitem.set_submenu(None)
|
||||
|
@ -296,8 +292,6 @@ class StatusIcon:
|
|||
if app.connections[account].is_zeroconf or \
|
||||
not app.account_is_connected(account):
|
||||
continue
|
||||
if app.connections[account].private_storage_supported:
|
||||
connected_accounts_with_private_storage += 1
|
||||
# for single message
|
||||
item = Gtk.MenuItem.new_with_label(
|
||||
_('using account %s') % account_label)
|
||||
|
@ -320,9 +314,12 @@ class StatusIcon:
|
|||
newitem = Gtk.MenuItem.new_with_mnemonic(_('_Manage Bookmarks…'))
|
||||
newitem.connect('activate',
|
||||
app.interface.roster.on_manage_bookmarks_menuitem_activate)
|
||||
gc_sub_menu.append(newitem)
|
||||
if connected_accounts_with_private_storage == 0:
|
||||
newitem.set_sensitive(False)
|
||||
gc_sub_menu.append(newitem)
|
||||
for account in accounts_list:
|
||||
if app.account_supports_private_storage(account):
|
||||
newitem.set_sensitive(True)
|
||||
break
|
||||
|
||||
sounds_mute_menuitem.set_active(not app.config.get('sounds_on'))
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ class MockConnection(Mock, ConnectionHandlers):
|
|||
self.connected = 2
|
||||
self.pep = {}
|
||||
self.sessions = {}
|
||||
self.nested_group_delimiter = '::'
|
||||
self.server_resource = 'Gajim'
|
||||
|
||||
app.interface.instances[account] = {'infos': {}, 'disco': {},
|
||||
|
|
Loading…
Reference in New Issue