slidge 0.2.0a9__py3-none-any.whl → 0.2.0b0__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/__main__.py +2 -3
- slidge/__version__.py +1 -1
- slidge/command/adhoc.py +1 -1
- slidge/command/base.py +4 -4
- slidge/command/user.py +5 -1
- slidge/contact/roster.py +9 -0
- slidge/core/config.py +0 -3
- slidge/core/dispatcher/__init__.py +3 -0
- slidge/core/{gateway → dispatcher}/caps.py +6 -4
- slidge/core/{gateway → dispatcher}/disco.py +11 -17
- slidge/core/dispatcher/message/__init__.py +10 -0
- slidge/core/dispatcher/message/chat_state.py +40 -0
- slidge/core/dispatcher/message/marker.py +62 -0
- slidge/core/dispatcher/message/message.py +397 -0
- slidge/core/dispatcher/muc/__init__.py +12 -0
- slidge/core/dispatcher/muc/admin.py +98 -0
- slidge/core/{gateway → dispatcher/muc}/mam.py +26 -15
- slidge/core/dispatcher/muc/misc.py +121 -0
- slidge/core/dispatcher/muc/owner.py +96 -0
- slidge/core/{gateway → dispatcher/muc}/ping.py +10 -15
- slidge/core/dispatcher/presence.py +177 -0
- slidge/core/{gateway → dispatcher}/registration.py +23 -2
- slidge/core/{gateway → dispatcher}/search.py +9 -14
- slidge/core/dispatcher/session_dispatcher.py +84 -0
- slidge/core/dispatcher/util.py +174 -0
- slidge/core/{gateway/vcard_temp.py → dispatcher/vcard.py} +26 -12
- slidge/core/{gateway/base.py → gateway.py} +42 -137
- slidge/core/mixins/attachment.py +24 -8
- slidge/core/mixins/base.py +2 -2
- slidge/core/mixins/lock.py +10 -8
- slidge/core/mixins/message.py +9 -203
- slidge/core/mixins/message_text.py +211 -0
- slidge/core/pubsub.py +2 -1
- slidge/core/session.py +28 -2
- slidge/db/alembic/versions/15b0bd83407a_remove_bogus_unique_constraints_on_room_.py +83 -0
- slidge/db/alembic/versions/45c24cc73c91_add_bob.py +42 -0
- slidge/db/alembic/versions/5bd48bfdffa2_lift_room_legacy_id_constraint.py +12 -1
- slidge/db/models.py +16 -1
- slidge/db/store.py +144 -11
- slidge/group/bookmarks.py +23 -1
- slidge/group/participant.py +5 -5
- slidge/group/room.py +10 -1
- slidge/{core/gateway → slixfix}/delivery_receipt.py +1 -1
- slidge/util/test.py +9 -5
- slidge/util/types.py +6 -0
- slidge/util/util.py +5 -2
- {slidge-0.2.0a9.dist-info → slidge-0.2.0b0.dist-info}/METADATA +2 -1
- {slidge-0.2.0a9.dist-info → slidge-0.2.0b0.dist-info}/RECORD +51 -40
- slidge-0.2.0b0.dist-info/entry_points.txt +3 -0
- slidge/core/gateway/__init__.py +0 -3
- slidge/core/gateway/muc_admin.py +0 -35
- slidge/core/gateway/presence.py +0 -95
- slidge/core/gateway/session_dispatcher.py +0 -895
- slidge-0.2.0a9.dist-info/entry_points.txt +0 -3
- {slidge-0.2.0a9.dist-info → slidge-0.2.0b0.dist-info}/LICENSE +0 -0
- {slidge-0.2.0a9.dist-info → slidge-0.2.0b0.dist-info}/WHEEL +0 -0
slidge/__main__.py
CHANGED
slidge/__version__.py
CHANGED
slidge/command/adhoc.py
CHANGED
@@ -13,7 +13,7 @@ from . import Command, CommandResponseType, Confirmation, Form, TableResult
|
|
13
13
|
from .base import FormField
|
14
14
|
|
15
15
|
if TYPE_CHECKING:
|
16
|
-
from ..core.gateway
|
16
|
+
from ..core.gateway import BaseGateway
|
17
17
|
from ..core.session import BaseSession
|
18
18
|
|
19
19
|
|
slidge/command/base.py
CHANGED
@@ -6,9 +6,9 @@ from typing import (
|
|
6
6
|
Any,
|
7
7
|
Awaitable,
|
8
8
|
Callable,
|
9
|
-
Collection,
|
10
9
|
Iterable,
|
11
10
|
Optional,
|
11
|
+
Sequence,
|
12
12
|
Type,
|
13
13
|
TypedDict,
|
14
14
|
Union,
|
@@ -54,11 +54,11 @@ class TableResult:
|
|
54
54
|
Structured data as the result of a command
|
55
55
|
"""
|
56
56
|
|
57
|
-
fields:
|
57
|
+
fields: Sequence["FormField"]
|
58
58
|
"""
|
59
59
|
The 'columns names' of the table.
|
60
60
|
"""
|
61
|
-
items:
|
61
|
+
items: Sequence[dict[str, Union[str, JID]]]
|
62
62
|
"""
|
63
63
|
The rows of the table. Each row is a dict where keys are the fields ``var``
|
64
64
|
attribute.
|
@@ -149,7 +149,7 @@ class Form:
|
|
149
149
|
|
150
150
|
title: str
|
151
151
|
instructions: str
|
152
|
-
fields:
|
152
|
+
fields: Sequence["FormField"]
|
153
153
|
handler: FormHandlerType
|
154
154
|
handler_args: Iterable[Any] = field(default_factory=list)
|
155
155
|
handler_kwargs: dict[str, Any] = field(default_factory=dict)
|
slidge/command/user.py
CHANGED
@@ -305,7 +305,10 @@ class LeaveGroup(Command):
|
|
305
305
|
FormField(
|
306
306
|
"group",
|
307
307
|
"Group name",
|
308
|
-
|
308
|
+
type="list-single",
|
309
|
+
options=[
|
310
|
+
{"label": g.name, "value": str(i)} for i, g in enumerate(groups)
|
311
|
+
],
|
309
312
|
)
|
310
313
|
],
|
311
314
|
handler=self.confirm, # type:ignore
|
@@ -329,3 +332,4 @@ class LeaveGroup(Command):
|
|
329
332
|
@staticmethod
|
330
333
|
async def finish(session: AnyBaseSession, _ifrom, group: LegacyMUC):
|
331
334
|
await session.on_leave_group(group.legacy_id)
|
335
|
+
await session.bookmarks.remove(group, reason="You left this group via slidge.")
|
slidge/contact/roster.py
CHANGED
@@ -92,6 +92,13 @@ class LegacyRoster(
|
|
92
92
|
stored = self.__store.get_by_jid(self.session.user_pk, contact_jid)
|
93
93
|
return await self.__update_contact(stored, legacy_id, username)
|
94
94
|
|
95
|
+
def by_jid_only_if_exists(self, contact_jid: JID) -> LegacyContactType | None:
|
96
|
+
with self.__store.session():
|
97
|
+
stored = self.__store.get_by_jid(self.session.user_pk, contact_jid)
|
98
|
+
if stored is not None and stored.updated:
|
99
|
+
return self._contact_cls.from_store(self.session, stored)
|
100
|
+
return None
|
101
|
+
|
95
102
|
async def by_legacy_id(
|
96
103
|
self, legacy_id: LegacyUserIdType, *args, **kwargs
|
97
104
|
) -> LegacyContactType:
|
@@ -147,6 +154,8 @@ class LegacyRoster(
|
|
147
154
|
try:
|
148
155
|
with contact.updating_info():
|
149
156
|
await contact.avatar_wrap_update_info()
|
157
|
+
except XMPPError:
|
158
|
+
raise
|
150
159
|
except Exception as e:
|
151
160
|
raise XMPPError("internal-server-error", str(e))
|
152
161
|
contact._caps_ver = await contact.get_caps_ver(contact.jid)
|
slidge/core/config.py
CHANGED
@@ -154,9 +154,6 @@ LAST_SEEN_FALLBACK__DOC = (
|
|
154
154
|
QR_TIMEOUT = 60
|
155
155
|
QR_TIMEOUT__DOC = "Timeout for QR code flashing confirmation."
|
156
156
|
|
157
|
-
DOWNLOAD_CHUNK_SIZE = 1024
|
158
|
-
DOWNLOAD_CHUNK_SIZE__DOC = "Chunk size when slidge needs to download files using HTTP."
|
159
|
-
|
160
157
|
LAST_MESSAGE_CORRECTION_RETRACTION_WORKAROUND = False
|
161
158
|
LAST_MESSAGE_CORRECTION_RETRACTION_WORKAROUND__DOC = (
|
162
159
|
"If the legacy service does not support last message correction but supports"
|
@@ -5,17 +5,19 @@ from slixmpp import Presence
|
|
5
5
|
from slixmpp.exceptions import XMPPError
|
6
6
|
from slixmpp.xmlstream import StanzaBase
|
7
7
|
|
8
|
+
from .util import DispatcherMixin
|
9
|
+
|
8
10
|
if TYPE_CHECKING:
|
9
|
-
from .
|
11
|
+
from slidge.core.gateway import BaseGateway
|
10
12
|
|
11
13
|
|
12
|
-
class
|
14
|
+
class CapsMixin(DispatcherMixin):
|
13
15
|
def __init__(self, xmpp: "BaseGateway"):
|
14
|
-
|
16
|
+
super().__init__(xmpp)
|
15
17
|
xmpp.del_filter("out", xmpp.plugin["xep_0115"]._filter_add_caps)
|
16
18
|
xmpp.add_filter("out", self._filter_add_caps) # type:ignore
|
17
19
|
|
18
|
-
async def _filter_add_caps(self, stanza: StanzaBase):
|
20
|
+
async def _filter_add_caps(self, stanza: StanzaBase) -> StanzaBase:
|
19
21
|
# we rolled our own "add caps on presences" filter because
|
20
22
|
# there is too much magic happening in slixmpp
|
21
23
|
# anyway, we probably want to roll our own "dynamic disco"/caps
|
@@ -5,13 +5,15 @@ from slixmpp.exceptions import XMPPError
|
|
5
5
|
from slixmpp.plugins.xep_0030.stanza.items import DiscoItems
|
6
6
|
from slixmpp.types import OptJid
|
7
7
|
|
8
|
+
from .util import DispatcherMixin
|
9
|
+
|
8
10
|
if TYPE_CHECKING:
|
9
|
-
from .
|
11
|
+
from slidge.core.gateway import BaseGateway
|
10
12
|
|
11
13
|
|
12
|
-
class
|
14
|
+
class DiscoMixin(DispatcherMixin):
|
13
15
|
def __init__(self, xmpp: "BaseGateway"):
|
14
|
-
|
16
|
+
super().__init__(xmpp)
|
15
17
|
|
16
18
|
xmpp.plugin["xep_0030"].set_node_handler(
|
17
19
|
"get_info",
|
@@ -36,15 +38,11 @@ class Disco:
|
|
36
38
|
if ifrom is None:
|
37
39
|
raise XMPPError("subscription-required")
|
38
40
|
|
39
|
-
|
40
|
-
|
41
|
-
raise XMPPError("registration-required")
|
42
|
-
session = self.xmpp.get_session_from_user(user)
|
43
|
-
await session.wait_for_ready()
|
41
|
+
assert jid is not None
|
42
|
+
session = await self._get_session_from_jid(jid=ifrom)
|
44
43
|
|
45
44
|
log.debug("Looking for entity: %s", jid)
|
46
45
|
|
47
|
-
assert jid is not None
|
48
46
|
entity = await session.get_contact_or_group_or_participant(jid)
|
49
47
|
|
50
48
|
if entity is None:
|
@@ -61,16 +59,12 @@ class Disco:
|
|
61
59
|
if jid != self.xmpp.boundjid.bare:
|
62
60
|
return DiscoItems()
|
63
61
|
|
64
|
-
|
65
|
-
|
66
|
-
raise XMPPError("registration-required")
|
67
|
-
|
68
|
-
session = self.xmpp.get_session_from_user(user)
|
69
|
-
await session.wait_for_ready()
|
62
|
+
assert ifrom is not None
|
63
|
+
session = await self._get_session_from_jid(ifrom)
|
70
64
|
|
71
65
|
d = DiscoItems()
|
72
|
-
for
|
73
|
-
d.add_item(
|
66
|
+
for room in self.xmpp.store.rooms.get_all_jid_and_names(session.user_pk):
|
67
|
+
d.add_item(room.jid, name=room.name)
|
74
68
|
|
75
69
|
return d
|
76
70
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
from slixmpp import Message
|
2
|
+
from slixmpp.xmlstream import StanzaBase
|
3
|
+
|
4
|
+
from ..util import DispatcherMixin, exceptions_to_xmpp_errors
|
5
|
+
|
6
|
+
|
7
|
+
class ChatStateMixin(DispatcherMixin):
|
8
|
+
def __init__(self, xmpp) -> None:
|
9
|
+
super().__init__(xmpp)
|
10
|
+
xmpp.add_event_handler("chatstate_active", self.on_chatstate_active)
|
11
|
+
xmpp.add_event_handler("chatstate_inactive", self.on_chatstate_inactive)
|
12
|
+
xmpp.add_event_handler("chatstate_composing", self.on_chatstate_composing)
|
13
|
+
xmpp.add_event_handler("chatstate_paused", self.on_chatstate_paused)
|
14
|
+
|
15
|
+
@exceptions_to_xmpp_errors
|
16
|
+
async def on_chatstate_active(self, msg: StanzaBase) -> None:
|
17
|
+
assert isinstance(msg, Message)
|
18
|
+
if msg["body"]:
|
19
|
+
# if there is a body, it's handled in on_legacy_message()
|
20
|
+
return
|
21
|
+
session, entity, thread = await self._get_session_entity_thread(msg)
|
22
|
+
await session.on_active(entity, thread)
|
23
|
+
|
24
|
+
@exceptions_to_xmpp_errors
|
25
|
+
async def on_chatstate_inactive(self, msg: StanzaBase) -> None:
|
26
|
+
assert isinstance(msg, Message)
|
27
|
+
session, entity, thread = await self._get_session_entity_thread(msg)
|
28
|
+
await session.on_inactive(entity, thread)
|
29
|
+
|
30
|
+
@exceptions_to_xmpp_errors
|
31
|
+
async def on_chatstate_composing(self, msg: StanzaBase) -> None:
|
32
|
+
assert isinstance(msg, Message)
|
33
|
+
session, entity, thread = await self._get_session_entity_thread(msg)
|
34
|
+
await session.on_composing(entity, thread)
|
35
|
+
|
36
|
+
@exceptions_to_xmpp_errors
|
37
|
+
async def on_chatstate_paused(self, msg: StanzaBase) -> None:
|
38
|
+
assert isinstance(msg, Message)
|
39
|
+
session, entity, thread = await self._get_session_entity_thread(msg)
|
40
|
+
await session.on_paused(entity, thread)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
from slixmpp import JID, Message
|
2
|
+
from slixmpp.xmlstream import StanzaBase
|
3
|
+
|
4
|
+
from ....group.room import LegacyMUC
|
5
|
+
from ....util.types import Recipient
|
6
|
+
from ..util import DispatcherMixin, _get_entity, exceptions_to_xmpp_errors
|
7
|
+
|
8
|
+
|
9
|
+
class MarkerMixin(DispatcherMixin):
|
10
|
+
def __init__(self, xmpp) -> None:
|
11
|
+
super().__init__(xmpp)
|
12
|
+
xmpp.add_event_handler("marker_displayed", self.on_marker_displayed)
|
13
|
+
xmpp.add_event_handler(
|
14
|
+
"message_displayed_synchronization_publish",
|
15
|
+
self.on_message_displayed_synchronization_publish,
|
16
|
+
)
|
17
|
+
|
18
|
+
@exceptions_to_xmpp_errors
|
19
|
+
async def on_marker_displayed(self, msg: StanzaBase) -> None:
|
20
|
+
assert isinstance(msg, Message)
|
21
|
+
session = await self._get_session(msg)
|
22
|
+
|
23
|
+
e: Recipient = await _get_entity(session, msg)
|
24
|
+
legacy_thread = await self._xmpp_to_legacy_thread(session, msg, e)
|
25
|
+
displayed_msg_id = msg["displayed"]["id"]
|
26
|
+
if not isinstance(e, LegacyMUC) and self.xmpp.MARK_ALL_MESSAGES:
|
27
|
+
to_mark = e.get_msg_xmpp_id_up_to(displayed_msg_id) # type: ignore
|
28
|
+
if to_mark is None:
|
29
|
+
session.log.debug("Can't mark all messages up to %s", displayed_msg_id)
|
30
|
+
to_mark = [displayed_msg_id]
|
31
|
+
else:
|
32
|
+
to_mark = [displayed_msg_id]
|
33
|
+
for xmpp_id in to_mark:
|
34
|
+
await session.on_displayed(
|
35
|
+
e, self._xmpp_msg_id_to_legacy(session, xmpp_id), legacy_thread
|
36
|
+
)
|
37
|
+
if isinstance(e, LegacyMUC):
|
38
|
+
await e.echo(msg, None)
|
39
|
+
|
40
|
+
@exceptions_to_xmpp_errors
|
41
|
+
async def on_message_displayed_synchronization_publish(
|
42
|
+
self, msg: StanzaBase
|
43
|
+
) -> None:
|
44
|
+
assert isinstance(msg, Message)
|
45
|
+
chat_jid = JID(msg["pubsub_event"]["items"]["item"]["id"])
|
46
|
+
if chat_jid.server != self.xmpp.boundjid.bare:
|
47
|
+
return
|
48
|
+
|
49
|
+
session = await self._get_session(msg, timeout=None)
|
50
|
+
|
51
|
+
if chat_jid == self.xmpp.boundjid.bare:
|
52
|
+
return
|
53
|
+
|
54
|
+
chat = await session.get_contact_or_group_or_participant(chat_jid)
|
55
|
+
if not isinstance(chat, LegacyMUC):
|
56
|
+
session.log.debug("Ignoring non-groupchat MDS event")
|
57
|
+
return
|
58
|
+
|
59
|
+
stanza_id = msg["pubsub_event"]["items"]["item"]["displayed"]["stanza_id"]["id"]
|
60
|
+
await session.on_displayed(
|
61
|
+
chat, self._xmpp_msg_id_to_legacy(session, stanza_id)
|
62
|
+
)
|