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
slidge/group/archive.py
CHANGED
@@ -1,24 +1,22 @@
|
|
1
1
|
import logging
|
2
2
|
import uuid
|
3
3
|
from copy import copy
|
4
|
-
from datetime import datetime
|
4
|
+
from datetime import datetime, timezone
|
5
5
|
from typing import TYPE_CHECKING, Collection, Optional
|
6
6
|
|
7
7
|
from slixmpp import Iq, Message
|
8
8
|
|
9
|
+
from ..db.store import MAMStore
|
9
10
|
from ..util.archive_msg import HistoryMessage
|
10
|
-
from ..util.db import GatewayUser
|
11
|
-
from ..util.sql import db
|
12
11
|
|
13
12
|
if TYPE_CHECKING:
|
14
13
|
from .participant import LegacyParticipant
|
15
14
|
|
16
15
|
|
17
16
|
class MessageArchive:
|
18
|
-
def __init__(self,
|
19
|
-
self.
|
20
|
-
self.
|
21
|
-
db.mam_add_muc(db_id, user)
|
17
|
+
def __init__(self, room_pk: int, store: MAMStore):
|
18
|
+
self.room_pk = room_pk
|
19
|
+
self.__store = store
|
22
20
|
|
23
21
|
def add(
|
24
22
|
self,
|
@@ -40,7 +38,7 @@ class MessageArchive:
|
|
40
38
|
if participant.contact:
|
41
39
|
new_msg["muc"]["jid"] = participant.contact.jid.bare
|
42
40
|
elif participant.is_user:
|
43
|
-
new_msg["muc"]["jid"] = participant.
|
41
|
+
new_msg["muc"]["jid"] = participant.user_jid.bare
|
44
42
|
elif participant.is_system:
|
45
43
|
new_msg["muc"]["jid"] = participant.muc.jid
|
46
44
|
else:
|
@@ -49,7 +47,7 @@ class MessageArchive:
|
|
49
47
|
"jid"
|
50
48
|
] = f"{uuid.uuid4()}@{participant.xmpp.boundjid.bare}"
|
51
49
|
|
52
|
-
|
50
|
+
self.__store.add_message(self.room_pk, HistoryMessage(new_msg))
|
53
51
|
|
54
52
|
def __iter__(self):
|
55
53
|
return iter(self.get_all())
|
@@ -65,9 +63,8 @@ class MessageArchive:
|
|
65
63
|
sender: Optional[str] = None,
|
66
64
|
flip=False,
|
67
65
|
):
|
68
|
-
for msg in
|
69
|
-
self.
|
70
|
-
self.db_id,
|
66
|
+
for msg in self.__store.get_messages(
|
67
|
+
self.room_pk,
|
71
68
|
before_id=before_id,
|
72
69
|
after_id=after_id,
|
73
70
|
ids=ids,
|
@@ -87,11 +84,13 @@ class MessageArchive:
|
|
87
84
|
:return:
|
88
85
|
"""
|
89
86
|
reply = iq.reply()
|
90
|
-
messages =
|
87
|
+
messages = self.__store.get_first_and_last(self.room_pk)
|
91
88
|
if messages:
|
92
89
|
for x, m in [("start", messages[0]), ("end", messages[-1])]:
|
93
90
|
reply["mam_metadata"][x]["id"] = m.id
|
94
|
-
reply["mam_metadata"][x]["timestamp"] = m.sent_on
|
91
|
+
reply["mam_metadata"][x]["timestamp"] = m.sent_on.replace(
|
92
|
+
tzinfo=timezone.utc
|
93
|
+
)
|
95
94
|
else:
|
96
95
|
reply.enable("mam_metadata")
|
97
96
|
reply.send()
|
slidge/group/bookmarks.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import abc
|
2
2
|
import logging
|
3
|
-
from typing import TYPE_CHECKING, Generic, Type
|
3
|
+
from typing import TYPE_CHECKING, Generic, Iterator, Optional, Type
|
4
4
|
|
5
5
|
from slixmpp import JID
|
6
6
|
from slixmpp.jid import _unescape_node
|
@@ -9,6 +9,7 @@ from ..contact.roster import ESCAPE_TABLE
|
|
9
9
|
from ..core.mixins.lock import NamedLockMixin
|
10
10
|
from ..util import SubclassableOnce
|
11
11
|
from ..util.types import LegacyGroupIdType, LegacyMUCType
|
12
|
+
from .archive import MessageArchive
|
12
13
|
from .room import LegacyMUC
|
13
14
|
|
14
15
|
if TYPE_CHECKING:
|
@@ -27,17 +28,15 @@ class LegacyBookmarks(
|
|
27
28
|
def __init__(self, session: "BaseSession"):
|
28
29
|
self.session = session
|
29
30
|
self.xmpp = session.xmpp
|
30
|
-
self.
|
31
|
-
|
32
|
-
self._mucs_by_legacy_id = dict[LegacyGroupIdType, LegacyMUCType]()
|
33
|
-
self._mucs_by_bare_jid = dict[str, LegacyMUCType]()
|
31
|
+
self.user_jid = session.user_jid
|
32
|
+
self.__store = self.xmpp.store.rooms
|
34
33
|
|
35
34
|
self._muc_class: Type[LegacyMUCType] = LegacyMUC.get_self_or_unique_subclass()
|
36
35
|
|
37
|
-
self._user_nick: str = self.session.
|
36
|
+
self._user_nick: str = self.session.user_jid.node
|
38
37
|
|
39
38
|
super().__init__()
|
40
|
-
self.log = logging.getLogger(f"{self.
|
39
|
+
self.log = logging.getLogger(f"{self.user_jid.bare}:bookmarks")
|
41
40
|
self.ready = self.session.xmpp.loop.create_future()
|
42
41
|
if not self.xmpp.GROUPS:
|
43
42
|
self.ready.set_result(True)
|
@@ -50,20 +49,23 @@ class LegacyBookmarks(
|
|
50
49
|
def user_nick(self, nick: str):
|
51
50
|
self._user_nick = nick
|
52
51
|
|
53
|
-
def __iter__(self):
|
54
|
-
|
52
|
+
def __iter__(self) -> Iterator[LegacyMUCType]:
|
53
|
+
for stored in self.__store.get_all(user_pk=self.session.user_pk):
|
54
|
+
yield self._muc_class.from_store(self.session, stored)
|
55
55
|
|
56
56
|
def __repr__(self):
|
57
|
-
return f"<Bookmarks of {self.
|
57
|
+
return f"<Bookmarks of {self.user_jid}>"
|
58
58
|
|
59
59
|
async def __finish_init_muc(self, legacy_id: LegacyGroupIdType, jid: JID):
|
60
60
|
muc = self._muc_class(self.session, legacy_id=legacy_id, jid=jid)
|
61
|
-
|
62
|
-
|
63
|
-
muc.
|
64
|
-
|
65
|
-
|
66
|
-
|
61
|
+
with self.__store.session():
|
62
|
+
muc.pk = self.__store.add(self.session.user_pk, str(muc.legacy_id), muc.jid)
|
63
|
+
muc.archive = MessageArchive(muc.pk, self.xmpp.store.mam)
|
64
|
+
await muc.avatar_wrap_update_info()
|
65
|
+
if not muc.user_nick:
|
66
|
+
muc.user_nick = self._user_nick
|
67
|
+
self.log.debug("MUC created: %r", muc)
|
68
|
+
self.__store.update(muc)
|
67
69
|
return muc
|
68
70
|
|
69
71
|
async def legacy_id_to_jid_local_part(self, legacy_id: LegacyGroupIdType):
|
@@ -94,36 +96,50 @@ class LegacyBookmarks(
|
|
94
96
|
return _unescape_node(username)
|
95
97
|
|
96
98
|
async def by_jid(self, jid: JID) -> LegacyMUCType:
|
99
|
+
if jid.resource:
|
100
|
+
jid = JID(jid.bare)
|
97
101
|
bare = jid.bare
|
98
102
|
async with self.lock(("bare", bare)):
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
103
|
+
assert isinstance(jid.username, str)
|
104
|
+
legacy_id = await self.jid_local_part_to_legacy_id(jid.username)
|
105
|
+
if self.get_lock(("legacy_id", legacy_id)):
|
106
|
+
self.log.debug("Not instantiating %s after all", jid)
|
107
|
+
return await self.by_legacy_id(legacy_id)
|
108
|
+
|
109
|
+
with self.__store.session():
|
110
|
+
stored = self.__store.get_by_jid(self.session.user_pk, jid)
|
111
|
+
if stored is not None and stored.updated:
|
112
|
+
return self._muc_class.from_store(self.session, stored)
|
113
|
+
|
114
|
+
self.log.debug("Attempting to instantiate a new MUC for JID %s", jid)
|
115
|
+
local_part = jid.node
|
116
|
+
|
117
|
+
self.log.debug("%r is group %r", local_part, legacy_id)
|
118
|
+
return await self.__finish_init_muc(legacy_id, JID(bare))
|
119
|
+
|
120
|
+
def by_jid_only_if_exists(self, jid: JID) -> Optional[LegacyMUCType]:
|
121
|
+
with self.__store.session():
|
122
|
+
stored = self.__store.get_by_jid(self.session.user_pk, jid)
|
123
|
+
if stored is not None and stored.updated:
|
124
|
+
return self._muc_class.from_store(self.session, stored)
|
125
|
+
return None
|
112
126
|
|
113
127
|
async def by_legacy_id(self, legacy_id: LegacyGroupIdType) -> LegacyMUCType:
|
114
128
|
async with self.lock(("legacy_id", legacy_id)):
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
self.log.
|
129
|
+
with self.__store.session():
|
130
|
+
stored = self.__store.get_by_legacy_id(
|
131
|
+
self.session.user_pk, str(legacy_id)
|
132
|
+
)
|
133
|
+
if stored is not None and stored.updated:
|
134
|
+
return self._muc_class.from_store(self.session, stored)
|
135
|
+
self.log.debug("Create new MUC instance for legacy ID %s", legacy_id)
|
136
|
+
local = await self.legacy_id_to_jid_local_part(legacy_id)
|
137
|
+
bare = f"{local}@{self.xmpp.boundjid}"
|
138
|
+
jid = JID(bare)
|
139
|
+
if self.get_lock(("bare", bare)):
|
140
|
+
self.log.debug("Not instantiating %s after all", legacy_id)
|
141
|
+
return await self.by_jid(jid)
|
142
|
+
muc = await self.__finish_init_muc(legacy_id, jid)
|
127
143
|
|
128
144
|
return muc
|
129
145
|
|
@@ -146,18 +162,5 @@ class LegacyBookmarks(
|
|
146
162
|
)
|
147
163
|
|
148
164
|
def remove(self, muc: LegacyMUC):
|
149
|
-
|
150
|
-
|
151
|
-
except KeyError:
|
152
|
-
self.log.warning("Removed a MUC that we didn't store by legacy ID")
|
153
|
-
try:
|
154
|
-
del self._mucs_by_bare_jid[muc.jid.bare]
|
155
|
-
except KeyError:
|
156
|
-
self.log.warning("Removed a MUC that we didn't store by JID")
|
157
|
-
for part in muc._participants_by_contacts.values():
|
158
|
-
try:
|
159
|
-
part.contact.participants.remove(part)
|
160
|
-
except KeyError:
|
161
|
-
part.log.warning(
|
162
|
-
"That participant wasn't stored in the contact's participants attribute"
|
163
|
-
)
|
165
|
+
assert muc.pk is not None
|
166
|
+
self.__store.delete(muc.pk)
|
slidge/group/participant.py
CHANGED
@@ -6,7 +6,7 @@ import warnings
|
|
6
6
|
from copy import copy
|
7
7
|
from datetime import datetime
|
8
8
|
from functools import cached_property
|
9
|
-
from typing import TYPE_CHECKING, Optional, Union
|
9
|
+
from typing import TYPE_CHECKING, Optional, Self, Union
|
10
10
|
|
11
11
|
from slixmpp import JID, InvalidJID, Message, Presence
|
12
12
|
from slixmpp.plugins.xep_0045.stanza import MUCAdminItem
|
@@ -15,10 +15,16 @@ from slixmpp.types import MessageTypes, OptJid
|
|
15
15
|
from slixmpp.util.stringprep_profiles import StringPrepError, prohibit_output
|
16
16
|
|
17
17
|
from ..contact import LegacyContact
|
18
|
-
from ..core.mixins import
|
18
|
+
from ..core.mixins import (
|
19
|
+
ChatterDiscoMixin,
|
20
|
+
MessageMixin,
|
21
|
+
PresenceMixin,
|
22
|
+
StoredAttributeMixin,
|
23
|
+
)
|
24
|
+
from ..db.models import Participant
|
19
25
|
from ..util import SubclassableOnce, strip_illegal_chars
|
20
|
-
from ..util.sql import CachedPresence
|
21
26
|
from ..util.types import (
|
27
|
+
CachedPresence,
|
22
28
|
Hat,
|
23
29
|
LegacyMessageType,
|
24
30
|
MessageOrPresenceTypeVar,
|
@@ -40,6 +46,7 @@ def strip_non_printable(nickname: str):
|
|
40
46
|
|
41
47
|
|
42
48
|
class LegacyParticipant(
|
49
|
+
StoredAttributeMixin,
|
43
50
|
PresenceMixin,
|
44
51
|
MessageMixin,
|
45
52
|
ChatterDiscoMixin,
|
@@ -53,6 +60,7 @@ class LegacyParticipant(
|
|
53
60
|
_can_send_carbon = False
|
54
61
|
USE_STANZA_ID = True
|
55
62
|
STRIP_SHORT_DELAY = False
|
63
|
+
pk: int
|
56
64
|
|
57
65
|
def __init__(
|
58
66
|
self,
|
@@ -63,12 +71,11 @@ class LegacyParticipant(
|
|
63
71
|
role: MucRole = "participant",
|
64
72
|
affiliation: MucAffiliation = "member",
|
65
73
|
):
|
74
|
+
self.session = session = muc.session
|
75
|
+
self.xmpp = session.xmpp
|
66
76
|
super().__init__()
|
67
77
|
self._hats = list[Hat]()
|
68
78
|
self.muc = muc
|
69
|
-
self.session = session = muc.session
|
70
|
-
self.user = session.user
|
71
|
-
self.xmpp = session.xmpp
|
72
79
|
self._role = role
|
73
80
|
self._affiliation = affiliation
|
74
81
|
self.is_user: bool = is_user
|
@@ -84,8 +91,19 @@ class LegacyParticipant(
|
|
84
91
|
# if we didn't, we send it before the first message.
|
85
92
|
# this way, event in plugins that don't map "user has joined" events,
|
86
93
|
# we send a "join"-presence from the participant before the first message
|
87
|
-
self.
|
88
|
-
self.log = logging.getLogger(f"{self.
|
94
|
+
self._presence_sent: bool = False
|
95
|
+
self.log = logging.getLogger(f"{self.user_jid.bare}:{self.jid}")
|
96
|
+
self.__part_store = self.xmpp.store.participants
|
97
|
+
|
98
|
+
@property
|
99
|
+
def contact_pk(self) -> Optional[int]: # type:ignore
|
100
|
+
if self.contact:
|
101
|
+
return self.contact.contact_pk
|
102
|
+
return None
|
103
|
+
|
104
|
+
@property
|
105
|
+
def user_jid(self):
|
106
|
+
return self.session.user_jid
|
89
107
|
|
90
108
|
def __repr__(self):
|
91
109
|
return f"<Participant '{self.nickname}'/'{self.jid}' of '{self.muc}'>"
|
@@ -99,7 +117,8 @@ class LegacyParticipant(
|
|
99
117
|
if self._affiliation == affiliation:
|
100
118
|
return
|
101
119
|
self._affiliation = affiliation
|
102
|
-
|
120
|
+
self.__part_store.set_affiliation(self.pk, affiliation)
|
121
|
+
if not self._presence_sent:
|
103
122
|
return
|
104
123
|
self.send_last_presence(force=True, no_cache_online=True)
|
105
124
|
|
@@ -126,7 +145,8 @@ class LegacyParticipant(
|
|
126
145
|
if self._role == role:
|
127
146
|
return
|
128
147
|
self._role = role
|
129
|
-
|
148
|
+
self.__part_store.set_role(self.pk, role)
|
149
|
+
if not self._presence_sent:
|
130
150
|
return
|
131
151
|
self.send_last_presence(force=True, no_cache_online=True)
|
132
152
|
|
@@ -134,7 +154,8 @@ class LegacyParticipant(
|
|
134
154
|
if self._hats == hats:
|
135
155
|
return
|
136
156
|
self._hats = hats
|
137
|
-
|
157
|
+
self.__part_store.set_hats(self.pk, hats)
|
158
|
+
if not self._presence_sent:
|
138
159
|
return
|
139
160
|
self.send_last_presence(force=True, no_cache_online=True)
|
140
161
|
|
@@ -143,6 +164,7 @@ class LegacyParticipant(
|
|
143
164
|
|
144
165
|
if self.is_system:
|
145
166
|
self.jid = j
|
167
|
+
self._nickname_no_illegal = ""
|
146
168
|
return
|
147
169
|
|
148
170
|
nickname = unescaped_nickname
|
@@ -170,9 +192,6 @@ class LegacyParticipant(
|
|
170
192
|
except InvalidJID:
|
171
193
|
j.resource = strip_non_printable(nickname)
|
172
194
|
|
173
|
-
if nickname != unescaped_nickname:
|
174
|
-
self.muc._participants_by_escaped_nicknames[nickname] = self # type:ignore
|
175
|
-
|
176
195
|
self.jid = j
|
177
196
|
|
178
197
|
def send_configuration_change(self, codes: tuple[int]):
|
@@ -213,12 +232,8 @@ class LegacyParticipant(
|
|
213
232
|
|
214
233
|
kwargs["status_codes"] = set()
|
215
234
|
p = self._make_presence(ptype="available", last_seen=last_seen, **kwargs)
|
216
|
-
self.__add_nick_element(p)
|
217
235
|
self._send(p)
|
218
236
|
|
219
|
-
if old:
|
220
|
-
self.muc.rename_participant(old, new_nickname)
|
221
|
-
|
222
237
|
def _make_presence(
|
223
238
|
self,
|
224
239
|
*,
|
@@ -240,14 +255,14 @@ class LegacyParticipant(
|
|
240
255
|
if user_full_jid:
|
241
256
|
p["muc"]["jid"] = user_full_jid
|
242
257
|
else:
|
243
|
-
jid = copy(self.
|
258
|
+
jid = copy(self.user_jid)
|
244
259
|
try:
|
245
260
|
jid.resource = next(
|
246
|
-
iter(self.muc.
|
261
|
+
iter(self.muc.get_user_resources()) # type:ignore
|
247
262
|
)
|
248
263
|
except StopIteration:
|
249
264
|
jid.resource = "pseudo-resource"
|
250
|
-
p["muc"]["jid"] = self.
|
265
|
+
p["muc"]["jid"] = self.user_jid
|
251
266
|
codes.add(100)
|
252
267
|
elif self.contact:
|
253
268
|
p["muc"]["jid"] = self.contact.jid
|
@@ -257,7 +272,7 @@ class LegacyParticipant(
|
|
257
272
|
warnings.warn(
|
258
273
|
f"Private group but no 1:1 JID associated to '{self}'",
|
259
274
|
)
|
260
|
-
if self.is_user and (hash_ := self.session.avatar_hash):
|
275
|
+
if self.is_user and (hash_ := self.session.user.avatar_hash):
|
261
276
|
p["vcard_temp_update"]["photo"] = hash_
|
262
277
|
p["muc"]["status_codes"] = codes
|
263
278
|
return p
|
@@ -273,7 +288,7 @@ class LegacyParticipant(
|
|
273
288
|
archive_only
|
274
289
|
or self.is_system
|
275
290
|
or self.is_user
|
276
|
-
or self.
|
291
|
+
or self._presence_sent
|
277
292
|
or stanza["subject"]
|
278
293
|
):
|
279
294
|
return
|
@@ -301,10 +316,12 @@ class LegacyParticipant(
|
|
301
316
|
**send_kwargs,
|
302
317
|
) -> MessageOrPresenceTypeVar:
|
303
318
|
stanza["occupant-id"]["id"] = self.__occupant_id
|
319
|
+
self.__add_nick_element(stanza)
|
304
320
|
if isinstance(stanza, Presence):
|
305
|
-
if stanza["type"] == "unavailable" and not self.
|
321
|
+
if stanza["type"] == "unavailable" and not self._presence_sent:
|
306
322
|
return stanza # type:ignore
|
307
|
-
self.
|
323
|
+
self._presence_sent = True
|
324
|
+
self.__part_store.set_presence_sent(self.pk)
|
308
325
|
if full_jid:
|
309
326
|
stanza["to"] = full_jid
|
310
327
|
self.__send_presence_if_needed(stanza, full_jid, archive_only)
|
@@ -332,7 +349,7 @@ class LegacyParticipant(
|
|
332
349
|
item["role"] = self.role
|
333
350
|
if not self.muc.is_anonymous:
|
334
351
|
if self.is_user:
|
335
|
-
item["jid"] = self.
|
352
|
+
item["jid"] = self.user_jid.bare
|
336
353
|
elif self.contact:
|
337
354
|
item["jid"] = self.contact.jid.bare
|
338
355
|
else:
|
@@ -344,11 +361,11 @@ class LegacyParticipant(
|
|
344
361
|
)
|
345
362
|
return item
|
346
363
|
|
347
|
-
def __add_nick_element(self,
|
364
|
+
def __add_nick_element(self, stanza: Union[Presence, Message]):
|
348
365
|
if (nick := self._nickname_no_illegal) != self.jid.resource:
|
349
366
|
n = self.xmpp.plugin["xep_0172"].stanza.UserNick()
|
350
367
|
n["nick"] = nick
|
351
|
-
|
368
|
+
stanza.append(n)
|
352
369
|
|
353
370
|
def _get_last_presence(self) -> Optional[CachedPresence]:
|
354
371
|
own = super()._get_last_presence()
|
@@ -400,7 +417,6 @@ class LegacyParticipant(
|
|
400
417
|
)
|
401
418
|
if presence_id:
|
402
419
|
p["id"] = presence_id
|
403
|
-
self.__add_nick_element(p)
|
404
420
|
self._send(p, full_jid)
|
405
421
|
|
406
422
|
def leave(self):
|
@@ -454,5 +470,41 @@ class LegacyParticipant(
|
|
454
470
|
msg["subject"] = subject or str(self.muc.name)
|
455
471
|
self._send(msg, full_jid)
|
456
472
|
|
473
|
+
@classmethod
|
474
|
+
def from_store(
|
475
|
+
cls,
|
476
|
+
session,
|
477
|
+
stored: Participant,
|
478
|
+
contact: Optional[LegacyContact] = None,
|
479
|
+
muc: Optional["LegacyMUC"] = None,
|
480
|
+
) -> Self:
|
481
|
+
from slidge.group.room import LegacyMUC
|
482
|
+
|
483
|
+
if muc is None:
|
484
|
+
muc = LegacyMUC.get_self_or_unique_subclass().from_store(
|
485
|
+
session, stored.room
|
486
|
+
)
|
487
|
+
part = cls(
|
488
|
+
muc,
|
489
|
+
stored.nickname,
|
490
|
+
role=stored.role,
|
491
|
+
affiliation=stored.affiliation,
|
492
|
+
)
|
493
|
+
part.pk = stored.id
|
494
|
+
if contact is not None:
|
495
|
+
part.contact = contact
|
496
|
+
elif stored.contact is not None:
|
497
|
+
contact = LegacyContact.get_self_or_unique_subclass().from_store(
|
498
|
+
session, stored.contact
|
499
|
+
)
|
500
|
+
part.contact = contact
|
501
|
+
|
502
|
+
part.is_user = stored.is_user
|
503
|
+
if (data := stored.extra_attributes) is not None:
|
504
|
+
muc.deserialize_extra_attributes(data)
|
505
|
+
part._presence_sent = stored.presence_sent
|
506
|
+
part._hats = [Hat(h.uri, h.title) for h in stored.hats]
|
507
|
+
return part
|
508
|
+
|
457
509
|
|
458
510
|
log = logging.getLogger(__name__)
|