slidge 0.1.2__py3-none-any.whl → 0.2.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- slidge/__init__.py +3 -5
- slidge/__main__.py +2 -197
- slidge/__version__.py +5 -0
- slidge/command/adhoc.py +40 -17
- slidge/command/admin.py +24 -12
- slidge/command/base.py +10 -8
- slidge/command/categories.py +13 -3
- slidge/command/chat_command.py +29 -2
- slidge/command/register.py +32 -16
- slidge/command/user.py +106 -13
- slidge/contact/contact.py +254 -50
- slidge/contact/roster.py +124 -53
- slidge/core/config.py +19 -13
- slidge/core/dispatcher/__init__.py +3 -0
- slidge/core/{gateway → dispatcher}/caps.py +12 -8
- slidge/core/{gateway → dispatcher}/disco.py +10 -18
- 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 +25 -17
- slidge/core/dispatcher/muc/misc.py +121 -0
- slidge/core/dispatcher/muc/owner.py +96 -0
- slidge/core/{gateway → dispatcher/muc}/ping.py +11 -17
- slidge/core/dispatcher/presence.py +176 -0
- slidge/core/dispatcher/registration.py +85 -0
- slidge/core/{gateway → dispatcher}/search.py +9 -16
- slidge/core/dispatcher/session_dispatcher.py +84 -0
- slidge/core/dispatcher/util.py +174 -0
- slidge/core/{gateway/vcard_temp.py → dispatcher/vcard.py} +35 -19
- slidge/core/{gateway/base.py → gateway.py} +176 -153
- slidge/core/mixins/__init__.py +11 -1
- slidge/core/mixins/attachment.py +106 -67
- slidge/core/mixins/avatar.py +94 -25
- slidge/core/mixins/base.py +10 -4
- slidge/core/mixins/db.py +18 -0
- slidge/core/mixins/disco.py +0 -10
- slidge/core/mixins/lock.py +10 -8
- slidge/core/mixins/message.py +11 -195
- slidge/core/mixins/message_maker.py +17 -9
- slidge/core/mixins/message_text.py +211 -0
- slidge/core/mixins/presence.py +17 -4
- slidge/core/pubsub.py +114 -288
- slidge/core/session.py +101 -40
- slidge/db/__init__.py +4 -0
- slidge/db/alembic/__init__.py +0 -0
- slidge/db/alembic/env.py +64 -0
- slidge/db/alembic/old_user_store.py +183 -0
- slidge/db/alembic/script.py.mako +26 -0
- slidge/db/alembic/versions/09f27f098baa_add_missing_attributes_in_room.py +36 -0
- slidge/db/alembic/versions/15b0bd83407a_remove_bogus_unique_constraints_on_room_.py +85 -0
- slidge/db/alembic/versions/2461390c0af2_store_contacts_caps_verstring_in_db.py +36 -0
- slidge/db/alembic/versions/29f5280c61aa_store_subject_setter_in_room.py +37 -0
- slidge/db/alembic/versions/2b1f45ab7379_store_room_subject_setter_by_nickname.py +41 -0
- slidge/db/alembic/versions/3071e0fa69d4_add_contact_client_type.py +52 -0
- slidge/db/alembic/versions/45c24cc73c91_add_bob.py +42 -0
- slidge/db/alembic/versions/5bd48bfdffa2_lift_room_legacy_id_constraint.py +61 -0
- slidge/db/alembic/versions/82a4af84b679_add_muc_history_filled.py +48 -0
- slidge/db/alembic/versions/8b993243a536_add_vcard_content_to_contact_table.py +43 -0
- slidge/db/alembic/versions/8d2ced764698_rely_on_db_to_store_contacts_rooms_and_.py +139 -0
- slidge/db/alembic/versions/aa9d82a7f6ef_db_creation.py +101 -0
- slidge/db/alembic/versions/abba1ae0edb3_store_avatar_legacy_id_in_the_contact_.py +79 -0
- slidge/db/alembic/versions/b33993e87db3_move_everything_to_persistent_db.py +214 -0
- slidge/db/alembic/versions/b64b1a793483_add_source_and_legacy_id_for_archived_.py +52 -0
- slidge/db/alembic/versions/c4a8ec35a0e8_per_room_user_nick.py +34 -0
- slidge/db/alembic/versions/e91195719c2c_store_users_avatars_persistently.py +26 -0
- slidge/db/avatar.py +205 -0
- slidge/db/meta.py +72 -0
- slidge/db/models.py +405 -0
- slidge/db/store.py +1257 -0
- slidge/group/archive.py +58 -14
- slidge/group/bookmarks.py +89 -65
- slidge/group/participant.py +111 -44
- slidge/group/room.py +402 -213
- slidge/main.py +202 -0
- slidge/migration.py +45 -1
- slidge/slixfix/__init__.py +31 -1
- slidge/{core/gateway → slixfix}/delivery_receipt.py +1 -1
- slidge/slixfix/roster.py +13 -4
- slidge/slixfix/xep_0292/vcard4.py +1 -87
- slidge/util/archive_msg.py +2 -1
- slidge/util/db.py +4 -228
- slidge/util/test.py +91 -4
- slidge/util/types.py +39 -4
- slidge/util/util.py +45 -2
- {slidge-0.1.2.dist-info → slidge-0.2.0.dist-info}/METADATA +10 -5
- slidge-0.2.0.dist-info/RECORD +131 -0
- slidge-0.2.0.dist-info/entry_points.txt +3 -0
- slidge/core/cache.py +0 -183
- 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/registration.py +0 -53
- slidge/core/gateway/session_dispatcher.py +0 -795
- slidge/util/schema.sql +0 -126
- slidge/util/sql.py +0 -508
- slidge-0.1.2.dist-info/RECORD +0 -96
- slidge-0.1.2.dist-info/entry_points.txt +0 -3
- {slidge-0.1.2.dist-info → slidge-0.2.0.dist-info}/LICENSE +0 -0
- {slidge-0.1.2.dist-info → slidge-0.2.0.dist-info}/WHEEL +0 -0
slidge/core/mixins/message.py
CHANGED
@@ -1,23 +1,15 @@
|
|
1
1
|
import logging
|
2
2
|
import uuid
|
3
3
|
import warnings
|
4
|
-
from
|
5
|
-
from typing import TYPE_CHECKING, Iterable, Optional
|
4
|
+
from typing import TYPE_CHECKING, Optional
|
6
5
|
|
7
6
|
from slixmpp import Iq, Message
|
8
7
|
|
9
8
|
from ...slixfix.xep_0490.mds import PUBLISH_OPTIONS
|
10
|
-
from ...util.types import
|
11
|
-
ChatState,
|
12
|
-
LegacyMessageType,
|
13
|
-
LegacyThreadType,
|
14
|
-
LinkPreview,
|
15
|
-
Marker,
|
16
|
-
MessageReference,
|
17
|
-
ProcessingHint,
|
18
|
-
)
|
9
|
+
from ...util.types import ChatState, LegacyMessageType, Marker
|
19
10
|
from .attachment import AttachmentMixin
|
20
11
|
from .message_maker import MessageMaker
|
12
|
+
from .message_text import TextMessageMixin
|
21
13
|
|
22
14
|
if TYPE_CHECKING:
|
23
15
|
from ...group import LegacyMUC
|
@@ -111,7 +103,7 @@ class MarkerMixin(MessageMaker):
|
|
111
103
|
self.xmpp.delivery_receipt.make_ack(
|
112
104
|
self._legacy_to_xmpp(legacy_msg_id),
|
113
105
|
mfrom=self.jid,
|
114
|
-
mto=self.
|
106
|
+
mto=self.user_jid,
|
115
107
|
)
|
116
108
|
)
|
117
109
|
self._send(
|
@@ -144,7 +136,7 @@ class MarkerMixin(MessageMaker):
|
|
144
136
|
# We'll see if we need to implement that later
|
145
137
|
return
|
146
138
|
xmpp_msg_id = self._legacy_to_xmpp(legacy_msg_id)
|
147
|
-
iq = Iq(sto=self.
|
139
|
+
iq = Iq(sto=self.user_jid.bare, sfrom=self.user_jid.bare, stype="set")
|
148
140
|
iq["pubsub"]["publish"]["node"] = self.xmpp["xep_0490"].stanza.NS
|
149
141
|
iq["pubsub"]["publish"]["item"]["id"] = muc_jid
|
150
142
|
displayed = self.xmpp["xep_0490"].stanza.Displayed()
|
@@ -158,195 +150,19 @@ class MarkerMixin(MessageMaker):
|
|
158
150
|
self.session.log.debug("Could not MDS mark", exc_info=e)
|
159
151
|
|
160
152
|
|
161
|
-
class ContentMessageMixin(AttachmentMixin):
|
162
|
-
|
163
|
-
if hints is not None:
|
164
|
-
return hints
|
165
|
-
elif self.mtype == "chat":
|
166
|
-
return {"markable", "store"}
|
167
|
-
elif self.mtype == "groupchat":
|
168
|
-
return {"markable"}
|
169
|
-
|
170
|
-
def __replace_id(self, legacy_msg_id: LegacyMessageType):
|
171
|
-
if self.mtype == "groupchat":
|
172
|
-
return self.session.muc_sent_msg_ids.get(
|
173
|
-
legacy_msg_id
|
174
|
-
) or self._legacy_to_xmpp(legacy_msg_id)
|
175
|
-
else:
|
176
|
-
return self._legacy_to_xmpp(legacy_msg_id)
|
177
|
-
|
178
|
-
def send_text(
|
179
|
-
self,
|
180
|
-
body: str,
|
181
|
-
legacy_msg_id: Optional[LegacyMessageType] = None,
|
182
|
-
*,
|
183
|
-
when: Optional[datetime] = None,
|
184
|
-
reply_to: Optional[MessageReference] = None,
|
185
|
-
thread: Optional[LegacyThreadType] = None,
|
186
|
-
hints: Optional[Iterable[ProcessingHint]] = None,
|
187
|
-
carbon=False,
|
188
|
-
archive_only=False,
|
189
|
-
correction=False,
|
190
|
-
correction_event_id: Optional[LegacyMessageType] = None,
|
191
|
-
link_previews: Optional[list[LinkPreview]] = None,
|
192
|
-
**send_kwargs,
|
193
|
-
):
|
194
|
-
"""
|
195
|
-
Send a text message from this :term:`XMPP Entity`.
|
196
|
-
|
197
|
-
:param body: Content of the message
|
198
|
-
:param legacy_msg_id: If you want to be able to transport read markers from the gateway
|
199
|
-
user to the legacy network, specify this
|
200
|
-
:param when: when the message was sent, for a "delay" tag (:xep:`0203`)
|
201
|
-
:param reply_to: Quote another message (:xep:`0461`)
|
202
|
-
:param hints:
|
203
|
-
:param thread:
|
204
|
-
:param carbon: (only used if called on a :class:`LegacyContact`)
|
205
|
-
Set this to ``True`` if this is actually a message sent **to** the
|
206
|
-
:class:`LegacyContact` by the :term:`User`.
|
207
|
-
Use this to synchronize outgoing history for legacy official apps.
|
208
|
-
:param correction: whether this message is a correction or not
|
209
|
-
:param correction_event_id: in the case where an ID is associated with the legacy
|
210
|
-
'correction event', specify it here to use it on the XMPP side. If not specified,
|
211
|
-
a random ID will be used.
|
212
|
-
:param link_previews: A little of sender (or server, or gateway)-generated
|
213
|
-
previews of URLs linked in the body.
|
214
|
-
:param archive_only: (only in groups) Do not send this message to user,
|
215
|
-
but store it in the archive. Meant to be used during ``MUC.backfill()``
|
216
|
-
"""
|
217
|
-
if carbon:
|
218
|
-
if not correction and legacy_msg_id in self.session.sent:
|
219
|
-
log.warning(
|
220
|
-
"Carbon message for a message an XMPP has sent? This is a bug! %s",
|
221
|
-
legacy_msg_id,
|
222
|
-
)
|
223
|
-
return
|
224
|
-
self.session.sent[legacy_msg_id] = self.session.legacy_to_xmpp_msg_id(
|
225
|
-
legacy_msg_id
|
226
|
-
)
|
227
|
-
hints = self.__default_hints(hints)
|
228
|
-
msg = self._make_message(
|
229
|
-
mbody=body,
|
230
|
-
legacy_msg_id=correction_event_id if correction else legacy_msg_id,
|
231
|
-
when=when,
|
232
|
-
reply_to=reply_to,
|
233
|
-
hints=hints or (),
|
234
|
-
carbon=carbon,
|
235
|
-
thread=thread,
|
236
|
-
link_previews=link_previews,
|
237
|
-
)
|
238
|
-
if correction:
|
239
|
-
msg["replace"]["id"] = self.__replace_id(legacy_msg_id)
|
240
|
-
return self._send(msg, archive_only=archive_only, carbon=carbon, **send_kwargs)
|
241
|
-
|
242
|
-
def correct(
|
243
|
-
self,
|
244
|
-
legacy_msg_id: LegacyMessageType,
|
245
|
-
new_text: str,
|
246
|
-
*,
|
247
|
-
when: Optional[datetime] = None,
|
248
|
-
reply_to: Optional[MessageReference] = None,
|
249
|
-
thread: Optional[LegacyThreadType] = None,
|
250
|
-
hints: Optional[Iterable[ProcessingHint]] = None,
|
251
|
-
carbon=False,
|
252
|
-
archive_only=False,
|
253
|
-
correction_event_id: Optional[LegacyMessageType] = None,
|
254
|
-
link_previews: Optional[list[LinkPreview]] = None,
|
255
|
-
**send_kwargs,
|
256
|
-
):
|
257
|
-
"""
|
258
|
-
Modify a message that was previously sent by this :term:`XMPP Entity`.
|
259
|
-
|
260
|
-
Uses last message correction (:xep:`0308`)
|
261
|
-
|
262
|
-
:param new_text: New content of the message
|
263
|
-
:param legacy_msg_id: The legacy message ID of the message to correct
|
264
|
-
:param when: when the message was sent, for a "delay" tag (:xep:`0203`)
|
265
|
-
:param reply_to: Quote another message (:xep:`0461`)
|
266
|
-
:param hints:
|
267
|
-
:param thread:
|
268
|
-
:param carbon: (only in 1:1) Reflect a message sent to this ``Contact`` by the user.
|
269
|
-
Use this to synchronize outgoing history for legacy official apps.
|
270
|
-
:param archive_only: (only in groups) Do not send this message to user,
|
271
|
-
but store it in the archive. Meant to be used during ``MUC.backfill()``
|
272
|
-
:param correction_event_id: in the case where an ID is associated with the legacy
|
273
|
-
'correction event', specify it here to use it on the XMPP side. If not specified,
|
274
|
-
a random ID will be used.
|
275
|
-
:param link_previews: A little of sender (or server, or gateway)-generated
|
276
|
-
previews of URLs linked in the body.
|
277
|
-
"""
|
278
|
-
self.send_text(
|
279
|
-
new_text,
|
280
|
-
legacy_msg_id,
|
281
|
-
when=when,
|
282
|
-
reply_to=reply_to,
|
283
|
-
hints=hints,
|
284
|
-
carbon=carbon,
|
285
|
-
thread=thread,
|
286
|
-
correction=True,
|
287
|
-
archive_only=archive_only,
|
288
|
-
correction_event_id=correction_event_id,
|
289
|
-
link_previews=link_previews,
|
290
|
-
**send_kwargs,
|
291
|
-
)
|
292
|
-
|
293
|
-
def react(
|
294
|
-
self,
|
295
|
-
legacy_msg_id: LegacyMessageType,
|
296
|
-
emojis: Iterable[str] = (),
|
297
|
-
thread: Optional[LegacyThreadType] = None,
|
298
|
-
**kwargs,
|
299
|
-
):
|
300
|
-
"""
|
301
|
-
Send a reaction (:xep:`0444`) from this :term:`XMPP Entity`.
|
302
|
-
|
303
|
-
:param legacy_msg_id: The message which the reaction refers to.
|
304
|
-
:param emojis: An iterable of emojis used as reactions
|
305
|
-
:param thread:
|
306
|
-
"""
|
307
|
-
msg = self._make_message(
|
308
|
-
hints={"store"}, carbon=kwargs.get("carbon"), thread=thread
|
309
|
-
)
|
310
|
-
xmpp_id = kwargs.pop("xmpp_id", None)
|
311
|
-
if not xmpp_id:
|
312
|
-
xmpp_id = self._legacy_to_xmpp(legacy_msg_id)
|
313
|
-
self.xmpp["xep_0444"].set_reactions(msg, to_id=xmpp_id, reactions=emojis)
|
314
|
-
self._send(msg, **kwargs)
|
315
|
-
|
316
|
-
def retract(
|
317
|
-
self,
|
318
|
-
legacy_msg_id: LegacyMessageType,
|
319
|
-
thread: Optional[LegacyThreadType] = None,
|
320
|
-
**kwargs,
|
321
|
-
):
|
322
|
-
"""
|
323
|
-
Send a message retraction (:XEP:`0424`) from this :term:`XMPP Entity`.
|
324
|
-
|
325
|
-
:param legacy_msg_id: Legacy ID of the message to delete
|
326
|
-
:param thread:
|
327
|
-
"""
|
328
|
-
msg = self._make_message(
|
329
|
-
state=None,
|
330
|
-
hints={"store"},
|
331
|
-
mbody=f"/me retracted the message {legacy_msg_id}",
|
332
|
-
carbon=kwargs.get("carbon"),
|
333
|
-
thread=thread,
|
334
|
-
)
|
335
|
-
msg.enable("fallback")
|
336
|
-
# namespace version mismatch between slidge and slixmpp, update me later
|
337
|
-
msg["fallback"]["for"] = self.xmpp["xep_0424"].namespace[:-1] + "1"
|
338
|
-
msg["retract"]["id"] = msg["replace"]["id"] = self.__replace_id(legacy_msg_id)
|
339
|
-
self._send(msg, **kwargs)
|
153
|
+
class ContentMessageMixin(AttachmentMixin, TextMessageMixin):
|
154
|
+
pass
|
340
155
|
|
341
156
|
|
342
157
|
class CarbonMessageMixin(ContentMessageMixin, MarkerMixin):
|
343
158
|
def _privileged_send(self, msg: Message):
|
344
159
|
i = msg.get_id()
|
345
|
-
if
|
346
|
-
|
160
|
+
if i:
|
161
|
+
self.session.ignore_messages.add(i)
|
162
|
+
else:
|
163
|
+
i = "slidge-carbon-" + str(uuid.uuid4())
|
347
164
|
msg.set_id(i)
|
348
165
|
msg.del_origin_id()
|
349
|
-
self.session.ignore_messages.add(i)
|
350
166
|
try:
|
351
167
|
self.xmpp["xep_0356"].send_privileged_message(msg)
|
352
168
|
except PermissionError:
|
@@ -7,8 +7,8 @@ from uuid import uuid4
|
|
7
7
|
from slixmpp import Message
|
8
8
|
from slixmpp.types import MessageTypes
|
9
9
|
|
10
|
+
from ...db.models import GatewayUser
|
10
11
|
from ...slixfix.link_preview.stanza import LinkPreview as LinkPreviewStanza
|
11
|
-
from ...util.db import GatewayUser
|
12
12
|
from ...util.types import (
|
13
13
|
ChatState,
|
14
14
|
LegacyMessageType,
|
@@ -60,8 +60,9 @@ class MessageMaker(BaseSender):
|
|
60
60
|
msg["body"] = body
|
61
61
|
state = "active"
|
62
62
|
if thread:
|
63
|
-
|
64
|
-
|
63
|
+
msg["thread"] = self.xmpp.store.sent.get_legacy_thread(
|
64
|
+
self.user_pk, str(thread)
|
65
|
+
) or str(thread)
|
65
66
|
if state:
|
66
67
|
msg["chat_state"] = state
|
67
68
|
for hint in hints:
|
@@ -88,9 +89,9 @@ class MessageMaker(BaseSender):
|
|
88
89
|
msg["stanza_id"]["by"] = self.muc.jid # type: ignore
|
89
90
|
|
90
91
|
def _legacy_to_xmpp(self, legacy_id: LegacyMessageType):
|
91
|
-
return self.
|
92
|
-
legacy_id
|
93
|
-
)
|
92
|
+
return self.xmpp.store.sent.get_xmpp_id(
|
93
|
+
self.session.user_pk, str(legacy_id)
|
94
|
+
) or self.session.legacy_to_xmpp_msg_id(legacy_id)
|
94
95
|
|
95
96
|
def _add_delay(self, msg: Message, when: Optional[datetime]):
|
96
97
|
if when:
|
@@ -110,16 +111,23 @@ class MessageMaker(BaseSender):
|
|
110
111
|
muc = getattr(self, "muc", None)
|
111
112
|
|
112
113
|
if entity := reply_to.author:
|
113
|
-
if isinstance(entity, GatewayUser):
|
114
|
+
if entity == "user" or isinstance(entity, GatewayUser):
|
115
|
+
if isinstance(entity, GatewayUser):
|
116
|
+
warnings.warn(
|
117
|
+
"Using a GatewayUser as the author of a "
|
118
|
+
"MessageReference is deprecated. Use the string 'user' "
|
119
|
+
"instead.",
|
120
|
+
DeprecationWarning,
|
121
|
+
)
|
114
122
|
if muc:
|
115
123
|
jid = copy(muc.jid)
|
116
124
|
jid.resource = fallback_nick = muc.user_nick
|
117
125
|
msg["reply"]["to"] = jid
|
118
126
|
else:
|
119
|
-
msg["reply"]["to"] =
|
127
|
+
msg["reply"]["to"] = self.session.user_jid
|
120
128
|
# TODO: here we should use preferably use the PEP nick of the user
|
121
129
|
# (but it doesn't matter much)
|
122
|
-
fallback_nick =
|
130
|
+
fallback_nick = self.session.user_jid.local
|
123
131
|
else:
|
124
132
|
if muc:
|
125
133
|
if hasattr(entity, "muc"):
|
@@ -0,0 +1,211 @@
|
|
1
|
+
import logging
|
2
|
+
from datetime import datetime
|
3
|
+
from typing import Iterable, Optional
|
4
|
+
|
5
|
+
from ...util.types import (
|
6
|
+
LegacyMessageType,
|
7
|
+
LegacyThreadType,
|
8
|
+
LinkPreview,
|
9
|
+
MessageReference,
|
10
|
+
ProcessingHint,
|
11
|
+
)
|
12
|
+
from .message_maker import MessageMaker
|
13
|
+
|
14
|
+
|
15
|
+
class TextMessageMixin(MessageMaker):
|
16
|
+
def __default_hints(self, hints: Optional[Iterable[ProcessingHint]] = None):
|
17
|
+
if hints is not None:
|
18
|
+
return hints
|
19
|
+
elif self.mtype == "chat":
|
20
|
+
return {"markable", "store"}
|
21
|
+
elif self.mtype == "groupchat":
|
22
|
+
return {"markable"}
|
23
|
+
|
24
|
+
def _replace_id(self, legacy_msg_id: LegacyMessageType):
|
25
|
+
if self.mtype == "groupchat":
|
26
|
+
return self.xmpp.store.sent.get_group_xmpp_id(
|
27
|
+
self.session.user_pk, str(legacy_msg_id)
|
28
|
+
) or self._legacy_to_xmpp(legacy_msg_id)
|
29
|
+
else:
|
30
|
+
return self._legacy_to_xmpp(legacy_msg_id)
|
31
|
+
|
32
|
+
def send_text(
|
33
|
+
self,
|
34
|
+
body: str,
|
35
|
+
legacy_msg_id: Optional[LegacyMessageType] = None,
|
36
|
+
*,
|
37
|
+
when: Optional[datetime] = None,
|
38
|
+
reply_to: Optional[MessageReference] = None,
|
39
|
+
thread: Optional[LegacyThreadType] = None,
|
40
|
+
hints: Optional[Iterable[ProcessingHint]] = None,
|
41
|
+
carbon=False,
|
42
|
+
archive_only=False,
|
43
|
+
correction=False,
|
44
|
+
correction_event_id: Optional[LegacyMessageType] = None,
|
45
|
+
link_previews: Optional[list[LinkPreview]] = None,
|
46
|
+
**send_kwargs,
|
47
|
+
):
|
48
|
+
"""
|
49
|
+
Send a text message from this :term:`XMPP Entity`.
|
50
|
+
|
51
|
+
:param body: Content of the message
|
52
|
+
:param legacy_msg_id: If you want to be able to transport read markers from the gateway
|
53
|
+
user to the legacy network, specify this
|
54
|
+
:param when: when the message was sent, for a "delay" tag (:xep:`0203`)
|
55
|
+
:param reply_to: Quote another message (:xep:`0461`)
|
56
|
+
:param hints:
|
57
|
+
:param thread:
|
58
|
+
:param carbon: (only used if called on a :class:`LegacyContact`)
|
59
|
+
Set this to ``True`` if this is actually a message sent **to** the
|
60
|
+
:class:`LegacyContact` by the :term:`User`.
|
61
|
+
Use this to synchronize outgoing history for legacy official apps.
|
62
|
+
:param correction: whether this message is a correction or not
|
63
|
+
:param correction_event_id: in the case where an ID is associated with the legacy
|
64
|
+
'correction event', specify it here to use it on the XMPP side. If not specified,
|
65
|
+
a random ID will be used.
|
66
|
+
:param link_previews: A little of sender (or server, or gateway)-generated
|
67
|
+
previews of URLs linked in the body.
|
68
|
+
:param archive_only: (only in groups) Do not send this message to user,
|
69
|
+
but store it in the archive. Meant to be used during ``MUC.backfill()``
|
70
|
+
"""
|
71
|
+
if carbon and not hasattr(self, "muc"):
|
72
|
+
if not correction and self.xmpp.store.sent.was_sent_by_user(
|
73
|
+
self.session.user_pk, str(legacy_msg_id)
|
74
|
+
):
|
75
|
+
log.warning(
|
76
|
+
"Carbon message for a message an XMPP has sent? This is a bug! %s",
|
77
|
+
legacy_msg_id,
|
78
|
+
)
|
79
|
+
return
|
80
|
+
if hasattr(self, "muc") and not self.is_user: # type:ignore
|
81
|
+
log.warning(
|
82
|
+
"send_text() called with carbon=True on a participant who is not the user",
|
83
|
+
legacy_msg_id,
|
84
|
+
)
|
85
|
+
self.xmpp.store.sent.set_message(
|
86
|
+
self.session.user_pk,
|
87
|
+
str(legacy_msg_id),
|
88
|
+
self.session.legacy_to_xmpp_msg_id(legacy_msg_id),
|
89
|
+
)
|
90
|
+
hints = self.__default_hints(hints)
|
91
|
+
msg = self._make_message(
|
92
|
+
mbody=body,
|
93
|
+
legacy_msg_id=correction_event_id if correction else legacy_msg_id,
|
94
|
+
when=when,
|
95
|
+
reply_to=reply_to,
|
96
|
+
hints=hints or (),
|
97
|
+
carbon=carbon,
|
98
|
+
thread=thread,
|
99
|
+
link_previews=link_previews,
|
100
|
+
)
|
101
|
+
if correction:
|
102
|
+
msg["replace"]["id"] = self._replace_id(legacy_msg_id)
|
103
|
+
return self._send(
|
104
|
+
msg,
|
105
|
+
archive_only=archive_only,
|
106
|
+
carbon=carbon,
|
107
|
+
legacy_msg_id=legacy_msg_id,
|
108
|
+
**send_kwargs,
|
109
|
+
)
|
110
|
+
|
111
|
+
def correct(
|
112
|
+
self,
|
113
|
+
legacy_msg_id: LegacyMessageType,
|
114
|
+
new_text: str,
|
115
|
+
*,
|
116
|
+
when: Optional[datetime] = None,
|
117
|
+
reply_to: Optional[MessageReference] = None,
|
118
|
+
thread: Optional[LegacyThreadType] = None,
|
119
|
+
hints: Optional[Iterable[ProcessingHint]] = None,
|
120
|
+
carbon=False,
|
121
|
+
archive_only=False,
|
122
|
+
correction_event_id: Optional[LegacyMessageType] = None,
|
123
|
+
link_previews: Optional[list[LinkPreview]] = None,
|
124
|
+
**send_kwargs,
|
125
|
+
):
|
126
|
+
"""
|
127
|
+
Modify a message that was previously sent by this :term:`XMPP Entity`.
|
128
|
+
|
129
|
+
Uses last message correction (:xep:`0308`)
|
130
|
+
|
131
|
+
:param new_text: New content of the message
|
132
|
+
:param legacy_msg_id: The legacy message ID of the message to correct
|
133
|
+
:param when: when the message was sent, for a "delay" tag (:xep:`0203`)
|
134
|
+
:param reply_to: Quote another message (:xep:`0461`)
|
135
|
+
:param hints:
|
136
|
+
:param thread:
|
137
|
+
:param carbon: (only in 1:1) Reflect a message sent to this ``Contact`` by the user.
|
138
|
+
Use this to synchronize outgoing history for legacy official apps.
|
139
|
+
:param archive_only: (only in groups) Do not send this message to user,
|
140
|
+
but store it in the archive. Meant to be used during ``MUC.backfill()``
|
141
|
+
:param correction_event_id: in the case where an ID is associated with the legacy
|
142
|
+
'correction event', specify it here to use it on the XMPP side. If not specified,
|
143
|
+
a random ID will be used.
|
144
|
+
:param link_previews: A little of sender (or server, or gateway)-generated
|
145
|
+
previews of URLs linked in the body.
|
146
|
+
"""
|
147
|
+
self.send_text(
|
148
|
+
new_text,
|
149
|
+
legacy_msg_id,
|
150
|
+
when=when,
|
151
|
+
reply_to=reply_to,
|
152
|
+
hints=hints,
|
153
|
+
carbon=carbon,
|
154
|
+
thread=thread,
|
155
|
+
correction=True,
|
156
|
+
archive_only=archive_only,
|
157
|
+
correction_event_id=correction_event_id,
|
158
|
+
link_previews=link_previews,
|
159
|
+
**send_kwargs,
|
160
|
+
)
|
161
|
+
|
162
|
+
def react(
|
163
|
+
self,
|
164
|
+
legacy_msg_id: LegacyMessageType,
|
165
|
+
emojis: Iterable[str] = (),
|
166
|
+
thread: Optional[LegacyThreadType] = None,
|
167
|
+
**kwargs,
|
168
|
+
):
|
169
|
+
"""
|
170
|
+
Send a reaction (:xep:`0444`) from this :term:`XMPP Entity`.
|
171
|
+
|
172
|
+
:param legacy_msg_id: The message which the reaction refers to.
|
173
|
+
:param emojis: An iterable of emojis used as reactions
|
174
|
+
:param thread:
|
175
|
+
"""
|
176
|
+
msg = self._make_message(
|
177
|
+
hints={"store"}, carbon=kwargs.get("carbon"), thread=thread
|
178
|
+
)
|
179
|
+
xmpp_id = kwargs.pop("xmpp_id", None)
|
180
|
+
if not xmpp_id:
|
181
|
+
xmpp_id = self._legacy_to_xmpp(legacy_msg_id)
|
182
|
+
self.xmpp["xep_0444"].set_reactions(msg, to_id=xmpp_id, reactions=emojis)
|
183
|
+
self._send(msg, **kwargs)
|
184
|
+
|
185
|
+
def retract(
|
186
|
+
self,
|
187
|
+
legacy_msg_id: LegacyMessageType,
|
188
|
+
thread: Optional[LegacyThreadType] = None,
|
189
|
+
**kwargs,
|
190
|
+
):
|
191
|
+
"""
|
192
|
+
Send a message retraction (:XEP:`0424`) from this :term:`XMPP Entity`.
|
193
|
+
|
194
|
+
:param legacy_msg_id: Legacy ID of the message to delete
|
195
|
+
:param thread:
|
196
|
+
"""
|
197
|
+
msg = self._make_message(
|
198
|
+
state=None,
|
199
|
+
hints={"store"},
|
200
|
+
mbody=f"/me retracted the message {legacy_msg_id}",
|
201
|
+
carbon=kwargs.get("carbon"),
|
202
|
+
thread=thread,
|
203
|
+
)
|
204
|
+
msg.enable("fallback")
|
205
|
+
# namespace version mismatch between slidge and slixmpp, update me later
|
206
|
+
msg["fallback"]["for"] = self.xmpp["xep_0424"].namespace[:-1] + "1"
|
207
|
+
msg["retract"]["id"] = msg["replace"]["id"] = self._replace_id(legacy_msg_id)
|
208
|
+
self._send(msg, **kwargs)
|
209
|
+
|
210
|
+
|
211
|
+
log = logging.getLogger(__name__)
|
slidge/core/mixins/presence.py
CHANGED
@@ -5,7 +5,7 @@ from typing import Optional
|
|
5
5
|
|
6
6
|
from slixmpp.types import PresenceShows, PresenceTypes
|
7
7
|
|
8
|
-
from ...util.
|
8
|
+
from ...util.types import CachedPresence
|
9
9
|
from .. import config
|
10
10
|
from .base import BaseSender
|
11
11
|
|
@@ -19,20 +19,32 @@ _FRIEND_REQUEST_PRESENCES = {"subscribe", "unsubscribe", "subscribed", "unsubscr
|
|
19
19
|
|
20
20
|
class PresenceMixin(BaseSender):
|
21
21
|
_ONLY_SEND_PRESENCE_CHANGES = False
|
22
|
+
contact_pk: Optional[int] = None
|
22
23
|
|
23
24
|
def __init__(self, *a, **k):
|
24
25
|
super().__init__(*a, **k)
|
26
|
+
# FIXME: this should not be an attribute of this mixin to allow garbage
|
27
|
+
# collection of instances
|
25
28
|
self.__update_last_seen_fallback_task: Optional[Task] = None
|
29
|
+
# this is only used when a presence is set during Contact.update_info(),
|
30
|
+
# when the contact does not have a DB primary key yet, and is written
|
31
|
+
# to DB at the end of update_info()
|
32
|
+
self.cached_presence: Optional[CachedPresence] = None
|
26
33
|
|
27
34
|
async def __update_last_seen_fallback(self):
|
28
35
|
await sleep(3600 * 7)
|
29
36
|
self.send_last_presence(force=True, no_cache_online=False)
|
30
37
|
|
31
38
|
def _get_last_presence(self) -> Optional[CachedPresence]:
|
32
|
-
|
39
|
+
if self.contact_pk is None:
|
40
|
+
return None
|
41
|
+
return self.xmpp.store.contacts.get_presence(self.contact_pk)
|
33
42
|
|
34
43
|
def _store_last_presence(self, new: CachedPresence):
|
35
|
-
|
44
|
+
if self.contact_pk is None:
|
45
|
+
self.cached_presence = new
|
46
|
+
return
|
47
|
+
self.xmpp.store.contacts.set_presence(self.contact_pk, new)
|
36
48
|
|
37
49
|
def _make_presence(
|
38
50
|
self,
|
@@ -55,7 +67,8 @@ class PresenceMixin(BaseSender):
|
|
55
67
|
)
|
56
68
|
if old != new:
|
57
69
|
if hasattr(self, "muc") and ptype == "unavailable":
|
58
|
-
|
70
|
+
if self.contact_pk is not None:
|
71
|
+
self.xmpp.store.contacts.reset_presence(self.contact_pk)
|
59
72
|
else:
|
60
73
|
self._store_last_presence(new)
|
61
74
|
if old and not force and self._ONLY_SEND_PRESENCE_CHANGES:
|