slidge 0.1.2__py3-none-any.whl → 0.2.0a0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- slidge/__init__.py +3 -5
- slidge/__main__.py +2 -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__)
|