slidge 0.1.3__py3-none-any.whl → 0.2.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 +3 -5
- slidge/__main__.py +2 -196
- slidge/__version__.py +5 -0
- slidge/command/adhoc.py +8 -1
- slidge/command/admin.py +5 -6
- slidge/command/base.py +1 -2
- slidge/command/register.py +32 -16
- slidge/command/user.py +85 -5
- slidge/contact/contact.py +93 -31
- slidge/contact/roster.py +54 -39
- slidge/core/config.py +13 -7
- slidge/core/gateway/base.py +139 -34
- slidge/core/gateway/disco.py +2 -4
- slidge/core/gateway/mam.py +1 -4
- slidge/core/gateway/ping.py +2 -3
- slidge/core/gateway/presence.py +1 -1
- slidge/core/gateway/registration.py +32 -21
- slidge/core/gateway/search.py +3 -5
- slidge/core/gateway/session_dispatcher.py +100 -51
- slidge/core/gateway/vcard_temp.py +6 -4
- slidge/core/mixins/__init__.py +11 -1
- slidge/core/mixins/attachment.py +15 -10
- slidge/core/mixins/avatar.py +66 -18
- slidge/core/mixins/base.py +8 -2
- slidge/core/mixins/message.py +11 -7
- slidge/core/mixins/message_maker.py +17 -9
- slidge/core/mixins/presence.py +14 -4
- slidge/core/pubsub.py +54 -212
- slidge/core/session.py +65 -33
- slidge/db/__init__.py +4 -0
- slidge/db/alembic/env.py +64 -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/29f5280c61aa_store_subject_setter_in_room.py +37 -0
- slidge/db/alembic/versions/8d2ced764698_rely_on_db_to_store_contacts_rooms_and_.py +133 -0
- slidge/db/alembic/versions/aa9d82a7f6ef_db_creation.py +76 -0
- slidge/db/alembic/versions/b33993e87db3_move_everything_to_persistent_db.py +214 -0
- slidge/db/alembic/versions/e91195719c2c_store_users_avatars_persistently.py +26 -0
- slidge/db/avatar.py +224 -0
- slidge/db/meta.py +65 -0
- slidge/db/models.py +365 -0
- slidge/db/store.py +976 -0
- slidge/group/archive.py +13 -14
- slidge/group/bookmarks.py +59 -56
- slidge/group/participant.py +77 -25
- slidge/group/room.py +242 -142
- slidge/main.py +201 -0
- slidge/migration.py +30 -0
- slidge/slixfix/__init__.py +35 -2
- slidge/slixfix/roster.py +11 -4
- slidge/slixfix/xep_0292/vcard4.py +1 -0
- slidge/util/db.py +1 -47
- slidge/util/test.py +21 -4
- slidge/util/types.py +24 -4
- {slidge-0.1.3.dist-info → slidge-0.2.0a0.dist-info}/METADATA +3 -1
- slidge-0.2.0a0.dist-info/RECORD +108 -0
- slidge/core/cache.py +0 -183
- slidge/util/schema.sql +0 -126
- slidge/util/sql.py +0 -508
- slidge-0.1.3.dist-info/RECORD +0 -96
- {slidge-0.1.3.dist-info → slidge-0.2.0a0.dist-info}/LICENSE +0 -0
- {slidge-0.1.3.dist-info → slidge-0.2.0a0.dist-info}/WHEEL +0 -0
- {slidge-0.1.3.dist-info → slidge-0.2.0a0.dist-info}/entry_points.txt +0 -0
@@ -9,7 +9,6 @@ from slixmpp.plugins.xep_0084.stanza import Info
|
|
9
9
|
|
10
10
|
from ... import LegacyContact
|
11
11
|
from ...group.room import LegacyMUC
|
12
|
-
from ...util.sql import db
|
13
12
|
from ...util.types import LinkPreview, Recipient, RecipientType
|
14
13
|
from ...util.util import (
|
15
14
|
dict_to_named_tuple,
|
@@ -62,6 +61,13 @@ class SessionDispatcher:
|
|
62
61
|
_exceptions_to_xmpp_errors(self.on_muc_owner_set), # type: ignore
|
63
62
|
)
|
64
63
|
)
|
64
|
+
xmpp.register_handler(
|
65
|
+
CoroutineCallback(
|
66
|
+
"ibr_remove",
|
67
|
+
StanzaPath("/iq/register"),
|
68
|
+
_exceptions_to_xmpp_errors(self.on_ibr_remove), # type: ignore
|
69
|
+
)
|
70
|
+
)
|
65
71
|
|
66
72
|
for event in (
|
67
73
|
"legacy_message",
|
@@ -157,7 +163,7 @@ class SessionDispatcher:
|
|
157
163
|
reply_fallback = None
|
158
164
|
if msg.get_plugin("reply", check=True):
|
159
165
|
try:
|
160
|
-
reply_to_msg_xmpp_id = _xmpp_msg_id_to_legacy(
|
166
|
+
reply_to_msg_xmpp_id = self._xmpp_msg_id_to_legacy(
|
161
167
|
session, msg["reply"]["id"]
|
162
168
|
)
|
163
169
|
except XMPPError:
|
@@ -170,7 +176,7 @@ class SessionDispatcher:
|
|
170
176
|
else:
|
171
177
|
reply_to_jid = JID(msg["reply"]["to"])
|
172
178
|
if msg["type"] == "chat":
|
173
|
-
if reply_to_jid.bare != session.
|
179
|
+
if reply_to_jid.bare != session.user_jid.bare:
|
174
180
|
try:
|
175
181
|
reply_to = await session.contacts.by_jid(reply_to_jid)
|
176
182
|
except XMPPError:
|
@@ -242,13 +248,17 @@ class SessionDispatcher:
|
|
242
248
|
if isinstance(e, LegacyMUC):
|
243
249
|
await e.echo(msg, legacy_msg_id)
|
244
250
|
if legacy_msg_id is not None:
|
245
|
-
|
251
|
+
self.xmpp.store.sent.set_group_message(
|
252
|
+
session.user_pk, legacy_msg_id, msg.get_id()
|
253
|
+
)
|
246
254
|
else:
|
247
255
|
self.__ack(msg)
|
248
256
|
if legacy_msg_id is not None:
|
249
|
-
|
257
|
+
self.xmpp.store.sent.set_message(
|
258
|
+
session.user_pk, legacy_msg_id, msg.get_id()
|
259
|
+
)
|
250
260
|
if session.MESSAGE_IDS_ARE_THREAD_IDS and (t := msg["thread"]):
|
251
|
-
session.
|
261
|
+
self.xmpp.store.sent.set_thread(session.user_pk, t, legacy_msg_id)
|
252
262
|
|
253
263
|
async def on_groupchat_message(self, msg: Message):
|
254
264
|
await self.on_legacy_message(msg)
|
@@ -257,9 +267,11 @@ class SessionDispatcher:
|
|
257
267
|
session, entity, thread = await self.__get_session_entity_thread(msg)
|
258
268
|
xmpp_id = msg["replace"]["id"]
|
259
269
|
if isinstance(entity, LegacyMUC):
|
260
|
-
legacy_id =
|
270
|
+
legacy_id = self.xmpp.store.sent.get_group_legacy_id(
|
271
|
+
session.user_pk, xmpp_id
|
272
|
+
)
|
261
273
|
else:
|
262
|
-
legacy_id = _xmpp_msg_id_to_legacy(session, xmpp_id)
|
274
|
+
legacy_id = self._xmpp_msg_id_to_legacy(session, xmpp_id)
|
263
275
|
|
264
276
|
if isinstance(entity, LegacyMUC):
|
265
277
|
mentions = await entity.parse_mentions(msg["body"])
|
@@ -323,12 +335,16 @@ class SessionDispatcher:
|
|
323
335
|
|
324
336
|
if isinstance(entity, LegacyMUC):
|
325
337
|
if new_legacy_msg_id is not None:
|
326
|
-
|
338
|
+
self.xmpp.store.sent.set_group_message(
|
339
|
+
session.user_pk, new_legacy_msg_id, msg.get_id()
|
340
|
+
)
|
327
341
|
await entity.echo(msg, new_legacy_msg_id)
|
328
342
|
else:
|
329
343
|
self.__ack(msg)
|
330
344
|
if new_legacy_msg_id is not None:
|
331
|
-
|
345
|
+
self.xmpp.store.sent.set_message(
|
346
|
+
session.user_pk, new_legacy_msg_id, msg.get_id()
|
347
|
+
)
|
332
348
|
|
333
349
|
async def on_message_retract(self, msg: Message):
|
334
350
|
session, entity, thread = await self.__get_session_entity_thread(msg)
|
@@ -338,7 +354,7 @@ class SessionDispatcher:
|
|
338
354
|
"This legacy service does not support message retraction.",
|
339
355
|
)
|
340
356
|
xmpp_id: str = msg["retract"]["id"]
|
341
|
-
legacy_id = _xmpp_msg_id_to_legacy(session, xmpp_id)
|
357
|
+
legacy_id = self._xmpp_msg_id_to_legacy(session, xmpp_id)
|
342
358
|
if legacy_id:
|
343
359
|
await session.on_retract(entity, legacy_id, thread=thread)
|
344
360
|
if isinstance(entity, LegacyMUC):
|
@@ -362,7 +378,7 @@ class SessionDispatcher:
|
|
362
378
|
to_mark = [displayed_msg_id]
|
363
379
|
for xmpp_id in to_mark:
|
364
380
|
await session.on_displayed(
|
365
|
-
e, _xmpp_msg_id_to_legacy(session, xmpp_id), legacy_thread
|
381
|
+
e, self._xmpp_msg_id_to_legacy(session, xmpp_id), legacy_thread
|
366
382
|
)
|
367
383
|
if isinstance(e, LegacyMUC):
|
368
384
|
await e.echo(msg, None)
|
@@ -397,7 +413,7 @@ class SessionDispatcher:
|
|
397
413
|
if special_msg:
|
398
414
|
legacy_id = react_to
|
399
415
|
else:
|
400
|
-
legacy_id = _xmpp_msg_id_to_legacy(session, react_to)
|
416
|
+
legacy_id = self._xmpp_msg_id_to_legacy(session, react_to)
|
401
417
|
|
402
418
|
if not legacy_id:
|
403
419
|
log.debug("Ignored reaction from user")
|
@@ -434,9 +450,10 @@ class SessionDispatcher:
|
|
434
450
|
else:
|
435
451
|
self.__ack(msg)
|
436
452
|
|
437
|
-
multi =
|
453
|
+
multi = self.xmpp.store.multi.get_xmpp_ids(session.user_pk, react_to)
|
438
454
|
if not multi:
|
439
455
|
return
|
456
|
+
multi = [m for m in multi if react_to != m]
|
440
457
|
|
441
458
|
if isinstance(entity, LegacyMUC):
|
442
459
|
for xmpp_id in multi:
|
@@ -461,14 +478,17 @@ class SessionDispatcher:
|
|
461
478
|
|
462
479
|
pto = p.get_to()
|
463
480
|
if pto == self.xmpp.boundjid.bare:
|
464
|
-
|
465
|
-
# a presence show if available. Weird, weird, weird slix.
|
481
|
+
session.log.debug("Received a presence from %s", p.get_from())
|
466
482
|
if (ptype := p.get_type()) not in _USEFUL_PRESENCES:
|
467
483
|
return
|
484
|
+
if not session.user.preferences.get("sync_presence", False):
|
485
|
+
session.log.debug("User does not want to sync their presence")
|
486
|
+
return
|
487
|
+
# NB: get_type() returns either a proper presence type or
|
488
|
+
# a presence show if available. Weird, weird, weird slix.
|
468
489
|
resources = self.xmpp.roster[self.xmpp.boundjid.bare][
|
469
490
|
p.get_from()
|
470
491
|
].resources
|
471
|
-
session.log.debug("Received a presence from %s", p.get_from())
|
472
492
|
await session.on_presence(
|
473
493
|
p.get_from().resource,
|
474
494
|
ptype, # type: ignore
|
@@ -478,8 +498,12 @@ class SessionDispatcher:
|
|
478
498
|
)
|
479
499
|
return
|
480
500
|
|
481
|
-
muc = session.bookmarks.
|
482
|
-
|
501
|
+
muc = session.bookmarks.by_jid_only_if_exists(JID(pto.bare))
|
502
|
+
|
503
|
+
if muc is not None and p.get_type() == "unavailable":
|
504
|
+
return muc.on_presence_unavailable(p)
|
505
|
+
|
506
|
+
if muc is None or p.get_from().resource not in muc.get_user_resources():
|
483
507
|
return
|
484
508
|
|
485
509
|
if pto.resource == muc.user_nick:
|
@@ -530,29 +554,36 @@ class SessionDispatcher:
|
|
530
554
|
return
|
531
555
|
|
532
556
|
stanza_id = msg["pubsub_event"]["items"]["item"]["displayed"]["stanza_id"]["id"]
|
533
|
-
await session.on_displayed(
|
557
|
+
await session.on_displayed(
|
558
|
+
chat, self._xmpp_msg_id_to_legacy(session, stanza_id)
|
559
|
+
)
|
534
560
|
|
535
561
|
async def on_avatar_metadata_publish(self, m: Message):
|
536
|
-
if not config.SYNC_AVATAR:
|
537
|
-
return
|
538
|
-
|
539
562
|
session = await self.__get_session(m, timeout=None)
|
563
|
+
if not session.user.preferences.get("sync_avatar", False):
|
564
|
+
session.log.debug("User does not want to sync their avatar")
|
565
|
+
return
|
540
566
|
info = m["pubsub_event"]["items"]["item"]["avatar_metadata"]["info"]
|
541
567
|
|
542
568
|
await self.on_avatar_metadata_info(session, info)
|
543
569
|
|
544
570
|
async def on_avatar_metadata_info(self, session: BaseSession, info: Info):
|
545
|
-
session.log.debug("Avatar metadata info: %s", info)
|
546
571
|
hash_ = info["id"]
|
547
572
|
|
548
|
-
if session.avatar_hash == hash_:
|
573
|
+
if session.user.avatar_hash == hash_:
|
574
|
+
session.log.debug("We already know this avatar hash")
|
549
575
|
return
|
550
|
-
session
|
576
|
+
with self.xmpp.store.session() as orm_session:
|
577
|
+
user = self.xmpp.store.users.get(session.user_jid)
|
578
|
+
assert user is not None
|
579
|
+
user.avatar_hash = hash_
|
580
|
+
orm_session.add(user)
|
581
|
+
orm_session.commit()
|
551
582
|
|
552
583
|
if hash_:
|
553
584
|
try:
|
554
585
|
iq = await self.xmpp.plugin["xep_0084"].retrieve_avatar(
|
555
|
-
session.
|
586
|
+
session.user_jid, hash_, ifrom=self.xmpp.boundjid.bare
|
556
587
|
)
|
557
588
|
except IqError as e:
|
558
589
|
session.log.warning("Could not fetch the user's avatar: %s", e)
|
@@ -593,7 +624,7 @@ class SessionDispatcher:
|
|
593
624
|
"Slidge only implements moderation/retraction",
|
594
625
|
)
|
595
626
|
|
596
|
-
legacy_id = _xmpp_msg_id_to_legacy(session, xmpp_id)
|
627
|
+
legacy_id = self._xmpp_msg_id_to_legacy(session, xmpp_id)
|
597
628
|
await session.on_moderate(muc, legacy_id, moderate["reason"] or None)
|
598
629
|
iq.reply(clear=True).send()
|
599
630
|
|
@@ -718,25 +749,39 @@ class SessionDispatcher:
|
|
718
749
|
)
|
719
750
|
await muc.on_set_subject(msg["subject"])
|
720
751
|
|
752
|
+
async def on_ibr_remove(self, iq: Iq):
|
753
|
+
if iq.get_to() == self.xmpp.boundjid.bare:
|
754
|
+
return
|
755
|
+
|
756
|
+
session = await self.__get_session(iq)
|
757
|
+
session.raise_if_not_logged()
|
721
758
|
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
759
|
+
if iq["type"] == "set" and iq["register"]["remove"]:
|
760
|
+
muc = await session.bookmarks.by_jid(iq.get_to())
|
761
|
+
await session.on_leave_group(muc.legacy_id)
|
762
|
+
iq.reply().send()
|
763
|
+
return
|
726
764
|
|
727
|
-
|
728
|
-
if multi:
|
729
|
-
return multi
|
765
|
+
raise XMPPError("feature-not-implemented")
|
730
766
|
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
767
|
+
def _xmpp_msg_id_to_legacy(self, session: "BaseSession", xmpp_id: str):
|
768
|
+
sent = self.xmpp.store.sent.get_legacy_id(session.user_pk, xmpp_id)
|
769
|
+
if sent is not None:
|
770
|
+
return self.xmpp.LEGACY_MSG_ID_TYPE(sent)
|
771
|
+
|
772
|
+
multi = self.xmpp.store.multi.get_legacy_id(session.user_pk, xmpp_id)
|
773
|
+
if multi:
|
774
|
+
return self.xmpp.LEGACY_MSG_ID_TYPE(multi)
|
775
|
+
|
776
|
+
try:
|
777
|
+
return session.xmpp_to_legacy_msg_id(xmpp_id)
|
778
|
+
except XMPPError:
|
779
|
+
raise
|
780
|
+
except Exception as e:
|
781
|
+
log.debug("Couldn't convert xmpp msg ID to legacy ID.", exc_info=e)
|
782
|
+
raise XMPPError(
|
783
|
+
"internal-server-error", "Couldn't convert xmpp msg ID to legacy ID."
|
784
|
+
)
|
740
785
|
|
741
786
|
|
742
787
|
def _ignore(session: "BaseSession", msg: Message):
|
@@ -755,14 +800,18 @@ async def _xmpp_to_legacy_thread(
|
|
755
800
|
return
|
756
801
|
|
757
802
|
if session.MESSAGE_IDS_ARE_THREAD_IDS:
|
758
|
-
return session.
|
803
|
+
return session.xmpp.store.sent.get_legacy_thread(session.user_pk, xmpp_thread)
|
759
804
|
|
760
805
|
async with session.thread_creation_lock:
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
806
|
+
legacy_thread_str = session.xmpp.store.sent.get_legacy_thread(
|
807
|
+
session.user_pk, xmpp_thread
|
808
|
+
)
|
809
|
+
if legacy_thread_str is None:
|
810
|
+
legacy_thread = str(await recipient.create_thread(xmpp_thread))
|
811
|
+
session.xmpp.store.sent.set_thread(
|
812
|
+
session.user_pk, xmpp_thread, legacy_thread
|
813
|
+
)
|
814
|
+
return session.xmpp.LEGACY_MSG_ID_TYPE(legacy_thread)
|
766
815
|
|
767
816
|
|
768
817
|
async def _get_entity(session: "BaseSession", m: Message) -> RecipientType:
|
@@ -770,7 +819,7 @@ async def _get_entity(session: "BaseSession", m: Message) -> RecipientType:
|
|
770
819
|
if m.get_type() == "groupchat":
|
771
820
|
muc = await session.bookmarks.by_jid(m.get_to())
|
772
821
|
r = m.get_from().resource
|
773
|
-
if r not in muc.
|
822
|
+
if r not in muc.get_user_resources():
|
774
823
|
session.create_task(muc.kick_resource(r))
|
775
824
|
raise XMPPError("not-acceptable", "You are not connected to this chat")
|
776
825
|
return muc
|
@@ -40,11 +40,13 @@ class VCardTemp:
|
|
40
40
|
return await self.__handle_set_vcard_temp(iq)
|
41
41
|
|
42
42
|
async def __fetch_user_avatar(self, session: BaseSession):
|
43
|
-
hash_ = session.avatar_hash
|
43
|
+
hash_ = session.user.avatar_hash
|
44
44
|
if not hash_:
|
45
|
-
raise XMPPError(
|
45
|
+
raise XMPPError(
|
46
|
+
"item-not-found", "The slidge user does not have any avatar set"
|
47
|
+
)
|
46
48
|
meta_iq = await self.xmpp.plugin["xep_0060"].get_item(
|
47
|
-
session.
|
49
|
+
session.user_jid,
|
48
50
|
MetaData.namespace,
|
49
51
|
hash_,
|
50
52
|
ifrom=self.xmpp.boundjid.bare,
|
@@ -52,7 +54,7 @@ class VCardTemp:
|
|
52
54
|
info = meta_iq["pubsub"]["items"]["item"]["avatar_metadata"]["info"]
|
53
55
|
type_ = info["type"]
|
54
56
|
data_iq = await self.xmpp.plugin["xep_0084"].retrieve_avatar(
|
55
|
-
session.
|
57
|
+
session.user_jid, hash_, ifrom=self.xmpp.boundjid.bare
|
56
58
|
)
|
57
59
|
bytes_ = data_iq["pubsub"]["items"]["item"]["avatar_data"]["value"]
|
58
60
|
return bytes_, type_
|
slidge/core/mixins/__init__.py
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
Mixins
|
3
3
|
"""
|
4
4
|
|
5
|
+
from typing import Optional
|
6
|
+
|
5
7
|
from .avatar import AvatarMixin
|
6
8
|
from .disco import ChatterDiscoMixin
|
7
9
|
from .message import MessageCarbonMixin, MessageMixin
|
@@ -16,4 +18,12 @@ class FullCarbonMixin(ChatterDiscoMixin, MessageCarbonMixin, PresenceMixin):
|
|
16
18
|
pass
|
17
19
|
|
18
20
|
|
19
|
-
|
21
|
+
class StoredAttributeMixin:
|
22
|
+
def serialize_extra_attributes(self) -> Optional[dict]:
|
23
|
+
return None
|
24
|
+
|
25
|
+
def deserialize_extra_attributes(self, data: dict) -> None:
|
26
|
+
pass
|
27
|
+
|
28
|
+
|
29
|
+
__all__ = ("AvatarMixin", "FullCarbonMixin", "StoredAttributeMixin")
|
slidge/core/mixins/attachment.py
CHANGED
@@ -22,7 +22,7 @@ from slixmpp.plugins.xep_0363 import FileUploadError
|
|
22
22
|
from slixmpp.plugins.xep_0385.stanza import Sims
|
23
23
|
from slixmpp.plugins.xep_0447.stanza import StatelessFileSharing
|
24
24
|
|
25
|
-
from ...
|
25
|
+
from ...db.avatar import avatar_cache
|
26
26
|
from ...util.types import (
|
27
27
|
LegacyAttachment,
|
28
28
|
LegacyMessageType,
|
@@ -31,11 +31,14 @@ from ...util.types import (
|
|
31
31
|
)
|
32
32
|
from ...util.util import fix_suffix
|
33
33
|
from .. import config
|
34
|
-
from ..cache import avatar_cache
|
35
34
|
from .message_maker import MessageMaker
|
36
35
|
|
37
36
|
|
38
37
|
class AttachmentMixin(MessageMaker):
|
38
|
+
def __init__(self, *a, **kw):
|
39
|
+
super().__init__(*a, **kw)
|
40
|
+
self.__store = self.xmpp.store.attachments
|
41
|
+
|
39
42
|
def send_text(self, *_, **k) -> Optional[Message]:
|
40
43
|
raise NotImplementedError
|
41
44
|
|
@@ -146,13 +149,13 @@ class AttachmentMixin(MessageMaker):
|
|
146
149
|
legacy_file_id: Optional[Union[str, int]] = None,
|
147
150
|
) -> tuple[bool, Optional[Path], str]:
|
148
151
|
if legacy_file_id:
|
149
|
-
cache =
|
152
|
+
cache = self.__store.get_url(str(legacy_file_id))
|
150
153
|
if cache is not None:
|
151
154
|
async with self.session.http.head(cache) as r:
|
152
155
|
if r.status < 400:
|
153
156
|
return False, None, cache
|
154
157
|
else:
|
155
|
-
|
158
|
+
self.__store.remove(str(legacy_file_id))
|
156
159
|
|
157
160
|
if file_url and config.USE_ATTACHMENT_ORIGINAL_URLS:
|
158
161
|
return False, None, file_url
|
@@ -198,7 +201,7 @@ class AttachmentMixin(MessageMaker):
|
|
198
201
|
local_path = file_path
|
199
202
|
new_url = await self.__upload(file_path, file_name, content_type)
|
200
203
|
if legacy_file_id:
|
201
|
-
|
204
|
+
self.__store.set_url(self.session.user_pk, str(legacy_file_id), new_url)
|
202
205
|
|
203
206
|
return is_temp, local_path, new_url
|
204
207
|
|
@@ -211,7 +214,7 @@ class AttachmentMixin(MessageMaker):
|
|
211
214
|
caption: Optional[str] = None,
|
212
215
|
file_name: Optional[str] = None,
|
213
216
|
):
|
214
|
-
cache =
|
217
|
+
cache = self.__store.get_sims(uploaded_url)
|
215
218
|
if cache:
|
216
219
|
msg.append(Sims(xml=ET.fromstring(cache)))
|
217
220
|
return
|
@@ -238,7 +241,7 @@ class AttachmentMixin(MessageMaker):
|
|
238
241
|
thumbnail["media-type"] = "image/blurhash"
|
239
242
|
thumbnail["uri"] = "data:image/blurhash," + urlquote(h)
|
240
243
|
|
241
|
-
|
244
|
+
self.__store.set_sims(uploaded_url, str(sims))
|
242
245
|
|
243
246
|
msg.append(sims)
|
244
247
|
|
@@ -251,7 +254,7 @@ class AttachmentMixin(MessageMaker):
|
|
251
254
|
caption: Optional[str] = None,
|
252
255
|
file_name: Optional[str] = None,
|
253
256
|
):
|
254
|
-
cache =
|
257
|
+
cache = self.__store.get_sfs(uploaded_url)
|
255
258
|
if cache:
|
256
259
|
msg.append(StatelessFileSharing(xml=ET.fromstring(cache)))
|
257
260
|
return
|
@@ -262,7 +265,7 @@ class AttachmentMixin(MessageMaker):
|
|
262
265
|
sfs = self.xmpp["xep_0447"].get_sfs(path, [uploaded_url], content_type, caption)
|
263
266
|
if file_name:
|
264
267
|
sfs["file"]["name"] = file_name
|
265
|
-
|
268
|
+
self.__store.set_sfs(uploaded_url, str(sfs))
|
266
269
|
|
267
270
|
msg.append(sfs)
|
268
271
|
|
@@ -472,7 +475,9 @@ class AttachmentMixin(MessageMaker):
|
|
472
475
|
ids.append(stanza_id["id"])
|
473
476
|
else:
|
474
477
|
ids.append(msg.get_id())
|
475
|
-
|
478
|
+
self.xmpp.store.multi.set_xmpp_ids(
|
479
|
+
self.session.user_pk, str(legacy_msg_id), ids
|
480
|
+
)
|
476
481
|
|
477
482
|
|
478
483
|
def get_blurhash(path: Path, n=9) -> tuple[str, int, int]:
|
slidge/core/mixins/avatar.py
CHANGED
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING, Optional
|
|
5
5
|
|
6
6
|
from slixmpp import JID
|
7
7
|
|
8
|
+
from ...db.avatar import CachedAvatar, avatar_cache
|
8
9
|
from ...util.types import (
|
9
10
|
URL,
|
10
11
|
AnyBaseSession,
|
@@ -12,7 +13,6 @@ from ...util.types import (
|
|
12
13
|
AvatarType,
|
13
14
|
LegacyFileIdType,
|
14
15
|
)
|
15
|
-
from ..cache import avatar_cache
|
16
16
|
|
17
17
|
if TYPE_CHECKING:
|
18
18
|
from ..pubsub import PepAvatar
|
@@ -34,7 +34,9 @@ class AvatarMixin:
|
|
34
34
|
def __init__(self) -> None:
|
35
35
|
super().__init__()
|
36
36
|
self._set_avatar_task: Optional[Task] = None
|
37
|
+
self.__broadcast_task: Optional[Task] = None
|
37
38
|
self.__avatar_unique_id: Optional[AvatarIdType] = None
|
39
|
+
self._avatar_pk: Optional[int] = None
|
38
40
|
|
39
41
|
@property
|
40
42
|
def __avatar_jid(self):
|
@@ -86,13 +88,28 @@ class AvatarMixin:
|
|
86
88
|
|
87
89
|
async def __set_avatar(self, a: Optional[AvatarType], uid: Optional[AvatarIdType]):
|
88
90
|
self.__avatar_unique_id = uid
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
91
|
+
|
92
|
+
if a is None:
|
93
|
+
cached_avatar = None
|
94
|
+
self._avatar_pk = None
|
95
|
+
else:
|
96
|
+
try:
|
97
|
+
cached_avatar = await avatar_cache.convert_or_get(
|
98
|
+
URL(a) if isinstance(a, URL) else a,
|
99
|
+
None if isinstance(uid, URL) else uid,
|
100
|
+
)
|
101
|
+
except Exception as e:
|
102
|
+
self.session.log.error("Failed to set avatar %s", a, exc_info=e)
|
103
|
+
self._avatar_pk = None
|
104
|
+
self.__avatar_unique_id = uid
|
105
|
+
return
|
106
|
+
self._avatar_pk = cached_avatar.pk
|
107
|
+
|
108
|
+
if self._avatar_pubsub_broadcast:
|
109
|
+
await self.session.xmpp.pubsub.broadcast_avatar(
|
110
|
+
self.__avatar_jid, self.session.user_jid, cached_avatar
|
111
|
+
)
|
112
|
+
|
96
113
|
self._post_avatar_update()
|
97
114
|
|
98
115
|
async def _no_change(self, a: Optional[AvatarType], uid: Optional[AvatarIdType]):
|
@@ -103,7 +120,7 @@ class AvatarMixin:
|
|
103
120
|
if isinstance(uid, URL):
|
104
121
|
if self.__avatar_unique_id != uid:
|
105
122
|
return False
|
106
|
-
return not await avatar_cache.
|
123
|
+
return not await avatar_cache.url_modified(uid)
|
107
124
|
return self.__avatar_unique_id == uid
|
108
125
|
|
109
126
|
async def set_avatar(
|
@@ -136,32 +153,63 @@ class AvatarMixin:
|
|
136
153
|
if blocking:
|
137
154
|
await awaitable
|
138
155
|
|
139
|
-
def
|
156
|
+
def get_cached_avatar(self) -> Optional["CachedAvatar"]:
|
140
157
|
if not self.__avatar_unique_id:
|
141
158
|
return None
|
142
|
-
return
|
159
|
+
return avatar_cache.get(self.__avatar_unique_id)
|
160
|
+
|
161
|
+
def get_avatar(self) -> Optional["PepAvatar"]:
|
162
|
+
cached_avatar = self.get_cached_avatar()
|
163
|
+
if cached_avatar is None:
|
164
|
+
return None
|
165
|
+
from ..pubsub import PepAvatar
|
166
|
+
|
167
|
+
item = PepAvatar()
|
168
|
+
item.set_avatar_from_cache(cached_avatar)
|
169
|
+
return item
|
143
170
|
|
144
171
|
def _post_avatar_update(self) -> None:
|
145
172
|
return
|
146
173
|
|
174
|
+
def __get_cached_avatar_id(self):
|
175
|
+
i = self._get_cached_avatar_id()
|
176
|
+
if i is None:
|
177
|
+
return None
|
178
|
+
return self.session.xmpp.AVATAR_ID_TYPE(i)
|
179
|
+
|
180
|
+
def _get_cached_avatar_id(self) -> Optional[str]:
|
181
|
+
raise NotImplementedError
|
182
|
+
|
147
183
|
async def avatar_wrap_update_info(self):
|
148
|
-
cached_id =
|
184
|
+
cached_id = self.__get_cached_avatar_id()
|
149
185
|
self.__avatar_unique_id = cached_id
|
150
186
|
try:
|
151
187
|
await self.update_info() # type:ignore
|
152
188
|
except NotImplementedError:
|
153
189
|
return
|
154
190
|
new_id = self.avatar
|
155
|
-
if isinstance(new_id, URL) and not await avatar_cache.
|
191
|
+
if isinstance(new_id, URL) and not await avatar_cache.url_modified(new_id):
|
156
192
|
return
|
157
193
|
elif new_id != cached_id:
|
158
194
|
# at this point it means that update_info set the avatar, and we don't
|
159
195
|
# need to do anything else
|
160
196
|
return
|
161
197
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
self.
|
198
|
+
if self._avatar_pubsub_broadcast:
|
199
|
+
if new_id is None and cached_id is None:
|
200
|
+
return
|
201
|
+
cached_avatar = avatar_cache.get(cached_id)
|
202
|
+
self.__broadcast_task = self.session.xmpp.loop.create_task(
|
203
|
+
self.session.xmpp.pubsub.broadcast_avatar(
|
204
|
+
self.__avatar_jid, self.session.user_jid, cached_avatar
|
205
|
+
)
|
206
|
+
)
|
207
|
+
|
208
|
+
def _set_avatar_from_store(self, stored):
|
209
|
+
if stored.avatar_id is None:
|
210
|
+
return
|
211
|
+
self.__avatar_unique_id = (
|
212
|
+
stored.avatar.legacy_id
|
213
|
+
if stored.avatar.legacy_id is not None
|
214
|
+
else URL(stored.avatar.url)
|
167
215
|
)
|
slidge/core/mixins/base.py
CHANGED
@@ -8,7 +8,6 @@ from ...util.types import MessageOrPresenceTypeVar
|
|
8
8
|
if TYPE_CHECKING:
|
9
9
|
from slidge.core.gateway import BaseGateway
|
10
10
|
from slidge.core.session import BaseSession
|
11
|
-
from slidge.util.db import GatewayUser
|
12
11
|
|
13
12
|
|
14
13
|
class MetaBase(ABCMeta):
|
@@ -18,11 +17,18 @@ class MetaBase(ABCMeta):
|
|
18
17
|
class Base:
|
19
18
|
session: "BaseSession" = NotImplemented
|
20
19
|
xmpp: "BaseGateway" = NotImplemented
|
21
|
-
user: "GatewayUser" = NotImplemented
|
22
20
|
|
23
21
|
jid: JID = NotImplemented
|
24
22
|
name: str = NotImplemented
|
25
23
|
|
24
|
+
@property
|
25
|
+
def user_jid(self):
|
26
|
+
return self.session.user_jid
|
27
|
+
|
28
|
+
@property
|
29
|
+
def user_pk(self):
|
30
|
+
return self.session.user_pk
|
31
|
+
|
26
32
|
|
27
33
|
class BaseSender(Base):
|
28
34
|
def _send(
|
slidge/core/mixins/message.py
CHANGED
@@ -111,7 +111,7 @@ class MarkerMixin(MessageMaker):
|
|
111
111
|
self.xmpp.delivery_receipt.make_ack(
|
112
112
|
self._legacy_to_xmpp(legacy_msg_id),
|
113
113
|
mfrom=self.jid,
|
114
|
-
mto=self.
|
114
|
+
mto=self.user_jid,
|
115
115
|
)
|
116
116
|
)
|
117
117
|
self._send(
|
@@ -144,7 +144,7 @@ class MarkerMixin(MessageMaker):
|
|
144
144
|
# We'll see if we need to implement that later
|
145
145
|
return
|
146
146
|
xmpp_msg_id = self._legacy_to_xmpp(legacy_msg_id)
|
147
|
-
iq = Iq(sto=self.
|
147
|
+
iq = Iq(sto=self.user_jid.bare, sfrom=self.user_jid.bare, stype="set")
|
148
148
|
iq["pubsub"]["publish"]["node"] = self.xmpp["xep_0490"].stanza.NS
|
149
149
|
iq["pubsub"]["publish"]["item"]["id"] = muc_jid
|
150
150
|
displayed = self.xmpp["xep_0490"].stanza.Displayed()
|
@@ -169,8 +169,8 @@ class ContentMessageMixin(AttachmentMixin):
|
|
169
169
|
|
170
170
|
def __replace_id(self, legacy_msg_id: LegacyMessageType):
|
171
171
|
if self.mtype == "groupchat":
|
172
|
-
return self.
|
173
|
-
legacy_msg_id
|
172
|
+
return self.xmpp.store.sent.get_group_xmpp_id(
|
173
|
+
self.session.user_pk, str(legacy_msg_id)
|
174
174
|
) or self._legacy_to_xmpp(legacy_msg_id)
|
175
175
|
else:
|
176
176
|
return self._legacy_to_xmpp(legacy_msg_id)
|
@@ -215,14 +215,18 @@ class ContentMessageMixin(AttachmentMixin):
|
|
215
215
|
but store it in the archive. Meant to be used during ``MUC.backfill()``
|
216
216
|
"""
|
217
217
|
if carbon:
|
218
|
-
if not correction and
|
218
|
+
if not correction and self.xmpp.store.sent.was_sent_by_user(
|
219
|
+
self.session.user_pk, str(legacy_msg_id)
|
220
|
+
):
|
219
221
|
log.warning(
|
220
222
|
"Carbon message for a message an XMPP has sent? This is a bug! %s",
|
221
223
|
legacy_msg_id,
|
222
224
|
)
|
223
225
|
return
|
224
|
-
self.
|
225
|
-
|
226
|
+
self.xmpp.store.sent.set_message(
|
227
|
+
self.session.user_pk,
|
228
|
+
str(legacy_msg_id),
|
229
|
+
self.session.legacy_to_xmpp_msg_id(legacy_msg_id),
|
226
230
|
)
|
227
231
|
hints = self.__default_hints(hints)
|
228
232
|
msg = self._make_message(
|