slidge 0.2.0a3__py3-none-any.whl → 0.2.0a4__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
slidge/__version__.py CHANGED
@@ -2,4 +2,4 @@ from slidge.util.util import get_version # noqa: F401
2
2
 
3
3
  # this is modified before publish, but if someone cloned from the repo,
4
4
  # it can help
5
- __version__ = "0.2.0alpha3"
5
+ __version__ = "0.2.0alpha4"
slidge/command/admin.py CHANGED
@@ -1,5 +1,6 @@
1
1
  # Commands only accessible for slidge admins
2
2
  import functools
3
+ import importlib
3
4
  import logging
4
5
  from datetime import datetime
5
6
  from typing import Any, Optional
@@ -7,6 +8,7 @@ from typing import Any, Optional
7
8
  from slixmpp import JID
8
9
  from slixmpp.exceptions import XMPPError
9
10
 
11
+ from ..core import config
10
12
  from ..util.types import AnyBaseSession
11
13
  from .base import (
12
14
  Command,
@@ -90,8 +92,12 @@ class SlidgeInfo(AdminCommand):
90
92
  [a for a in (days_ago, hours_ago, minutes_ago, seconds_ago) if a]
91
93
  )
92
94
 
95
+ legacy_module = importlib.import_module(config.LEGACY_MODULE)
96
+ version = getattr(legacy_module, "__version__", "No version")
97
+
93
98
  return (
94
- f"{self.xmpp.COMPONENT_NAME} version {__version__}\n"
99
+ f"{self.xmpp.COMPONENT_NAME} (slidge core {__version__},"
100
+ f" {config.LEGACY_MODULE} {version})\n"
95
101
  f"Up since {start:%Y-%m-%d %H:%M} ({ago} ago)"
96
102
  )
97
103
 
