slidge 0.3.0b1__py3-none-any.whl → 0.3.0b3__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/contact/roster.py CHANGED
@@ -95,6 +95,8 @@ class LegacyRoster(
95
95
  contact_jid = JID(contact_jid.bare)
96
96
  async with self.lock(("username", username)):
97
97
  legacy_id = await self.jid_username_to_legacy_id(username)
98
+ if legacy_id == self.user_legacy_id:
99
+ raise ContactIsUser
98
100
  if self.get_lock(("legacy_id", legacy_id)):
99
101
  self.log.debug("Already updating %s via by_legacy_id()", contact_jid)
100
102
  return await self.by_legacy_id(legacy_id)
@@ -415,7 +415,9 @@ class MessageContentMixin(DispatcherMixin):
415
415
  with self.xmpp.store.session() as orm:
416
416
  sticker = self.xmpp.store.bob.get_sticker(orm, cid)
417
417
  if sticker is None:
418
- await self.xmpp.plugin["xep_0231"].get_bob(from_, cid)
418
+ await self.xmpp.plugin["xep_0231"].get_bob(
419
+ from_, cid, ifrom=self.xmpp.boundjid
420
+ )
419
421
  with self.xmpp.store.session() as orm:
420
422
  sticker = self.xmpp.store.bob.get_sticker(orm, cid)
421
423
  assert sticker is not None
@@ -3,6 +3,7 @@ import logging
3
3
  from slixmpp import JID, Presence
4
4
  from slixmpp.exceptions import XMPPError
5
5
 
6
+ from ...contact.roster import ContactIsUser
6
7
  from ...util.util import merge_resources
7
8
  from ..session import BaseSession
8
9
  from .util import DispatcherMixin, exceptions_to_xmpp_errors
@@ -142,6 +143,10 @@ class PresenceHandlerMixin(DispatcherMixin):
142
143
  contact = await session.contacts.by_jid(pto)
143
144
  except XMPPError:
144
145
  contact = None
146
+ except ContactIsUser:
147
+ raise XMPPError(
148
+ "bad-request", "Actions with yourself are not supported."
149
+ )
145
150
  if contact is not None:
146
151
  await self.xmpp.pubsub.on_presence_available(p, contact)
147
152
  return
@@ -303,6 +303,10 @@ class AttachmentMixin(TextMessageMixin):
303
303
  )
304
304
  if attachment.name:
305
305
  sfs["file"]["name"] = attachment.name
306
+ if attachment.disposition:
307
+ sfs["disposition"] = attachment.disposition
308
+ else:
309
+ del sfs["disposition"]
306
310
  if thumbnail is not None:
307
311
  sfs["file"].append(thumbnail)
308
312
  stored.sfs = str(sfs)
@@ -4,7 +4,6 @@ from typing import TYPE_CHECKING, Optional
4
4
 
5
5
  from PIL import UnidentifiedImageError
6
6
  from slixmpp import JID
7
- from sqlalchemy.exc import IntegrityError
8
7
  from sqlalchemy.orm.exc import DetachedInstanceError
9
8
 
10
9
  from ...db.avatar import CachedAvatar, avatar_cache
@@ -124,25 +123,14 @@ class AvatarMixin(UpdateInfoMixin):
124
123
  avatar.path.unlink()
125
124
 
126
125
  stored_avatar = None if cached_avatar is None else cached_avatar.stored
127
- self.stored.avatar = stored_avatar
128
-
129
- try:
130
- self.commit(merge=True)
131
- except IntegrityError as e:
132
- with self.xmpp.store.session(expire_on_commit=False) as orm:
133
- if orm.object_session(self.stored):
134
- self.log.debug(
135
- "Hit integrity error, attempting to fix by refreshing participants"
136
- )
137
- orm.refresh(self.stored, ["participants"])
138
- else:
139
- self.log.debug(
140
- "Hit integrity error, attempting to fix by merging contact.stored"
141
- )
126
+ if not self._updating_info:
127
+ with self.xmpp.store.session() as orm:
128
+ with orm.no_autoflush:
142
129
  self.stored = orm.merge(self.stored)
143
- self.stored.avatar = stored_avatar
144
- orm.add(self.stored)
145
- orm.commit()
130
+ orm.refresh(self.stored)
131
+
132
+ self.stored.avatar = stored_avatar
133
+ self.commit(merge=True)
146
134
 
