slidge 0.2.0a10__tar.gz → 0.2.0b0__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {slidge-0.2.0a10 → slidge-0.2.0b0}/PKG-INFO +1 -1
- {slidge-0.2.0a10 → slidge-0.2.0b0}/pyproject.toml +2 -3
- slidge-0.2.0b0/slidge/__main__.py +3 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/__version__.py +1 -1
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/command/user.py +5 -1
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/contact/roster.py +2 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/config.py +0 -3
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/message/marker.py +2 -7
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/muc/misc.py +3 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/muc/owner.py +1 -1
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/util.py +23 -23
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/mixins/attachment.py +24 -8
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/mixins/lock.py +10 -8
- slidge-0.2.0b0/slidge/core/mixins/message.py +214 -0
- slidge-0.2.0a10/slidge/core/mixins/message.py → slidge-0.2.0b0/slidge/core/mixins/message_text.py +5 -208
- slidge-0.2.0b0/slidge/db/alembic/versions/15b0bd83407a_remove_bogus_unique_constraints_on_room_.py +83 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/versions/5bd48bfdffa2_lift_room_legacy_id_constraint.py +12 -1
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/models.py +3 -1
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/store.py +16 -9
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/group/bookmarks.py +23 -1
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/group/participant.py +5 -5
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/group/room.py +10 -1
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/util/test.py +4 -4
- slidge-0.2.0a10/slidge/__main__.py +0 -4
- {slidge-0.2.0a10 → slidge-0.2.0b0}/LICENSE +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/README.md +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/command/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/command/adhoc.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/command/admin.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/command/base.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/command/categories.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/command/chat_command.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/command/register.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/contact/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/contact/contact.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/caps.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/disco.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/message/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/message/chat_state.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/message/message.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/muc/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/muc/admin.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/muc/mam.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/muc/ping.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/presence.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/registration.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/search.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/session_dispatcher.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/dispatcher/vcard.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/gateway.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/mixins/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/mixins/avatar.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/mixins/base.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/mixins/db.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/mixins/disco.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/mixins/message_maker.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/mixins/presence.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/mixins/recipient.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/pubsub.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/core/session.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/env.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/old_user_store.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/script.py.mako +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/versions/09f27f098baa_add_missing_attributes_in_room.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/versions/2461390c0af2_store_contacts_caps_verstring_in_db.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/versions/29f5280c61aa_store_subject_setter_in_room.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/versions/2b1f45ab7379_store_room_subject_setter_by_nickname.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/versions/3071e0fa69d4_add_contact_client_type.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/versions/45c24cc73c91_add_bob.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/versions/82a4af84b679_add_muc_history_filled.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/versions/8b993243a536_add_vcard_content_to_contact_table.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/versions/8d2ced764698_rely_on_db_to_store_contacts_rooms_and_.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/versions/aa9d82a7f6ef_db_creation.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/versions/abba1ae0edb3_store_avatar_legacy_id_in_the_contact_.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/versions/b33993e87db3_move_everything_to_persistent_db.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/versions/b64b1a793483_add_source_and_legacy_id_for_archived_.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/versions/c4a8ec35a0e8_per_room_user_nick.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/alembic/versions/e91195719c2c_store_users_avatars_persistently.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/avatar.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/db/meta.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/group/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/group/archive.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/main.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/migration.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/py.typed +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/delivery_receipt.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/link_preview/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/link_preview/link_preview.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/link_preview/stanza.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/roster.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0077/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0077/register.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0077/stanza.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0100/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0100/gateway.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0100/stanza.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0153/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0153/stanza.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0153/vcard_avatar.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0264/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0264/stanza.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0264/thumbnail.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0292/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0292/vcard4.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0313/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0313/mam.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0313/stanza.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0317/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0317/hats.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0317/stanza.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0356_old/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0356_old/privilege.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0356_old/stanza.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0424/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0424/retraction.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0424/stanza.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0490/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0490/mds.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/slixfix/xep_0490/stanza.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/util/__init__.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/util/archive_msg.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/util/conf.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/util/db.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/util/types.py +0 -0
- {slidge-0.2.0a10 → slidge-0.2.0b0}/slidge/util/util.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "slidge"
|
3
|
-
version = "0.2.
|
3
|
+
version = "0.2.0beta0"
|
4
4
|
description = "XMPP bridging framework"
|
5
5
|
authors = ["Nicolas Cedilnik <nicoco@nicoco.fr>"]
|
6
6
|
readme = "README.md"
|
@@ -57,7 +57,7 @@ git = "https://git.sr.ht/~nicoco/slidge-dev-helpers"
|
|
57
57
|
branch = "master"
|
58
58
|
|
59
59
|
[tool.poetry.scripts]
|
60
|
-
slidge = 'slidge.
|
60
|
+
slidge = 'slidge.main:main'
|
61
61
|
|
62
62
|
[tool.mypy]
|
63
63
|
check_untyped_defs = true
|
@@ -89,7 +89,6 @@ exclude_lines = [
|
|
89
89
|
]
|
90
90
|
|
91
91
|
[tool.pytest.ini_options]
|
92
|
-
log_cli = true
|
93
92
|
log_level = "DEBUG"
|
94
93
|
asyncio_mode = "strict"
|
95
94
|
filterwarnings = [
|
@@ -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.")
|
@@ -154,6 +154,8 @@ class LegacyRoster(
|
|
154
154
|
try:
|
155
155
|
with contact.updating_info():
|
156
156
|
await contact.avatar_wrap_update_info()
|
157
|
+
except XMPPError:
|
158
|
+
raise
|
157
159
|
except Exception as e:
|
158
160
|
raise XMPPError("internal-server-error", str(e))
|
159
161
|
contact._caps_ver = await contact.get_caps_ver(contact.jid)
|
@@ -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"
|
@@ -3,12 +3,7 @@ from slixmpp.xmlstream import StanzaBase
|
|
3
3
|
|
4
4
|
from ....group.room import LegacyMUC
|
5
5
|
from ....util.types import Recipient
|
6
|
-
from ..util import
|
7
|
-
DispatcherMixin,
|
8
|
-
_get_entity,
|
9
|
-
_xmpp_to_legacy_thread,
|
10
|
-
exceptions_to_xmpp_errors,
|
11
|
-
)
|
6
|
+
from ..util import DispatcherMixin, _get_entity, exceptions_to_xmpp_errors
|
12
7
|
|
13
8
|
|
14
9
|
class MarkerMixin(DispatcherMixin):
|
@@ -26,7 +21,7 @@ class MarkerMixin(DispatcherMixin):
|
|
26
21
|
session = await self._get_session(msg)
|
27
22
|
|
28
23
|
e: Recipient = await _get_entity(session, msg)
|
29
|
-
legacy_thread = await _xmpp_to_legacy_thread(session, msg, e)
|
24
|
+
legacy_thread = await self._xmpp_to_legacy_thread(session, msg, e)
|
30
25
|
displayed_msg_id = msg["displayed"]["id"]
|
31
26
|
if not isinstance(e, LegacyMUC) and self.xmpp.MARK_ALL_MESSAGES:
|
32
27
|
to_mark = e.get_msg_xmpp_id_up_to(displayed_msg_id) # type: ignore
|
@@ -54,6 +54,9 @@ class MucMiscMixin(DispatcherMixin):
|
|
54
54
|
muc = await self.get_muc_from_stanza(iq)
|
55
55
|
await muc.session.on_leave_group(muc.legacy_id)
|
56
56
|
iq.reply().send()
|
57
|
+
await muc.session.bookmarks.remove(
|
58
|
+
muc, "You left this chat from an XMPP client."
|
59
|
+
)
|
57
60
|
return
|
58
61
|
|
59
62
|
raise XMPPError("feature-not-implemented")
|
@@ -88,7 +88,7 @@ class MucOwnerMixin(DispatcherMixin):
|
|
88
88
|
if reason is not None:
|
89
89
|
presence["muc"]["destroy"]["reason"] = reason
|
90
90
|
user_participant._send(presence)
|
91
|
-
muc.session.bookmarks.remove(muc)
|
91
|
+
await muc.session.bookmarks.remove(muc, kick=False)
|
92
92
|
clear = True
|
93
93
|
else:
|
94
94
|
raise XMPPError("bad-request")
|
@@ -96,9 +96,31 @@ class DispatcherMixin:
|
|
96
96
|
) -> tuple["BaseSession", Recipient, int | str]:
|
97
97
|
session = await self._get_session(msg)
|
98
98
|
e: Recipient = await _get_entity(session, msg)
|
99
|
-
legacy_thread = await _xmpp_to_legacy_thread(session, msg, e)
|
99
|
+
legacy_thread = await self._xmpp_to_legacy_thread(session, msg, e)
|
100
100
|
return session, e, legacy_thread
|
101
101
|
|
102
|
+
async def _xmpp_to_legacy_thread(
|
103
|
+
self, session: "BaseSession", msg: Message, recipient: RecipientType
|
104
|
+
):
|
105
|
+
xmpp_thread = msg["thread"]
|
106
|
+
if not xmpp_thread:
|
107
|
+
return None
|
108
|
+
|
109
|
+
if session.MESSAGE_IDS_ARE_THREAD_IDS:
|
110
|
+
return self._xmpp_msg_id_to_legacy(session, xmpp_thread)
|
111
|
+
|
112
|
+
legacy_thread_str = session.xmpp.store.sent.get_legacy_thread(
|
113
|
+
session.user_pk, xmpp_thread
|
114
|
+
)
|
115
|
+
if legacy_thread_str is not None:
|
116
|
+
return session.xmpp.LEGACY_MSG_ID_TYPE(legacy_thread_str)
|
117
|
+
async with session.thread_creation_lock:
|
118
|
+
legacy_thread = await recipient.create_thread(xmpp_thread)
|
119
|
+
session.xmpp.store.sent.set_thread(
|
120
|
+
session.user_pk, str(legacy_thread), xmpp_thread
|
121
|
+
)
|
122
|
+
return legacy_thread
|
123
|
+
|
102
124
|
|
103
125
|
def _ignore(session: "BaseSession", msg: Message):
|
104
126
|
i = msg.get_id()
|
@@ -111,28 +133,6 @@ def _ignore(session: "BaseSession", msg: Message):
|
|
111
133
|
return True
|
112
134
|
|
113
135
|
|
114
|
-
async def _xmpp_to_legacy_thread(
|
115
|
-
session: "BaseSession", msg: Message, recipient: RecipientType
|
116
|
-
):
|
117
|
-
xmpp_thread = msg["thread"]
|
118
|
-
if not xmpp_thread:
|
119
|
-
return
|
120
|
-
|
121
|
-
if session.MESSAGE_IDS_ARE_THREAD_IDS:
|
122
|
-
return session.xmpp.store.sent.get_legacy_thread(session.user_pk, xmpp_thread)
|
123
|
-
|
124
|
-
async with session.thread_creation_lock:
|
125
|
-
legacy_thread_str = session.xmpp.store.sent.get_legacy_thread(
|
126
|
-
session.user_pk, xmpp_thread
|
127
|
-
)
|
128
|
-
if legacy_thread_str is None:
|
129
|
-
legacy_thread = str(await recipient.create_thread(xmpp_thread))
|
130
|
-
session.xmpp.store.sent.set_thread(
|
131
|
-
session.user_pk, xmpp_thread, legacy_thread
|
132
|
-
)
|
133
|
-
return session.xmpp.LEGACY_MSG_ID_TYPE(legacy_thread)
|
134
|
-
|
135
|
-
|
136
136
|
async def _get_entity(session: "BaseSession", m: Message) -> RecipientType:
|
137
137
|
session.raise_if_not_logged()
|
138
138
|
if m.get_type() == "groupchat":
|
@@ -33,17 +33,14 @@ from ...util.types import (
|
|
33
33
|
)
|
34
34
|
from ...util.util import fix_suffix
|
35
35
|
from .. import config
|
36
|
-
from .
|
36
|
+
from .message_text import TextMessageMixin
|
37
37
|
|
38
38
|
|
39
|
-
class AttachmentMixin(
|
39
|
+
class AttachmentMixin(TextMessageMixin):
|
40
40
|
def __init__(self, *a, **kw):
|
41
41
|
super().__init__(*a, **kw)
|
42
42
|
self.__store = self.xmpp.store.attachments
|
43
43
|
|
44
|
-
def send_text(self, *_, **k) -> Optional[Message]:
|
45
|
-
raise NotImplementedError
|
46
|
-
|
47
44
|
async def __upload(
|
48
45
|
self,
|
49
46
|
file_path: Path,
|
@@ -261,7 +258,7 @@ class AttachmentMixin(MessageMaker):
|
|
261
258
|
thumbnail["width"] = x
|
262
259
|
thumbnail["height"] = y
|
263
260
|
thumbnail["media-type"] = "image/thumbhash"
|
264
|
-
thumbnail["uri"] = "data:image/thumbhash," + urlquote(h)
|
261
|
+
thumbnail["uri"] = "data:image/thumbhash;base64," + urlquote(h)
|
265
262
|
|
266
263
|
self.__store.set_sims(uploaded_url, str(ref))
|
267
264
|
|
@@ -304,6 +301,7 @@ class AttachmentMixin(MessageMaker):
|
|
304
301
|
caption: Optional[str] = None,
|
305
302
|
carbon=False,
|
306
303
|
when: Optional[datetime] = None,
|
304
|
+
correction=False,
|
307
305
|
**kwargs,
|
308
306
|
) -> list[Message]:
|
309
307
|
msg["oob"]["url"] = uploaded_url
|
@@ -311,11 +309,19 @@ class AttachmentMixin(MessageMaker):
|
|
311
309
|
if caption:
|
312
310
|
m1 = self._send(msg, carbon=carbon, **kwargs)
|
313
311
|
m2 = self.send_text(
|
314
|
-
caption,
|
312
|
+
caption,
|
313
|
+
legacy_msg_id=legacy_msg_id,
|
314
|
+
when=when,
|
315
|
+
carbon=carbon,
|
316
|
+
correction=correction,
|
317
|
+
**kwargs,
|
315
318
|
)
|
316
319
|
return [m1, m2] if m2 else [m1]
|
317
320
|
else:
|
318
|
-
|
321
|
+
if correction:
|
322
|
+
msg["replace"]["id"] = self._replace_id(legacy_msg_id)
|
323
|
+
else:
|
324
|
+
self._set_msg_id(msg, legacy_msg_id)
|
319
325
|
return [self._send(msg, carbon=carbon, **kwargs)]
|
320
326
|
|
321
327
|
async def send_file(
|
@@ -358,6 +364,16 @@ class AttachmentMixin(MessageMaker):
|
|
358
364
|
carbon = kwargs.pop("carbon", False)
|
359
365
|
mto = kwargs.pop("mto", None)
|
360
366
|
store_multi = kwargs.pop("store_multi", True)
|
367
|
+
correction = kwargs.get("correction", False)
|
368
|
+
if correction and (original_xmpp_id := self._legacy_to_xmpp(legacy_msg_id)):
|
369
|
+
xmpp_ids = self.xmpp.store.multi.get_xmpp_ids(
|
370
|
+
self.session.user_pk, original_xmpp_id
|
371
|
+
)
|
372
|
+
|
373
|
+
for xmpp_id in xmpp_ids:
|
374
|
+
if xmpp_id == original_xmpp_id:
|
375
|
+
continue
|
376
|
+
self.retract(xmpp_id, thread)
|
361
377
|
msg = self._make_message(
|
362
378
|
when=when,
|
363
379
|
reply_to=reply_to,
|
@@ -15,14 +15,16 @@ class NamedLockMixin:
|
|
15
15
|
locks = self.__locks
|
16
16
|
if not locks.get(id_):
|
17
17
|
locks[id_] = asyncio.Lock()
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
18
|
+
try:
|
19
|
+
async with locks[id_]:
|
20
|
+
log.trace("acquired %s", id_) # type:ignore
|
21
|
+
yield
|
22
|
+
finally:
|
23
|
+
log.trace("releasing %s", id_) # type:ignore
|
24
|
+
waiters = locks[id_]._waiters # type:ignore
|
25
|
+
if not waiters:
|
26
|
+
del locks[id_]
|
27
|
+
log.trace("erasing %s", id_) # type:ignore
|
26
28
|
|
27
29
|
def get_lock(self, id_: Hashable):
|
28
30
|
return self.__locks.get(id_)
|
@@ -0,0 +1,214 @@
|
|
1
|
+
import logging
|
2
|
+
import uuid
|
3
|
+
import warnings
|
4
|
+
from typing import TYPE_CHECKING, Optional
|
5
|
+
|
6
|
+
from slixmpp import Iq, Message
|
7
|
+
|
8
|
+
from ...slixfix.xep_0490.mds import PUBLISH_OPTIONS
|
9
|
+
from ...util.types import ChatState, LegacyMessageType, Marker
|
10
|
+
from .attachment import AttachmentMixin
|
11
|
+
from .message_maker import MessageMaker
|
12
|
+
from .message_text import TextMessageMixin
|
13
|
+
|
14
|
+
if TYPE_CHECKING:
|
15
|
+
from ...group import LegacyMUC
|
16
|
+
|
17
|
+
|
18
|
+
class ChatStateMixin(MessageMaker):
|
19
|
+
def __init__(self):
|
20
|
+
super().__init__()
|
21
|
+
self.__last_chat_state: Optional[ChatState] = None
|
22
|
+
|
23
|
+
def _chat_state(self, state: ChatState, forced=False, **kwargs):
|
24
|
+
carbon = kwargs.get("carbon", False)
|
25
|
+
if carbon or (state == self.__last_chat_state and not forced):
|
26
|
+
return
|
27
|
+
self.__last_chat_state = state
|
28
|
+
msg = self._make_message(state=state, hints={"no-store"})
|
29
|
+
self._send(msg, **kwargs)
|
30
|
+
|
31
|
+
def active(self, **kwargs):
|
32
|
+
"""
|
33
|
+
Send an "active" chat state (:xep:`0085`) from this
|
34
|
+
:term:`XMPP Entity`.
|
35
|
+
"""
|
36
|
+
self._chat_state("active", **kwargs)
|
37
|
+
|
38
|
+
def composing(self, **kwargs):
|
39
|
+
"""
|
40
|
+
Send a "composing" (ie "typing notification") chat state (:xep:`0085`)
|
41
|
+
from this :term:`XMPP Entity`.
|
42
|
+
"""
|
43
|
+
self._chat_state("composing", forced=True, **kwargs)
|
44
|
+
|
45
|
+
def paused(self, **kwargs):
|
46
|
+
"""
|
47
|
+
Send a "paused" (ie "typing paused notification") chat state
|
48
|
+
(:xep:`0085`) from this :term:`XMPP Entity`.
|
49
|
+
"""
|
50
|
+
self._chat_state("paused", **kwargs)
|
51
|
+
|
52
|
+
def inactive(self, **kwargs):
|
53
|
+
"""
|
54
|
+
Send an "inactive" (ie "contact has not interacted with the chat session
|
55
|
+
interface for an intermediate period of time") chat state (:xep:`0085`)
|
56
|
+
from this :term:`XMPP Entity`.
|
57
|
+
"""
|
58
|
+
self._chat_state("inactive", **kwargs)
|
59
|
+
|
60
|
+
def gone(self, **kwargs):
|
61
|
+
"""
|
62
|
+
Send a "gone" (ie "contact has not interacted with the chat session interface,
|
63
|
+
system, or device for a relatively long period of time") chat state
|
64
|
+
(:xep:`0085`) from this :term:`XMPP Entity`.
|
65
|
+
"""
|
66
|
+
self._chat_state("gone", **kwargs)
|
67
|
+
|
68
|
+
|
69
|
+
class MarkerMixin(MessageMaker):
|
70
|
+
is_group: bool = NotImplemented
|
71
|
+
|
72
|
+
def _make_marker(
|
73
|
+
self, legacy_msg_id: LegacyMessageType, marker: Marker, carbon=False
|
74
|
+
):
|
75
|
+
msg = self._make_message(carbon=carbon)
|
76
|
+
msg[marker]["id"] = self._legacy_to_xmpp(legacy_msg_id)
|
77
|
+
return msg
|
78
|
+
|
79
|
+
def ack(self, legacy_msg_id: LegacyMessageType, **kwargs):
|
80
|
+
"""
|
81
|
+
Send an "acknowledged" message marker (:xep:`0333`) from this :term:`XMPP Entity`.
|
82
|
+
|
83
|
+
:param legacy_msg_id: The message this marker refers to
|
84
|
+
"""
|
85
|
+
self._send(
|
86
|
+
self._make_marker(
|
87
|
+
legacy_msg_id, "acknowledged", carbon=kwargs.get("carbon")
|
88
|
+
),
|
89
|
+
**kwargs,
|
90
|
+
)
|
91
|
+
|
92
|
+
def received(self, legacy_msg_id: LegacyMessageType, **kwargs):
|
93
|
+
"""
|
94
|
+
Send a "received" message marker (:xep:`0333`) from this :term:`XMPP Entity`.
|
95
|
+
If called on a :class:`LegacyContact`, also send a delivery receipt
|
96
|
+
marker (:xep:`0184`).
|
97
|
+
|
98
|
+
:param legacy_msg_id: The message this marker refers to
|
99
|
+
"""
|
100
|
+
carbon = kwargs.get("carbon")
|
101
|
+
if self.mtype == "chat":
|
102
|
+
self._send(
|
103
|
+
self.xmpp.delivery_receipt.make_ack(
|
104
|
+
self._legacy_to_xmpp(legacy_msg_id),
|
105
|
+
mfrom=self.jid,
|
106
|
+
mto=self.user_jid,
|
107
|
+
)
|
108
|
+
)
|
109
|
+
self._send(
|
110
|
+
self._make_marker(legacy_msg_id, "received", carbon=carbon), **kwargs
|
111
|
+
)
|
112
|
+
|
113
|
+
def displayed(self, legacy_msg_id: LegacyMessageType, **kwargs):
|
114
|
+
"""
|
115
|
+
Send a "displayed" message marker (:xep:`0333`) from this :term:`XMPP Entity`.
|
116
|
+
|
117
|
+
:param legacy_msg_id: The message this marker refers to
|
118
|
+
"""
|
119
|
+
self._send(
|
120
|
+
self._make_marker(legacy_msg_id, "displayed", carbon=kwargs.get("carbon")),
|
121
|
+
**kwargs,
|
122
|
+
)
|
123
|
+
if getattr(self, "is_user", False):
|
124
|
+
self.session.create_task(self.__send_mds(legacy_msg_id))
|
125
|
+
|
126
|
+
async def __send_mds(self, legacy_msg_id: LegacyMessageType):
|
127
|
+
# Send a MDS displayed marker on behalf of the user for a group chat
|
128
|
+
if muc := getattr(self, "muc", None):
|
129
|
+
muc_jid = muc.jid.bare
|
130
|
+
else:
|
131
|
+
# This is not implemented for 1:1 chat because it would rely on
|
132
|
+
# storing the XMPP-server injected stanza-id, which we don't track
|
133
|
+
# ATM.
|
134
|
+
# In practice, MDS should mostly be useful for public group chats,
|
135
|
+
# so it should not be an issue.
|
136
|
+
# We'll see if we need to implement that later
|
137
|
+
return
|
138
|
+
xmpp_msg_id = self._legacy_to_xmpp(legacy_msg_id)
|
139
|
+
iq = Iq(sto=self.user_jid.bare, sfrom=self.user_jid.bare, stype="set")
|
140
|
+
iq["pubsub"]["publish"]["node"] = self.xmpp["xep_0490"].stanza.NS
|
141
|
+
iq["pubsub"]["publish"]["item"]["id"] = muc_jid
|
142
|
+
displayed = self.xmpp["xep_0490"].stanza.Displayed()
|
143
|
+
displayed["stanza_id"]["id"] = xmpp_msg_id
|
144
|
+
displayed["stanza_id"]["by"] = muc_jid
|
145
|
+
iq["pubsub"]["publish"]["item"]["payload"] = displayed
|
146
|
+
iq["pubsub"]["publish_options"] = PUBLISH_OPTIONS
|
147
|
+
try:
|
148
|
+
await self.xmpp["xep_0356"].send_privileged_iq(iq)
|
149
|
+
except Exception as e:
|
150
|
+
self.session.log.debug("Could not MDS mark", exc_info=e)
|
151
|
+
|
152
|
+
|
153
|
+
class ContentMessageMixin(AttachmentMixin, TextMessageMixin):
|
154
|
+
pass
|
155
|
+
|
156
|
+
|
157
|
+
class CarbonMessageMixin(ContentMessageMixin, MarkerMixin):
|
158
|
+
def _privileged_send(self, msg: Message):
|
159
|
+
i = msg.get_id()
|
160
|
+
if i:
|
161
|
+
self.session.ignore_messages.add(i)
|
162
|
+
else:
|
163
|
+
i = "slidge-carbon-" + str(uuid.uuid4())
|
164
|
+
msg.set_id(i)
|
165
|
+
msg.del_origin_id()
|
166
|
+
try:
|
167
|
+
self.xmpp["xep_0356"].send_privileged_message(msg)
|
168
|
+
except PermissionError:
|
169
|
+
try:
|
170
|
+
self.xmpp["xep_0356_old"].send_privileged_message(msg)
|
171
|
+
except PermissionError:
|
172
|
+
warnings.warn(
|
173
|
+
"Slidge does not have privileges to send message on behalf of"
|
174
|
+
" user.Refer to"
|
175
|
+
" https://slidge.readthedocs.io/en/latest/admin/xmpp_server.html"
|
176
|
+
" for more info."
|
177
|
+
)
|
178
|
+
|
179
|
+
|
180
|
+
class InviteMixin(MessageMaker):
|
181
|
+
def invite_to(
|
182
|
+
self,
|
183
|
+
muc: "LegacyMUC",
|
184
|
+
reason: Optional[str] = None,
|
185
|
+
password: Optional[str] = None,
|
186
|
+
**send_kwargs,
|
187
|
+
):
|
188
|
+
"""
|
189
|
+
Send an invitation to join a group (:xep:`0249`) from this :term:`XMPP Entity`.
|
190
|
+
|
191
|
+
:param muc: the muc the user is invited to
|
192
|
+
:param reason: a text explaining why the user should join this muc
|
193
|
+
:param password: maybe this will make sense later? not sure
|
194
|
+
:param send_kwargs: additional kwargs to be passed to _send()
|
195
|
+
(internal use by slidge)
|
196
|
+
"""
|
197
|
+
msg = self._make_message(mtype="normal")
|
198
|
+
msg["groupchat_invite"]["jid"] = muc.jid
|
199
|
+
if reason:
|
200
|
+
msg["groupchat_invite"]["reason"] = reason
|
201
|
+
if password:
|
202
|
+
msg["groupchat_invite"]["password"] = password
|
203
|
+
self._send(msg, **send_kwargs)
|
204
|
+
|
205
|
+
|
206
|
+
class MessageMixin(InviteMixin, ChatStateMixin, MarkerMixin, ContentMessageMixin):
|
207
|
+
pass
|
208
|
+
|
209
|
+
|
210
|
+
class MessageCarbonMixin(InviteMixin, ChatStateMixin, CarbonMessageMixin):
|
211
|
+
pass
|
212
|
+
|
213
|
+
|
214
|
+
log = logging.getLogger(__name__)
|