slidge 0.2.2__py3-none-any.whl → 0.2.4__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. slidge/__version__.py +1 -1
  2. slidge/command/register.py +1 -3
  3. slidge/contact/contact.py +1 -1
  4. slidge/core/dispatcher/message/message.py +4 -1
  5. slidge/core/dispatcher/muc/admin.py +3 -4
  6. slidge/core/dispatcher/presence.py +3 -3
  7. slidge/core/gateway.py +2 -0
  8. slidge/core/mixins/attachment.py +1 -1
  9. slidge/core/mixins/avatar.py +6 -0
  10. slidge/core/mixins/message.py +13 -2
  11. slidge/core/mixins/recipient.py +2 -2
  12. slidge/db/store.py +9 -3
  13. slidge/group/archive.py +3 -3
  14. slidge/group/participant.py +11 -5
  15. slidge/group/room.py +21 -1
  16. slidge/main.py +1 -1
  17. slidge/slixfix/__init__.py +69 -13
  18. slidge/slixfix/xep_0153/__init__.py +0 -1
  19. slidge/slixfix/xep_0153/vcard_avatar.py +1 -10
  20. slidge/slixfix/xep_0492/__init__.py +8 -0
  21. slidge/slixfix/xep_0492/notify.py +16 -0
  22. slidge/slixfix/xep_0492/stanza.py +102 -0
  23. slidge/util/test.py +9 -2
  24. slidge-0.2.4.dist-info/METADATA +793 -0
  25. {slidge-0.2.2.dist-info → slidge-0.2.4.dist-info}/RECORD +41 -54
  26. {slidge-0.2.2.dist-info → slidge-0.2.4.dist-info}/WHEEL +2 -1
  27. slidge-0.2.4.dist-info/entry_points.txt +2 -0
  28. slidge-0.2.4.dist-info/top_level.txt +1 -0
  29. slidge/slixfix/xep_0153/stanza.py +0 -25
  30. slidge/slixfix/xep_0264/__init__.py +0 -5
  31. slidge/slixfix/xep_0264/stanza.py +0 -36
  32. slidge/slixfix/xep_0264/thumbnail.py +0 -23
  33. slidge/slixfix/xep_0313/__init__.py +0 -12
  34. slidge/slixfix/xep_0313/mam.py +0 -262
  35. slidge/slixfix/xep_0313/stanza.py +0 -359
  36. slidge/slixfix/xep_0317/__init__.py +0 -5
  37. slidge/slixfix/xep_0317/hats.py +0 -17
  38. slidge/slixfix/xep_0317/stanza.py +0 -28
  39. slidge/slixfix/xep_0424/__init__.py +0 -9
  40. slidge/slixfix/xep_0424/retraction.py +0 -77
  41. slidge/slixfix/xep_0424/stanza.py +0 -28
  42. slidge/slixfix/xep_0490/__init__.py +0 -8
  43. slidge/slixfix/xep_0490/mds.py +0 -47
  44. slidge/slixfix/xep_0490/stanza.py +0 -17
  45. slidge-0.2.2.dist-info/LICENSE +0 -661
  46. slidge-0.2.2.dist-info/METADATA +0 -116
  47. slidge-0.2.2.dist-info/entry_points.txt +0 -3
