142 lines
5.2 KiB
Python
142 lines
5.2 KiB
Python
|
|
# Slixmpp: The Slick XMPP Library
|
|
# Copyright (C) 2011 Nathanael C. Fritz, Lance J.T. Stout
|
|
# This file is part of Slixmpp.
|
|
# See the file LICENSE for copying permission.
|
|
import logging
|
|
|
|
from slixmpp.xmlstream import JID
|
|
from slixmpp.exceptions import IqError, IqTimeout
|
|
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
class StaticCaps(object):
|
|
|
|
"""
|
|
Extend the default StaticDisco implementation to provide
|
|
support for extended identity information.
|
|
"""
|
|
|
|
def __init__(self, xmpp, static):
|
|
"""
|
|
Augment the default XEP-0030 static handler object.
|
|
|
|
Arguments:
|
|
static -- The default static XEP-0030 handler object.
|
|
"""
|
|
self.xmpp = xmpp
|
|
self.disco = self.xmpp['xep_0030']
|
|
self.caps = self.xmpp['xep_0115']
|
|
self.static = static
|
|
self.jid_vers = {}
|
|
|
|
async def supports(self, jid, node, ifrom, data):
|
|
"""
|
|
Check if a JID supports a given feature.
|
|
|
|
The data parameter may provide:
|
|
feature -- The feature to check for support.
|
|
local -- If true, then the query is for a JID/node
|
|
combination handled by this Slixmpp instance and
|
|
no stanzas need to be sent.
|
|
Otherwise, a disco stanza must be sent to the
|
|
remove JID to retrieve the info.
|
|
cached -- If true, then look for the disco info data from
|
|
the local cache system. If no results are found,
|
|
send the query as usual. The self.use_cache
|
|
setting must be set to true for this option to
|
|
be useful. If set to false, then the cache will
|
|
be skipped, even if a result has already been
|
|
cached. Defaults to false.
|
|
"""
|
|
feature = data.get('feature', None)
|
|
|
|
data = {'local': data.get('local', False),
|
|
'cached': data.get('cached', True)}
|
|
|
|
if not feature:
|
|
return False
|
|
|
|
if node in (None, ''):
|
|
info = await self.caps.get_caps(jid)
|
|
if info and feature in info['features']:
|
|
return True
|
|
|
|
try:
|
|
info = await self.disco.get_info(jid=jid, node=node,
|
|
ifrom=ifrom, **data)
|
|
info = self.disco._wrap(ifrom, jid, info, True)
|
|
return feature in info['disco_info']['features']
|
|
except IqError:
|
|
return False
|
|
except IqTimeout:
|
|
return None
|
|
|
|
async def has_identity(self, jid, node, ifrom, data):
|
|
"""
|
|
Check if a JID has a given identity.
|
|
|
|
The data parameter may provide:
|
|
category -- The category of the identity to check.
|
|
itype -- The type of the identity to check.
|
|
lang -- The language of the identity to check.
|
|
local -- If true, then the query is for a JID/node
|
|
combination handled by this Slixmpp instance and
|
|
no stanzas need to be sent.
|
|
Otherwise, a disco stanza must be sent to the
|
|
remove JID to retrieve the info.
|
|
cached -- If true, then look for the disco info data from
|
|
the local cache system. If no results are found,
|
|
send the query as usual. The self.use_cache
|
|
setting must be set to true for this option to
|
|
be useful. If set to false, then the cache will
|
|
be skipped, even if a result has already been
|
|
cached. Defaults to false.
|
|
"""
|
|
identity = (data.get('category', None),
|
|
data.get('itype', None),
|
|
data.get('lang', None))
|
|
|
|
data = {'local': data.get('local', False),
|
|
'cached': data.get('cached', True)}
|
|
|
|
trunc = lambda i: (i[0], i[1], i[2])
|
|
|
|
if node in (None, ''):
|
|
info = self.caps.get_caps(jid)
|
|
if info and identity in map(trunc, info['identities']):
|
|
return True
|
|
|
|
try:
|
|
info = await self.disco.get_info(jid=jid, node=node,
|
|
ifrom=ifrom, **data)
|
|
info = self.disco._wrap(ifrom, jid, info, True)
|
|
return identity in map(trunc, info['disco_info']['identities'])
|
|
except IqError:
|
|
return False
|
|
except IqTimeout:
|
|
return None
|
|
|
|
def cache_caps(self, jid, node, ifrom, data):
|
|
verstring = data.get('verstring', None)
|
|
info = data.get('info', None)
|
|
if not verstring or not info:
|
|
return
|
|
self.caps.cache.store(verstring, info)
|
|
|
|
def assign_verstring(self, jid, node, ifrom, data):
|
|
if isinstance(jid, JID):
|
|
jid = jid.full
|
|
self.jid_vers[jid] = data.get('verstring', None)
|
|
|
|
def get_verstring(self, jid, node, ifrom, data):
|
|
return self.jid_vers.get(jid, None)
|
|
|
|
async def get_caps(self, jid, node, ifrom, data):
|
|
verstring = data.get('verstring', None)
|
|
if verstring is None:
|
|
return None
|
|
return self.caps.cache.retrieve(verstring)
|