slidge 0.2.11__py3-none-any.whl → 0.3.0__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 +5 -2
- slidge/command/adhoc.py +9 -3
- slidge/command/admin.py +16 -12
- slidge/command/base.py +16 -12
- slidge/command/chat_command.py +25 -16
- slidge/command/user.py +7 -8
- slidge/contact/contact.py +123 -210
- slidge/contact/roster.py +108 -105
- slidge/core/config.py +2 -43
- slidge/core/dispatcher/caps.py +9 -2
- slidge/core/dispatcher/disco.py +13 -3
- slidge/core/dispatcher/message/__init__.py +1 -1
- slidge/core/dispatcher/message/chat_state.py +17 -8
- slidge/core/dispatcher/message/marker.py +7 -5
- slidge/core/dispatcher/message/message.py +120 -93
- slidge/core/dispatcher/muc/__init__.py +1 -1
- slidge/core/dispatcher/muc/admin.py +4 -4
- slidge/core/dispatcher/muc/mam.py +10 -6
- slidge/core/dispatcher/muc/misc.py +4 -2
- slidge/core/dispatcher/muc/owner.py +5 -3
- slidge/core/dispatcher/muc/ping.py +3 -1
- slidge/core/dispatcher/presence.py +26 -15
- slidge/core/dispatcher/registration.py +20 -12
- slidge/core/dispatcher/search.py +7 -3
- slidge/core/dispatcher/session_dispatcher.py +13 -5
- slidge/core/dispatcher/util.py +37 -27
- slidge/core/dispatcher/vcard.py +7 -4
- slidge/core/gateway.py +177 -87
- slidge/core/mixins/__init__.py +1 -11
- slidge/core/mixins/attachment.py +200 -147
- slidge/core/mixins/avatar.py +105 -177
- slidge/core/mixins/base.py +3 -1
- slidge/core/mixins/db.py +50 -2
- slidge/core/mixins/disco.py +1 -1
- slidge/core/mixins/message.py +19 -17
- slidge/core/mixins/message_maker.py +29 -15
- slidge/core/mixins/message_text.py +67 -30
- slidge/core/mixins/presence.py +94 -37
- slidge/core/pubsub.py +42 -47
- slidge/core/session.py +95 -60
- slidge/db/alembic/versions/cef02a8b1451_initial_schema.py +361 -0
- slidge/db/avatar.py +150 -119
- slidge/db/meta.py +33 -22
- slidge/db/models.py +69 -117
- slidge/db/store.py +414 -1094
- slidge/group/archive.py +65 -55
- slidge/group/bookmarks.py +96 -59
- slidge/group/participant.py +150 -144
- slidge/group/room.py +351 -328
- slidge/main.py +34 -22
- slidge/migration.py +17 -29
- slidge/slixfix/__init__.py +20 -4
- slidge/slixfix/delivery_receipt.py +6 -4
- slidge/slixfix/link_preview/link_preview.py +1 -1
- slidge/slixfix/link_preview/stanza.py +1 -1
- slidge/slixfix/roster.py +5 -7
- slidge/slixfix/xep_0077/register.py +8 -8
- slidge/slixfix/xep_0077/stanza.py +7 -7
- slidge/slixfix/xep_0100/gateway.py +12 -13
- slidge/slixfix/xep_0153/vcard_avatar.py +1 -1
- slidge/slixfix/xep_0292/vcard4.py +12 -2
- slidge/util/archive_msg.py +11 -5
- slidge/util/conf.py +27 -21
- slidge/util/jid_escaping.py +1 -1
- slidge/{core/mixins → util}/lock.py +6 -6
- slidge/util/test.py +30 -29
- slidge/util/types.py +24 -18
- slidge/util/util.py +26 -22
- {slidge-0.2.11.dist-info → slidge-0.3.0.dist-info}/METADATA +1 -1
- slidge-0.3.0.dist-info/RECORD +95 -0
- {slidge-0.2.11.dist-info → slidge-0.3.0.dist-info}/WHEEL +1 -1
- slidge/db/alembic/versions/04cf35e3cf85_add_participant_nickname_no_illegal.py +0 -33
- slidge/db/alembic/versions/09f27f098baa_add_missing_attributes_in_room.py +0 -36
- slidge/db/alembic/versions/15b0bd83407a_remove_bogus_unique_constraints_on_room_.py +0 -85
- slidge/db/alembic/versions/2461390c0af2_store_contacts_caps_verstring_in_db.py +0 -36
- slidge/db/alembic/versions/29f5280c61aa_store_subject_setter_in_room.py +0 -37
- slidge/db/alembic/versions/2b1f45ab7379_store_room_subject_setter_by_nickname.py +0 -41
- slidge/db/alembic/versions/3071e0fa69d4_add_contact_client_type.py +0 -52
- slidge/db/alembic/versions/45c24cc73c91_add_bob.py +0 -42
- slidge/db/alembic/versions/5bd48bfdffa2_lift_room_legacy_id_constraint.py +0 -61
- slidge/db/alembic/versions/82a4af84b679_add_muc_history_filled.py +0 -48
- slidge/db/alembic/versions/8b993243a536_add_vcard_content_to_contact_table.py +0 -43
- slidge/db/alembic/versions/8d2ced764698_rely_on_db_to_store_contacts_rooms_and_.py +0 -139
- slidge/db/alembic/versions/aa9d82a7f6ef_db_creation.py +0 -50
- slidge/db/alembic/versions/abba1ae0edb3_store_avatar_legacy_id_in_the_contact_.py +0 -79
- slidge/db/alembic/versions/b33993e87db3_move_everything_to_persistent_db.py +0 -214
- slidge/db/alembic/versions/b64b1a793483_add_source_and_legacy_id_for_archived_.py +0 -52
- slidge/db/alembic/versions/c4a8ec35a0e8_per_room_user_nick.py +0 -34
- slidge/db/alembic/versions/e91195719c2c_store_users_avatars_persistently.py +0 -26
- slidge-0.2.11.dist-info/RECORD +0 -112
- {slidge-0.2.11.dist-info → slidge-0.3.0.dist-info}/entry_points.txt +0 -0
- {slidge-0.2.11.dist-info → slidge-0.3.0.dist-info}/licenses/LICENSE +0 -0
- {slidge-0.2.11.dist-info → slidge-0.3.0.dist-info}/top_level.txt +0 -0
slidge/core/session.py
CHANGED
@@ -7,21 +7,24 @@ from typing import (
|
|
7
7
|
Iterable,
|
8
8
|
NamedTuple,
|
9
9
|
Optional,
|
10
|
+
Type,
|
10
11
|
Union,
|
11
12
|
cast,
|
12
13
|
)
|
13
14
|
|
14
15
|
import aiohttp
|
16
|
+
import sqlalchemy as sa
|
15
17
|
from slixmpp import JID, Message
|
16
18
|
from slixmpp.exceptions import XMPPError
|
17
19
|
from slixmpp.types import PresenceShows
|
18
20
|
|
19
21
|
from ..command import SearchResult
|
20
22
|
from ..contact import LegacyContact, LegacyRoster
|
21
|
-
from ..db.models import GatewayUser
|
23
|
+
from ..db.models import Contact, GatewayUser
|
22
24
|
from ..group.bookmarks import LegacyBookmarks
|
23
25
|
from ..group.room import LegacyMUC
|
24
26
|
from ..util import ABCSubclassableOnceAtMost
|
27
|
+
from ..util.lock import NamedLockMixin
|
25
28
|
from ..util.types import (
|
26
29
|
LegacyGroupIdType,
|
27
30
|
LegacyMessageType,
|
@@ -48,7 +51,9 @@ class CachedPresence(NamedTuple):
|
|
48
51
|
|
49
52
|
|
50
53
|
class BaseSession(
|
51
|
-
Generic[LegacyMessageType, RecipientType],
|
54
|
+
Generic[LegacyMessageType, RecipientType],
|
55
|
+
NamedLockMixin,
|
56
|
+
metaclass=ABCSubclassableOnceAtMost,
|
52
57
|
):
|
53
58
|
"""
|
54
59
|
The session of a registered :term:`User`.
|
@@ -89,22 +94,22 @@ class BaseSession(
|
|
89
94
|
This can be used to implement voting in polls in a hacky way.
|
90
95
|
"""
|
91
96
|
|
92
|
-
|
93
|
-
|
97
|
+
_roster_cls: Type[LegacyRoster]
|
98
|
+
_bookmarks_cls: Type[LegacyBookmarks]
|
94
99
|
|
95
|
-
|
96
|
-
|
100
|
+
def __init__(self, user: GatewayUser) -> None:
|
101
|
+
super().__init__()
|
102
|
+
self.user = user
|
103
|
+
self.log = logging.getLogger(user.jid.bare)
|
97
104
|
|
98
105
|
self.ignore_messages = set[str]()
|
99
106
|
|
100
|
-
self.contacts
|
107
|
+
self.contacts = self._roster_cls(self)
|
101
108
|
self.is_logging_in = False
|
102
109
|
self._logged = False
|
103
110
|
self.__reset_ready()
|
104
111
|
|
105
|
-
self.bookmarks
|
106
|
-
self
|
107
|
-
)
|
112
|
+
self.bookmarks = self._bookmarks_cls(self)
|
108
113
|
|
109
114
|
self.thread_creation_lock = asyncio.Lock()
|
110
115
|
|
@@ -113,25 +118,29 @@ class BaseSession(
|
|
113
118
|
self.__tasks = set[asyncio.Task]()
|
114
119
|
|
115
120
|
@property
|
116
|
-
def
|
117
|
-
return self.
|
121
|
+
def user_jid(self) -> JID:
|
122
|
+
return self.user.jid
|
123
|
+
|
124
|
+
@property
|
125
|
+
def user_pk(self) -> int:
|
126
|
+
return self.user.id
|
118
127
|
|
119
128
|
@property
|
120
129
|
def http(self) -> aiohttp.ClientSession:
|
121
130
|
return self.xmpp.http
|
122
131
|
|
123
|
-
def __remove_task(self, fut):
|
132
|
+
def __remove_task(self, fut) -> None:
|
124
133
|
self.log.debug("Removing fut %s", fut)
|
125
134
|
self.__tasks.remove(fut)
|
126
135
|
|
127
|
-
def create_task(self, coro) -> asyncio.Task:
|
128
|
-
task = self.xmpp.loop.create_task(coro)
|
136
|
+
def create_task(self, coro, name: str | None = None) -> asyncio.Task:
|
137
|
+
task = self.xmpp.loop.create_task(coro, name=name)
|
129
138
|
self.__tasks.add(task)
|
130
139
|
self.log.debug("Creating task %s", task)
|
131
140
|
task.add_done_callback(lambda _: self.__remove_task(task))
|
132
141
|
return task
|
133
142
|
|
134
|
-
def cancel_all_tasks(self):
|
143
|
+
def cancel_all_tasks(self) -> None:
|
135
144
|
for task in self.__tasks:
|
136
145
|
task.cancel()
|
137
146
|
|
@@ -148,7 +157,7 @@ class BaseSession(
|
|
148
157
|
"""
|
149
158
|
raise NotImplementedError
|
150
159
|
|
151
|
-
async def logout(self):
|
160
|
+
async def logout(self) -> None:
|
152
161
|
"""
|
153
162
|
Logs out the gateway user from the legacy network.
|
154
163
|
|
@@ -304,6 +313,17 @@ class BaseSession(
|
|
304
313
|
|
305
314
|
paused = deprecated("BaseSession.paused", on_paused)
|
306
315
|
|
316
|
+
async def on_gone(
|
317
|
+
self, chat: RecipientType, thread: Optional[LegacyThreadType] = None
|
318
|
+
):
|
319
|
+
"""
|
320
|
+
Triggered when the user is "gone" in a legacy chat (:xep:`0085`)
|
321
|
+
|
322
|
+
:param chat: See :meth:`.BaseSession.on_text`
|
323
|
+
:param thread:
|
324
|
+
"""
|
325
|
+
raise NotImplementedError
|
326
|
+
|
307
327
|
async def on_displayed(
|
308
328
|
self,
|
309
329
|
chat: RecipientType,
|
@@ -493,7 +513,7 @@ class BaseSession(
|
|
493
513
|
|
494
514
|
async def on_invitation(
|
495
515
|
self, contact: LegacyContact, muc: LegacyMUC, reason: Optional[str]
|
496
|
-
):
|
516
|
+
) -> None:
|
497
517
|
"""
|
498
518
|
Triggered when the user invites a :term:`Contact` to a legacy MUC via
|
499
519
|
:xep:`0249`.
|
@@ -519,7 +539,7 @@ class BaseSession(
|
|
519
539
|
"""
|
520
540
|
raise NotImplementedError
|
521
541
|
|
522
|
-
def __reset_ready(self):
|
542
|
+
def __reset_ready(self) -> None:
|
523
543
|
self.ready = self.xmpp.loop.create_future()
|
524
544
|
|
525
545
|
@property
|
@@ -527,7 +547,7 @@ class BaseSession(
|
|
527
547
|
return self._logged
|
528
548
|
|
529
549
|
@logged.setter
|
530
|
-
def logged(self, v: bool):
|
550
|
+
def logged(self, v: bool) -> None:
|
531
551
|
self.is_logging_in = False
|
532
552
|
self._logged = v
|
533
553
|
if self.ready.done():
|
@@ -539,19 +559,34 @@ class BaseSession(
|
|
539
559
|
if v:
|
540
560
|
self.ready.set_result(True)
|
541
561
|
|
542
|
-
def __repr__(self):
|
562
|
+
def __repr__(self) -> str:
|
543
563
|
return f"<Session of {self.user_jid}>"
|
544
564
|
|
545
|
-
def shutdown(self, logout=True) -> asyncio.Task:
|
565
|
+
def shutdown(self, logout: bool = True) -> asyncio.Task:
|
546
566
|
for m in self.bookmarks:
|
547
567
|
m.shutdown()
|
548
|
-
|
549
|
-
|
568
|
+
with self.xmpp.store.session() as orm:
|
569
|
+
for jid in orm.execute(
|
570
|
+
sa.select(Contact.jid).filter_by(user=self.user, is_friend=True)
|
571
|
+
).scalars():
|
572
|
+
pres = self.xmpp.make_presence(
|
573
|
+
pfrom=jid,
|
574
|
+
pto=self.user_jid,
|
575
|
+
ptype="unavailable",
|
576
|
+
pstatus="Gateway has shut down.",
|
577
|
+
)
|
578
|
+
pres.send()
|
550
579
|
if logout:
|
551
|
-
return self.xmpp.loop.create_task(self.
|
580
|
+
return self.xmpp.loop.create_task(self.__logout())
|
552
581
|
else:
|
553
582
|
return self.xmpp.loop.create_task(noop_coro())
|
554
583
|
|
584
|
+
async def __logout(self) -> None:
|
585
|
+
try:
|
586
|
+
await self.logout()
|
587
|
+
except NotImplementedError:
|
588
|
+
pass
|
589
|
+
|
555
590
|
@staticmethod
|
556
591
|
def legacy_to_xmpp_msg_id(legacy_msg_id: LegacyMessageType) -> str:
|
557
592
|
"""
|
@@ -604,7 +639,7 @@ class BaseSession(
|
|
604
639
|
@classmethod
|
605
640
|
def _from_user_or_none(cls, user):
|
606
641
|
if user is None:
|
607
|
-
log.debug("user not found"
|
642
|
+
log.debug("user not found")
|
608
643
|
raise XMPPError(text="User not found", condition="subscription-required")
|
609
644
|
|
610
645
|
session = _sessions.get(user.jid.bare)
|
@@ -641,11 +676,12 @@ class BaseSession(
|
|
641
676
|
session = _sessions.get(jid.bare)
|
642
677
|
if session is not None:
|
643
678
|
return session
|
644
|
-
|
679
|
+
with cls.xmpp.store.session() as orm:
|
680
|
+
user = orm.query(GatewayUser).filter_by(jid=jid.bare).one_or_none()
|
645
681
|
return cls._from_user_or_none(user)
|
646
682
|
|
647
683
|
@classmethod
|
648
|
-
async def kill_by_jid(cls, jid: JID):
|
684
|
+
async def kill_by_jid(cls, jid: JID) -> None:
|
649
685
|
# """
|
650
686
|
# Terminate a user session.
|
651
687
|
#
|
@@ -665,17 +701,19 @@ class BaseSession(
|
|
665
701
|
c.unsubscribe()
|
666
702
|
for m in session.bookmarks:
|
667
703
|
m.shutdown()
|
668
|
-
|
669
|
-
|
704
|
+
|
705
|
+
try:
|
706
|
+
session = _sessions.pop(jid.bare)
|
707
|
+
except KeyError:
|
670
708
|
log.warning("User not found during unregistration")
|
671
709
|
return
|
672
|
-
await cls.xmpp.unregister(user)
|
673
|
-
cls.xmpp.store.users.delete(user.jid)
|
674
|
-
del _sessions[user.jid.bare]
|
675
|
-
del user
|
676
|
-
del session
|
677
710
|
|
678
|
-
|
711
|
+
await cls.xmpp.unregister(session)
|
712
|
+
with cls.xmpp.store.session() as orm:
|
713
|
+
orm.delete(session.user)
|
714
|
+
orm.commit()
|
715
|
+
|
716
|
+
def __ack(self, msg: Message) -> None:
|
679
717
|
if not self.xmpp.PROPER_RECEIPTS:
|
680
718
|
self.xmpp.delivery_receipt.ack(msg)
|
681
719
|
|
@@ -684,7 +722,7 @@ class BaseSession(
|
|
684
722
|
status: Optional[str] = None,
|
685
723
|
show=Optional[PresenceShows],
|
686
724
|
**kwargs,
|
687
|
-
):
|
725
|
+
) -> None:
|
688
726
|
"""
|
689
727
|
Send a presence from the gateway to the user.
|
690
728
|
|
@@ -699,7 +737,7 @@ class BaseSession(
|
|
699
737
|
pto=self.user_jid.bare, pstatus=status, pshow=show, **kwargs
|
700
738
|
)
|
701
739
|
|
702
|
-
def send_cached_presence(self, to: JID):
|
740
|
+
def send_cached_presence(self, to: JID) -> None:
|
703
741
|
if not self.__cached_presence:
|
704
742
|
self.xmpp.send_presence(pto=to, ptype="unavailable")
|
705
743
|
return
|
@@ -710,7 +748,7 @@ class BaseSession(
|
|
710
748
|
**self.__cached_presence.kwargs,
|
711
749
|
)
|
712
750
|
|
713
|
-
def send_gateway_message(self, text: str, **msg_kwargs):
|
751
|
+
def send_gateway_message(self, text: str, **msg_kwargs) -> None:
|
714
752
|
"""
|
715
753
|
Send a message from the gateway component to the user.
|
716
754
|
|
@@ -725,7 +763,7 @@ class BaseSession(
|
|
725
763
|
muc: LegacyMUC,
|
726
764
|
reason: Optional[str] = None,
|
727
765
|
password: Optional[str] = None,
|
728
|
-
):
|
766
|
+
) -> None:
|
729
767
|
"""
|
730
768
|
Send an invitation to join a MUC, emanating from the gateway component.
|
731
769
|
|
@@ -747,7 +785,7 @@ class BaseSession(
|
|
747
785
|
"""
|
748
786
|
return await self.xmpp.input(self.user_jid, text, **msg_kwargs)
|
749
787
|
|
750
|
-
async def send_qr(self, text: str):
|
788
|
+
async def send_qr(self, text: str) -> None:
|
751
789
|
"""
|
752
790
|
Sends a QR code generated from 'text' via HTTP Upload and send the URL to
|
753
791
|
``self.user``
|
@@ -756,13 +794,13 @@ class BaseSession(
|
|
756
794
|
"""
|
757
795
|
await self.xmpp.send_qr(text, mto=self.user_jid)
|
758
796
|
|
759
|
-
def re_login(self):
|
797
|
+
def re_login(self) -> None:
|
760
798
|
# Logout then re-login
|
761
799
|
#
|
762
800
|
# No reason to override this
|
763
801
|
self.xmpp.re_login(self)
|
764
802
|
|
765
|
-
async def get_contact_or_group_or_participant(self, jid: JID, create=True):
|
803
|
+
async def get_contact_or_group_or_participant(self, jid: JID, create: bool = True):
|
766
804
|
if (contact := self.contacts.by_jid_only_if_exists(jid)) is not None:
|
767
805
|
return contact
|
768
806
|
if (muc := self.bookmarks.by_jid_only_if_exists(JID(jid.bare))) is not None:
|
@@ -813,23 +851,20 @@ class BaseSession(
|
|
813
851
|
"Legacy session is not fully initialized, retry later",
|
814
852
|
)
|
815
853
|
|
816
|
-
def legacy_module_data_update(self, data: dict):
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
user = self.user
|
831
|
-
user.legacy_module_data.clear()
|
832
|
-
self.xmpp.store.users.update(user)
|
854
|
+
def legacy_module_data_update(self, data: dict) -> None:
|
855
|
+
user = self.user
|
856
|
+
user.legacy_module_data.update(data)
|
857
|
+
self.xmpp.store.users.update(user)
|
858
|
+
|
859
|
+
def legacy_module_data_set(self, data: dict) -> None:
|
860
|
+
user = self.user
|
861
|
+
user.legacy_module_data = data
|
862
|
+
self.xmpp.store.users.update(user)
|
863
|
+
|
864
|
+
def legacy_module_data_clear(self) -> None:
|
865
|
+
user = self.user
|
866
|
+
user.legacy_module_data.clear()
|
867
|
+
self.xmpp.store.users.update(user)
|
833
868
|
|
834
869
|
|
835
870
|
# keys = user.jid.bare
|