slidge 0.1.0b2__py3-none-any.whl → 0.1.1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. slidge/__init__.py +55 -31
  2. slidge/__main__.py +118 -116
  3. slidge/command/__init__.py +28 -0
  4. slidge/command/adhoc.py +258 -0
  5. slidge/command/admin.py +193 -0
  6. slidge/command/base.py +441 -0
  7. slidge/command/categories.py +3 -0
  8. slidge/command/chat_command.py +288 -0
  9. slidge/command/register.py +179 -0
  10. slidge/command/user.py +250 -0
  11. slidge/contact/__init__.py +8 -0
  12. slidge/contact/contact.py +452 -0
  13. slidge/contact/roster.py +192 -0
  14. slidge/core/__init__.py +2 -0
  15. slidge/core/cache.py +183 -0
  16. slidge/core/config.py +216 -0
  17. slidge/core/gateway/__init__.py +3 -0
  18. slidge/core/gateway/base.py +895 -0
  19. slidge/core/gateway/caps.py +63 -0
  20. slidge/core/gateway/delivery_receipt.py +52 -0
  21. slidge/core/gateway/disco.py +80 -0
  22. slidge/core/gateway/mam.py +75 -0
  23. slidge/core/gateway/muc_admin.py +35 -0
  24. slidge/core/gateway/ping.py +66 -0
  25. slidge/core/gateway/presence.py +95 -0
  26. slidge/core/gateway/registration.py +53 -0
  27. slidge/core/gateway/search.py +102 -0
  28. slidge/core/gateway/session_dispatcher.py +789 -0
  29. slidge/core/gateway/vcard_temp.py +130 -0
  30. slidge/core/mixins/__init__.py +19 -0
  31. slidge/core/mixins/attachment.py +506 -0
  32. slidge/core/mixins/avatar.py +167 -0
  33. slidge/core/mixins/base.py +31 -0
  34. slidge/core/mixins/disco.py +130 -0
  35. slidge/core/mixins/lock.py +31 -0
  36. slidge/core/mixins/message.py +398 -0
  37. slidge/core/mixins/message_maker.py +154 -0
  38. slidge/core/mixins/presence.py +217 -0
  39. slidge/core/mixins/recipient.py +43 -0
  40. slidge/core/pubsub.py +282 -116
  41. slidge/core/session.py +595 -372
  42. slidge/group/__init__.py +10 -0
  43. slidge/group/archive.py +125 -0
  44. slidge/group/bookmarks.py +163 -0
  45. slidge/group/participant.py +458 -0
  46. slidge/group/room.py +1103 -0
  47. slidge/migration.py +18 -0
  48. slidge/slixfix/__init__.py +68 -0
  49. slidge/{util/xep_0084 → slixfix/link_preview}/__init__.py +3 -5
  50. slidge/slixfix/link_preview/link_preview.py +17 -0
  51. slidge/slixfix/link_preview/stanza.py +99 -0
  52. slidge/slixfix/roster.py +60 -0
  53. slidge/{util → slixfix}/xep_0077/register.py +14 -2
  54. slidge/slixfix/xep_0077/stanza.py +104 -0
  55. slidge/{util → slixfix}/xep_0100/gateway.py +25 -15
  56. slidge/slixfix/xep_0100/stanza.py +9 -0
  57. slidge/slixfix/xep_0153/__init__.py +10 -0
  58. slidge/slixfix/xep_0153/stanza.py +25 -0
  59. slidge/slixfix/xep_0153/vcard_avatar.py +23 -0
  60. slidge/slixfix/xep_0264/__init__.py +5 -0
  61. slidge/slixfix/xep_0264/stanza.py +36 -0
  62. slidge/slixfix/xep_0264/thumbnail.py +23 -0
  63. slidge/slixfix/xep_0292/__init__.py +5 -0
  64. slidge/slixfix/xep_0292/vcard4.py +100 -0
  65. slidge/slixfix/xep_0313/__init__.py +12 -0
  66. slidge/slixfix/xep_0313/mam.py +262 -0
  67. slidge/slixfix/xep_0313/stanza.py +359 -0
  68. slidge/slixfix/xep_0317/__init__.py +5 -0
  69. slidge/slixfix/xep_0317/hats.py +17 -0
  70. slidge/slixfix/xep_0317/stanza.py +28 -0
  71. slidge/{util → slixfix}/xep_0356_old/privilege.py +9 -7
  72. slidge/slixfix/xep_0424/__init__.py +9 -0
  73. slidge/slixfix/xep_0424/retraction.py +77 -0
  74. slidge/slixfix/xep_0424/stanza.py +28 -0
  75. slidge/slixfix/xep_0490/__init__.py +8 -0
  76. slidge/slixfix/xep_0490/mds.py +47 -0
  77. slidge/slixfix/xep_0490/stanza.py +17 -0
  78. slidge/util/__init__.py +4 -6
  79. slidge/util/archive_msg.py +61 -0
  80. slidge/util/conf.py +206 -0
  81. slidge/util/db.py +57 -76
  82. slidge/util/schema.sql +126 -0
  83. slidge/util/sql.py +508 -0
  84. slidge/util/test.py +215 -25
  85. slidge/util/types.py +177 -4
  86. slidge/util/util.py +225 -59
  87. slidge-0.1.1.dist-info/METADATA +110 -0
  88. slidge-0.1.1.dist-info/RECORD +96 -0
  89. {slidge-0.1.0b2.dist-info → slidge-0.1.1.dist-info}/WHEEL +1 -1
  90. slidge/core/contact.py +0 -891
  91. slidge/core/gateway.py +0 -916
  92. slidge/plugins/discord/__init__.py +0 -90
  93. slidge/plugins/discord/client.py +0 -108
  94. slidge/plugins/discord/session.py +0 -162
  95. slidge/plugins/dummy.py +0 -203
  96. slidge/plugins/facebook.py +0 -493
  97. slidge/plugins/hackernews.py +0 -213
  98. slidge/plugins/mattermost/__init__.py +0 -1
  99. slidge/plugins/mattermost/api.py +0 -280
  100. slidge/plugins/mattermost/gateway.py +0 -365
  101. slidge/plugins/mattermost/websocket.py +0 -252
  102. slidge/plugins/signal/__init__.py +0 -3
  103. slidge/plugins/signal/contact.py +0 -106
  104. slidge/plugins/signal/gateway.py +0 -282
  105. slidge/plugins/signal/session.py +0 -448
  106. slidge/plugins/signal/txt.py +0 -53
  107. slidge/plugins/skype.py +0 -325
  108. slidge/plugins/steam.py +0 -310
  109. slidge/plugins/telegram/__init__.py +0 -5
  110. slidge/plugins/telegram/client.py +0 -228
  111. slidge/plugins/telegram/config.py +0 -12
  112. slidge/plugins/telegram/contact.py +0 -176
  113. slidge/plugins/telegram/gateway.py +0 -150
  114. slidge/plugins/telegram/session.py +0 -256
  115. slidge/util/xep_0030/__init__.py +0 -13
  116. slidge/util/xep_0030/disco.py +0 -811
  117. slidge/util/xep_0030/stanza/__init__.py +0 -7
  118. slidge/util/xep_0030/stanza/info.py +0 -270
  119. slidge/util/xep_0030/stanza/items.py +0 -147
  120. slidge/util/xep_0030/static.py +0 -467
  121. slidge/util/xep_0055/__init__.py +0 -5
  122. slidge/util/xep_0055/search.py +0 -75
  123. slidge/util/xep_0055/stanza.py +0 -10
  124. slidge/util/xep_0077/stanza.py +0 -71
  125. slidge/util/xep_0084/avatar.py +0 -137
  126. slidge/util/xep_0084/stanza.py +0 -104
  127. slidge/util/xep_0115/__init__.py +0 -12
  128. slidge/util/xep_0115/caps.py +0 -379
  129. slidge/util/xep_0115/stanza.py +0 -16
  130. slidge/util/xep_0115/static.py +0 -137
  131. slidge/util/xep_0292/__init__.py +0 -1
  132. slidge/util/xep_0292/stanza.py +0 -167
  133. slidge/util/xep_0292/vcard4.py +0 -75
  134. slidge/util/xep_0333/__init__.py +0 -10
  135. slidge/util/xep_0333/markers.py +0 -96
  136. slidge/util/xep_0333/stanza.py +0 -34
  137. slidge/util/xep_0356/__init__.py +0 -7
  138. slidge/util/xep_0356/permissions.py +0 -35
  139. slidge/util/xep_0356/privilege.py +0 -160
  140. slidge/util/xep_0356/stanza.py +0 -44
  141. slidge/util/xep_0363/__init__.py +0 -16
  142. slidge/util/xep_0363/http_upload.py +0 -215
  143. slidge/util/xep_0363/stanza.py +0 -46
  144. slidge/util/xep_0461/__init__.py +0 -6
  145. slidge/util/xep_0461/reply.py +0 -48
  146. slidge/util/xep_0461/stanza.py +0 -47
  147. slidge-0.1.0b2.dist-info/METADATA +0 -171
  148. slidge-0.1.0b2.dist-info/RECORD +0 -81
  149. /slidge/{plugins/__init__.py → py.typed} +0 -0
  150. /slidge/{util → slixfix}/xep_0077/__init__.py +0 -0
  151. /slidge/{util → slixfix}/xep_0100/__init__.py +0 -0
  152. /slidge/{util → slixfix}/xep_0356_old/__init__.py +0 -0
  153. /slidge/{util → slixfix}/xep_0356_old/stanza.py +0 -0
  154. {slidge-0.1.0b2.dist-info → slidge-0.1.1.dist-info}/LICENSE +0 -0
  155. {slidge-0.1.0b2.dist-info → slidge-0.1.1.dist-info}/entry_points.txt +0 -0
