slidge 0.1.0rc1__py3-none-any.whl → 0.1.2__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- slidge/__init__.py +54 -31
- slidge/__main__.py +51 -5
- slidge/command/__init__.py +28 -0
- slidge/command/adhoc.py +258 -0
- slidge/command/admin.py +193 -0
- slidge/command/base.py +441 -0
- slidge/command/categories.py +3 -0
- slidge/command/chat_command.py +288 -0
- slidge/command/register.py +179 -0
- slidge/command/user.py +250 -0
- slidge/contact/__init__.py +8 -0
- slidge/contact/contact.py +452 -0
- slidge/contact/roster.py +192 -0
- slidge/core/__init__.py +2 -0
- slidge/core/cache.py +121 -39
- slidge/core/config.py +116 -11
- slidge/core/gateway/__init__.py +3 -0
- slidge/core/gateway/base.py +895 -0
- slidge/core/gateway/caps.py +63 -0
- slidge/core/gateway/delivery_receipt.py +52 -0
- slidge/core/gateway/disco.py +80 -0
- slidge/core/gateway/mam.py +75 -0
- slidge/core/gateway/muc_admin.py +35 -0
- slidge/core/gateway/ping.py +66 -0
- slidge/core/gateway/presence.py +95 -0
- slidge/core/gateway/registration.py +53 -0
- slidge/core/gateway/search.py +102 -0
- slidge/core/gateway/session_dispatcher.py +795 -0
- slidge/core/gateway/vcard_temp.py +130 -0
- slidge/core/mixins/__init__.py +9 -1
- slidge/core/mixins/attachment.py +506 -0
- slidge/core/mixins/avatar.py +167 -0
- slidge/core/mixins/base.py +6 -19
- slidge/core/mixins/disco.py +66 -15
- slidge/core/mixins/lock.py +31 -0
- slidge/core/mixins/message.py +254 -252
- slidge/core/mixins/message_maker.py +154 -0
- slidge/core/mixins/presence.py +128 -31
- slidge/core/mixins/recipient.py +43 -0
- slidge/core/pubsub.py +275 -116
- slidge/core/session.py +586 -518
- slidge/group/__init__.py +10 -0
- slidge/group/archive.py +125 -0
- slidge/group/bookmarks.py +163 -0
- slidge/group/participant.py +458 -0
- slidge/group/room.py +1103 -0
- slidge/migration.py +18 -0
- slidge/slixfix/__init__.py +68 -0
- slidge/{util/xep_0050 → slixfix/link_preview}/__init__.py +4 -5
- slidge/slixfix/link_preview/link_preview.py +17 -0
- slidge/slixfix/link_preview/stanza.py +99 -0
- slidge/slixfix/roster.py +60 -0
- slidge/{util → slixfix}/xep_0077/register.py +1 -2
- slidge/slixfix/xep_0077/stanza.py +104 -0
- slidge/{util → slixfix}/xep_0100/gateway.py +17 -12
- slidge/slixfix/xep_0153/__init__.py +10 -0
- slidge/slixfix/xep_0153/stanza.py +25 -0
- slidge/slixfix/xep_0153/vcard_avatar.py +23 -0
- slidge/slixfix/xep_0264/__init__.py +5 -0
- slidge/slixfix/xep_0264/stanza.py +36 -0
- slidge/slixfix/xep_0264/thumbnail.py +23 -0
- slidge/slixfix/xep_0292/__init__.py +5 -0
- slidge/slixfix/xep_0292/vcard4.py +100 -0
- slidge/slixfix/xep_0313/__init__.py +12 -0
- slidge/slixfix/xep_0313/mam.py +262 -0
- slidge/slixfix/xep_0313/stanza.py +359 -0
- slidge/slixfix/xep_0317/__init__.py +5 -0
- slidge/slixfix/xep_0317/hats.py +17 -0
- slidge/slixfix/xep_0317/stanza.py +28 -0
- slidge/{util → slixfix}/xep_0356_old/privilege.py +9 -7
- slidge/slixfix/xep_0424/__init__.py +9 -0
- slidge/slixfix/xep_0424/retraction.py +77 -0
- slidge/slixfix/xep_0424/stanza.py +28 -0
- slidge/slixfix/xep_0490/__init__.py +8 -0
- slidge/slixfix/xep_0490/mds.py +47 -0
- slidge/slixfix/xep_0490/stanza.py +17 -0
- slidge/util/__init__.py +4 -6
- slidge/util/archive_msg.py +61 -0
- slidge/util/conf.py +25 -4
- slidge/util/db.py +23 -69
- slidge/util/schema.sql +126 -0
- slidge/util/sql.py +508 -0
- slidge/util/test.py +136 -86
- slidge/util/types.py +155 -14
- slidge/util/util.py +225 -51
- slidge-0.1.2.dist-info/METADATA +111 -0
- slidge-0.1.2.dist-info/RECORD +96 -0
- {slidge-0.1.0rc1.dist-info → slidge-0.1.2.dist-info}/WHEEL +1 -1
- slidge/core/adhoc.py +0 -492
- slidge/core/chat_command.py +0 -197
- slidge/core/contact.py +0 -441
- slidge/core/disco.py +0 -59
- slidge/core/gateway.py +0 -899
- slidge/core/muc/__init__.py +0 -3
- slidge/core/muc/bookmarks.py +0 -74
- slidge/core/muc/participant.py +0 -152
- slidge/core/muc/room.py +0 -348
- slidge/plugins/discord/__init__.py +0 -121
- slidge/plugins/discord/client.py +0 -121
- slidge/plugins/discord/session.py +0 -172
- slidge/plugins/dummy.py +0 -334
- slidge/plugins/facebook.py +0 -591
- slidge/plugins/hackernews.py +0 -209
- slidge/plugins/mattermost/__init__.py +0 -1
- slidge/plugins/mattermost/api.py +0 -288
- slidge/plugins/mattermost/gateway.py +0 -417
- slidge/plugins/mattermost/websocket.py +0 -248
- slidge/plugins/signal/__init__.py +0 -4
- slidge/plugins/signal/config.py +0 -4
- slidge/plugins/signal/contact.py +0 -104
- slidge/plugins/signal/gateway.py +0 -379
- slidge/plugins/signal/group.py +0 -76
- slidge/plugins/signal/session.py +0 -515
- slidge/plugins/signal/txt.py +0 -13
- slidge/plugins/signal/util.py +0 -32
- slidge/plugins/skype.py +0 -310
- slidge/plugins/steam.py +0 -400
- slidge/plugins/telegram/__init__.py +0 -6
- slidge/plugins/telegram/client.py +0 -325
- slidge/plugins/telegram/config.py +0 -21
- slidge/plugins/telegram/contact.py +0 -154
- slidge/plugins/telegram/gateway.py +0 -182
- slidge/plugins/telegram/group.py +0 -184
- slidge/plugins/telegram/session.py +0 -275
- slidge/plugins/telegram/util.py +0 -153
- slidge/plugins/whatsapp/__init__.py +0 -6
- slidge/plugins/whatsapp/config.py +0 -17
- slidge/plugins/whatsapp/contact.py +0 -33
- slidge/plugins/whatsapp/event.go +0 -455
- slidge/plugins/whatsapp/gateway.go +0 -156
- slidge/plugins/whatsapp/gateway.py +0 -69
- slidge/plugins/whatsapp/go.mod +0 -17
- slidge/plugins/whatsapp/go.sum +0 -22
- slidge/plugins/whatsapp/session.go +0 -371
- slidge/plugins/whatsapp/session.py +0 -370
- slidge/util/xep_0030/__init__.py +0 -13
- slidge/util/xep_0030/disco.py +0 -811
- slidge/util/xep_0030/stanza/__init__.py +0 -7
- slidge/util/xep_0030/stanza/info.py +0 -270
- slidge/util/xep_0030/stanza/items.py +0 -147
- slidge/util/xep_0030/static.py +0 -467
- slidge/util/xep_0050/adhoc.py +0 -631
- slidge/util/xep_0050/stanza.py +0 -180
- slidge/util/xep_0077/stanza.py +0 -71
- slidge/util/xep_0292/__init__.py +0 -1
- slidge/util/xep_0292/stanza.py +0 -167
- slidge/util/xep_0292/vcard4.py +0 -74
- slidge/util/xep_0356/__init__.py +0 -7
- slidge/util/xep_0356/permissions.py +0 -35
- slidge/util/xep_0356/privilege.py +0 -160
- slidge/util/xep_0356/stanza.py +0 -44
- slidge/util/xep_0461/__init__.py +0 -6
- slidge/util/xep_0461/reply.py +0 -48
- slidge/util/xep_0461/stanza.py +0 -80
- slidge-0.1.0rc1.dist-info/METADATA +0 -171
- slidge-0.1.0rc1.dist-info/RECORD +0 -99
- /slidge/{plugins/__init__.py → py.typed} +0 -0
- /slidge/{util → slixfix}/xep_0077/__init__.py +0 -0
- /slidge/{util → slixfix}/xep_0100/__init__.py +0 -0
- /slidge/{util → slixfix}/xep_0100/stanza.py +0 -0
- /slidge/{util → slixfix}/xep_0356_old/__init__.py +0 -0
- /slidge/{util → slixfix}/xep_0356_old/stanza.py +0 -0
- {slidge-0.1.0rc1.dist-info → slidge-0.1.2.dist-info}/LICENSE +0 -0
- {slidge-0.1.0rc1.dist-info → slidge-0.1.2.dist-info}/entry_points.txt +0 -0
@@ -1,7 +0,0 @@
|
|
1
|
-
|
2
|
-
# Slixmpp: The Slick XMPP Library
|
3
|
-
# Copyright (C) 2010 Nathanael C. Fritz, Lance J.T. Stout
|
4
|
-
# This file is part of Slixmpp.
|
5
|
-
# See the file LICENSE for copying permission.
|
6
|
-
from slixmpp.plugins.xep_0030.stanza.info import DiscoInfo
|
7
|
-
from slixmpp.plugins.xep_0030.stanza.items import DiscoItems
|
@@ -1,270 +0,0 @@
|
|
1
|
-
# Slixmpp: The Slick XMPP Library
|
2
|
-
# Copyright (C) 2010 Nathanael C. Fritz, Lance J.T. Stout
|
3
|
-
# This file is part of Slixmpp.
|
4
|
-
# See the file LICENSE for copying permission.
|
5
|
-
from typing import Iterable, List, Optional, Set, Tuple, Union
|
6
|
-
|
7
|
-
from slixmpp.xmlstream import ET, ElementBase
|
8
|
-
|
9
|
-
IdentityType = Tuple[str, str, Optional[str], Optional[str]]
|
10
|
-
|
11
|
-
|
12
|
-
class DiscoInfo(ElementBase):
|
13
|
-
|
14
|
-
"""
|
15
|
-
XMPP allows for users and agents to find the identities and features
|
16
|
-
supported by other entities in the XMPP network through service discovery,
|
17
|
-
or "disco". In particular, the "disco#info" query type for <iq> stanzas is
|
18
|
-
used to request the list of identities and features offered by a JID.
|
19
|
-
|
20
|
-
An identity is a combination of a category and type, such as the 'client'
|
21
|
-
category with a type of 'pc' to indicate the agent is a human operated
|
22
|
-
client with a GUI, or a category of 'gateway' with a type of 'aim' to
|
23
|
-
identify the agent as a gateway for the legacy AIM protocol. See
|
24
|
-
`XMPP Registrar Disco Categories`_ for a full list of
|
25
|
-
accepted category and type combinations.
|
26
|
-
|
27
|
-
.. _XMPP Registrar Disco Categories: <http://xmpp.org/registrar/disco-categories.html>
|
28
|
-
|
29
|
-
Features are simply a set of the namespaces that identify the supported
|
30
|
-
features. For example, a client that supports service discovery will
|
31
|
-
include the feature ``http://jabber.org/protocol/disco#info``.
|
32
|
-
|
33
|
-
Since clients and components may operate in several roles at once, identity
|
34
|
-
and feature information may be grouped into "nodes". If one were to write
|
35
|
-
all of the identities and features used by a client, then node names would
|
36
|
-
be like section headings.
|
37
|
-
|
38
|
-
Example disco#info stanza:
|
39
|
-
|
40
|
-
.. code-block:: xml
|
41
|
-
|
42
|
-
<iq type="get">
|
43
|
-
<query xmlns="http://jabber.org/protocol/disco#info" />
|
44
|
-
</iq>
|
45
|
-
|
46
|
-
<iq type="result">
|
47
|
-
<query xmlns="http://jabber.org/protocol/disco#info">
|
48
|
-
<identity category="client" type="bot" name="Slixmpp Bot" />
|
49
|
-
<feature var="http://jabber.org/protocol/disco#info" />
|
50
|
-
<feature var="jabber:x:data" />
|
51
|
-
<feature var="urn:xmpp:ping" />
|
52
|
-
</query>
|
53
|
-
</iq>
|
54
|
-
"""
|
55
|
-
|
56
|
-
name = 'query'
|
57
|
-
namespace = 'http://jabber.org/protocol/disco#info'
|
58
|
-
plugin_attrib = 'disco_info'
|
59
|
-
#: Stanza interfaces:
|
60
|
-
#:
|
61
|
-
#: - ``node``: The name of the node to either query or return the info from
|
62
|
-
#: - ``identities``: A set of 4-tuples, where each tuple contains the
|
63
|
-
#: category, type, xml:lang and name of an identity
|
64
|
-
#: - ``features``: A set of namespaces for features
|
65
|
-
#:
|
66
|
-
interfaces = {'node', 'features', 'identities'}
|
67
|
-
lang_interfaces = {'identities'}
|
68
|
-
|
69
|
-
# Cache identities and features
|
70
|
-
_identities: Set[Tuple[str, str, Optional[str]]]
|
71
|
-
_features: Set[str]
|
72
|
-
|
73
|
-
def setup(self, xml: Optional[ET.ElementTree] = None):
|
74
|
-
"""
|
75
|
-
Populate the stanza object using an optional XML object.
|
76
|
-
|
77
|
-
Overrides ElementBase.setup
|
78
|
-
|
79
|
-
Caches identity and feature information.
|
80
|
-
|
81
|
-
:param xml: Use an existing XML object for the stanza's values.
|
82
|
-
"""
|
83
|
-
ElementBase.setup(self, xml)
|
84
|
-
|
85
|
-
self._identities = {id[0:3] for id in self['identities']}
|
86
|
-
self._features = self['features']
|
87
|
-
|
88
|
-
def add_identity(self, category: str, itype: str,
|
89
|
-
name: Optional[str] = None, lang: Optional[str] = None
|
90
|
-
) -> bool:
|
91
|
-
"""
|
92
|
-
Add a new identity element. Each identity must be unique
|
93
|
-
in terms of all four identity components.
|
94
|
-
|
95
|
-
Multiple, identical category/type pairs are allowed only
|
96
|
-
if the xml:lang values are different. Likewise, multiple
|
97
|
-
category/type/xml:lang pairs are allowed so long as the names
|
98
|
-
are different. In any case, a category and type are required.
|
99
|
-
|
100
|
-
:param category: The general category to which the agent belongs.
|
101
|
-
:param itype: A more specific designation with the category.
|
102
|
-
:param name: Optional human readable name for this identity.
|
103
|
-
:param lang: Optional standard xml:lang value.
|
104
|
-
"""
|
105
|
-
identity = (category, itype, lang)
|
106
|
-
if identity not in self._identities:
|
107
|
-
self._identities.add(identity)
|
108
|
-
id_xml = ET.Element('{%s}identity' % self.namespace)
|
109
|
-
id_xml.attrib['category'] = category
|
110
|
-
id_xml.attrib['type'] = itype
|
111
|
-
if lang:
|
112
|
-
id_xml.attrib['{%s}lang' % self.xml_ns] = lang
|
113
|
-
if name:
|
114
|
-
id_xml.attrib['name'] = name
|
115
|
-
self.xml.insert(0, id_xml)
|
116
|
-
return True
|
117
|
-
return False
|
118
|
-
|
119
|
-
def del_identity(self, category: str, itype: str, name=None,
|
120
|
-
lang: Optional[str] = None) -> bool:
|
121
|
-
"""
|
122
|
-
Remove a given identity.
|
123
|
-
|
124
|
-
:param category: The general category to which the agent belonged.
|
125
|
-
:param itype: A more specific designation with the category.
|
126
|
-
:param name: Optional human readable name for this identity.
|
127
|
-
:param lang: Optional, standard xml:lang value.
|
128
|
-
"""
|
129
|
-
identity = (category, itype, lang)
|
130
|
-
if identity in self._identities:
|
131
|
-
self._identities.remove(identity)
|
132
|
-
for id_xml in self.xml.findall('{%s}identity' % self.namespace):
|
133
|
-
id = (id_xml.attrib['category'],
|
134
|
-
id_xml.attrib['type'],
|
135
|
-
id_xml.attrib.get('{%s}lang' % self.xml_ns, None))
|
136
|
-
if id == identity:
|
137
|
-
self.xml.remove(id_xml)
|
138
|
-
return True
|
139
|
-
return False
|
140
|
-
|
141
|
-
def get_identities(self, lang: Optional[str] = None, dedupe: bool = True
|
142
|
-
) -> Iterable[IdentityType]:
|
143
|
-
"""
|
144
|
-
Return a set of all identities in tuple form as so:
|
145
|
-
|
146
|
-
(category, type, lang, name)
|
147
|
-
|
148
|
-
If a language was specified, only return identities using
|
149
|
-
that language.
|
150
|
-
|
151
|
-
:param lang: Optional, standard xml:lang value.
|
152
|
-
:param dedupe: If True, de-duplicate identities, otherwise
|
153
|
-
return a list of all identities.
|
154
|
-
"""
|
155
|
-
identities: Union[List[IdentityType], Set[IdentityType]]
|
156
|
-
if dedupe:
|
157
|
-
identities = set()
|
158
|
-
else:
|
159
|
-
identities = []
|
160
|
-
for id_xml in self.xml.findall('{%s}identity' % self.namespace):
|
161
|
-
xml_lang = id_xml.attrib.get('{%s}lang' % self.xml_ns, None)
|
162
|
-
if lang is None or xml_lang == lang:
|
163
|
-
id = (id_xml.attrib['category'],
|
164
|
-
id_xml.attrib['type'],
|
165
|
-
id_xml.attrib.get('{%s}lang' % self.xml_ns, None),
|
166
|
-
id_xml.attrib.get('name', None))
|
167
|
-
if isinstance(identities, set):
|
168
|
-
identities.add(id)
|
169
|
-
else:
|
170
|
-
identities.append(id)
|
171
|
-
return identities
|
172
|
-
|
173
|
-
def set_identities(self, identities: Iterable[IdentityType],
|
174
|
-
lang: Optional[str] = None):
|
175
|
-
"""
|
176
|
-
Add or replace all identities. The identities must be a in set
|
177
|
-
where each identity is a tuple of the form:
|
178
|
-
|
179
|
-
(category, type, lang, name)
|
180
|
-
|
181
|
-
If a language is specifified, any identities using that language
|
182
|
-
will be removed to be replaced with the given identities.
|
183
|
-
|
184
|
-
.. note::
|
185
|
-
|
186
|
-
An identity's language will not be changed regardless of
|
187
|
-
the value of lang.
|
188
|
-
|
189
|
-
:param identities: A set of identities in tuple form.
|
190
|
-
:param lang: Optional, standard xml:lang value.
|
191
|
-
"""
|
192
|
-
self.del_identities(lang)
|
193
|
-
for identity in identities:
|
194
|
-
category, itype, lang, name = identity
|
195
|
-
self.add_identity(category, itype, name, lang)
|
196
|
-
|
197
|
-
def del_identities(self, lang: Optional[str] = None):
|
198
|
-
"""
|
199
|
-
Remove all identities. If a language was specified, only
|
200
|
-
remove identities using that language.
|
201
|
-
|
202
|
-
:param lang: Optional, standard xml:lang value.
|
203
|
-
"""
|
204
|
-
for id_xml in self.xml.findall('{%s}identity' % self.namespace):
|
205
|
-
if lang is None:
|
206
|
-
self.xml.remove(id_xml)
|
207
|
-
elif id_xml.attrib.get('{%s}lang' % self.xml_ns, None) == lang:
|
208
|
-
self._identities.remove((
|
209
|
-
id_xml.attrib['category'],
|
210
|
-
id_xml.attrib['type'],
|
211
|
-
id_xml.attrib.get('{%s}lang' % self.xml_ns, None)))
|
212
|
-
self.xml.remove(id_xml)
|
213
|
-
|
214
|
-
def add_feature(self, feature: str) -> bool:
|
215
|
-
"""
|
216
|
-
Add a single, new feature.
|
217
|
-
|
218
|
-
:param feature: The namespace of the supported feature.
|
219
|
-
"""
|
220
|
-
if feature not in self._features:
|
221
|
-
self._features.add(feature)
|
222
|
-
feature_xml = ET.Element('{%s}feature' % self.namespace)
|
223
|
-
feature_xml.attrib['var'] = feature
|
224
|
-
self.xml.append(feature_xml)
|
225
|
-
return True
|
226
|
-
return False
|
227
|
-
|
228
|
-
def del_feature(self, feature: str) -> bool:
|
229
|
-
"""
|
230
|
-
Remove a single feature.
|
231
|
-
|
232
|
-
:param feature: The namespace of the removed feature.
|
233
|
-
"""
|
234
|
-
if feature in self._features:
|
235
|
-
self._features.remove(feature)
|
236
|
-
for feature_xml in self.xml.findall('{%s}feature' % self.namespace):
|
237
|
-
if feature_xml.attrib['var'] == feature:
|
238
|
-
self.xml.remove(feature_xml)
|
239
|
-
return True
|
240
|
-
return False
|
241
|
-
|
242
|
-
def get_features(self, dedupe: bool = True) -> Iterable[str]:
|
243
|
-
"""Return the set of all supported features."""
|
244
|
-
features: Union[List[str], Set[str]]
|
245
|
-
if dedupe:
|
246
|
-
features = set()
|
247
|
-
else:
|
248
|
-
features = []
|
249
|
-
for feature_xml in self.xml.findall('{%s}feature' % self.namespace):
|
250
|
-
if isinstance(features, set):
|
251
|
-
features.add(feature_xml.attrib['var'])
|
252
|
-
else:
|
253
|
-
features.append(feature_xml.attrib['var'])
|
254
|
-
return features
|
255
|
-
|
256
|
-
def set_features(self, features: Iterable[str]):
|
257
|
-
"""
|
258
|
-
Add or replace the set of supported features.
|
259
|
-
|
260
|
-
:param features: The new set of supported features.
|
261
|
-
"""
|
262
|
-
self.del_features()
|
263
|
-
for feature in features:
|
264
|
-
self.add_feature(feature)
|
265
|
-
|
266
|
-
def del_features(self):
|
267
|
-
"""Remove all features."""
|
268
|
-
self._features = set()
|
269
|
-
for feature_xml in self.xml.findall('{%s}feature' % self.namespace):
|
270
|
-
self.xml.remove(feature_xml)
|
@@ -1,147 +0,0 @@
|
|
1
|
-
# Slixmpp: The Slick XMPP Library
|
2
|
-
# Copyright (C) 2010 Nathanael C. Fritz, Lance J.T. Stout
|
3
|
-
# This file is part of Slixmpp.
|
4
|
-
# See the file LICENSE for copying permission.
|
5
|
-
from typing import Iterable, Optional, Set, Tuple
|
6
|
-
|
7
|
-
from slixmpp import JID
|
8
|
-
from slixmpp.xmlstream import ET, ElementBase, register_stanza_plugin
|
9
|
-
|
10
|
-
|
11
|
-
class DiscoItem(ElementBase):
|
12
|
-
name = 'item'
|
13
|
-
namespace = 'http://jabber.org/protocol/disco#items'
|
14
|
-
plugin_attrib = name
|
15
|
-
interfaces = {'jid', 'node', 'name'}
|
16
|
-
|
17
|
-
def get_node(self) -> Optional[str]:
|
18
|
-
"""Return the item's node name or ``None``."""
|
19
|
-
return self._get_attr('node', None)
|
20
|
-
|
21
|
-
def get_name(self) -> Optional[str]:
|
22
|
-
"""Return the item's human readable name, or ``None``."""
|
23
|
-
return self._get_attr('name', None)
|
24
|
-
|
25
|
-
|
26
|
-
class DiscoItems(ElementBase):
|
27
|
-
|
28
|
-
"""
|
29
|
-
Example disco#items stanzas:
|
30
|
-
|
31
|
-
.. code-block:: xml
|
32
|
-
|
33
|
-
<iq type="get">
|
34
|
-
<query xmlns="http://jabber.org/protocol/disco#items" />
|
35
|
-
</iq>
|
36
|
-
|
37
|
-
<iq type="result">
|
38
|
-
<query xmlns="http://jabber.org/protocol/disco#items">
|
39
|
-
<item jid="chat.example.com"
|
40
|
-
node="xmppdev"
|
41
|
-
name="XMPP Dev" />
|
42
|
-
<item jid="chat.example.com"
|
43
|
-
node="slixdev"
|
44
|
-
name="Slixmpp Dev" />
|
45
|
-
</query>
|
46
|
-
</iq>
|
47
|
-
|
48
|
-
"""
|
49
|
-
|
50
|
-
name = 'query'
|
51
|
-
namespace = 'http://jabber.org/protocol/disco#items'
|
52
|
-
plugin_attrib = 'disco_items'
|
53
|
-
#: Stanza Interface:
|
54
|
-
#:
|
55
|
-
#: - ``node``: The name of the node to either
|
56
|
-
#: query or return info from.
|
57
|
-
#: - ``items``: A list of 3-tuples, where each tuple contains
|
58
|
-
#: the JID, node, and name of an item.
|
59
|
-
#:
|
60
|
-
interfaces = {'node', 'items'}
|
61
|
-
|
62
|
-
# Cache items
|
63
|
-
_items: Set[Tuple[JID, Optional[str]]]
|
64
|
-
|
65
|
-
def setup(self, xml: Optional[ET.ElementTree] = None):
|
66
|
-
"""
|
67
|
-
Populate the stanza object using an optional XML object.
|
68
|
-
|
69
|
-
Overrides ElementBase.setup
|
70
|
-
|
71
|
-
Caches item information.
|
72
|
-
|
73
|
-
:param xml: Use an existing XML object for the stanza's values.
|
74
|
-
"""
|
75
|
-
ElementBase.setup(self, xml)
|
76
|
-
self._items = {item[0:2] for item in self['items']}
|
77
|
-
|
78
|
-
def add_item(self, jid: JID, node: Optional[str] = None,
|
79
|
-
name: Optional[str] = None):
|
80
|
-
"""
|
81
|
-
Add a new item element. Each item is required to have a
|
82
|
-
JID, but may also specify a node value to reference
|
83
|
-
non-addressable entitities.
|
84
|
-
|
85
|
-
:param jid: The JID for the item.
|
86
|
-
:param node: Optional additional information to reference
|
87
|
-
non-addressable items.
|
88
|
-
:param name: Optional human readable name for the item.
|
89
|
-
"""
|
90
|
-
if (jid, node) not in self._items:
|
91
|
-
self._items.add((jid, node))
|
92
|
-
item = DiscoItem(parent=self)
|
93
|
-
item['jid'] = jid
|
94
|
-
item['node'] = node
|
95
|
-
item['name'] = name
|
96
|
-
self.iterables.append(item)
|
97
|
-
return True
|
98
|
-
return False
|
99
|
-
|
100
|
-
def del_item(self, jid: JID, node: Optional[str] = None) -> bool:
|
101
|
-
"""
|
102
|
-
Remove a single item.
|
103
|
-
|
104
|
-
:param jid: JID of the item to remove.
|
105
|
-
:param node: Optional extra identifying information.
|
106
|
-
"""
|
107
|
-
if (jid, node) in self._items:
|
108
|
-
for item_xml in self.xml.findall('{%s}item' % self.namespace):
|
109
|
-
item = (item_xml.attrib['jid'],
|
110
|
-
item_xml.attrib.get('node', None))
|
111
|
-
if item == (jid, node):
|
112
|
-
self.xml.remove(item_xml)
|
113
|
-
return True
|
114
|
-
return False
|
115
|
-
|
116
|
-
def get_items(self) -> Set[DiscoItem]:
|
117
|
-
"""Return all items."""
|
118
|
-
items = set()
|
119
|
-
for item in self['substanzas']:
|
120
|
-
if isinstance(item, DiscoItem):
|
121
|
-
items.add((item['jid'], item['node'], item['name']))
|
122
|
-
return items
|
123
|
-
|
124
|
-
def set_items(self, items: Iterable[DiscoItem]):
|
125
|
-
"""
|
126
|
-
Set or replace all items. The given items must be in a
|
127
|
-
list or set where each item is a tuple of the form:
|
128
|
-
|
129
|
-
(jid, node, name)
|
130
|
-
|
131
|
-
:param items: A series of items in tuple format.
|
132
|
-
"""
|
133
|
-
self.del_items()
|
134
|
-
for item in items:
|
135
|
-
jid, node, name = item
|
136
|
-
self.add_item(jid, node, name)
|
137
|
-
|
138
|
-
def del_items(self):
|
139
|
-
"""Remove all items."""
|
140
|
-
self._items = set()
|
141
|
-
items = [i for i in self.iterables if isinstance(i, DiscoItem)]
|
142
|
-
for item in items:
|
143
|
-
self.xml.remove(item.xml)
|
144
|
-
self.iterables.remove(item)
|
145
|
-
|
146
|
-
|
147
|
-
register_stanza_plugin(DiscoItems, DiscoItem, iterable=True)
|