slidge 0.1.2__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 +109 -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 +81 -29
- 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.2.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.2.dist-info/RECORD +0 -96
- {slidge-0.1.2.dist-info → slidge-0.2.0a0.dist-info}/LICENSE +0 -0
- {slidge-0.1.2.dist-info → slidge-0.2.0a0.dist-info}/WHEEL +0 -0
- {slidge-0.1.2.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:
|
@@ -448,18 +465,30 @@ class SessionDispatcher:
|
|
448
465
|
entity.react(legacy_id, emojis, xmpp_id=xmpp_id, carbon=True)
|
449
466
|
|
450
467
|
async def on_presence(self, p: Presence):
|
468
|
+
if p.get_plugin("muc_join", check=True):
|
469
|
+
# handled in on_groupchat_join
|
470
|
+
# without this early return, since we switch from and to in this
|
471
|
+
# presence stanza, on_groupchat_join ends up trying to instantiate
|
472
|
+
# a MUC with the user's JID, which in turn leads to slidge sending
|
473
|
+
# a (error) presence from=the user's JID, which terminates the
|
474
|
+
# XML stream.
|
475
|
+
return
|
476
|
+
|
451
477
|
session = await self.__get_session(p)
|
452
478
|
|
453
479
|
pto = p.get_to()
|
454
480
|
if pto == self.xmpp.boundjid.bare:
|
455
|
-
|
456
|
-
# a presence show if available. Weird, weird, weird slix.
|
481
|
+
session.log.debug("Received a presence from %s", p.get_from())
|
457
482
|
if (ptype := p.get_type()) not in _USEFUL_PRESENCES:
|
458
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.
|
459
489
|
resources = self.xmpp.roster[self.xmpp.boundjid.bare][
|
460
490
|
p.get_from()
|
461
491
|
].resources
|
462
|
-
session.log.debug("Received a presence from %s", p.get_from())
|
463
492
|
await session.on_presence(
|
464
493
|
p.get_from().resource,
|
465
494
|
ptype, # type: ignore
|
@@ -469,8 +498,12 @@ class SessionDispatcher:
|
|
469
498
|
)
|
470
499
|
return
|
471
500
|
|
472
|
-
muc = session.bookmarks.
|
473
|
-
|
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():
|
474
507
|
return
|
475
508
|
|
476
509
|
if pto.resource == muc.user_nick:
|
@@ -521,29 +554,36 @@ class SessionDispatcher:
|
|
521
554
|
return
|
522
555
|
|
523
556
|
stanza_id = msg["pubsub_event"]["items"]["item"]["displayed"]["stanza_id"]["id"]
|
524
|
-
await session.on_displayed(
|
557
|
+
await session.on_displayed(
|
558
|
+
chat, self._xmpp_msg_id_to_legacy(session, stanza_id)
|
559
|
+
)
|
525
560
|
|
526
561
|
async def on_avatar_metadata_publish(self, m: Message):
|
527
|
-
if not config.SYNC_AVATAR:
|
528
|
-
return
|
529
|
-
|
530
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
|
531
566
|
info = m["pubsub_event"]["items"]["item"]["avatar_metadata"]["info"]
|
532
567
|
|
533
568
|
await self.on_avatar_metadata_info(session, info)
|
534
569
|
|
535
570
|
async def on_avatar_metadata_info(self, session: BaseSession, info: Info):
|
536
|
-
session.log.debug("Avatar metadata info: %s", info)
|
537
571
|
hash_ = info["id"]
|
538
572
|
|
539
|
-
if session.avatar_hash == hash_:
|
573
|
+
if session.user.avatar_hash == hash_:
|
574
|
+
session.log.debug("We already know this avatar hash")
|
540
575
|
return
|
541
|
-
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()
|
542
582
|
|
543
583
|
if hash_:
|
544
584
|
try:
|
545
585
|
iq = await self.xmpp.plugin["xep_0084"].retrieve_avatar(
|
546
|
-
session.
|
586
|
+
session.user_jid, hash_, ifrom=self.xmpp.boundjid.bare
|
547
587
|
)
|
548
588
|
except IqError as e:
|
549
589
|
session.log.warning("Could not fetch the user's avatar: %s", e)
|
@@ -584,7 +624,7 @@ class SessionDispatcher:
|
|
584
624
|
"Slidge only implements moderation/retraction",
|
585
625
|
)
|
586
626
|
|
587
|
-
legacy_id = _xmpp_msg_id_to_legacy(session, xmpp_id)
|
627
|
+
legacy_id = self._xmpp_msg_id_to_legacy(session, xmpp_id)
|
588
628
|
await session.on_moderate(muc, legacy_id, moderate["reason"] or None)
|
589
629
|
iq.reply(clear=True).send()
|
590
630
|
|
@@ -709,25 +749,39 @@ class SessionDispatcher:
|
|
709
749
|
)
|
710
750
|
await muc.on_set_subject(msg["subject"])
|
711
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()
|
712
758
|
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
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
|
717
764
|
|
718
|
-
|
719
|
-
if multi:
|
720
|
-
return multi
|
765
|
+
raise XMPPError("feature-not-implemented")
|
721
766
|
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
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
|
+
)
|
731
785
|
|
732
786
|
|
733
787
|
def _ignore(session: "BaseSession", msg: Message):
|
@@ -746,14 +800,18 @@ async def _xmpp_to_legacy_thread(
|
|
746
800
|
return
|
747
801
|
|
748
802
|
if session.MESSAGE_IDS_ARE_THREAD_IDS:
|
749
|
-
return session.
|
803
|
+
return session.xmpp.store.sent.get_legacy_thread(session.user_pk, xmpp_thread)
|
750
804
|
|
751
805
|
async with session.thread_creation_lock:
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
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)
|
757
815
|
|
758
816
|
|
759
817
|
async def _get_entity(session: "BaseSession", m: Message) -> RecipientType:
|
@@ -761,7 +819,7 @@ async def _get_entity(session: "BaseSession", m: Message) -> RecipientType:
|
|
761
819
|
if m.get_type() == "groupchat":
|
762
820
|
muc = await session.bookmarks.by_jid(m.get_to())
|
763
821
|
r = m.get_from().resource
|
764
|
-
if r not in muc.
|
822
|
+
if r not in muc.get_user_resources():
|
765
823
|
session.create_task(muc.kick_resource(r))
|
766
824
|
raise XMPPError("not-acceptable", "You are not connected to this chat")
|
767
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(
|