@@ -1,359 +0,0 @@
1
- # Slixmpp: The Slick XMPP Library
2
- # Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
3
- # This file is part of Slixmpp.
4
- # See the file LICENSE for copying permissio
5
- from datetime import datetime
6
- from typing import Any, Iterable, List, Optional, Set, Union
7
-
8
- from slixmpp.jid import JID
9
- from slixmpp.plugins import xep_0082
10
- from slixmpp.stanza import Message
11
- from slixmpp.xmlstream import ET, ElementBase
12
-
13
-
14
- class MAM(ElementBase):
15
- """A MAM Query element.
16
-
17
- .. code-block:: xml
18
-
19
- <iq type='set' id='juliet1'>
20
- <query xmlns='urn:xmpp:mam:2'>
21
- <x xmlns='jabber:x:data' type='submit'>
22
- <field var='FORM_TYPE' type='hidden'>
23
- <value>urn:xmpp:mam:2</value>
24
- </field>
25
- <field var='with'>
26
- <value>juliet@capulet.lit</value>
27
- </field>
28
- </x>
29
- </query>
30
- </iq>
31
-
32
- """
33
-
34
- name = "query"
35
- namespace = "urn:xmpp:mam:2"
36
- plugin_attrib = "mam"
37
- #: Available interfaces:
38
- #:
39
- #: - ``queryid``: The MAM query id
40
- #: - ``start`` and ``end``: Temporal boundaries of the query
41
- #: - ``with``: JID of the other entity the conversation is with
42
- #: - ``after_id``: Fetch stanzas after this specific ID
43
- #: - ``before_id``: Fetch stanzas before this specific ID
44
- #: - ``ids``: Fetch the stanzas matching those IDs
45
- #: - ``results``: pseudo-interface used to accumulate MAM results during
46
- #: fetch, not relevant for the stanza itself.
47
- interfaces = {
48
- "queryid",
49
- "start",
50
- "end",
51
- "with",
52
- "results",
53
- "before_id",
54
- "after_id",
55
- "ids",
56
- "flip_page",
57
- }
58
- sub_interfaces = {
59
- "start",
60
- "end",
61
- "with",
62
- "before_id",
63
- "after_id",
64
- "ids",
65
- "flip_page",
66
- }
67
-
68
- def setup(self, xml=None):
69
- ElementBase.setup(self, xml)
70
- self._results: List[Message] = []
71
-
72
- def _setup_form(self):
73
- found = self.xml.find(
74
- "{jabber:x:data}x/"
75
- '{jabber:x:data}field[@var="FORM_TYPE"]/'
76
- "{jabber:x:data}value[.='urn:xmpp:mam:2']"
77
- )
78
- if found is None:
79
- self["form"]["type"] = "submit"
80
- self["form"].add_field(
81
- var="FORM_TYPE", ftype="hidden", value="urn:xmpp:mam:2"
82
- )
83
-
84
- def get_fields(self):
85
- form = self.get_plugin("form", check=True)
86
- if not form:
87
- return {}
88
- return form.get_fields()
89
-
90
- def get_start(self) -> Optional[datetime]:
91
- fields = self.get_fields()
92
- field = fields.get("start")
93
- if field and field["value"]:
94
- return xep_0082.parse(field["value"])
95
- return None
96
-
97
- def set_start(self, value: Union[str, datetime]):
98
- self._setup_form()
99
- if isinstance(value, datetime):
100
- value = xep_0082.format_datetime(value)
101
- self.set_custom_field("start", value)
102
-
103
- def get_end(self) -> Optional[datetime]:
104
- fields = self.get_fields()
105
- field = fields.get("end")
106
- if field and field["value"]:
107
- return xep_0082.parse(field["value"])
108
- return None
109
-
110
- def set_end(self, value: Union[str, datetime]):
111
- if isinstance(value, datetime):
112
- value = xep_0082.format_datetime(value)
113
- self.set_custom_field("end", value)
114
-
115
- def get_with(self) -> Optional[JID]:
116
- fields = self.get_fields()
117
- field = fields.get("with")
118
- if field:
119
- return JID(field["value"])
120
- return None
121
-
122
- def set_with(self, value: JID):
123
- self.set_custom_field("with", value)
124
-
125
- def set_custom_field(self, fieldname: str, value: Any):
126
- self._setup_form()
127
- fields = self.get_fields()
128
- field = fields.get(fieldname)
129
- if field:
130
- field["value"] = str(value)
131
- else:
132
- field = self["form"].add_field(var=fieldname)
133
- field["value"] = str(value)
134
-
135
- def get_custom_field(self, fieldname: str) -> Optional[str]:
136
- fields = self.get_fields()
137
- field = fields.get(fieldname)
138
- if field:
139
- return field["value"]
140
- return None
141
-
142
- def set_before_id(self, value: str):
143
- self.set_custom_field("before-id", value)
144
-
145
- def get_before_id(self):
146
- self.get_custom_field("before-id")
147
-
148
- def set_after_id(self, value: str):
149
- self.set_custom_field("after-id", value)
150
-
151
- def get_after_id(self):
152
- self.get_custom_field("after-id")
153
-
154
- def set_ids(self, value: List[str]):
155
- self._setup_form()
156
- fields = self.get_fields()
157
- field = fields.get("ids")
158
- if field:
159
- field["ids"] = value
160
- else:
161
- field = self["form"].add_field(var="ids")
162
- field["value"] = value
163
-
164
- def get_ids(self):
165
- self.get_custom_field("id")
166
-
167
- # The results interface is meant only as an easy
168
- # way to access the set of collected message responses
169
- # from the query.
170
-
171
- def get_results(self) -> List[Message]:
172
- return self._results
173
-
174
- def set_results(self, values: List[Message]):
175
- self._results = values
176
-
177
- def del_results(self):
178
- self._results = []
179
-
180
- def get_flip_page(self):
181
- return self.xml.find(f"{{{self.namespace}}}flip-page") is not None
182
-
183
-
184
- class Fin(ElementBase):
185
- """A MAM fin element (end of query).
186
-
187
- .. code-block:: xml
188
-
189
- <iq type='result' id='juliet1'>
190
- <fin xmlns='urn:xmpp:mam:2'>
191
- <set xmlns='http://jabber.org/protocol/rsm'>
192
- <first index='0'>28482-98726-73623</first>
193
- <last>09af3-cc343-b409f</last>
194
- </set>
195
- </fin>
196
- </iq>
197
-
198
- """
199
-
200
- name = "fin"
201
- namespace = "urn:xmpp:mam:2"
202
- plugin_attrib = "mam_fin"
203
- interfaces = {"results", "stable", "complete"}
204
-
205
- def setup(self, xml=None):
206
- ElementBase.setup(self, xml)
207
- self._results: List[Message] = []
208
-
209
- # The results interface is meant only as an easy
210
- # way to access the set of collected message responses
211
- # from the query.
212
-
213
- def get_results(self) -> List[Message]:
214
- return self._results
215
-
216
- def set_results(self, values: List[Message]):
217
- self._results = values
218
-
219
- def del_results(self):
220
- self._results = []
221
-
222
-
223
- class Result(ElementBase):
224
- """A MAM result payload.
225
-
226
- .. code-block:: xml
227
-
228
- <message id='aeb213' to='juliet@capulet.lit/chamber'>
229
- <result xmlns='urn:xmpp:mam:2' queryid='f27' id='28482-98726-73623'>
230
- <forwarded xmlns='urn:xmpp:forward:0'>
231
- <delay xmlns='urn:xmpp:delay' stamp='2010-07-10T23:08:25Z'/>
232
- <message xmlns='jabber:client' from="witch@shakespeare.lit"
233
- to="macbeth@shakespeare.lit">
234
- <body>Hail to thee</body>
235
- </message>
236
- </forwarded>
237
- </result>
238
- </message>
239
- """
240
-
241
- name = "result"
242
- namespace = "urn:xmpp:mam:2"
243
- plugin_attrib = "mam_result"
244
- #: Available interfaces:
245
- #:
246
- #: - ``queryid``: MAM queryid
247
- #: - ``id``: ID of the result
248
- interfaces = {"queryid", "id"}
249
-
250
-
251
- class Metadata(ElementBase):
252
- """Element containing archive metadata
253
-
254
- .. code-block:: xml
255
-
256
- <iq type='result' id='jui8921rr9'>
257
- <metadata xmlns='urn:xmpp:mam:2'>
258
- <start id='YWxwaGEg' timestamp='2008-08-22T21:09:04Z' />
259
- <end id='b21lZ2Eg' timestamp='2020-04-20T14:34:21Z' />
260
- </metadata>
261
- </iq>
262
-
263
- """
264
-
265
- name = "metadata"
266
- namespace = "urn:xmpp:mam:2"
267
- plugin_attrib = "mam_metadata"
268
-
269
-
270
- class Start(ElementBase):
271
- """Metadata about the start of an archive.
272
-
273
- .. code-block:: xml
274
-
275
- <iq type='result' id='jui8921rr9'>
276
- <metadata xmlns='urn:xmpp:mam:2'>
277
- <start id='YWxwaGEg' timestamp='2008-08-22T21:09:04Z' />
278
- <end id='b21lZ2Eg' timestamp='2020-04-20T14:34:21Z' />
279
- </metadata>
280
- </iq>
281
-
282
- """
283
-
284
- name = "start"
285
- namespace = "urn:xmpp:mam:2"
286
- plugin_attrib = name
287
- #: Available interfaces:
288
- #:
289
- #: - ``id``: ID of the first message of the archive
290
- #: - ``timestamp`` (``datetime``): timestamp of the first message of the
291
- #: archive
292
- interfaces = {"id", "timestamp"}
293
-
294
- def get_timestamp(self) -> Optional[datetime]:
295
- """Get the timestamp.
296
-
297
- :returns: The timestamp.
298
- """
299
- stamp = self.xml.attrib.get("timestamp", None)
300
- if stamp is not None:
301
- return xep_0082.parse(stamp)
302
- return stamp
303
-
304
- def set_timestamp(self, value: Union[datetime, str]):
305
- """Set the timestamp.
306
-
307
- :param value: Value of the timestamp (either a datetime or a
308
- XEP-0082 timestamp string.
309
- """
310
- if isinstance(value, str):
311
- value = xep_0082.parse(value)
312
- value = xep_0082.format_datetime(value)
313
- self.xml.attrib["timestamp"] = value
314
-
315
-
316
- class End(ElementBase):
317
- """Metadata about the end of an archive.
318
-
319
- .. code-block:: xml
320
-
321
- <iq type='result' id='jui8921rr9'>
322
- <metadata xmlns='urn:xmpp:mam:2'>
323
- <start id='YWxwaGEg' timestamp='2008-08-22T21:09:04Z' />
324
- <end id='b21lZ2Eg' timestamp='2020-04-20T14:34:21Z' />
325
- </metadata>
326
- </iq>
327
-
328
- """
329
-
330
- name = "end"
331
- namespace = "urn:xmpp:mam:2"
332
- plugin_attrib = name
333
- #: Available interfaces:
334
- #:
335
- #: - ``id``: ID of the first message of the archive
336
- #: - ``timestamp`` (``datetime``): timestamp of the first message of the
337
- #: archive
338
- interfaces = {"id", "timestamp"}
339
-
340
- def get_timestamp(self) -> Optional[datetime]:
341
- """Get the timestamp.
342
-
343
- :returns: The timestamp.
344
- """
345
- stamp = self.xml.attrib.get("timestamp", None)
346
- if stamp is not None:
347
- return xep_0082.parse(stamp)
348
- return stamp
349
-
350
- def set_timestamp(self, value: Union[datetime, str]):
351
- """Set the timestamp.
352
-
353
- :param value: Value of the timestamp (either a datetime or a
354
- XEP-0082 timestamp string.
355
- """
356
- if isinstance(value, str):
357
- value = xep_0082.parse(value)
358
- value = xep_0082.format_datetime(value)
359
- self.xml.attrib["timestamp"] = value
@@ -1,5 +0,0 @@
1
- from slixmpp.plugins.base import register_plugin
2
-
3
- from .hats import XEP_0317
4
-
5
- register_plugin(XEP_0317)
@@ -1,17 +0,0 @@
1
- from slixmpp.plugins import BasePlugin
2
-
3
- from . import stanza
4
-
5
-
6
- class XEP_0317(BasePlugin):
7
- """
8
- XEP-0317: Hats
9
- """
10
-
11
- name = "xep_0317"
12
- description = "XEP-0317: Hats"
13
- dependencies = {"xep_0045"}
14
- stanza = stanza
15
-
16
- def plugin_init(self):
17
- stanza.register()
@@ -1,28 +0,0 @@
1
- from slixmpp import Presence
2
- from slixmpp.xmlstream import ElementBase, register_stanza_plugin
3
-
4
- NS = "urn:xmpp:hats:0"
5
-
6
-
7
- class Hats(ElementBase):
8
- name = plugin_attrib = "hats"
9
- namespace = NS
10
-
11
- def add_hats(self, data: list[tuple[str, str]]):
12
- for uri, title in data:
13
- hat = Hat()
14
- hat["uri"] = uri
15
- hat["title"] = title
16
- self.append(hat)
17
-
18
-
19
- class Hat(ElementBase):
20
- name = plugin_attrib = "hat"
21
- namespace = NS
22
- interfaces = {"uri", "title"}
23
- plugin_multi_attrib = "hats"
24
-
25
-
26
- def register():
27
- register_stanza_plugin(Hats, Hat, iterable=True)
28
- register_stanza_plugin(Presence, Hats)
@@ -1,9 +0,0 @@
1
- # Slixmpp: The Slick XMPP Library
2
- # Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
3
- # This file is part of Slixmpp.
4
- # See the file LICENSE for copying permission.
5
- from slixmpp.plugins.base import register_plugin
6
-
7
- from .retraction import XEP_0424
8
-
9
- register_plugin(XEP_0424)
@@ -1,77 +0,0 @@
1
- # Slixmpp: The Slick XMPP Library
2
- # Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
3
- # This file is part of Slixmpp.
4
- # See the file LICENSE for copying permission.
5
- from typing import Optional
6
-
7
- from slixmpp import JID, Message
8
- from slixmpp.exceptions import IqError, IqTimeout
9
- from slixmpp.plugins import BasePlugin
10
- from slixmpp.xmlstream.handler import Callback
11
- from slixmpp.xmlstream.matcher import StanzaPath
12
-
13
- from . import stanza
14
-
15
- DEFAULT_FALLBACK = (
16
- "This person attempted to retract a previous message, but your client "
17
- "does not support it."
18
- )
19
-
20
-
21
- class XEP_0424(BasePlugin):
22
- """XEP-0424: Message Retraction"""
23
-
24
- name = "xep_0424"
25
- description = "XEP-0424: Message Retraction (fix Slidge)"
26
- dependencies = {"xep_0422", "xep_0030", "xep_0359", "xep_0428", "xep_0334"}
27
- stanza = stanza
28
- namespace = stanza.NS
29
-
30
- def plugin_init(self) -> None:
31
- stanza.register_plugins()
32
- self.xmpp.register_handler(
33
- Callback(
34
- "Message Retracted",
35
- StanzaPath("message/retract"),
36
- self._handle_retract_message,
37
- )
38
- )
39
-
40
- def session_bind(self, jid):
41
- self.xmpp.plugin["xep_0030"].add_feature(feature=stanza.NS)
42
-
43
- def plugin_end(self):
44
- self.xmpp.plugin["xep_0030"].del_feature(feature=stanza.NS)
45
-
46
- def _handle_retract_message(self, message: Message):
47
- self.xmpp.event("message_retract", message)
48
-
49
- def send_retraction(
50
- self,
51
- mto: JID,
52
- id: str,
53
- mtype: str = "chat",
54
- include_fallback: bool = True,
55
- fallback_text: Optional[str] = None,
56
- *,
57
- mfrom: Optional[JID] = None
58
- ):
59
- """
60
- Send a message retraction
61
-
62
- :param JID mto: The JID to retract the message from
63
- :param str id: Message ID to retract
64
- :param str mtype: Message type
65
- :param bool include_fallback: Whether to include a fallback body
66
- :param Optional[str] fallback_text: The content of the fallback
67
- body. None will set the default value.
68
- """
69
- if fallback_text is None:
70
- fallback_text = DEFAULT_FALLBACK
71
- msg = self.xmpp.make_message(mto=mto, mtype=mtype, mfrom=mfrom)
72
- if include_fallback:
73
- msg["body"] = fallback_text
74
- msg.enable("fallback")
75
- msg["retract"]["id"] = id
76
- msg.enable("store")
77
- msg.send()
@@ -1,28 +0,0 @@
1
- # Slixmpp: The Slick XMPP Library
2
- # Copyright (C) 2020 Mathieu Pasquet <mathieui@mathieui.net>
3
- # This file is part of Slixmpp.
4
- # See the file LICENSE for copying permissio
5
- from slixmpp.plugins.xep_0359 import OriginID
6
- from slixmpp.stanza import Message
7
- from slixmpp.xmlstream import ElementBase, register_stanza_plugin
8
-
9
- NS = "urn:xmpp:message-retract:1"
10
-
11
-
12
- class Retract(ElementBase):
13
- namespace = NS
14
- name = "retract"
15
- plugin_attrib = "retract"
16
-
17
-
18
- class Retracted(ElementBase):
19
- namespace = NS
20
- name = "retracted"
21
- plugin_attrib = "retracted"
22
- interfaces = {"stamp"}
23
-
24
-
25
- def register_plugins():
26
- register_stanza_plugin(Message, Retract)
27
- register_stanza_plugin(Message, Retracted)
28
- register_stanza_plugin(Retracted, OriginID)
@@ -1,8 +0,0 @@
1
- from slixmpp.plugins.base import register_plugin
2
-
3
- from . import stanza
4
- from .mds import XEP_0490
5
-
6
- register_plugin(XEP_0490)
7
-
8
- __all__ = ["stanza", "XEP_0490"]
@@ -1,47 +0,0 @@
1
- from slixmpp import Iq
2
- from slixmpp.plugins import BasePlugin
3
- from slixmpp.plugins.xep_0004 import Form
4
- from slixmpp.types import JidStr
5
-
6
- from . import stanza
7
-
8
-
9
- class XEP_0490(BasePlugin):
10
- """
11
- XEP-0490: Message Displayed Synchronization
12
- """
13
-
14
- name = "xep_0490"
15
- description = "XEP-0490: Message Displayed Synchronization"
16
- dependencies = {"xep_0060", "xep_0163", "xep_0359"}
17
- stanza = stanza
18
-
19
- def plugin_init(self):
20
- stanza.register_plugin()
21
- self.xmpp.plugin["xep_0163"].register_pep(
22
- "message_displayed_synchronization",
23
- stanza.Displayed,
24
- )
25
-
26
- def flag_chat(self, chat: JidStr, stanza_id: str, **kwargs) -> Iq:
27
- displayed = stanza.Displayed()
28
- displayed["stanza_id"]["id"] = stanza_id
29
- return self.xmpp.plugin["xep_0163"].publish(
30
- displayed, node=stanza.NS, options=PUBLISH_OPTIONS, id=str(chat), **kwargs
31
- )
32
-
33
- def catch_up(self, **kwargs):
34
- return self.xmpp.plugin["xep_0060"].get_items(
35
- self.xmpp.boundjid.bare, stanza.NS, **kwargs
36
- )
37
-
38
-
39
- PUBLISH_OPTIONS = Form()
40
- PUBLISH_OPTIONS["type"] = "submit"
41
- PUBLISH_OPTIONS.add_field(
42
- "FORM_TYPE", "hidden", value="http://jabber.org/protocol/pubsub#publish-options"
43
- )
44
- PUBLISH_OPTIONS.add_field("pubsub#persist_items", value="true")
45
- PUBLISH_OPTIONS.add_field("pubsub#max_items", value="max")
46
- PUBLISH_OPTIONS.add_field("pubsub#send_last_published_item", value="never")
47
- PUBLISH_OPTIONS.add_field("pubsub#access_model", value="whitelist")
@@ -1,17 +0,0 @@
1
- from slixmpp import register_stanza_plugin
2
- from slixmpp.plugins.xep_0060.stanza import Item
3
- from slixmpp.plugins.xep_0359.stanza import StanzaID
4
- from slixmpp.xmlstream import ElementBase
5
-
6
- NS = "urn:xmpp:mds:displayed:0"
7
-
8
-
9
- class Displayed(ElementBase):
10
- namespace = NS
11
- name = "displayed"
12
- plugin_attrib = "displayed"
13
-
14
-
15
- def register_plugin():
16
- register_stanza_plugin(Displayed, StanzaID)
17
- register_stanza_plugin(Item, Displayed)