slidge/migration.py ADDED
@@ -0,0 +1,18 @@
1
+ import logging
2
+ import shutil
3
+
4
+ from .core import config
5
+
6
+
7
+ def remove_avatar_cache_v1():
8
+ old_dir = config.HOME_DIR / "slidge_avatars"
9
+ if old_dir.exists():
10
+ log.info("Avatar cache dir v1 found, clearing it.")
11
+ shutil.rmtree(old_dir)
12
+
13
+
14
+ def migrate():
15
+ remove_avatar_cache_v1()
16
+
17
+
18
+ log = logging.getLogger(__name__)
@@ -0,0 +1,68 @@
1
+ # This module contains patches for slixmpp; some have pending requests upstream
2
+ # and should be removed on the next slixmpp release.
3
+
4
+ # ruff: noqa: F401
5
+
6
+ import slixmpp.plugins
7
+ from slixmpp import Message
8
+ from slixmpp.plugins.xep_0050 import XEP_0050, Command
9
+ from slixmpp.xmlstream import StanzaBase
10
+
11
+ from . import ( # xep_0356,
12
+ link_preview,
13
+ xep_0077,
14
+ xep_0100,
15
+ xep_0153,
16
+ xep_0264,
17
+ xep_0292,
18
+ xep_0313,
19
+ xep_0317,
20
+ xep_0356_old,
21
+ xep_0424,
22
+ xep_0490,
23
+ )
24
+
25
+
26
+ def session_bind(self, jid):
27
+ self.xmpp["xep_0030"].add_feature(Command.namespace)
28
+ # awful hack to for the disco items: we need to comment this line
29
+ # related issue: https://todo.sr.ht/~nicoco/slidge/131
30
+ # self.xmpp['xep_0030'].set_items(node=Command.namespace, items=tuple())
31
+
32
+
33
+ XEP_0050.session_bind = session_bind # type:ignore
34
+
35
+
36
+ def reply(self, body=None, clear=True):
37
+ """
38
+ Overrides slixmpp's Message.reply(), since it strips to sender's resource
39
+ for mtype=groupchat, and we do not want that, because when we raise an XMPPError,
40
+ we actually want to preserve the resource.
41
+ (this is called in RootStanza.exception() to handle XMPPErrors)
42
+ """
43
+ new_message = StanzaBase.reply(self, clear)
44
+ new_message["thread"] = self["thread"]
45
+ new_message["parent_thread"] = self["parent_thread"]
46
+
47
+ del new_message["id"]
48
+ if self.stream is not None and self.stream.use_message_ids:
49
+ new_message["id"] = self.stream.new_id()
50
+
51
+ if body is not None:
52
+ new_message["body"] = body
53
+ return new_message
54
+
55
+
56
+ slixmpp.plugins.PLUGINS.extend(
57
+ [
58
+ "link_preview",
59
+ "xep_0264",
60
+ "xep_0292_provider",
61
+ "xep_0317",
62
+ "xep_0356_old",
63
+ "xep_0490",
64
+ ]
65
+ )
66
+
67
+
68
+ Message.reply = reply # type: ignore
@@ -1,12 +1,10 @@
1
-
2
1
  # Slixmpp: The Slick XMPP Library
