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.
- slidge/__init__.py +55 -31
- slidge/__main__.py +118 -116
- 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 +183 -0
- slidge/core/config.py +216 -0
- 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 +789 -0
- slidge/core/gateway/vcard_temp.py +130 -0
- slidge/core/mixins/__init__.py +19 -0
- slidge/core/mixins/attachment.py +506 -0
- slidge/core/mixins/avatar.py +167 -0
- slidge/core/mixins/base.py +31 -0
- slidge/core/mixins/disco.py +130 -0
- slidge/core/mixins/lock.py +31 -0
- slidge/core/mixins/message.py +398 -0
- slidge/core/mixins/message_maker.py +154 -0
- slidge/core/mixins/presence.py +217 -0
- slidge/core/mixins/recipient.py +43 -0
- slidge/core/pubsub.py +282 -116
- slidge/core/session.py +595 -372
- 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_0084 → slixfix/link_preview}/__init__.py +3 -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 +14 -2
- slidge/slixfix/xep_0077/stanza.py +104 -0
- slidge/{util → slixfix}/xep_0100/gateway.py +25 -15
- slidge/slixfix/xep_0100/stanza.py +9 -0
- 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 +206 -0
- slidge/util/db.py +57 -76
- slidge/util/schema.sql +126 -0
- slidge/util/sql.py +508 -0
- slidge/util/test.py +215 -25
- slidge/util/types.py +177 -4
- slidge/util/util.py +225 -59
- slidge-0.1.1.dist-info/METADATA +110 -0
- slidge-0.1.1.dist-info/RECORD +96 -0
- {slidge-0.1.0b2.dist-info → slidge-0.1.1.dist-info}/WHEEL +1 -1
- slidge/core/contact.py +0 -891
- slidge/core/gateway.py +0 -916
- slidge/plugins/discord/__init__.py +0 -90
- slidge/plugins/discord/client.py +0 -108
- slidge/plugins/discord/session.py +0 -162
- slidge/plugins/dummy.py +0 -203
- slidge/plugins/facebook.py +0 -493
- slidge/plugins/hackernews.py +0 -213
- slidge/plugins/mattermost/__init__.py +0 -1
- slidge/plugins/mattermost/api.py +0 -280
- slidge/plugins/mattermost/gateway.py +0 -365
- slidge/plugins/mattermost/websocket.py +0 -252
- slidge/plugins/signal/__init__.py +0 -3
- slidge/plugins/signal/contact.py +0 -106
- slidge/plugins/signal/gateway.py +0 -282
- slidge/plugins/signal/session.py +0 -448
- slidge/plugins/signal/txt.py +0 -53
- slidge/plugins/skype.py +0 -325
- slidge/plugins/steam.py +0 -310
- slidge/plugins/telegram/__init__.py +0 -5
- slidge/plugins/telegram/client.py +0 -228
- slidge/plugins/telegram/config.py +0 -12
- slidge/plugins/telegram/contact.py +0 -176
- slidge/plugins/telegram/gateway.py +0 -150
- slidge/plugins/telegram/session.py +0 -256
- 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_0055/__init__.py +0 -5
- slidge/util/xep_0055/search.py +0 -75
- slidge/util/xep_0055/stanza.py +0 -10
- slidge/util/xep_0077/stanza.py +0 -71
- slidge/util/xep_0084/avatar.py +0 -137
- slidge/util/xep_0084/stanza.py +0 -104
- slidge/util/xep_0115/__init__.py +0 -12
- slidge/util/xep_0115/caps.py +0 -379
- slidge/util/xep_0115/stanza.py +0 -16
- slidge/util/xep_0115/static.py +0 -137
- slidge/util/xep_0292/__init__.py +0 -1
- slidge/util/xep_0292/stanza.py +0 -167
- slidge/util/xep_0292/vcard4.py +0 -75
- slidge/util/xep_0333/__init__.py +0 -10
- slidge/util/xep_0333/markers.py +0 -96
- slidge/util/xep_0333/stanza.py +0 -34
- 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_0363/__init__.py +0 -16
- slidge/util/xep_0363/http_upload.py +0 -215
- slidge/util/xep_0363/stanza.py +0 -46
- slidge/util/xep_0461/__init__.py +0 -6
- slidge/util/xep_0461/reply.py +0 -48
- slidge/util/xep_0461/stanza.py +0 -47
- slidge-0.1.0b2.dist-info/METADATA +0 -171
- slidge-0.1.0b2.dist-info/RECORD +0 -81
- /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_0356_old/__init__.py +0 -0
- /slidge/{util → slixfix}/xep_0356_old/stanza.py +0 -0
- {slidge-0.1.0b2.dist-info → slidge-0.1.1.dist-info}/LICENSE +0 -0
- {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
|
9
|
-
from .avatar import XEP_0084
|
10
|
-
from .stanza import Data, MetaData
|
8
|
+
from .link_preview import LinkPreview
|
11
9
|
|
12
|
-
register_plugin(
|
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)
|
slidge/slixfix/roster.py
ADDED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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,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,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()
|