147
135
  self._post_avatar_update(cached_avatar)
148
136
 
@@ -19,7 +19,7 @@ class Base:
19
19
  xmpp: "BaseGateway" = NotImplemented
20
20
 
21
21
  jid: JID = NotImplemented
22
- name: str = NotImplemented
22
+ name: str | None = NotImplemented
23
23
 
24
24
  @property
25
25
  def user_jid(self):
@@ -13,7 +13,7 @@ class BaseDiscoMixin(Base):
13
13
  DISCO_NAME: str = NotImplemented
14
14
  DISCO_LANG = None
15
15
 
16
- def _get_disco_name(self):
16
+ def _get_disco_name(self) -> str | None:
17
17
  if self.DISCO_NAME is NotImplemented:
18
18
  return self.xmpp.COMPONENT_NAME
19
19
  return self.DISCO_NAME or self.xmpp.COMPONENT_NAME
slidge/core/session.py CHANGED
@@ -133,8 +133,8 @@ class BaseSession(
133
133
  self.log.debug("Removing fut %s", fut)
134
134
  self.__tasks.remove(fut)
135
135
 
136
- def create_task(self, coro) -> asyncio.Task:
137
- 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)
138
138
  self.__tasks.add(task)
139
139
  self.log.debug("Creating task %s", task)
140
140
  task.add_done_callback(lambda _: self.__remove_task(task))
slidge/db/store.py CHANGED
@@ -478,7 +478,7 @@ class ParticipantStore:
478
478
 
479
479
  @staticmethod
480
480
  def get_all(
481
- session, room_pk: int, user_included: bool = True
481
+ session: Session, room_pk: int, user_included: bool = True
482
482
  ) -> Iterator[Participant]:
483
483
  query = select(Participant).where(Participant.room_id == room_pk)
484
484
  if not user_included:
slidge/group/bookmarks.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import abc
2
2
  import logging
3
- from typing import TYPE_CHECKING, Generic, Iterator, Optional, Type
3
+ from typing import TYPE_CHECKING, Generic, Iterator, Literal, Optional, Type, overload
4
4
 
5
5
  from slixmpp import JID
6
6
  from slixmpp.exceptions import XMPPError