3
2
  # Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
4
3
  # This file is part of Slixmpp.
5
4
  # See the file LICENSE for copying permission.
5
+
6
6
  from slixmpp.plugins.base import register_plugin
7
7
 
8
- from . import stanza
9
- from .avatar import XEP_0084
10
- from .stanza import Data, MetaData
8
+ from .link_preview import LinkPreview
11
9
 
12
- register_plugin(XEP_0084)
10
+ register_plugin(LinkPreview)
@@ -0,0 +1,17 @@
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 permission.
5
+ from slixmpp.plugins import BasePlugin
6
+
7
+ from . import stanza
8
+
9
+
10
+ class LinkPreview(BasePlugin):
11
+ name = "link_preview"
12
+ description = "Sender-generated link previews"
13
+ dependencies = set()
14
+ stanza = stanza
15
+
16
+ def plugin_init(self):
17
+ stanza.register_plugin()
@@ -0,0 +1,99 @@
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 permission.
5
+ from typing import Optional, Type
6
+
7
+ from slixmpp.stanza.message import Message
8
+ from slixmpp.xmlstream import ElementBase, register_stanza_plugin
9
+
10
+
11
+ class LinkPreview(ElementBase):
12
+ name = "Description"
13
+ namespace = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
14
+ plugin_attrib = "link_preview"
15
+ plugin_multi_attrib = "link_previews"
16
+ interfaces = {"about", "title", "description", "url", "image", "type", "site_name"}
17
+
18
+ def _set_og(self, el: ElementBase, value: str) -> None:
19
+ el.xml.text = value
20
+ self.xml.append(el.xml)
21
+
22
+ def _get_og(self, el: Type[ElementBase]) -> Optional[str]:
23
+ child = self.xml.find(f"{{{el.namespace}}}{el.name}")
24
+ if child is None:
25
+ return None
26
+ return child.text
27
+
28
+ def set_title(self, v: str) -> None:
29
+ self._set_og(Title(), v)
30
+
31
+ def get_title(self) -> Optional[str]:
32
+ return self._get_og(Title)
33
+
34
+ def set_description(self, v: str) -> None:
35
+ self._set_og(Description(), v)
36
+
37
+ def get_description(self) -> Optional[str]:
38
+ return self._get_og(Description)
39
+
40
+ def set_url(self, v: str) -> None:
41
+ self._set_og(Url(), v)
42
+
43
+ def get_url(self) -> Optional[str]:
44
+ return self._get_og(Url)
45
+
46
+ def set_image(self, v: str) -> None:
47
+ self._set_og(Image(), v)
48
+
49
+ def get_image(self) -> Optional[str]:
50
+ return self._get_og(Image)
51
+
52
+ def set_type(self, v: str) -> None:
53
+ self._set_og(Type_(), v)
54
+
55
+ def get_type(self) -> Optional[str]:
56
+ return self._get_og(Type_)
57
+
58
+ def set_site_name(self, v: str) -> None:
59
+ self._set_og(SiteName(), v)
60
+
61
+ def get_site_name(self) -> Optional[str]:
62
+ return self._get_og(SiteName)
63
+
64
+ def get_about(self) -> Optional[str]:
65
+ return self.xml.attrib.get(f"{{{self.namespace}}}about")
66
+
67
+
68
+ class OpenGraphMixin(ElementBase):
69
+ namespace = "https://ogp.me/ns#"
70
+
71
+
72
+ class Title(OpenGraphMixin):
73
+ name = plugin_attrib = "title"
74
+
75
+
76
+ class Description(OpenGraphMixin):
77
+ name = plugin_attrib = "description"
78
+
79
+
80
+ class Url(OpenGraphMixin):
81
+ name = plugin_attrib = "url"
82
+
83
+
84
+ class Image(OpenGraphMixin):
85
+ name = plugin_attrib = "image"
86
+
87
+
88
+ class Type_(OpenGraphMixin):
89
+ name = plugin_attrib = "type"
90
+
91
+
92
+ class SiteName(OpenGraphMixin):
93
+ name = plugin_attrib = "site_name"
94
+
95
+
96
+ def register_plugin():
97
+ for plugin in Title, Description, Url, Image, Type_, SiteName:
98
+ register_stanza_plugin(plugin, Title)
99
+ register_stanza_plugin(Message, LinkPreview, iterable=True)
@@ -0,0 +1,60 @@
1
+ from slixmpp import JID
2
+
3
+ from ..util.db import log, user_store
4
+
5
+
6
+ class YesSet(set):
7
+ """
8
+ A pseudo-set which always test True for membership
9
+ """
10
+
11
+ def __contains__(self, item):
12
+ log.debug("Test in")
13
+ return True
14
+
15
+
16
+ class RosterBackend:
17
+ """
18
+ A pseudo-roster for the gateway component.
19
+
20
+ If a user is in the user store, this will behave as if the user is part of the
21
+ roster with subscription "both", and "none" otherwise.
22
+
23
+ This is rudimentary but the only sane way I could come up with so far.
24
+ """
25
+
26
+ @staticmethod
27
+ def entries(_owner_jid, _default=None):
28
+ return YesSet()
29
+
30
+ @staticmethod
31
+ def save(_owner_jid, _jid, _item_state, _db_state):
32
+ pass
33
+
34
+ @staticmethod
35
+ def load(_owner_jid, jid, _db_state):
36
+ log.debug("Load %s", jid)
37
+ user = user_store.get_by_jid(JID(jid))
38
+ log.debug("User %s", user)
39
+ if user is None:
40
+ return {
41
+ "name": "",
42
+ "groups": [],
43
+ "from": False,
44
+ "to": False,
45
+ "pending_in": False,
46
+ "pending_out": False,
47
+ "whitelisted": False,
48
+ "subscription": "both",
49
+ }
50
+ else:
51
+ return {
52
+ "name": "",
53
+ "groups": [],
54
+ "from": True,
55
+ "to": True,
56
+ "pending_in": False,
57
+ "pending_out": False,
58
+ "whitelisted": False,
59
+ "subscription": "none",
60
+ }
@@ -5,6 +5,7 @@
5
5
  import logging
