slidge 0.2.11__py3-none-any.whl → 0.3.0a0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- slidge/__init__.py +5 -2
- slidge/command/adhoc.py +9 -3
- slidge/command/admin.py +16 -12
- slidge/command/base.py +16 -12
- slidge/command/chat_command.py +25 -16
- slidge/command/user.py +7 -8
- slidge/contact/contact.py +119 -209
- slidge/contact/roster.py +106 -105
- slidge/core/config.py +2 -43
- slidge/core/dispatcher/caps.py +9 -2
- slidge/core/dispatcher/disco.py +13 -3
- slidge/core/dispatcher/message/__init__.py +1 -1
- slidge/core/dispatcher/message/chat_state.py +17 -8
- slidge/core/dispatcher/message/marker.py +7 -5
- slidge/core/dispatcher/message/message.py +117 -92
- slidge/core/dispatcher/muc/__init__.py +1 -1
- slidge/core/dispatcher/muc/admin.py +4 -4
- slidge/core/dispatcher/muc/mam.py +10 -6
- slidge/core/dispatcher/muc/misc.py +4 -2
- slidge/core/dispatcher/muc/owner.py +5 -3
- slidge/core/dispatcher/muc/ping.py +3 -1
- slidge/core/dispatcher/presence.py +21 -15
- slidge/core/dispatcher/registration.py +20 -12
- slidge/core/dispatcher/search.py +7 -3
- slidge/core/dispatcher/session_dispatcher.py +13 -5
- slidge/core/dispatcher/util.py +37 -27
- slidge/core/dispatcher/vcard.py +7 -4
- slidge/core/gateway.py +168 -84
- slidge/core/mixins/__init__.py +1 -11
- slidge/core/mixins/attachment.py +163 -148
- slidge/core/mixins/avatar.py +100 -177
- slidge/core/mixins/db.py +50 -2
- slidge/core/mixins/message.py +19 -17
- slidge/core/mixins/message_maker.py +29 -15
- slidge/core/mixins/message_text.py +38 -30
- slidge/core/mixins/presence.py +91 -35
- slidge/core/pubsub.py +42 -47
- slidge/core/session.py +88 -57
- slidge/db/alembic/versions/0337c90c0b96_unify_legacy_xmpp_id_mappings.py +183 -0
- slidge/db/alembic/versions/4dbd23a3f868_new_avatar_store.py +56 -0
- slidge/db/alembic/versions/54ce3cde350c_use_hash_for_avatar_filenames.py +50 -0
- slidge/db/alembic/versions/58b98dacf819_refactor.py +118 -0
- slidge/db/alembic/versions/75a62b74b239_ditch_hats_table.py +74 -0
- slidge/db/avatar.py +150 -119
- slidge/db/meta.py +33 -22
- slidge/db/models.py +68 -117
- slidge/db/store.py +412 -1094
- slidge/group/archive.py +61 -54
- slidge/group/bookmarks.py +74 -55
- slidge/group/participant.py +135 -142
- slidge/group/room.py +321 -313
- slidge/main.py +28 -18
- slidge/migration.py +2 -12
- slidge/slixfix/__init__.py +20 -4
- slidge/slixfix/delivery_receipt.py +6 -4
- slidge/slixfix/link_preview/link_preview.py +1 -1
- slidge/slixfix/link_preview/stanza.py +1 -1
- slidge/slixfix/roster.py +5 -7
- slidge/slixfix/xep_0077/register.py +8 -8
- slidge/slixfix/xep_0077/stanza.py +7 -7
- slidge/slixfix/xep_0100/gateway.py +12 -13
- slidge/slixfix/xep_0153/vcard_avatar.py +1 -1
- slidge/slixfix/xep_0292/vcard4.py +1 -1
- slidge/util/archive_msg.py +11 -5
- slidge/util/conf.py +23 -20
- slidge/util/jid_escaping.py +1 -1
- slidge/{core/mixins → util}/lock.py +6 -6
- slidge/util/test.py +30 -29
- slidge/util/types.py +22 -18
- slidge/util/util.py +19 -22
- {slidge-0.2.11.dist-info → slidge-0.3.0a0.dist-info}/METADATA +1 -1
- slidge-0.3.0a0.dist-info/RECORD +117 -0
- {slidge-0.2.11.dist-info → slidge-0.3.0a0.dist-info}/WHEEL +1 -1
- slidge-0.2.11.dist-info/RECORD +0 -112
- {slidge-0.2.11.dist-info → slidge-0.3.0a0.dist-info}/entry_points.txt +0 -0
- {slidge-0.2.11.dist-info → slidge-0.3.0a0.dist-info}/licenses/LICENSE +0 -0
- {slidge-0.2.11.dist-info → slidge-0.3.0a0.dist-info}/top_level.txt +0 -0
@@ -15,9 +15,10 @@ if TYPE_CHECKING:
|
|
15
15
|
|
16
16
|
|
17
17
|
class RegistrationMixin(DispatcherMixin):
|
18
|
-
|
18
|
+
__slots__: list[str] = []
|
19
|
+
|
20
|
+
def __init__(self, xmpp: "BaseGateway") -> None:
|
19
21
|
super().__init__(xmpp)
|
20
|
-
self.xmpp = xmpp
|
21
22
|
xmpp["xep_0077"].api.register(
|
22
23
|
self.xmpp.make_registration_form, "make_registration_form"
|
23
24
|
)
|
@@ -32,7 +33,10 @@ class RegistrationMixin(DispatcherMixin):
|
|
32
33
|
xmpp.add_event_handler("user_unregister", self._on_user_unregister)
|
33
34
|
|
34
35
|
def get_user(self, jid: JID) -> GatewayUser | None:
|
35
|
-
|
36
|
+
session = self.xmpp.get_session_from_jid(jid)
|
37
|
+
if session is None:
|
38
|
+
return None
|
39
|
+
return session.user
|
36
40
|
|
37
41
|
async def _user_get(
|
38
42
|
self, _gateway_jid, _node, ifrom: JID, iq: Iq
|
@@ -41,7 +45,7 @@ class RegistrationMixin(DispatcherMixin):
|
|
41
45
|
ifrom = iq.get_from()
|
42
46
|
return self.get_user(ifrom)
|
43
47
|
|
44
|
-
async def _user_validate(self, _gateway_jid, _node, ifrom: JID, iq: Iq):
|
48
|
+
async def _user_validate(self, _gateway_jid, _node, ifrom: JID, iq: Iq) -> None:
|
45
49
|
xmpp = self.xmpp
|
46
50
|
log.debug("User validate: %s", ifrom.bare)
|
47
51
|
form_dict = {f.var: iq.get(f.var) for f in xmpp.REGISTRATION_FIELDS}
|
@@ -49,10 +53,13 @@ class RegistrationMixin(DispatcherMixin):
|
|
49
53
|
legacy_module_data = await xmpp.user_prevalidate(ifrom, form_dict)
|
50
54
|
if legacy_module_data is None:
|
51
55
|
legacy_module_data = form_dict
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
+
with self.xmpp.store.session() as orm:
|
57
|
+
user = GatewayUser(
|
58
|
+
jid=ifrom.bare,
|
59
|
+
legacy_module_data=legacy_module_data,
|
60
|
+
)
|
61
|
+
orm.add(user)
|
62
|
+
orm.commit()
|
56
63
|
log.info("New user: %s", user)
|
57
64
|
|
58
65
|
async def _user_modify(
|
@@ -60,13 +67,14 @@ class RegistrationMixin(DispatcherMixin):
|
|
60
67
|
):
|
61
68
|
await self.xmpp.user_prevalidate(ifrom, form_dict)
|
62
69
|
log.debug("Modify user: %s", ifrom)
|
63
|
-
|
70
|
+
with self.xmpp.store.session() as orm:
|
71
|
+
user = orm.query(GatewayUser).one_or_none()
|
64
72
|
if user is None:
|
65
73
|
raise XMPPError("internal-server-error", "User not found")
|
66
74
|
user.legacy_module_data.update(form_dict)
|
67
75
|
self.xmpp.store.users.update(user)
|
68
76
|
|
69
|
-
async def _on_user_register(self, iq: Iq):
|
77
|
+
async def _on_user_register(self, iq: Iq) -> None:
|
70
78
|
session = await self._get_session(iq, wait_for_ready=False)
|
71
79
|
for jid in config.ADMINS:
|
72
80
|
self.xmpp.send_message(
|
@@ -78,8 +86,8 @@ class RegistrationMixin(DispatcherMixin):
|
|
78
86
|
session.send_gateway_message(self.xmpp.WELCOME_MESSAGE)
|
79
87
|
await self.xmpp.login_wrap(session)
|
80
88
|
|
81
|
-
async def _on_user_unregister(self, iq: Iq):
|
82
|
-
await self.xmpp.
|
89
|
+
async def _on_user_unregister(self, iq: Iq) -> None:
|
90
|
+
await self.xmpp.kill_session(iq.get_from())
|
83
91
|
|
84
92
|
|
85
93
|
log = logging.getLogger(__name__)
|
slidge/core/dispatcher/search.py
CHANGED
@@ -3,6 +3,7 @@ from typing import TYPE_CHECKING
|
|
3
3
|
from slixmpp import JID, CoroutineCallback, Iq, StanzaPath
|
4
4
|
from slixmpp.exceptions import XMPPError
|
5
5
|
|
6
|
+
from ...db.models import GatewayUser
|
6
7
|
from .util import DispatcherMixin, exceptions_to_xmpp_errors
|
7
8
|
|
8
9
|
if TYPE_CHECKING:
|
@@ -10,7 +11,9 @@ if TYPE_CHECKING:
|
|
10
11
|
|
11
12
|
|
12
13
|
class SearchMixin(DispatcherMixin):
|
13
|
-
|
14
|
+
__slots__: list[str] = []
|
15
|
+
|
16
|
+
def __init__(self, xmpp: "BaseGateway") -> None:
|
14
17
|
super().__init__(xmpp)
|
15
18
|
|
16
19
|
xmpp["xep_0055"].api.register(self.search_get_form, "search_get_form")
|
@@ -21,7 +24,7 @@ class SearchMixin(DispatcherMixin):
|
|
21
24
|
CoroutineCallback(
|
22
25
|
"iq:gateway",
|
23
26
|
StanzaPath("iq/gateway"),
|
24
|
-
self._handle_gateway_iq,
|
27
|
+
self._handle_gateway_iq,
|
25
28
|
)
|
26
29
|
)
|
27
30
|
|
@@ -29,7 +32,8 @@ class SearchMixin(DispatcherMixin):
|
|
29
32
|
"""
|
30
33
|
Prepare the search form using :attr:`.BaseSession.SEARCH_FIELDS`
|
31
34
|
"""
|
32
|
-
|
35
|
+
with self.xmpp.store.session() as orm:
|
36
|
+
user = orm.query(GatewayUser).one_or_none()
|
33
37
|
if user is None:
|
34
38
|
raise XMPPError(text="Search is only allowed for registered users")
|
35
39
|
|
@@ -30,14 +30,16 @@ class SessionDispatcher(
|
|
30
30
|
SearchMixin,
|
31
31
|
VCardMixin,
|
32
32
|
):
|
33
|
-
|
33
|
+
__slots__: list[str] = ["xmpp", "_MamMixin__mam_cleanup_task"]
|
34
|
+
|
35
|
+
def __init__(self, xmpp: "BaseGateway") -> None:
|
34
36
|
super().__init__(xmpp)
|
35
37
|
xmpp.add_event_handler(
|
36
38
|
"avatar_metadata_publish", self.on_avatar_metadata_publish
|
37
39
|
)
|
38
40
|
|
39
41
|
@exceptions_to_xmpp_errors
|
40
|
-
async def on_avatar_metadata_publish(self, m: Message):
|
42
|
+
async def on_avatar_metadata_publish(self, m: Message) -> None:
|
41
43
|
session = await self._get_session(m, timeout=None)
|
42
44
|
if not session.user.preferences.get("sync_avatar", False):
|
43
45
|
session.log.debug("User does not want to sync their avatar")
|
@@ -46,7 +48,7 @@ class SessionDispatcher(
|
|
46
48
|
|
47
49
|
await self.on_avatar_metadata_info(session, info)
|
48
50
|
|
49
|
-
async def on_avatar_metadata_info(self, session: BaseSession, info: Info):
|
51
|
+
async def on_avatar_metadata_info(self, session: BaseSession, info: Info) -> None:
|
50
52
|
hash_ = info["id"]
|
51
53
|
|
52
54
|
if session.user.avatar_hash == hash_:
|
@@ -66,7 +68,10 @@ class SessionDispatcher(
|
|
66
68
|
height = info["height"]
|
67
69
|
width = info["width"]
|
68
70
|
else:
|
69
|
-
self.xmpp.store.
|
71
|
+
with self.xmpp.store.session(expire_on_commit=False) as orm:
|
72
|
+
session.user.avatar_hash = None
|
73
|
+
orm.add(session.user)
|
74
|
+
orm.commit()
|
70
75
|
bytes_ = type_ = height = width = hash_ = None
|
71
76
|
try:
|
72
77
|
await session.on_avatar(bytes_, hash_, type_, width, height)
|
@@ -80,7 +85,10 @@ class SessionDispatcher(
|
|
80
85
|
f"Something went wrong trying to set your avatar: {e!r}"
|
81
86
|
)
|
82
87
|
else:
|
83
|
-
|
88
|
+
session.user.avatar_hash = hash_
|
89
|
+
with self.xmpp.store.session(expire_on_commit=False) as orm:
|
90
|
+
orm.add(session.user)
|
91
|
+
orm.commit()
|
84
92
|
for room in session.bookmarks:
|
85
93
|
participant = await room.get_user_participant()
|
86
94
|
participant.send_last_presence(force=True, no_cache_online=True)
|
slidge/core/dispatcher/util.py
CHANGED
@@ -19,15 +19,17 @@ class Ignore(BaseException):
|
|
19
19
|
|
20
20
|
|
21
21
|
class DispatcherMixin:
|
22
|
-
|
23
|
-
|
22
|
+
__slots__: list[str] = []
|
23
|
+
|
24
|
+
def __init__(self, xmpp: "BaseGateway") -> None:
|
25
|
+
self.xmpp = xmpp # type:ignore[misc]
|
24
26
|
|
25
27
|
async def _get_session(
|
26
28
|
self,
|
27
29
|
stanza: Message | Presence | Iq,
|
28
30
|
timeout: int | None = 10,
|
29
|
-
wait_for_ready=True,
|
30
|
-
logged=False,
|
31
|
+
wait_for_ready: bool = True,
|
32
|
+
logged: bool = False,
|
31
33
|
) -> BaseSession:
|
32
34
|
xmpp = self.xmpp
|
33
35
|
if stanza.get_from().server == xmpp.boundjid.bare:
|
@@ -51,8 +53,8 @@ class DispatcherMixin:
|
|
51
53
|
self,
|
52
54
|
jid: JID,
|
53
55
|
timeout: int | None = 10,
|
54
|
-
wait_for_ready=True,
|
55
|
-
logged=False,
|
56
|
+
wait_for_ready: bool = True,
|
57
|
+
logged: bool = False,
|
56
58
|
) -> BaseSession:
|
57
59
|
session = self.xmpp.get_session_from_jid(jid)
|
58
60
|
if session is None:
|
@@ -72,14 +74,15 @@ class DispatcherMixin:
|
|
72
74
|
muc = await session.bookmarks.by_jid(ito)
|
73
75
|
return muc
|
74
76
|
|
75
|
-
def _xmpp_msg_id_to_legacy(
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
77
|
+
def _xmpp_msg_id_to_legacy(
|
78
|
+
self, session: "BaseSession", xmpp_id: str, recipient: Recipient
|
79
|
+
):
|
80
|
+
with self.xmpp.store.session() as orm:
|
81
|
+
sent = self.xmpp.store.id_map.get_legacy(
|
82
|
+
orm, recipient.stored.id, xmpp_id, False
|
83
|
+
)
|
84
|
+
if sent is not None:
|
85
|
+
return self.xmpp.LEGACY_MSG_ID_TYPE(sent)
|
83
86
|
|
84
87
|
try:
|
85
88
|
return session.xmpp_to_legacy_msg_id(xmpp_id)
|
@@ -91,11 +94,11 @@ class DispatcherMixin:
|
|
91
94
|
"internal-server-error", "Couldn't convert xmpp msg ID to legacy ID."
|
92
95
|
)
|
93
96
|
|
94
|
-
async def
|
97
|
+
async def _get_session_recipient_thread(
|
95
98
|
self, msg: Message
|
96
99
|
) -> tuple["BaseSession", Recipient, int | str]:
|
97
100
|
session = await self._get_session(msg)
|
98
|
-
e: Recipient = await
|
101
|
+
e: Recipient = await get_recipient(session, msg)
|
99
102
|
legacy_thread = await self._xmpp_to_legacy_thread(session, msg, e)
|
100
103
|
return session, e, legacy_thread
|
101
104
|
|
@@ -107,22 +110,29 @@ class DispatcherMixin:
|
|
107
110
|
return None
|
108
111
|
|
109
112
|
if session.MESSAGE_IDS_ARE_THREAD_IDS:
|
110
|
-
return self._xmpp_msg_id_to_legacy(session, xmpp_thread)
|
113
|
+
return self._xmpp_msg_id_to_legacy(session, xmpp_thread, recipient)
|
111
114
|
|
112
|
-
|
113
|
-
session.
|
114
|
-
|
115
|
-
|
116
|
-
|
115
|
+
with session.xmpp.store.session() as orm:
|
116
|
+
legacy_thread_str = session.xmpp.store.id_map.get_thread(
|
117
|
+
orm, recipient.stored.id, xmpp_thread, recipient.is_group
|
118
|
+
)
|
119
|
+
if legacy_thread_str is not None:
|
120
|
+
return session.xmpp.LEGACY_MSG_ID_TYPE(legacy_thread_str)
|
117
121
|
async with session.thread_creation_lock:
|
118
122
|
legacy_thread = await recipient.create_thread(xmpp_thread)
|
119
|
-
session.xmpp.store.
|
120
|
-
session.
|
121
|
-
|
123
|
+
with session.xmpp.store.session() as orm:
|
124
|
+
session.xmpp.store.id_map.set_thread(
|
125
|
+
orm,
|
126
|
+
recipient.stored.id,
|
127
|
+
str(legacy_thread),
|
128
|
+
xmpp_thread,
|
129
|
+
recipient.is_group,
|
130
|
+
)
|
131
|
+
orm.commit()
|
122
132
|
return legacy_thread
|
123
133
|
|
124
134
|
|
125
|
-
def _ignore(session: "BaseSession", msg: Message):
|
135
|
+
def _ignore(session: "BaseSession", msg: Message) -> bool:
|
126
136
|
i = msg.get_id()
|
127
137
|
if i.startswith("slidge-carbon-"):
|
128
138
|
return True
|
@@ -133,7 +143,7 @@ def _ignore(session: "BaseSession", msg: Message):
|
|
133
143
|
return True
|
134
144
|
|
135
145
|
|
136
|
-
async def
|
146
|
+
async def get_recipient(session: "BaseSession", m: Message) -> RecipientType:
|
137
147
|
session.raise_if_not_logged()
|
138
148
|
if m.get_type() == "groupchat":
|
139
149
|
muc = await session.bookmarks.by_jid(m.get_to())
|
slidge/core/dispatcher/vcard.py
CHANGED
@@ -8,11 +8,14 @@ from slixmpp.plugins.xep_0292.stanza import NS as VCard4NS
|
|
8
8
|
from ...contact import LegacyContact
|
9
9
|
from ...core.session import BaseSession
|
10
10
|
from ...group import LegacyParticipant
|
11
|
+
from ...util.types import Avatar
|
11
12
|
from .util import DispatcherMixin, exceptions_to_xmpp_errors
|
12
13
|
|
13
14
|
|
14
15
|
class VCardMixin(DispatcherMixin):
|
15
|
-
|
16
|
+
__slots__: list[str] = []
|
17
|
+
|
18
|
+
def __init__(self, xmpp) -> None:
|
16
19
|
super().__init__(xmpp)
|
17
20
|
xmpp.register_handler(
|
18
21
|
CoroutineCallback(
|
@@ -34,7 +37,7 @@ class VCardMixin(DispatcherMixin):
|
|
34
37
|
)
|
35
38
|
|
36
39
|
@exceptions_to_xmpp_errors
|
37
|
-
async def on_get_vcard(self, iq: Iq):
|
40
|
+
async def on_get_vcard(self, iq: Iq) -> None:
|
38
41
|
session = await self._get_session(iq, logged=True)
|
39
42
|
contact = await session.contacts.by_jid(iq.get_to())
|
40
43
|
vcard = await contact.get_vcard()
|
@@ -139,8 +142,8 @@ class VCardMixin(DispatcherMixin):
|
|
139
142
|
reply.send()
|
140
143
|
|
141
144
|
if not data:
|
142
|
-
await muc.set_avatar(None
|
145
|
+
await muc.set_avatar(None)
|
143
146
|
return
|
144
147
|
|
145
148
|
if legacy_id:
|
146
|
-
await muc.set_avatar(data, legacy_id
|
149
|
+
await muc.set_avatar(Avatar(data=data, unique_id=legacy_id))
|