@@ -119,13 +119,31 @@ class LegacyBookmarks(
119
119
  return self.from_store(stored)
120
120
  return None
121
121
 
122
- async def by_legacy_id(self, legacy_id: LegacyGroupIdType) -> LegacyMUCType:
122
+ @overload
123
+ async def by_legacy_id(self, legacy_id: LegacyGroupIdType) -> "LegacyMUCType": ...
124
+
125
+ @overload
126
+ async def by_legacy_id(
127
+ self, legacy_id: LegacyGroupIdType, create: Literal[False]
128
+ ) -> "LegacyMUCType | None": ...
129
+
130
+ @overload
131
+ async def by_legacy_id(
132
+ self, legacy_id: LegacyGroupIdType, create: Literal[True]
133
+ ) -> "LegacyMUCType": ...
134
+
135
+ async def by_legacy_id(
136
+ self, legacy_id: LegacyGroupIdType, create: bool = False
137
+ ) -> LegacyMUCType | None:
123
138
  async with self.lock(("legacy_id", legacy_id)):
124
139
  local = await self.legacy_id_to_jid_local_part(legacy_id)
125
140
  jid = JID(f"{local}@{self.xmpp.boundjid}")
126
141
  if self.get_lock(("bare", jid.bare)):
127
142
  self.session.log.debug("Already updating %s via by_jid()", jid)
128
- return await self.by_jid(jid)
143
+ if create:
144
+ return await self.by_jid(jid)
145
+ else:
146
+ return self.by_jid_only_if_exists(jid)
129
147
 
130
148
  with self.xmpp.store.session() as orm:
131
149
  stored = (
slidge/group/room.py CHANGED
@@ -3,9 +3,20 @@ import logging
3
3
  import re
4
4
  import string
5
5
  import warnings
6
+ from asyncio import Lock
7
+ from contextlib import asynccontextmanager
6
8
  from copy import copy
7
9
  from datetime import datetime, timedelta, timezone
8
- from typing import TYPE_CHECKING, AsyncIterator, Generic, Optional, Type, Union
10
+ from typing import (
11
+ TYPE_CHECKING,
12
+ AsyncIterator,
13
+ Generic,
14
+ Literal,
15
+ Optional,
16
+ Type,
17
+ Union,
18
+ overload,
19
+ )
9
20
  from uuid import uuid4
10
21
 
11
22
  import sqlalchemy as sa
@@ -18,7 +29,6 @@ from slixmpp.plugins.xep_0469.stanza import NS as PINNING_NS
18
29
  from slixmpp.plugins.xep_0492.stanza import NS as NOTIFY_NS
19
30
  from slixmpp.plugins.xep_0492.stanza import WhenLiteral
20
31
  from slixmpp.xmlstream import ET
21
- from sqlalchemy.exc import InvalidRequestError
22
32
  from sqlalchemy.orm import Session as OrmSession
23
33
 
24
34
  from ..contact.contact import LegacyContact
@@ -28,7 +38,6 @@ from ..core.mixins.disco import ChatterDiscoMixin
28
38
  from ..core.mixins.recipient import ReactionRecipientMixin, ThreadRecipientMixin
29
39
  from ..db.models import Participant, Room
30
40
  from ..util.jid_escaping import unescape_node
31
- from ..util.lock import NamedLockMixin
32
41
  from ..util.types import (
33
42
  HoleBound,
34
43
  LegacyGroupIdType,
@@ -56,7 +65,6 @@ class LegacyMUC(
56
65
  LegacyGroupIdType, LegacyMessageType, LegacyParticipantType, LegacyUserIdType
57
66
  ],
58
67
  AvatarMixin,
59
- NamedLockMixin,
60
68
  ChatterDiscoMixin,
61
69
  ReactionRecipientMixin,
62
70
  ThreadRecipientMixin,
@@ -242,10 +250,22 @@ class LegacyMUC(
242
250
  )
243
251
  self.commit()
244
252
 
253
+ @asynccontextmanager
254
+ async def lock(self, id_: str) -> AsyncIterator[None]:
255
+ async with self.session.lock((self.legacy_id, id_)):
256
+ yield
257
+
258
+ def get_lock(self, id_: str) -> Lock | None:
259
+ return self.session.get_lock((self.legacy_id, id_))
260
+
245
261
  async def __fill_participants(self) -> None:
246
- if self.participants_filled:
247
- return
248
262
  async with self.lock("fill participants"):
263
+ with self.xmpp.store.session(expire_on_commit=False) as orm:
264
+ orm.add(self.stored)
265
+ with orm.no_autoflush:
266
+ orm.refresh(self.stored, ["participants_filled"])
267
+ if self.participants_filled:
268
+ return
249
269
  parts: list[Participant] = []
250
270
  resources = set[str]()
251
271
  # During fill_participants(), self.get_participant*() methods may
@@ -261,17 +281,13 @@ class LegacyMUC(
261
281
  resources.add(participant.stored.resource)
262
282
  with self.xmpp.store.session(expire_on_commit=False) as orm:
263
283
  orm.add(self.stored)
264
- # because self.participants() is async, self.stored may be out of sync at
265
- # this point.
284
+ # because self.fill_participants() is async, self.stored may be stale at
285
+ # this point, and the only thing we want to update is the participant list
286
+ # and the participant_filled attribute.
266
287
  with orm.no_autoflush:
267
288
  orm.refresh(self.stored)
268
- for part in parts:
269
- try:
270
- self.stored.participants.append(part)
271
- except InvalidRequestError:
272
- # the participant was already stored in the DB. `part` may even
273
- # be out-of-sync, so it's fine to just ditch it.
274
- pass
289
+ for part in parts:
290
+ orm.merge(part)
275
291
  self.stored.participants_filled = True
276
292
  orm.commit()
277
293
 
@@ -290,10 +306,14 @@ class LegacyMUC(
290
306
  yield self.participant_from_store(db_participant)
291
307
 
292
308
  async def __fill_history(self) -> None:
293
- if self.stored.history_filled:
294
- self.log.debug("History has already been fetched.")
295
- return
296
309
  async with self.lock("fill history"):
310
+ with self.xmpp.store.session(expire_on_commit=False) as orm:
311
+ orm.add(self.stored)
312
+ with orm.no_autoflush:
313
+ orm.refresh(self.stored, ["history_filled"])
314
+ if self.stored.history_filled:
315
+ self.log.debug("History has already been fetched.")
316
+ return
297
317
  log.debug("Fetching history for %s", self)
298
318
  try:
299
319
  before, after = self.archive.get_hole_bounds()
@@ -314,16 +334,15 @@ class LegacyMUC(
314
334
  self.stored.history_filled = True
315
335
  self.commit(merge=True)
316
336
 
317
- @property
318
- def DISCO_NAME(self) -> str: # type:ignore
319
- return self.name or "unnamed-room"
337
+ def _get_disco_name(self) -> str | None:
338
+ return self.name
320
339
 
321
340
  @property
322
- def name(self) -> str:
323
- return self.stored.name or "unnamed-room"
341
+ def name(self) -> str | None:
342
+ return self.stored.name
324
343
 
325
344
  @name.setter
326
- def name(self, n: str) -> None:
345
+ def name(self, n: str | None) -> None:
327
346
  if self.name == n:
328
347
  return
329
348
  self.stored.name = n
@@ -662,7 +681,7 @@ class LegacyMUC(
662
681
  since=since,
663
682
  )
664
683
  self.__get_subject_setter_participant().set_room_subject(
665
- self.subject if self.HAS_SUBJECT else (self.description or self.name),
684
+ self.subject if self.HAS_SUBJECT else (self.description or self.name or ""),
666
685
  user_full_jid,
667
686
  self.subject_date,
668
687
  )
@@ -753,9 +772,24 @@ class LegacyMUC(
753
772
  """
754
773
  return self._participant_cls(self, Participant(), is_system=True)
755
774
 
775
+ @overload
756
776
  async def get_participant_by_contact(
757
777
  self, c: "LegacyContact"
758
- ) -> "LegacyParticipantType":
778
+ ) -> "LegacyParticipantType": ...
779
+
780
+ @overload
781
+ async def get_participant_by_contact(
782
+ self, c: "LegacyContact", create: Literal[False]
783
+ ) -> "LegacyParticipantType | None": ...
784
+
785
+ @overload
786
+ async def get_participant_by_contact(
787
+ self, c: "LegacyContact", create: Literal[True]
788
+ ) -> "LegacyParticipantType": ...
789
+
790
+ async def get_participant_by_contact(
791
+ self, c: "LegacyContact", create: bool = True
792
+ ) -> "LegacyParticipantType | None":
759
793
  """
760
794
  Get a non-anonymous participant.
761
795
 
@@ -763,20 +797,23 @@ class LegacyMUC(
763
797
  that the Contact jid is associated to this participant
764
798
 
765
799
  :param c: The :class:`.LegacyContact` instance corresponding to this contact
800
+ :param create: Creates the participant if it does not exist.
766
801
  :return:
767
802
  """
768
803
  await self.session.contacts.ready
769
804
 
770
- if not self.get_lock("fill participants"):
771
- with self.xmpp.store.session() as orm:
772
- self.stored = orm.merge(self.stored)
773
- stored = (
774
- orm.query(Participant)
775
- .filter_by(contact=c.stored, room=self.stored)
776
- .one_or_none()
777
- )
778
- if stored is not None:
779
- return self.participant_from_store(stored=stored, contact=c)
805
+ with self.xmpp.store.session() as orm:
806
+ self.stored = orm.merge(self.stored)
807
+ stored = (
808
+ orm.query(Participant)
809
+ .filter_by(contact=c.stored, room=self.stored)
810
+ .one_or_none()
811
+ )
812
+ if stored is None:
813
+ if not create:
814
+ return None
815
+ else:
816
+ return self.participant_from_store(stored=stored, contact=c)
780
817
 
781
818
  nickname = c.name or unescape_node(c.jid.node)
782
819
 
slidge/main.py CHANGED
@@ -166,10 +166,12 @@ def main(module_name: str | None = None) -> None:
166
166
  f"_{config.LEGACY_MODULE.split('.')[-1].upper()}_"
167
167
  )
168
168
  logging.debug("Env var prefix: %s", ConfigModule.ENV_VAR_PREFIX)
169
- ConfigModule(plugin_config_obj).set_conf(unknown_argv)
170
- else:
171
- if unknown_argv:
172
- raise RuntimeError("Some arguments have not been recognized", unknown_argv)
169
+ _, unknown_argv = ConfigModule(plugin_config_obj).set_conf(unknown_argv)
170
+
171
+ if unknown_argv:
172
+ logging.error(
173
+ f"These config options have not been recognized and ignored: {unknown_argv}"
174
+ )
173
175
 
174
176
  migrate()
175
177
 
slidge/util/conf.py CHANGED
@@ -159,7 +159,10 @@ class ConfigModule:
159
159
  upper = _argv_to_option_name(a)
160
160
  opt = options_long.get(upper)
161
161
  if opt and opt.type is bool:
162
- if _argv_to_option_name(aa) not in options_long:
162
+ if (
163
+ not aa.startswith("-")
164
+ and _argv_to_option_name(aa) not in options_long
165
+ ):
163
166
  log.debug("Removing %s from argv", aa)
164
167
  skip_next = True
165
168
 
slidge/util/types.py CHANGED
@@ -72,6 +72,7 @@ MucRole = Literal["visitor", "participant", "moderator", "none"]
72
72
  ClientType = Literal[
73
73
  "bot", "console", "game", "handheld", "pc", "phone", "sms", "tablet", "web"
74
74
  ]
75
+ AttachmentDisposition = Literal["attachment", "inline"]
75
76
 
76
77
 
77
78
  @dataclass
@@ -115,6 +116,7 @@ class LegacyAttachment:
115
116
  legacy_file_id: Optional[Union[str, int]] = None
116
117
  url: Optional[str] = None
117
118
  caption: Optional[str] = None
119
+ disposition: Optional[AttachmentDisposition] = None
118
120
  """
119
121
  A caption for this specific image. For a global caption for a list of attachments,
120
122
  use the ``body`` parameter of :meth:`.AttachmentMixin.send_files`
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: slidge
3
- Version: 0.3.0b1
3
+ Version: 0.3.0b3
4
4
  Summary: XMPP bridging framework
5
5
  Author-email: Nicolas Cedilnik <nicoco@nicoco.fr>
6
6
  License-Expression: AGPL-3.0-or-later
@@ -1,6 +1,6 @@
1
1
  slidge/__init__.py,sha256=OWGOMz8wl6I6XNUT9ipE9IFD-OinS8zQGGn4U_z3IWw,1835
2
2
  slidge/__main__.py,sha256=ydjUklOoavS4YlGfjRX_8BQN2DaSbaXPMi47RkOgcFI,37
3
- slidge/main.py,sha256=Q2memNl050JJhUk-ZKHV2Q2lVpdMtoyLKupKswq-swM,7070
3
+ slidge/main.py,sha256=bUdAau6TorsPpDRBPfzvUolHlXF5K-BY9aJdSmNUcyw,7109
4
4
  slidge/migration.py,sha256=Y_PJ9ahHwcgwP1gnGByIiUJSxTu2DYFpmNiPdOpVgoQ,1545
5
5
  slidge/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  slidge/command/__init__.py,sha256=UYf1mjCYbZ5G7PIgaFTWSQRAzEJkQ6dTH8Fu_e_XnO0,613
@@ -13,16 +13,16 @@ slidge/command/register.py,sha256=BduDI31Kx8CbWWEdjybimTA5Wcfhn-Jkt8sSPsySCpo,67
13
13
  slidge/command/user.py,sha256=VS7xuADXXes941OyiJbxC_C8d5hcqm-TSS4Gu82_8PQ,12173
14
14
  slidge/contact/__init__.py,sha256=WMMaHk7UW7YT9EH2LtPdkU0bHQaOp4ikBhbBQskmoc8,191
15
15
  slidge/contact/contact.py,sha256=AZSpBInijGXn5hP_eJQhdyCOcUnzM62h65ZliyFZWhg,19497
16
- slidge/contact/roster.py,sha256=TAPvaPWUn77CHt8la_BLfQRkZZJhlG-hn2wEQZbGzJ8,9706
16
+ slidge/contact/roster.py,sha256=uZ3iCl8oa7kEpIptUVa9p1k51bSvbuQq1pUGnf_zru8,9791
17
17
  slidge/core/__init__.py,sha256=RG7Jj5JCJERjhqJ31lOLYV-7bH_oblClQD1KF9LsTXo,68
18
18
  slidge/core/config.py,sha256=1HxHQ5BOnYghi8V5KbCQ6sUsNnXzAZAIoFA5PrMqH4E,6060
19
19
  slidge/core/gateway.py,sha256=0nuWlig6K4urNowoEKCVkSvEVH46BhR70A52fH6O4AE,40956
20
20
  slidge/core/pubsub.py,sha256=-YK49tEdz_SLM3O8Y9zvu3p5KYhxgNpqbsD57rOIdNI,12141
21
- slidge/core/session.py,sha256=H6eZqjDYrQu5k26dCYH3GAWg-P2tdYin06aufuIrnWw,29464
21
+ slidge/core/session.py,sha256=Rji81tCEVI5zpKtKpMIuclKvDR0XuHZRki8ivIhtNnQ,29500
22
22
  slidge/core/dispatcher/__init__.py,sha256=1EXcjXietUKlxEqdrCWCV3xZ3q_DSsjHoqWrPMbtYao,84
23
23
  slidge/core/dispatcher/caps.py,sha256=gISaHtFwFDXtkSrSsAkZfPiHQyXfmXg3v_YYU0w9iDg,2254
24
24
  slidge/core/dispatcher/disco.py,sha256=xVPyBFnnkON-JjjM1oydRa-dqnDbwAZER2MGQACRhVk,2309
25
- slidge/core/dispatcher/presence.py,sha256=XrcWGjIHofmAu_8QIOMsF6Wlg4_kyPukp73FPm8BwOg,6721
25
+ slidge/core/dispatcher/presence.py,sha256=rxL2tDlH7a1NxfN_URDNFCHnjG_e-4Ke5UWMh8zXeOo,6928
26
26
  slidge/core/dispatcher/registration.py,sha256=Qa3fYZFJ4NaVz-FsnXorCmMQ9WyO7oZte1Zvro5f74E,3415
27
27
  slidge/core/dispatcher/search.py,sha256=bL5cwMOtsfnX5IH-t60S1PudpeMWZnF4-qksrKDuDyc,3411
28
28
  slidge/core/dispatcher/session_dispatcher.py,sha256=ysgPhns7NgUxhmkgEwRv-yDkSnUIXEdc-FsgqDqQAkE,3466
@@ -31,7 +31,7 @@ slidge/core/dispatcher/vcard.py,sha256=qHZZShq3Iyvgh1FkcAgGhdKXF5m1VUqeb4EWkY0cb
31
31
  slidge/core/dispatcher/message/__init__.py,sha256=gNeZZ0wtCI9JBqMe6tpumwV1TjY0mnPWTJc94uFTN-I,244
32
32
  slidge/core/dispatcher/message/chat_state.py,sha256=RbtM_nlZyvOHusZkDEP0TXA4wMp_N435490eE4wW8U0,2143
33
33
  slidge/core/dispatcher/message/marker.py,sha256=WZyf72_SM6sDGPMEOzhu93o2KbgxSxNF25jwsiM7h2A,2439
34
- slidge/core/dispatcher/message/message.py,sha256=IEXbgaErWk8L-xQhkUXdYlruzk7x84Q1BjltLGjFxXI,16146
34
+ slidge/core/dispatcher/message/message.py,sha256=RK1sX4cBSvPZLiUGYoT-pdCB01ll1761Ryr7Tu0AuBc,16202
35
35
  slidge/core/dispatcher/muc/__init__.py,sha256=60YUr0i8PCZEPyNNTynJueRbbxF5pqzdyVf8z_XFXmM,290
36
36
  slidge/core/dispatcher/muc/admin.py,sha256=1tDZ9hHD6q5SqCjsYOpDimPB3Iyl21YO5RnK1goEGso,3284
37
37
  slidge/core/dispatcher/muc/mam.py,sha256=7vfmMI_mJOIrc9KCbtTibJSowhZTBBFwXWc84Ikpu3I,2994
@@ -39,11 +39,11 @@ slidge/core/dispatcher/muc/misc.py,sha256=FYo5FdmzksEuUCfCLLOOm8_8plXtZFQP8IzvzV
39
39
  slidge/core/dispatcher/muc/owner.py,sha256=dDAxpRaA8H_NJQNIyBNixck2oG4GHZeEQqPhKd7MmDQ,3359
40
40
  slidge/core/dispatcher/muc/ping.py,sha256=EgKKS9AvMnW-vINGcoGbtk6NdbN9A7zVaGfT5T7F6YE,1699
41
41
  slidge/core/mixins/__init__.py,sha256=Zea39CCwjJU5XfHwcYPEZ9Sin8z1BZxoV68G2RwC3nE,386
42
- slidge/core/mixins/attachment.py,sha256=f_8SZGyEAK00fzpwUWyIocPzdkSl5awPihR6_GCgdDo,21766
43
- slidge/core/mixins/avatar.py,sha256=x-PAbJFoMKZLoScVjIVzFuQvnJ4geXoAQrFHr5G_SOA,6113
44
- slidge/core/mixins/base.py,sha256=MOd-pas38_52VawQVlxWtBtmTKC6My9G0ZaCeQxOJbs,748
42
+ slidge/core/mixins/attachment.py,sha256=6c1gZNydVZHgHB-_PjBLbT_9ntBSNG0AWqlv9Cgcku8,21906
43
+ slidge/core/mixins/avatar.py,sha256=0E0mQxdTUcJQrYXlBkYqkNl4bYuga4cIC1s4XA2rED8,5559
44
+ slidge/core/mixins/base.py,sha256=iGu1yPFgivouhXx0ckgbO7HbpFHOnbJnEWEUvwSg8KU,755
45
45
  slidge/core/mixins/db.py,sha256=a6idm-FgHWfDK-MJZWy5AkkBlyY8JmwOB8xAFmm0E9g,1934
46
- slidge/core/mixins/disco.py,sha256=jk3Z1B6zTuisHv8VKNRJodIo0ee5btYHh2ZrlflPj_Q,3670
46
+ slidge/core/mixins/disco.py,sha256=mrYhWO9qpnLMAVtKKqwbDh6CNOH2dPNERpyfmWzZGg8,3684
47
47
  slidge/core/mixins/message.py,sha256=xk4bgiJF9ATe-rgtH4sHU8hUwecBF4KjGIujm90mbXQ,8014
48
48
  slidge/core/mixins/message_maker.py,sha256=d9lMurnWCr7Y-pyyUkLoQYykb6lCCZuBNKFOe2hcY3A,6552
49
49
  slidge/core/mixins/message_text.py,sha256=UUbY-hdsMEUHe3b2h2Rwkaic43iDiaaUoEmuyw6FezY,8564
@@ -53,16 +53,16 @@ slidge/db/__init__.py,sha256=EBDH1JSEhgqYcli2Bw11CRC749wJk8AOucgBzmhDSvU,105
53
53
  slidge/db/avatar.py,sha256=MXFd1oe0eL5CCUYbc5CpsIcbio3cY3xVoKt39RAoj9I,8240
54
54
  slidge/db/meta.py,sha256=NtjGWcqPfG7uPfwR_cC6_23zyo8ftqgKX8CbP9IBq6U,2185
55
55
  slidge/db/models.py,sha256=8z5bbaEINfU1Qx12iyHu4zRD9s3PwC6oUOz-PyBoqYg,12841
56
- slidge/db/store.py,sha256=shgBqGutbAeMD6T3sqH7Qo4IKs9TWwjwfH5-NDpj-kY,19399
56
+ slidge/db/store.py,sha256=ZksmZlFaTia7eWy_trALc_iTEkk2x7CIlEQeYkHW21g,19408
57
57
  slidge/db/alembic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
58
  slidge/db/alembic/env.py,sha256=hsBlRNs0zF5diSHGRSa8Fi3qRVQDA2rJdR41AEIdvxc,1642
59
59
  slidge/db/alembic/script.py.mako,sha256=MEqL-2qATlST9TAOeYgscMn1uy6HUS9NFvDgl93dMj8,635
60
60
  slidge/db/alembic/versions/cef02a8b1451_initial_schema.py,sha256=D1K-flfTM9Vkk0YFzg6HbmoDyEb2u5c751aXk2YzVVg,14881
61
61
  slidge/group/__init__.py,sha256=yFt7cHqeaKIMN6f9ZyhhspOcJJvBtLedGv-iICG7lto,258
62
62
  slidge/group/archive.py,sha256=DKwyde15-Op2rXuQBvdSmFcAKhUyWuorpEFcRSmDHec,5956
63
- slidge/group/bookmarks.py,sha256=UWrUjZMWlDmwKFRuNEqxZSx4cvXFib4AP_l388ApJa8,7086
63
+ slidge/group/bookmarks.py,sha256=qOaopMQNoGUB05Kq4aYRmoE-DOtXmSAAGwfCs1hcWB4,7648
64
64
  slidge/group/participant.py,sha256=eMwUgbEtxGjWMmIqUfS8uSKlaStitZ3D68M_RixQeso,17676
65
- slidge/group/room.py,sha256=meASJZXRVM39SEzoLNjm0NAx6mLLa8dgA21tK828kik,47939
65
+ slidge/group/room.py,sha256=E3uiroLmqwM52Lw6zT4wUQmVjmxx6wkeF3f87bIt3VU,49026
66
66
  slidge/slixfix/__init__.py,sha256=LvaYZQYjr4l_45AYYpod1dB3MUaZye18vKF-4H8Bm20,4758
67
67
  slidge/slixfix/delivery_receipt.py,sha256=JmogxsiXYEbTmCM4fvC5wkQs0jBsaJtKl4j_B_18riE,1415
68
68
  slidge/slixfix/roster.py,sha256=DjjHQqCsKsPChUxV7S0Pm4IAgjfrwgm5tcTdJi3N_gY,1670
@@ -81,15 +81,15 @@ slidge/slixfix/xep_0292/__init__.py,sha256=_MvS9wGra6ig3P_dPAVlCPDJkiOFvUWGjaRsH
81
81
  slidge/slixfix/xep_0292/vcard4.py,sha256=I6EXdTQ51nfF5qvKh7WMAluELbFsdtnYHrsV_8PrjK4,366
82
82
  slidge/util/__init__.py,sha256=BELovoTMPcPPGz3D48esBr8A4BRRHXTvavfgnArBgEc,301
83
83
  slidge/util/archive_msg.py,sha256=hGNquu38ouSWSc-kz_oAYPXwjhUVZNSedIpwkrXHSd0,1826
84
- slidge/util/conf.py,sha256=uNDY6GdQyTZEV47ab9fi27wwRb0ZMvbuZ7Hbzfe_NT8,7269
84
+ slidge/util/conf.py,sha256=Wv-xr1fQfz6jDCBpj2e5Nm-igMpdIjsYsVfoY8grJoo,7380
85
85
  slidge/util/jid_escaping.py,sha256=QJ2Yj_j1gTmiO9g2r187iVCu7kia_O5ABhRiLAO2TG4,1073
86
86
  slidge/util/lock.py,sha256=ZnUi3LGiz271-YeYKo9JzxovJCoSwlP9P65pNyHIO9o,1029
87
87
  slidge/util/test.py,sha256=_E6er2BtQlpyzTUmp4u8C9KhBYzbLrmTwSVgxGObKHU,13988
88
- slidge/util/types.py,sha256=xJ84ZvaUOU_VVJSjEMysgNSl05k0_O9YKbyW-JUrsMI,5635
88
+ slidge/util/types.py,sha256=nilphTeJU3yb0MSqb86tZeWXis495oDvHSDDBs0hn_4,5747
89
89
  slidge/util/util.py,sha256=4hihLCl4SsB5S14TT3bP8tDPP_Zg9rYbSfLdLB9-G_Q,9332
90
- slidge-0.3.0b1.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
91
- slidge-0.3.0b1.dist-info/METADATA,sha256=6PmV4nthNFFylMq1FHcXwhSuEgN9mQ9EaeUWuGNNNl4,5056
92
- slidge-0.3.0b1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
93
- slidge-0.3.0b1.dist-info/entry_points.txt,sha256=py3_x834fFJ2TEzPd18Wt2DnysdAfuVqJ5zzBrXbAZs,44
94
- slidge-0.3.0b1.dist-info/top_level.txt,sha256=2LRjDYHaGZ5ieCMF8xy58JIiabRMzX-MGMbCZwfE17c,7
95
- slidge-0.3.0b1.dist-info/RECORD,,
90
+ slidge-0.3.0b3.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
91
+ slidge-0.3.0b3.dist-info/METADATA,sha256=ZAjh2fLNz60lo8cZygLkm89isXqMPbSYvWnHvCVAPr8,5056
92
+ slidge-0.3.0b3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
93
+ slidge-0.3.0b3.dist-info/entry_points.txt,sha256=py3_x834fFJ2TEzPd18Wt2DnysdAfuVqJ5zzBrXbAZs,44
94
+ slidge-0.3.0b3.dist-info/top_level.txt,sha256=2LRjDYHaGZ5ieCMF8xy58JIiabRMzX-MGMbCZwfE17c,7
95
+ slidge-0.3.0b3.dist-info/RECORD,,