6
6
  import ssl
7
7
 
8
+ from slixmpp.exceptions import XMPPError
8
9
  from slixmpp.plugins import BasePlugin
9
10
  from slixmpp.stanza import Iq, StreamFeatures
10
11
  from slixmpp.xmlstream import JID, StanzaBase, register_stanza_plugin
@@ -19,7 +20,6 @@ log = logging.getLogger(__name__)
19
20
 
20
21
  # noinspection PyPep8Naming
21
22
  class XEP_0077(BasePlugin):
22
-
23
23
  """
24
24
  XEP-0077: In-Band Registration
25
25
 
@@ -67,6 +67,7 @@ class XEP_0077(BasePlugin):
67
67
  "order": 50,
68
68
  "form_fields": {"username", "password"},
69
69
  "form_instructions": "Enter your credentials",
70
+ "enable_subscription": True,
70
71
  }
71
72
  _user_store: dict[str, dict[str, str]]
72
73
 
@@ -79,7 +80,7 @@ class XEP_0077(BasePlugin):
79
80
  self.xmpp.register_handler(
80
81
  CoroutineCallback(
81
82
  "registration",
82
- StanzaPath("/iq/register"),
83
+ StanzaPath(f"/iq@to={self.xmpp.boundjid.bare}/register"),
83
84
  self._handle_registration,
84
85
  )
85
86
  )
@@ -147,6 +148,11 @@ class XEP_0077(BasePlugin):
147
148
 
148
149
  async def _handle_registration(self, iq: StanzaBase):
149
150
  if iq["type"] == "get":
151
+ if not self.enable_subscription:
152
+ raise XMPPError(
153
+ "bad-request",
154
+ text="You must use adhoc commands to register to this gateway.",
155
+ )
150
156
  await self._send_form(iq)
151
157
  elif iq["type"] == "set":
152
158
  form_dict = iq["register"]["form"].get_values() or iq["register"]
@@ -168,6 +174,12 @@ class XEP_0077(BasePlugin):
168
174
  self.xmpp.event("user_unregister", iq)
169
175
  return
170
176
 
177
+ if not self.enable_subscription:
178
+ raise XMPPError(
179
+ "bad-request",
180
+ text="You must use adhoc commands to register to this gateway.",
181
+ )
182
+
171
183
  if self.form_fields is not None:
172
184
  for field in self.form_fields:
173
185
  if not iq["register"][field]:
@@ -0,0 +1,104 @@
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 permission.
5
+ from __future__ import unicode_literals
6
+
7
+ from typing import ClassVar, Set
8
+
9
+ from slixmpp.xmlstream import ElementBase
10
+
11
+
12
+ class Register(ElementBase):
13
+ namespace = "jabber:iq:register"
14
+ name = "query"
15
+ plugin_attrib = "register"
16
+ interfaces = {
17
+ "username",
18
+ "password",
19
+ "email",
20
+ "nick",
21
+ "name",
22
+ "first",
23
+ "last",
24
+ "address",
25
+ "city",
26
+ "state",
27
+ "zip",
28
+ "phone",
29
+ "url",
30
+ "date",
31
+ "misc",
32
+ "text",
33
+ "key",
34
+ "registered",
35
+ "remove",
36
+ "instructions",
37
+ "fields",
38
+ }
39
+ sub_interfaces = interfaces
40
+ form_fields = {
41
+ "username",
42
+ "password",
43
+ "email",
44
+ "nick",
45
+ "name",
46
+ "first",
47
+ "last",
48
+ "address",
49
+ "city",
50
+ "state",
51
+ "zip",
52
+ "phone",
53
+ "url",
54
+ "date",
55
+ "misc",
56
+ "text",
57
+ "key",
58
+ }
59
+
60
+ def get_registered(self):
61
+ present = self.xml.find("{%s}registered" % self.namespace)
62
+ return present is not None
63
+
64
+ def get_remove(self):
65
+ present = self.xml.find("{%s}remove" % self.namespace)
66
+ return present is not None
67
+
68
+ def set_registered(self, value):
69
+ if value:
70
+ self.add_field("registered")
71
+ else:
72
+ del self["registered"]
73
+
74
+ def set_remove(self, value):
75
+ if value:
76
+ self.add_field("remove")
77
+ else:
78
+ del self["remove"]
79
+
80
+ def add_field(self, value):
81
+ self._set_sub_text(value, "", keep=True)
82
+
83
+ def get_fields(self):
84
+ fields = set()
85
+ for field in self.form_fields:
86
+ if self.xml.find("{%s}%s" % (self.namespace, field)) is not None:
87
+ fields.add(field)
88
+ return fields
89
+
90
+ def set_fields(self, fields):
91
+ del self["fields"]
92
+ for field in fields:
93
+ self._set_sub_text(field, "", keep=True)
94
+
95
+ def del_fields(self):
96
+ for field in self.form_fields:
97
+ self._del_sub(field)
98
+
99
+
100
+ class RegisterFeature(ElementBase):
101
+ name = "register"
102
+ namespace = "http://jabber.org/features/iq-register"
103
+ plugin_attrib = name
104
+ interfaces: ClassVar[Set[str]] = set()
@@ -1,8 +1,14 @@
1
1
  import logging
2
+ import warnings
2
3
 
3
- from slixmpp import JID, Iq, Message, Presence
4
+ from slixmpp import JID, Iq, Message, Presence, register_stanza_plugin
5
+ from slixmpp.exceptions import XMPPError
4
6
  from slixmpp.plugins.base import BasePlugin
5
7
 
8
+ from slidge.core import config
9
+
10
+ from . import stanza
11
+
6
12
  log = logging.getLogger(__name__)
7
13
 
8
14
 
@@ -42,6 +48,8 @@ class XEP_0100(BasePlugin):
42
48
 
43
49
  self.xmpp.add_event_handler("message", self.on_message)
44
50
 
51
+ register_stanza_plugin(Iq, stanza.Gateway)
52
+
45
53
  def plugin_end(self):
46
54
  if not self.xmpp.is_component:
47
55
  self.xmpp.remove_event_handler("user_register", self.on_user_register)
@@ -65,10 +73,7 @@ class XEP_0100(BasePlugin):
65
73
  await self.add_component_to_roster(jid=iq.get_from())
66
74
 
67
75
  async def add_component_to_roster(self, jid: JID):
68
- try:
69
- if self.xmpp.no_roster_push:
70
- return
71
- except AttributeError:
76
+ if config.NO_ROSTER_PUSH:
72
77
  return
73
78
  items = {
74
79
  self.xmpp.boundjid.bare: {
@@ -77,18 +82,21 @@ class XEP_0100(BasePlugin):
77
82
  "groups": ["Slidge"],
78
83
  }
79
84
  }
85
+ try:
86
+ await self._set_roster(jid, items)
87
+ except PermissionError:
88
+ warnings.warn(
89
+ "Slidge does not have the privilege to manage users' rosters. "
90
+ "Users should add the slidge component to their rosters manually."
91
+ )
92
+ if config.ROSTER_PUSH_PRESENCE_SUBSCRIPTION_REQUEST_FALLBACK:
93
+ self.xmpp.send_presence(ptype="subscribe", pto=jid.bare)
94
+
95
+ async def _set_roster(self, jid, items):
80
96
  try:
81
97
  await self.xmpp["xep_0356"].set_roster(jid=jid.bare, roster_items=items)
82
98
  except PermissionError:
83
- try:
84
- await self.xmpp["xep_0356_old"].set_roster(
85
- jid=jid.bare, roster_items=items
86
- )
87
- except PermissionError:
88
- log.warning(
89
- "Slidge does not have the privilege to manage users' rosters. "
90
- "Users should add the slidge component to their rosters manually."
91
- )
99
+ await self.xmpp["xep_0356_old"].set_roster(jid=jid.bare, roster_items=items)
92
100
 
93
101
  def on_presence_unsubscribe(self, p: Presence):
94
102
  if p.get_to() == self.xmpp.boundjid.bare:
@@ -106,6 +114,8 @@ class XEP_0100(BasePlugin):
106
114
  return
107
115
 
108
116
  if self.needs_registration and await self.get_user(msg) is None:
109
- return
117
+ raise XMPPError(
118
+ "registration-required", text="You are not registered to this gateway"
119
+ )
110
120
 
111
121
  self.xmpp.event("legacy_message", msg)
@@ -0,0 +1,9 @@
1
+ from slixmpp.xmlstream import ElementBase
2
+
3
+
4
+ class Gateway(ElementBase):
5
+ namespace = "jabber:iq:gateway"
6
+ name = "query"
7
+ plugin_attrib = "gateway"
8
+ interfaces = {"desc", "prompt", "jid"}
9
+ sub_interfaces = interfaces
@@ -0,0 +1,10 @@
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 permission.
5
+ from slixmpp.plugins.base import register_plugin
6
+
7
+ from .stanza import VCardTempUpdate
8
+ from .vcard_avatar import XEP_0153
9
+
10
+ register_plugin(XEP_0153)
@@ -0,0 +1,25 @@
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 permission.
5
+ from slixmpp.xmlstream import ElementBase
6
+
7
+
8
+ class VCardTempUpdate(ElementBase):
9
+ name = "x"
10
+ namespace = "vcard-temp:x:update"
11
+ plugin_attrib = "vcard_temp_update"
12
+ interfaces = {"photo"}
13
+ sub_interfaces = interfaces
14
+
15
+ def set_photo(self, value):
16
+ if value is not None:
17
+ self._set_sub_text("photo", value, keep=True)
18
+ else:
19
+ self._del_sub("photo")
20
+
21
+ def get_photo(self):
22
+ photo = self.xml.find("{%s}photo" % self.namespace)
23
+ if photo is None:
24
+ return None
25
+ return photo.text
@@ -0,0 +1,23 @@
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 permission.
5
+ import logging
6
+
7
+ from slixmpp.plugins.base import BasePlugin
8
+ from slixmpp.stanza import Presence
9
+ from slixmpp.xmlstream import register_stanza_plugin
10
+
11
+ from . import VCardTempUpdate, stanza
12
+
13
+ log = logging.getLogger(__name__)
14
+
15
+
16
+ class XEP_0153(BasePlugin):
17
+ name = "xep_0153"
18
+ description = "XEP-0153: vCard-Based Avatars (slidge, just for MUCs)"
19
+ dependencies = {"xep_0054"}
20
+ stanza = stanza
21
+
22
+ def plugin_init(self):
23
+ register_stanza_plugin(Presence, VCardTempUpdate)
@@ -0,0 +1,5 @@
1
+ from slixmpp.plugins.base import register_plugin
2
+
3
+ from .thumbnail import XEP_0264
4
+
5
+ register_plugin(XEP_0264)
@@ -0,0 +1,36 @@
1
+ from typing import Optional
2
+
3
+ from slixmpp import register_stanza_plugin
4
+ from slixmpp.plugins.xep_0234.stanza import File
5
+ from slixmpp.xmlstream import ElementBase
6
+
7
+ NS = "urn:xmpp:thumbs:1"
8
+
9
+
10
+ class Thumbnail(ElementBase):
11
+ name = plugin_attrib = "thumbnail"
12
+ namespace = NS
13
+ interfaces = {"uri", "media-type", "width", "height"}
14
+
15
+ def get_width(self) -> float:
16
+ return _int_or_none(self._get_attr("width"))
17
+
18
+ def get_height(self) -> float:
19
+ return _int_or_none(self._get_attr("height"))
20
+
21
+ def set_width(self, v: int) -> None:
22
+ self._set_attr("width", str(v))
23
+
24
+ def set_height(self, v: int) -> None:
25
+ self._set_attr("height", str(v))
26
+
27
+
28
+ def _int_or_none(v) -> Optional[int]:
29
+ try:
30
+ return int(v)
31
+ except ValueError:
32
+ return None
33
+
34
+
35
+ def register_plugin():
36
+ register_stanza_plugin(File, Thumbnail)
@@ -0,0 +1,23 @@
1
+ import logging
2
+
3
+ from slixmpp.plugins import BasePlugin
4
+
5
+ from . import stanza
6
+
7
+ log = logging.getLogger(__name__)
8
+
9
+
10
+ class XEP_0264(BasePlugin):
11
+ """
12
+ XEP-0264: Jingle Content Thumbnails
13
+
14
+ Minimum needed for xep 0385 (Stateless inline media sharing)
15
+ """
16
+
17
+ name = "xep_0264"
18
+ description = "XEP-0264: Jingle Content Thumbnails"
19
+ dependencies = {"xep_0234"}
20
+ stanza = stanza
21
+
22
+ def plugin_init(self):
23
+ stanza.register_plugin()
@@ -0,0 +1,5 @@
1
+ from slixmpp.plugins.xep_0292 import stanza
2
+
3
+ from . import vcard4
4
+
5
+ __all__ = ("stanza", "vcard4")