slidge 0.3.0a1__py3-none-any.whl → 0.3.0a3__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/core/gateway.py CHANGED
@@ -906,16 +906,15 @@ class BaseGateway(
906
906
  await self.xmpp.plugin["xep_0077"].api["user_remove"](None, None, user.jid)
907
907
  await self.xmpp._session_cls.kill_by_jid(user.jid)
908
908
 
909
- async def unregister(self, user: GatewayUser) -> None:
909
+ async def unregister(self, session: BaseSession) -> None:
910
910
  """
911
911
  Optionally override this if you need to clean additional
912
912
  stuff after a user has been removed from the persistent user store.
913
913
 
914
914
  By default, this just calls :meth:`BaseSession.logout`.
915
915
 
916
- :param user:
916
+ :param session: The session of the user who just unregistered
917
917
  """
918
- session = self.get_session_from_user(user)
919
918
  try:
920
919
  await session.logout()
921
920
  except NotImplementedError:
@@ -141,11 +141,14 @@ class AttachmentMixin(TextMessageMixin):
141
141
  return r.status < 400
142
142
 
143
143
  async def __get_stored(self, attachment: LegacyAttachment) -> Attachment:
144
- if attachment.legacy_file_id is not None:
144
+ if attachment.legacy_file_id is not None and self.session is not NotImplemented:
145
145
  with self.xmpp.store.session() as orm:
146
146
  stored = (
147
147
  orm.query(Attachment)
148
- .filter_by(legacy_file_id=str(attachment.legacy_file_id))
148
+ .filter_by(
149
+ legacy_file_id=str(attachment.legacy_file_id),
150
+ user_account_id=self.session.user_pk,
151
+ )
149
152
  .one_or_none()
150
153
  )
151
154
  if stored is not None:
@@ -4,6 +4,7 @@ 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
7
8
  from sqlalchemy.orm.exc import DetachedInstanceError
8
9
 
9
10
  from ...db.avatar import CachedAvatar, avatar_cache
@@ -126,7 +127,16 @@ class AvatarMixin(UpdateInfoMixin):
126
127
  self.stored.avatar = None
127
128
  else:
128
129
  self.stored.avatar = cached_avatar.stored
129
- self.commit(merge=True)
130
+ try:
131
+ self.commit(merge=True)
132
+ except IntegrityError as e:
133
+ self.log.debug(
134
+ "Hit integrity error, attempting to fix by refreshing participants"
135
+ )
136
+ with self.xmpp.store.session() as orm:
137
+ orm.refresh(self.stored, ["participants"])
138
+ self.commit(merge=True)
139
+
130
140
  self._post_avatar_update(cached_avatar)
131
141
 
132
142
  def get_cached_avatar(self) -> Optional["CachedAvatar"]:
slidge/core/session.py CHANGED
@@ -704,8 +704,8 @@ class BaseSession(
704
704
  log.warning("User not found during unregistration")
705
705
  return
706
706
 
707
+ await cls.xmpp.unregister(session)
707
708
  with cls.xmpp.store.session() as orm:
708
- await cls.xmpp.unregister(session.user)
709
709
  orm.delete(session.user)
710
710
  orm.commit()
711
711
 
@@ -0,0 +1,33 @@
1
+ """Add unique contraint for attachment user/file_id
2
+
3
+ Revision ID: 3231d2c623bc
4
+ Revises: 75a62b74b239
5
+ Create Date: 2025-05-14 06:08:15.425495
6
+
7
+ """
8
+
9
+ from typing import Sequence, Union
10
+
11
+ import sqlalchemy as sa
12
+ from alembic import op
13
+
14
+ # revision identifiers, used by Alembic.
15
+ revision: str = "3231d2c623bc"
16
+ down_revision: Union[str, None] = "75a62b74b239"
17
+ branch_labels: Union[str, Sequence[str], None] = None
18
+ depends_on: Union[str, Sequence[str], None] = None
19
+
20
+
21
+ def upgrade() -> None:
22
+ with op.batch_alter_table("attachment", schema=None) as batch_op:
23
+ batch_op.create_unique_constraint(
24
+ batch_op.f("uq_attachment_user_account_id"),
25
+ ["user_account_id", "legacy_file_id"],
26
+ )
27
+
28
+
29
+ def downgrade() -> None:
30
+ with op.batch_alter_table("attachment", schema=None) as batch_op:
31
+ batch_op.drop_constraint(
32
+ batch_op.f("uq_attachment_user_account_id"), type_="unique"
33
+ )
slidge/db/models.py CHANGED
@@ -300,6 +300,7 @@ class Attachment(Base):
300
300
  """
301
301
 
302
302
  __tablename__ = "attachment"
303
+ __table_args__ = (UniqueConstraint("user_account_id", "legacy_file_id"),)
303
304
 
304
305
  id: Mapped[int] = mapped_column(primary_key=True)
305
306
  user_account_id: Mapped[int] = mapped_column(ForeignKey("user_account.id"))
slidge/db/store.py CHANGED
@@ -324,9 +324,10 @@ class MAMStore:
324
324
  if before_id is not None:
325
325
  stamp = session.execute(
326
326
  select(ArchivedMessage.timestamp).where(
327
- ArchivedMessage.stanza_id == before_id
327
+ ArchivedMessage.stanza_id == before_id,
328
+ ArchivedMessage.room_id == room_pk,
328
329
  )
329
- ).scalar()
330
+ ).scalar_one_or_none()
330
331
  if stamp is None:
331
332
  raise XMPPError(
332
333
  "item-not-found",
@@ -336,9 +337,10 @@ class MAMStore:
336
337
  if after_id is not None:
337
338
  stamp = session.execute(
338
339
  select(ArchivedMessage.timestamp).where(
339
- ArchivedMessage.stanza_id == after_id
340
+ ArchivedMessage.stanza_id == after_id,
341
+ ArchivedMessage.room_id == room_pk,
340
342
  )
341
- ).scalar()
343
+ ).scalar_one_or_none()
342
344
  if stamp is None:
343
345
  raise XMPPError(
344
346
  "item-not-found",
slidge/group/room.py CHANGED
@@ -19,6 +19,7 @@ from slixmpp.plugins.xep_0492.stanza import NS as NOTIFY_NS
19
19
  from slixmpp.plugins.xep_0492.stanza import WhenLiteral
20
20
  from slixmpp.xmlstream import ET
21
21
  from sqlalchemy.orm import Session as OrmSession
22
+ from sqlalchemy.orm.exc import DetachedInstanceError
22
23
 
23
24
  from ..contact.contact import LegacyContact
24
25
  from ..contact.roster import ContactIsUser
@@ -87,17 +88,6 @@ class LegacyMUC(
87
88
  This is just a flag on archive responses that most clients ignore anyway.
88
89
  """
89
90
 
90
- KEEP_BACKFILLED_PARTICIPANTS = False
91
- """
92
- Set this to ``True`` if the participant list is not full after calling
93
- ``fill_participants()``. This is a workaround for networks with huge
94
- participant lists which do not map really well the MUCs where all presences
95
- are sent on join.
96
- It allows to ensure that the participants that last spoke (within the
97
- ``fill_history()`` method are effectively participants, thus making possible
98
- for XMPP clients to fetch their avatars.
99
- """
100
-
101
91
  _ALL_INFO_FILLED_ON_STARTUP = False
102
92
  """
103
93
  Set this to true if the fill_participants() / fill_participants() design does not
@@ -320,10 +310,6 @@ class LegacyMUC(
320
310
  return
321
311
  async with self.lock("fill history"):
322
312
  log.debug("Fetching history for %s", self)
323
- if not self.KEEP_BACKFILLED_PARTICIPANTS:
324
- with self.xmpp.store.session() as orm:
325
- orm.add(self.stored)
326
- participants = list(self.stored.participants)
327
313
  try:
328
314
  before, after = self.archive.get_hole_bounds()
329
315
  if before is not None:
@@ -339,8 +325,7 @@ class LegacyMUC(
339
325
  return
340
326
  except Exception as e:
341
327
  self.log.exception("Could not backfill", exc_info=e)
342
- if not self.KEEP_BACKFILLED_PARTICIPANTS:
343
- self.stored.participants = participants
328
+
344
329
  self.stored.history_filled = True
345
330
  self.commit(merge=True)
346
331
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: slidge
3
- Version: 0.3.0a1
3
+ Version: 0.3.0a3
4
4
  Summary: XMPP bridging framework
5
5
  Author-email: Nicolas Cedilnik <nicoco@nicoco.fr>
6
6
  License-Expression: AGPL-3.0-or-later
@@ -16,9 +16,9 @@ slidge/contact/contact.py,sha256=ubqd3aH-TOcv5hsHGPSlDGyojQXn3wjalrO7l_LfZk8,194
16
16
  slidge/contact/roster.py,sha256=TAPvaPWUn77CHt8la_BLfQRkZZJhlG-hn2wEQZbGzJ8,9706
17
17
  slidge/core/__init__.py,sha256=RG7Jj5JCJERjhqJ31lOLYV-7bH_oblClQD1KF9LsTXo,68
18
18
  slidge/core/config.py,sha256=1HxHQ5BOnYghi8V5KbCQ6sUsNnXzAZAIoFA5PrMqH4E,6060
19
- slidge/core/gateway.py,sha256=IpnHk0D-MXBY2-oPu8u-WrO6bV2Smq95Quqeec5-DEI,40930
19
+ slidge/core/gateway.py,sha256=yQMMWQL-VTVNOecSQ18frroTd6brWbaiDqEQBUI9cAE,40931
20
20
  slidge/core/pubsub.py,sha256=-YK49tEdz_SLM3O8Y9zvu3p5KYhxgNpqbsD57rOIdNI,12141
21
- slidge/core/session.py,sha256=Arz8hQ99o_DJd4NnhRTPaeurywD48xahpjbUVFR8Lkk,29382
21
+ slidge/core/session.py,sha256=bVvSpLOrT7aj36gXtQV6fNZRG556V_Vc55mA_f9bEWI,29373
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
@@ -39,8 +39,8 @@ 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=nR_ZHaPbrrXi3Ko8we6vhlu6GD0k4lU6JD3PPzsnFwU,20484
43
- slidge/core/mixins/avatar.py,sha256=X5tS6jJmjEoHC6O9kMgkNJoXM8eCY53tzW8kv2NOyv4,5346
42
+ slidge/core/mixins/attachment.py,sha256=kCEZzEozujHQP5Eq_Y2g3RL67dUSe0WOLIcoQ0s17pk,20632
43
+ slidge/core/mixins/avatar.py,sha256=L6uMTHa4e9GLu3EXQWoc8Cu3k8fnSKTC2rvSDl5n1qE,5714
44
44
  slidge/core/mixins/base.py,sha256=MOd-pas38_52VawQVlxWtBtmTKC6My9G0ZaCeQxOJbs,748
45
45
  slidge/core/mixins/db.py,sha256=a6idm-FgHWfDK-MJZWy5AkkBlyY8JmwOB8xAFmm0E9g,1934
46
46
  slidge/core/mixins/disco.py,sha256=jk3Z1B6zTuisHv8VKNRJodIo0ee5btYHh2ZrlflPj_Q,3670
@@ -52,8 +52,8 @@ slidge/core/mixins/recipient.py,sha256=b0uFnpym-hOFgYxGjXT1xQcZ4YRbDSBftPcNWLzSw
52
52
  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
- slidge/db/models.py,sha256=xkTveglIbJDwcm1YEF7urEC1LTlwyXYrxgT4Vppdmmg,12763
56
- slidge/db/store.py,sha256=nRR0oAAHg16YX8zffavFh0i8d2QnZgyf0Zexev3M3sM,19261
55
+ slidge/db/models.py,sha256=8z5bbaEINfU1Qx12iyHu4zRD9s3PwC6oUOz-PyBoqYg,12841
56
+ slidge/db/store.py,sha256=shgBqGutbAeMD6T3sqH7Qo4IKs9TWwjwfH5-NDpj-kY,19399
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
@@ -65,6 +65,7 @@ slidge/db/alembic/versions/2461390c0af2_store_contacts_caps_verstring_in_db.py,s
65
65
  slidge/db/alembic/versions/29f5280c61aa_store_subject_setter_in_room.py,sha256=f8TFS28CXjGhvIn41UYMoHYeODfqhKfo4O7gk-JwA1E,1134
66
66
  slidge/db/alembic/versions/2b1f45ab7379_store_room_subject_setter_by_nickname.py,sha256=CMVP2wFz6s7t57eWdSaGtck8BXzfVPJhHE5AoWi34tI,1359
67
67
  slidge/db/alembic/versions/3071e0fa69d4_add_contact_client_type.py,sha256=jCdwCOnX9VDgnqIFFHGKaPA7w87Hm9nvR1rMY0LrA30,1394
68
+ slidge/db/alembic/versions/3231d2c623bc_add_unique_contraint_for_attachment_.py,sha256=eWO-j092aqrcYxUQwAGXNY7OMpgGi-a9zlg3Q9IB-Hk,926
68
69
  slidge/db/alembic/versions/45c24cc73c91_add_bob.py,sha256=UjMySZ5LaInyPt0KbAxx0rF4GQhZh8CwBeqHtNPdG1c,1249
69
70
  slidge/db/alembic/versions/4dbd23a3f868_new_avatar_store.py,sha256=JhT83RJfXlKu2y8iB4twtuINGfa9YKNh6jURXVedHOc,4002
70
71
  slidge/db/alembic/versions/54ce3cde350c_use_hash_for_avatar_filenames.py,sha256=aNwlpXCHI_TEnVt2w-C8OrdH02-FhgrKbZkEqt40ay4,1495
@@ -84,7 +85,7 @@ slidge/group/__init__.py,sha256=yFt7cHqeaKIMN6f9ZyhhspOcJJvBtLedGv-iICG7lto,258
84
85
  slidge/group/archive.py,sha256=DKwyde15-Op2rXuQBvdSmFcAKhUyWuorpEFcRSmDHec,5956
85
86
  slidge/group/bookmarks.py,sha256=UWrUjZMWlDmwKFRuNEqxZSx4cvXFib4AP_l388ApJa8,7086
86
87
  slidge/group/participant.py,sha256=6atjdHEgbfhPjPAkOVAQFFuCv5b8TO279HPHq-qpqIE,17651
87
- slidge/group/room.py,sha256=KKj1mmASoRH80AfI-IZMOeahdThEEGu77-DFUw0ZsZo,49299
88
+ slidge/group/room.py,sha256=p6qtDVJMFFrpPzYrBob6yC2Ct_boMVUViNs5N3CJwCI,48519
88
89
  slidge/slixfix/__init__.py,sha256=LvaYZQYjr4l_45AYYpod1dB3MUaZye18vKF-4H8Bm20,4758
89
90
  slidge/slixfix/delivery_receipt.py,sha256=JmogxsiXYEbTmCM4fvC5wkQs0jBsaJtKl4j_B_18riE,1415
90
91
  slidge/slixfix/roster.py,sha256=DjjHQqCsKsPChUxV7S0Pm4IAgjfrwgm5tcTdJi3N_gY,1670
@@ -109,9 +110,9 @@ slidge/util/lock.py,sha256=ZnUi3LGiz271-YeYKo9JzxovJCoSwlP9P65pNyHIO9o,1029
109
110
  slidge/util/test.py,sha256=_E6er2BtQlpyzTUmp4u8C9KhBYzbLrmTwSVgxGObKHU,13988
110
111
  slidge/util/types.py,sha256=xJ84ZvaUOU_VVJSjEMysgNSl05k0_O9YKbyW-JUrsMI,5635
111
112
  slidge/util/util.py,sha256=4hihLCl4SsB5S14TT3bP8tDPP_Zg9rYbSfLdLB9-G_Q,9332
112
- slidge-0.3.0a1.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
113
- slidge-0.3.0a1.dist-info/METADATA,sha256=8jkX8qNCMMIHufnOQRQk4Sd0_Z-pvC6iqOYsOd95RPc,5056
114
- slidge-0.3.0a1.dist-info/WHEEL,sha256=GHB6lJx2juba1wDgXDNlMTyM13ckjBMKf-OnwgKOCtA,91
115
- slidge-0.3.0a1.dist-info/entry_points.txt,sha256=py3_x834fFJ2TEzPd18Wt2DnysdAfuVqJ5zzBrXbAZs,44
116
- slidge-0.3.0a1.dist-info/top_level.txt,sha256=2LRjDYHaGZ5ieCMF8xy58JIiabRMzX-MGMbCZwfE17c,7
117
- slidge-0.3.0a1.dist-info/RECORD,,
113
+ slidge-0.3.0a3.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
114
+ slidge-0.3.0a3.dist-info/METADATA,sha256=JxQ19ez_SI8I7ycRYJd7M107KolTsrZH3wdgFyDPBmY,5056
115
+ slidge-0.3.0a3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
116
+ slidge-0.3.0a3.dist-info/entry_points.txt,sha256=py3_x834fFJ2TEzPd18Wt2DnysdAfuVqJ5zzBrXbAZs,44
117
+ slidge-0.3.0a3.dist-info/top_level.txt,sha256=2LRjDYHaGZ5ieCMF8xy58JIiabRMzX-MGMbCZwfE17c,7
118
+ slidge-0.3.0a3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.3.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5