slidge/contact/contact.py CHANGED
@@ -129,8 +129,8 @@ class LegacyContact(
129
129
  self._vcard_fetched = False
130
130
  self._vcard: str | None = None
131
131
 
132
- async def get_vcard(self) -> VCard4 | None:
133
- if not self._vcard_fetched:
132
+ async def get_vcard(self, fetch=True) -> VCard4 | None:
133
+ if fetch and not self._vcard_fetched:
134
134
  await self.fetch_vcard()
135
135
  if self._vcard is None:
136
136
  return None
slidge/contact/roster.py CHANGED
@@ -8,6 +8,7 @@ from slixmpp.exceptions import IqError, XMPPError
8
8
  from slixmpp.jid import JID_UNESCAPE_TRANSFORMATIONS, _unescape_node
9
9
 
10
10
  from ..core.mixins.lock import NamedLockMixin
11
+ from ..db.models import Contact
11
12
  from ..db.store import ContactStore
12
13
  from ..util import SubclassableOnce
13
14
  from ..util.types import LegacyContactType, LegacyUserIdType
@@ -63,37 +64,6 @@ class LegacyRoster(
63
64
  for stored in self.__store.get_all(user_pk=self.session.user_pk):
64
65
  yield self._contact_cls.from_store(self.session, stored)
65
66
 
66
- async def __finish_init_contact(
67
- self, legacy_id: LegacyUserIdType, jid_username: str, *args, **kwargs
68
- ):
69
- async with self.lock(("finish", legacy_id)):
70
- with self.__store.session():
71
- stored = self.__store.get_by_legacy_id(
72
- self.session.user_pk, str(legacy_id)
73
- )
74
- if stored is not None:
75
- if stored.updated:
76
- return self._contact_cls.from_store(self.session, stored)
77
- c: LegacyContact = self._contact_cls(
78
- self.session, legacy_id, jid_username, *args, **kwargs
79
- )
80
- c.contact_pk = stored.id
81
- else:
82
- c = self._contact_cls(
83
- self.session, legacy_id, jid_username, *args, **kwargs
84
- )
85
- try:
86
- with c.updating_info():
87
- await c.avatar_wrap_update_info()
88
- except Exception as e:
89
- raise XMPPError("internal-server-error", str(e))
90
- c._caps_ver = await c.get_caps_ver(c.jid)
91
- need_avatar = c.contact_pk is None
92
- c.contact_pk = self.__store.update(c, commit=not self.__filling)
93
- if need_avatar:
94
- c._post_avatar_update()
95
- return c
96
-
97
67
  def known_contacts(self, only_friends=True) -> dict[str, LegacyContactType]:
98
68
  if only_friends:
99
69
  return {c.jid.bare: c for c in self if c.is_friend}
@@ -112,17 +82,15 @@ class LegacyRoster(
112
82
  # """
113
83
  username = contact_jid.node
114
84
  async with self.lock(("username", username)):
115
- with self.__store.session():
116
- stored = self.__store.get_by_jid(self.session.user_pk, contact_jid)
117
- if stored is not None and stored.updated:
118
- return self._contact_cls.from_store(self.session, stored)
119
-
120
85
  legacy_id = await self.jid_username_to_legacy_id(username)
121
86
  log.debug("Contact %s not found", contact_jid)
122
87
  if self.get_lock(("legacy_id", legacy_id)):
123
88
  log.debug("Already updating %s", contact_jid)
124
89
  return await self.by_legacy_id(legacy_id)
125
- return await self.__finish_init_contact(legacy_id, username)
90
+
91
+ with self.__store.session():
92
+ stored = self.__store.get_by_jid(self.session.user_pk, contact_jid)
93
+ return await self.__update_contact(stored, legacy_id, username)
126
94
 
127
95
  async def by_legacy_id(
128
96
  self, legacy_id: LegacyUserIdType, *args, **kwargs
@@ -145,26 +113,48 @@ class LegacyRoster(
145
113
  if legacy_id == self.user_legacy_id:
146
114
  raise ContactIsUser
147
115
  async with self.lock(("legacy_id", legacy_id)):
148
- with self.__store.session():
149
- stored = self.__store.get_by_legacy_id(
150
- self.session.user_pk, str(legacy_id)
151
- )
152
- if stored is not None and stored.updated:
153
- return self._contact_cls.from_store(
154
- self.session, stored, *args, **kwargs
155
- )
156
-
157
116
  username = await self.legacy_id_to_jid_username(legacy_id)
158
- log.debug("Contact %s not found", legacy_id)
159
117
  if self.get_lock(("username", username)):
160
118
  log.debug("Already updating %s", username)
161
119
  jid = JID()
162
120
  jid.node = username
163
121
  jid.domain = self.session.xmpp.boundjid.bare
164
122
  return await self.by_jid(jid)
165
- return await self.__finish_init_contact(
166
- legacy_id, username, *args, **kwargs
167
- )
123
+
124
+ with self.__store.session():
125
+ stored = self.__store.get_by_legacy_id(
126
+ self.session.user_pk, str(legacy_id)
127
+ )
128
+ return await self.__update_contact(
129
+ stored, legacy_id, username, *args, **kwargs
130
+ )
131
+
132
+ async def __update_contact(
133
+ self,
134
+ stored: Contact | None,
135
+ legacy_id: LegacyUserIdType,
136
+ username: str,
137
+ *a,
138
+ **kw,
139
+ ) -> LegacyContactType:
140
+ if stored is None:
141
+ contact = self._contact_cls(self.session, legacy_id, username, *a, **kw)
142
+ else:
143
+ contact = self._contact_cls.from_store(self.session, stored, *a, **kw)
144
+ if stored.updated:
145
+ return contact
146
+
147
+ try:
148
+ with contact.updating_info():
149
+ await contact.avatar_wrap_update_info()
150
+ except Exception as e:
151
+ raise XMPPError("internal-server-error", str(e))
152
+ contact._caps_ver = await contact.get_caps_ver(contact.jid)
153
+ need_avatar = contact.contact_pk is None
154
+ contact.contact_pk = self.__store.update(contact, commit=not self.__filling)
155
+ if need_avatar:
156
+ contact._post_avatar_update()
157
+ return contact
168
158
 
169
159
  async def by_stanza(self, s) -> LegacyContact:
170
160
  # """
@@ -225,7 +215,7 @@ class LegacyRoster(
225
215
  item = contact.get_roster_item()
226
216
  old = user_roster.get(contact.jid.bare)
227
217
  if old is not None and all(
228
- old[k] == item[contact.jid.bare][k]
218
+ old[k] == item[contact.jid.bare].get(k)
229
219
  for k in ("subscription", "groups", "name")
230
220
  ):
231
221
  self.log.debug("No need to update roster")
@@ -315,7 +315,7 @@ class BaseGateway(
315
315
 
316
316
  from ...group.room import LegacyMUC
317
317
 
318
- LegacyMUC.get_unique_subclass().xmpp = self
318
+ LegacyMUC.get_self_or_unique_subclass().xmpp = self
319
319
 
320
320
  self.get_session_from_stanza: Callable[
321
321
  [Union[Message, Presence, Iq]], BaseSession
@@ -86,7 +86,7 @@ class VCardTemp:
86
86
  avatar = entity.get_avatar()
87
87
  type_ = "image/png"
88
88
  if isinstance(entity, LegacyContact):
89
- vcard = await entity.get_vcard()
89
+ vcard = await entity.get_vcard(fetch=False)
90
90
  else:
91
91
  vcard = None
92
92
  v = self.xmpp.plugin["xep_0054"].make_vcard()
slidge/core/pubsub.py CHANGED
@@ -22,6 +22,7 @@ from slixmpp.types import JidStr, OptJidStr
22
22
 
23
23
  from ..db.avatar import CachedAvatar, avatar_cache
24
24
  from ..db.store import ContactStore, SlidgeStore
25
+ from ..util.types import URL
25
26
  from .mixins.lock import NamedLockMixin
26
27
 
27
28
  if TYPE_CHECKING:
@@ -171,14 +172,13 @@ class PubSubComponent(NamedLockMixin, BasePlugin):
171
172
  except XMPPError:
172
173
  pass
173
174
  else:
174
- if pep_avatar.metadata is None:
175
- raise XMPPError("internal-server-error", "Avatar but no metadata?")
176
- await self.__broadcast(
177
- data=pep_avatar.metadata,
178
- from_=p.get_to(),
179
- to=from_,
180
- id=pep_avatar.metadata["info"]["id"],
181
- )
175
+ if pep_avatar.metadata is not None:
176
+ await self.__broadcast(
177
+ data=pep_avatar.metadata,
178
+ from_=p.get_to(),
179
+ to=from_,
180
+ id=pep_avatar.metadata["info"]["id"],
181
+ )
182
182
  if UserNick.namespace + "+notify" in features:
183
183
  try:
184
184
  pep_nick = await self._get_authorized_nick(p)
@@ -222,7 +222,9 @@ class PubSubComponent(NamedLockMixin, BasePlugin):
222
222
  item = PepAvatar()
223
223
  avatar_id = entity.avatar_id
224
224
  if avatar_id is not None:
225
- stored = avatar_cache.get(str(avatar_id))
225
+ stored = avatar_cache.get(
226
+ avatar_id if isinstance(avatar_id, URL) else str(avatar_id)
227
+ )
226
228
  assert stored is not None
227
229
  item.set_avatar_from_cache(stored)
228
230
  return item
slidge/db/avatar.py CHANGED
@@ -206,6 +206,11 @@ class AvatarCache:
206
206
  stored = orm.execute(select(Avatar).where(Avatar.hash == hash_)).scalar()
207
207
 
208
208
  if stored is not None:
209
+ if unique_id is not None:
210
+ log.warning("Updating 'unique' IDs of a known avatar.")
211
+ stored.legacy_id = str(unique_id)
212
+ orm.add(stored)
213
+ orm.commit()
209
214
  return CachedAvatar.from_store(stored, self.dir)
210
215
 
211
216
  stored = Avatar(
slidge/db/store.py CHANGED
@@ -162,12 +162,20 @@ class AvatarStore(EngineMixin):
162
162
  class SentStore(EngineMixin):
163
163
  def set_message(self, user_pk: int, legacy_id: str, xmpp_id: str) -> None:
164
164
  with self.session() as session:
165
- msg = XmppToLegacyIds(
166
- user_account_id=user_pk,
167
- legacy_id=legacy_id,
168
- xmpp_id=xmpp_id,
169
- type=XmppToLegacyEnum.DM,
165
+ msg = (
166
+ session.query(XmppToLegacyIds)
167
+ .filter(XmppToLegacyIds.user_account_id == user_pk)
168
+ .filter(XmppToLegacyIds.legacy_id == legacy_id)
169
+ .filter(XmppToLegacyIds.xmpp_id == xmpp_id)
170
+ .scalar()
170
171
  )
172
+ if msg is None:
173
+ msg = XmppToLegacyIds(user_account_id=user_pk)
174
+ else:
175
+ log.debug("Resetting a DM from sent store")
176
+ msg.legacy_id = legacy_id
177
+ msg.xmpp_id = xmpp_id
178
+ msg.type = XmppToLegacyEnum.DM
171
179
  session.add(msg)
172
180
  session.commit()
173
181
 
@@ -625,6 +633,7 @@ class MAMStore(EngineMixin):
625
633
  with self.session() as session:
626
634
  after_timestamp = (
627
635
  session.query(ArchivedMessage.timestamp)
636
+ .filter(ArchivedMessage.room_id == room_pk)
628
637
  .filter(ArchivedMessage.legacy_id == after_id)
629
638
  .scalar()
630
639
  )
@@ -778,7 +787,10 @@ class RoomStore(UpdatedMixin):
778
787
  with self.session() as session:
779
788
  session.execute(
780
789
  update(Room).values(
781
- subject_setter=None, user_resources=None, history_filled=False
790
+ subject_setter=None,
791
+ user_resources=None,
792
+ history_filled=False,
793
+ participants_filled=False,
782
794
  )
783
795
  )
784
796
  session.commit()
@@ -890,6 +902,13 @@ class RoomStore(UpdatedMixin):
890
902
  )
891
903
  session.commit()
892
904
 
905
+ def update_user_nick(self, room_pk, nick: str) -> None:
906
+ with self.session() as session:
907
+ session.execute(
908
+ update(Room).where(Room.id == room_pk).values(user_nick=nick)
909
+ )
910
+ session.commit()
911
+
893
912
  def delete(self, room_pk: int) -> None:
894
913
  with self.session() as session:
895
914
  session.execute(delete(Room).where(Room.id == room_pk))
slidge/group/bookmarks.py CHANGED
@@ -8,6 +8,7 @@ from slixmpp.jid import _unescape_node
8
8
 
9
9
  from ..contact.roster import ESCAPE_TABLE
10
10
  from ..core.mixins.lock import NamedLockMixin
11
+ from ..db.models import Room
11
12
  from ..util import SubclassableOnce
12
13
  from ..util.types import LegacyGroupIdType, LegacyMUCType
13
14
  from .archive import MessageArchive
@@ -57,29 +58,6 @@ class LegacyBookmarks(
57
58
  def __repr__(self):
58
59
  return f"<Bookmarks of {self.user_jid}>"
59
60
 
60
- async def __finish_init_muc(self, legacy_id: LegacyGroupIdType, jid: JID):
61
- with self.__store.session():
62
- stored = self.__store.get_by_legacy_id(self.session.user_pk, str(legacy_id))
63
- if stored is not None:
64
- if stored.updated:
65
- return self._muc_class.from_store(self.session, stored)
66
- muc = self._muc_class(self.session, legacy_id=legacy_id, jid=jid)
67
- muc.pk = stored.id
68
- else:
69
- muc = self._muc_class(self.session, legacy_id=legacy_id, jid=jid)
70
-
71
- try:
72
- with muc.updating_info():
73
- await muc.avatar_wrap_update_info()
74
- except Exception as e:
75
- raise XMPPError("internal-server-error", str(e))
76
- if not muc.user_nick:
77
- muc.user_nick = self._user_nick
78
- self.log.debug("MUC created: %r", muc)
79
- muc.pk = self.__store.update(muc)
80
- muc.archive = MessageArchive(muc.pk, self.xmpp.store.mam)
81
- return muc
82
-
83
61
  async def legacy_id_to_jid_local_part(self, legacy_id: LegacyGroupIdType):
84
62
  return await self.legacy_id_to_jid_username(legacy_id)
85
63
 
@@ -110,24 +88,16 @@ class LegacyBookmarks(
110
88
  async def by_jid(self, jid: JID) -> LegacyMUCType:
111
89
  if jid.resource:
112
90
  jid = JID(jid.bare)
113
- bare = jid.bare
114
- async with self.lock(("bare", bare)):
115
- assert isinstance(jid.username, str)
116
- legacy_id = await self.jid_local_part_to_legacy_id(jid.username)
91
+ async with self.lock(("bare", jid.bare)):
92
+ assert isinstance(jid.local, str)
93
+ legacy_id = await self.jid_local_part_to_legacy_id(jid.local)
117
94
  if self.get_lock(("legacy_id", legacy_id)):
118
95
  self.log.debug("Not instantiating %s after all", jid)
119
96
  return await self.by_legacy_id(legacy_id)
120
97
 
121
98
  with self.__store.session():
122
99
  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
-
126
- self.log.debug("Attempting to instantiate a new MUC for JID %s", jid)
127
- local_part = jid.node
128
-
129
- self.log.debug("%r is group %r", local_part, legacy_id)
130
- return await self.__finish_init_muc(legacy_id, JID(bare))
100
+ return await self.__update_muc(stored, legacy_id, jid)
131
101
 
132
102
  def by_jid_only_if_exists(self, jid: JID) -> Optional[LegacyMUCType]:
133
103
  with self.__store.session():
@@ -138,22 +108,39 @@ class LegacyBookmarks(
138
108
 
139
109
  async def by_legacy_id(self, legacy_id: LegacyGroupIdType) -> LegacyMUCType:
140
110
  async with self.lock(("legacy_id", legacy_id)):
141
- with self.__store.session():
142
- stored = self.__store.get_by_legacy_id(
143
- self.session.user_pk, str(legacy_id)
144
- )
145
- if stored is not None and stored.updated:
146
- return self._muc_class.from_store(self.session, stored)
147
- self.log.debug("Create new MUC instance for legacy ID %s", legacy_id)
148
111
  local = await self.legacy_id_to_jid_local_part(legacy_id)
149
- bare = f"{local}@{self.xmpp.boundjid}"
150
- jid = JID(bare)
151
- if self.get_lock(("bare", bare)):
112
+ jid = JID(f"{local}@{self.xmpp.boundjid}")
113
+ if self.get_lock(("bare", jid.bare)):
152
114
  self.log.debug("Not instantiating %s after all", legacy_id)
153
115
  return await self.by_jid(jid)
154
- muc = await self.__finish_init_muc(legacy_id, jid)
155
116
 
156
- return muc
117
+ with self.__store.session():
118
+ stored = self.__store.get_by_legacy_id(
119
+ self.session.user_pk, str(legacy_id)
120
+ )
121
+ return await self.__update_muc(stored, legacy_id, jid)
122
+
123
+ async def __update_muc(
124
+ self, stored: Room | None, legacy_id: LegacyGroupIdType, jid: JID
125
+ ):
126
+ if stored is None:
127
+ muc = self._muc_class(self.session, legacy_id=legacy_id, jid=jid)
128
+ else:
129
+ muc = self._muc_class.from_store(self.session, stored)
130
+ if stored.updated:
131
+ return muc
132
+
133
+ try:
134
+ with muc.updating_info():
135
+ await muc.avatar_wrap_update_info()
136
+ except Exception as e:
137
+ raise XMPPError("internal-server-error", str(e))
138
+ if not muc.user_nick:
139
+ muc.user_nick = self._user_nick
140
+ self.log.debug("MUC created: %r", muc)
141
+ muc.pk = self.__store.update(muc)
142
+ muc.archive = MessageArchive(muc.pk, self.xmpp.store.mam)
143
+ return muc
157
144
 
158
145
  @abc.abstractmethod
159
146
  async def fill(self):
@@ -450,13 +450,21 @@ class LegacyParticipant(
450
450
  return super().get_disco_info()
451
451
 
452
452
  def moderate(self, legacy_msg_id: LegacyMessageType, reason: Optional[str] = None):
453
- m = self.muc.get_system_participant()._make_message()
454
- m["apply_to"]["id"] = self._legacy_to_xmpp(legacy_msg_id)
455
- m["apply_to"]["moderated"].enable("retract")
456
- m["apply_to"]["moderated"]["by"] = self.jid
457
- if reason:
458
- m["apply_to"]["moderated"]["reason"] = reason
459
- self._send(m)
453
+ xmpp_id = self._legacy_to_xmpp(legacy_msg_id)
454
+ multi = self.xmpp.store.multi.get_xmpp_ids(self.session.user_pk, xmpp_id)
455
+ if multi is None:
456
+ msg_ids = [xmpp_id]
457
+ else:
458
+ msg_ids = multi + [xmpp_id]
459
+
460
+ for i in msg_ids:
461
+ m = self.muc.get_system_participant()._make_message()
462
+ m["apply_to"]["id"] = i
463
+ m["apply_to"]["moderated"].enable("retract")
464
+ m["apply_to"]["moderated"]["by"] = self.jid
465
+ if reason:
466
+ m["apply_to"]["moderated"]["reason"] = reason
467
+ self._send(m)
460
468
 
461
469
  def set_room_subject(
462
470
  self,
slidge/group/room.py CHANGED
@@ -206,6 +206,8 @@ class LegacyMUC(
206
206
  @user_nick.setter
207
207
  def user_nick(self, nick: str):
208
208
  self._user_nick = nick
209
+ if not self._updating_info:
210
+ self.__store.update_user_nick(self.pk, nick)
209
211
 
210
212
  def add_user_resource(self, resource: str) -> None:
211
213
  self._user_resources.add(resource)
@@ -1195,7 +1197,7 @@ class LegacyMUC(
1195
1197
  )
1196
1198
  muc.pk = stored.id
1197
1199
  muc.type = stored.muc_type # type: ignore
1198
- muc.user_nick = stored.user_nick
1200
+ muc._user_nick = stored.user_nick
1199
1201
  if stored.name:
1200
1202
  muc.DISCO_NAME = stored.name
1201
1203
  if stored.description:
slidge/util/db.py ADDED
@@ -0,0 +1,5 @@
1
+ # here to allow migration of the user store from v0.1
2
+ # since it relies on shelf, which relies on pickle, we need to keep objects
3
+ # importable where they were when the shelf was written
4
+
5
+ from ..db.alembic.old_user_store import * # noqa:F403
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: slidge
3
- Version: 0.2.0a3
3
+ Version: 0.2.0a4
4
4
  Summary: XMPP bridging framework
5
5
  Home-page: https://sr.ht/~nicoco/slidge/
6
6
  License: AGPL-3.0-or-later
@@ -1,21 +1,21 @@
1
1
  slidge/__init__.py,sha256=S0tUjqpZlzsr8G4Y_1Xt-KCYB07qaknTB0OwHU8k29U,1587
2
2
  slidge/__main__.py,sha256=Y12eh1TD_C5MB50KgEAuMffGnRFCvKYFKHD4UYSmHA0,72
3
- slidge/__version__.py,sha256=Ip83rsG7PNyMNP7tUYp3yfTqTCEX_G49W_HLxj1iJ7U,170
3
+ slidge/__version__.py,sha256=DiSDY0IeSP34Y0bfesUNWzvITu9c0Hjquli6h3JVwMk,170
4
4
  slidge/command/__init__.py,sha256=UYf1mjCYbZ5G7PIgaFTWSQRAzEJkQ6dTH8Fu_e_XnO0,613
5
5
  slidge/command/adhoc.py,sha256=5xLLoWyUJqCJB7kAwD2VKYTl_7MObCsgdz-qg_WkWGs,9417
6
- slidge/command/admin.py,sha256=JAN8s-b2KckgUozAQNBGOzkrEaQv-LtwezYgOsAR6Ng,5768
6
+ slidge/command/admin.py,sha256=x_kJ0TJhzf6d3OBIOXFjudZFO8bRYUG919td7OjMCug,6008
7
7
  slidge/command/base.py,sha256=xTlzxAbTWTpbFgQ0FxKjmp3ZImzempwJvGn9UiVUUTc,13044
8
8
  slidge/command/categories.py,sha256=BJCfaga2qoAxnHfgHD7I_RKZuBA5nnNOukkWHJwsUFE,99
9
9
  slidge/command/chat_command.py,sha256=kMnxrzmD7LhWgyO1w9Rgz1eA7PhfAJ2Rf34YWjoKrwQ,9975
10
10
  slidge/command/register.py,sha256=fzPcGUoJtainnDOiC13gWV-uYLuJcsmdKGJ-jXT1qIo,6697
11
11
  slidge/command/user.py,sha256=nJnoU4t1r9oPkFFHSHHwSY8WOQNLQn9mMcwZp-yZaKA,11422
12
12
  slidge/contact/__init__.py,sha256=WMMaHk7UW7YT9EH2LtPdkU0bHQaOp4ikBhbBQskmoc8,191
13
- slidge/contact/contact.py,sha256=l0zolnfrcSdS7z49TI-CSzjQiqJ-ARSMnZuszBcILXk,21894
14
- slidge/contact/roster.py,sha256=2EGV7q0km6JEahn2brr-td0KJILtXQGFWiSPuORA86I,10756
13
+ slidge/contact/contact.py,sha256=E7QEivJQ6GSVqi0BOe_7CohYDqCXHabGiPDe37WWKLI,21916
14
+ slidge/contact/roster.py,sha256=2UPuf2XkCdt9mdjhbATxxIH5dyIiJaxA0en8t1BgJuc,9989
15
15
  slidge/core/__init__.py,sha256=RG7Jj5JCJERjhqJ31lOLYV-7bH_oblClQD1KF9LsTXo,68
16
16
  slidge/core/config.py,sha256=leNcN_TI0Ka1hhzOHx7cBW3fNj5xZwsiv9l8AfRY_vU,7630
17
17
  slidge/core/gateway/__init__.py,sha256=rZckY2gAE-mon77_DSsAW1XtWqhBAETE2d4FqZ8pJXk,58
18
- slidge/core/gateway/base.py,sha256=6AOWuJPC4GkLcsgvrxHT5Y86g2x6Kv0iMbkp2wjepxo,38483
18
+ slidge/core/gateway/base.py,sha256=EWqDLhkCcVUJf0Cy-PZPYxdIEhXckHv1-XG7GlHYcdQ,38491
19
19
  slidge/core/gateway/caps.py,sha256=jemB4tB_2MTAxqQw5Bs4b7qNQ8gLPuAve0aoH6TzLEs,1937
20
20
  slidge/core/gateway/delivery_receipt.py,sha256=AT_9gvZrtWpSRsDJcYjE8CmF7TW-YBbUPdqNW5zWAdo,1352
21
21
  slidge/core/gateway/disco.py,sha256=uazgDXSDb5KrardjPCvElItARcxkeBRohtx82A2BlCQ,2203
@@ -26,7 +26,7 @@ slidge/core/gateway/presence.py,sha256=Ls8IY4uNQaW8F3F1CpRhfyFIVbd_py_VkZyJKMMei
26
26
  slidge/core/gateway/registration.py,sha256=JXwIQ-QqZCPXEmCU2G8FvIYDGvD8L8CqGb_Qkbycgt0,2303
27
27
  slidge/core/gateway/search.py,sha256=08ds6gvzX3EnTH-AU8X8J8JKEKYaSrRGTFwwClTT-Rc,3495
28
28
  slidge/core/gateway/session_dispatcher.py,sha256=F8YGUCB7hA1PNsGgQDaUYHmLnf4e8NWptIh-9ra_43c,32930
29
- slidge/core/gateway/vcard_temp.py,sha256=2FeP-comBg8A-OtB-II1jlxyDib_C4R8vfnJHGNkzyc,4626
29
+ slidge/core/gateway/vcard_temp.py,sha256=cnzHZO6qF8OUWSvBieEdNAV_Ndv1ixZOzBCBXy2Vopw,4637
30
30
  slidge/core/mixins/__init__.py,sha256=muReAzgvENgMvlfm0Fpe6BQFfm2EMjoDe9ZhGgo6Vig,627
31
31
  slidge/core/mixins/attachment.py,sha256=YXuObz68eem2AND1q-RBeZ-X9Zi_IlUgx0DRMiwM3Xw,18706
32
32
  slidge/core/mixins/avatar.py,sha256=ke3cwm6Iiz1AM0_SiARTUTU2nGYskPZlxtFrXKQT5fI,7812
@@ -38,7 +38,7 @@ slidge/core/mixins/message.py,sha256=jJz_peNQmDf0uVQcI7TWG7oUaSGjUL8eiulNicGgWhI
38
38
  slidge/core/mixins/message_maker.py,sha256=TcCutHi0sIwL6beJNkN7XyR0aDIbA0xZyxd2Gc9ulG4,6022
39
39
  slidge/core/mixins/presence.py,sha256=yywo6KAw8C7GaZSMrSMuioNfhW08MrnobHt8XbHd0q8,7891
40
40
  slidge/core/mixins/recipient.py,sha256=U-YppozUO8pA94jmD3-qmhkykTebPNaOVWc3JDPC9w8,1302
41
- slidge/core/pubsub.py,sha256=ofiZEw0tgckpdJJW102fj7MovUXBrCHYufaHaad4oFo,12390
41
+ slidge/core/pubsub.py,sha256=m70ahpZLKUWdBb4fG4e90UpPhdcGGZJD31oDU_O12Rg,12434
42
42
  slidge/core/session.py,sha256=IUZur7huNj066uy-Nh-I-R0etYmPJccgXFIimcSQ148,27161
43
43
  slidge/db/__init__.py,sha256=EBDH1JSEhgqYcli2Bw11CRC749wJk8AOucgBzmhDSvU,105
44
44
  slidge/db/alembic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -58,15 +58,15 @@ slidge/db/alembic/versions/b33993e87db3_move_everything_to_persistent_db.py,sha2
58
58
  slidge/db/alembic/versions/b64b1a793483_add_source_and_legacy_id_for_archived_.py,sha256=N6HYpFBhMckAFLZFW8PY8Us1qzXlauEQiDwEYwd9_K8,1422
59
59
  slidge/db/alembic/versions/c4a8ec35a0e8_per_room_user_nick.py,sha256=jjQmlRv6nqdm5q6LbwVpSUSkTBj1c76Hiq8e8q77q3g,933
60
60
  slidge/db/alembic/versions/e91195719c2c_store_users_avatars_persistently.py,sha256=8Ga3VFgKrzMs_-B8OPtfP-0rey_MFaDg-QGtSbaft3o,640
61
- slidge/db/avatar.py,sha256=khMqkhUSLOOAulhWHUtkIlE8asdqUuaY8cieij97Hsw,7640
61
+ slidge/db/avatar.py,sha256=C3BrEkEJbBEEY42DjXMacl8wOXgooUQ9KgIOUPs9620,7881
62
62
  slidge/db/meta.py,sha256=v1Jf-npZ28QwdGpsLQWLBHEbEP3-jnPrygRg05tJ_Iw,1831
63
63
  slidge/db/models.py,sha256=UoQnDYGuwp8VPYpqMKS9uFez_Vc8IMHtLADGlDCXC1Q,13179
64
- slidge/db/store.py,sha256=rlDwapJhMM2iOpJsjn371qG14nuwZoS5Scd8txF3rWM,40817
64
+ slidge/db/store.py,sha256=j-8MvzC_HVzjYXEimAq8ViPSZfrT90QLs1U3FUoYPJs,41597
65
65
  slidge/group/__init__.py,sha256=yFt7cHqeaKIMN6f9ZyhhspOcJJvBtLedGv-iICG7lto,258
66
66
  slidge/group/archive.py,sha256=xGPkdSk8-BT6t6lNVo1FEwiFVAttoxCma8Tsyk5r8Kg,5279
67
- slidge/group/bookmarks.py,sha256=NGEOTSrIIzSYVxUp2QlbW4cRNavPCaFLo21WrOjxBPc,6647
68
- slidge/group/participant.py,sha256=FhI8RjVMp5fpYMLxG38wWPI3GEke8rTs-tmLklCIpzA,16764
69
- slidge/group/room.py,sha256=OiV-qex_aGezGwOkKe2Uxscm7LA9F0NrvhRo-y-6Sjw,45232
67
+ slidge/group/bookmarks.py,sha256=_LDf7A7aWkwPH88v7c-mOp8VJs3gSFM1-uCqSb4ThO8,5825
68
+ slidge/group/participant.py,sha256=VNMtqr98QVuYgiTsJ9BaaIG1noz-xe3ewyKhLeDRhBk,17033
69
+ slidge/group/room.py,sha256=QGi1I5O8PDm_ivQOx5vZUeJ5v_ldrPHs4s-szyM-dCQ,45326
70
70
  slidge/main.py,sha256=TbkG5m1SgNmfaZ7TOD5VGTh4Q52XltLJayWnan8M9cw,5986
71
71
  slidge/migration.py,sha256=qUrux9dYCtOfFjPIlvGfWjoyqhkdxzaOByJRqTmCoUI,1072
72
72
  slidge/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -107,11 +107,12 @@ slidge/slixfix/xep_0490/stanza.py,sha256=ztec_ipyhUFz_uWQYkS0Q6LlsNiSBBC5aZK-qSm
107
107
  slidge/util/__init__.py,sha256=BELovoTMPcPPGz3D48esBr8A4BRRHXTvavfgnArBgEc,301
108
108
  slidge/util/archive_msg.py,sha256=xXAR0BI5r3d6KKWjae9594izCOv6iI03z2WLuTecNw8,1724
109
109
  slidge/util/conf.py,sha256=1j2OnOsCBar1tOObErhXR5RC3Vl3faliOZ1U8J3My58,6613
110
+ slidge/util/db.py,sha256=4LxZj8oBYgiSnyBUnF_ALjr0TblkfNQq_p28sCfkHMY,242
110
111
  slidge/util/test.py,sha256=nCldxi9dLPj-c4LqZChR9DbzXFU4WgT0o_Pe80JJIDc,13279
111
112
  slidge/util/types.py,sha256=Gif-Z9NVd_eTei1uM3_KOsdok3B1yMQwdOkOzf9vheE,5224
112
113
  slidge/util/util.py,sha256=8JeE0QObNGQr_Tw4OFPwQSz_EB_zh_0t9IJmNNhW0ic,9114
113
- slidge-0.2.0a3.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
114
- slidge-0.2.0a3.dist-info/METADATA,sha256=FHnY-NweSRtVFdxm75xTdbZD2MieNfqIvlagawopsWM,4723
115
- slidge-0.2.0a3.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
116
- slidge-0.2.0a3.dist-info/entry_points.txt,sha256=SNl72KSocF5plsu_67xyH6wVWfGTXQbzkQgXbLtzDrQ,47
117
- slidge-0.2.0a3.dist-info/RECORD,,
114
+ slidge-0.2.0a4.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
115
+ slidge-0.2.0a4.dist-info/METADATA,sha256=idAPh52VqnQnIO6w47GLlGeDUegzVQU0sycTqDezW1I,4723
116
+ slidge-0.2.0a4.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
117
+ slidge-0.2.0a4.dist-info/entry_points.txt,sha256=SNl72KSocF5plsu_67xyH6wVWfGTXQbzkQgXbLtzDrQ,47
118
+ slidge-0.2.0a4.dist-info/RECORD,,