slidge 0.2.0a10__py3-none-any.whl → 0.2.0b1__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.
Files changed (37) hide show
  1. slidge/__main__.py +2 -3
  2. slidge/__version__.py +1 -1
  3. slidge/command/adhoc.py +31 -15
  4. slidge/command/admin.py +11 -4
  5. slidge/command/base.py +5 -2
  6. slidge/command/categories.py +13 -3
  7. slidge/command/chat_command.py +14 -1
  8. slidge/command/user.py +22 -10
  9. slidge/contact/roster.py +2 -0
  10. slidge/core/config.py +6 -3
  11. slidge/core/dispatcher/message/marker.py +2 -7
  12. slidge/core/dispatcher/muc/misc.py +3 -0
  13. slidge/core/dispatcher/muc/owner.py +1 -1
  14. slidge/core/dispatcher/util.py +23 -23
  15. slidge/core/mixins/attachment.py +24 -8
  16. slidge/core/mixins/lock.py +10 -8
  17. slidge/core/mixins/message.py +5 -205
  18. slidge/core/mixins/message_text.py +211 -0
  19. slidge/db/alembic/versions/15b0bd83407a_remove_bogus_unique_constraints_on_room_.py +85 -0
  20. slidge/db/alembic/versions/3071e0fa69d4_add_contact_client_type.py +1 -1
  21. slidge/db/alembic/versions/5bd48bfdffa2_lift_room_legacy_id_constraint.py +12 -1
  22. slidge/db/alembic/versions/8d2ced764698_rely_on_db_to_store_contacts_rooms_and_.py +6 -0
  23. slidge/db/alembic/versions/abba1ae0edb3_store_avatar_legacy_id_in_the_contact_.py +7 -6
  24. slidge/db/alembic/versions/b64b1a793483_add_source_and_legacy_id_for_archived_.py +4 -0
  25. slidge/db/models.py +4 -2
  26. slidge/db/store.py +18 -11
  27. slidge/group/bookmarks.py +23 -1
  28. slidge/group/participant.py +5 -5
  29. slidge/group/room.py +10 -1
  30. slidge/util/test.py +4 -4
  31. slidge/util/util.py +18 -0
  32. {slidge-0.2.0a10.dist-info → slidge-0.2.0b1.dist-info}/METADATA +1 -1
  33. {slidge-0.2.0a10.dist-info → slidge-0.2.0b1.dist-info}/RECORD +36 -34
  34. slidge-0.2.0b1.dist-info/entry_points.txt +3 -0
  35. slidge-0.2.0a10.dist-info/entry_points.txt +0 -3
  36. {slidge-0.2.0a10.dist-info → slidge-0.2.0b1.dist-info}/LICENSE +0 -0
  37. {slidge-0.2.0a10.dist-info → slidge-0.2.0b1.dist-info}/WHEEL +0 -0
@@ -1,23 +1,15 @@
1
1
  import logging
2
2
  import uuid
3
3
  import warnings
4
- from datetime import datetime
5
- from typing import TYPE_CHECKING, Iterable, Optional
4
+ from typing import TYPE_CHECKING, Optional
6
5
 
7
6
  from slixmpp import Iq, Message
8
7
 
9
8
  from ...slixfix.xep_0490.mds import PUBLISH_OPTIONS
10
- from ...util.types import (
11
- ChatState,
12
- LegacyMessageType,
13
- LegacyThreadType,
14
- LinkPreview,
15
- Marker,
16
- MessageReference,
17
- ProcessingHint,
18
- )
9
+ from ...util.types import ChatState, LegacyMessageType, Marker
19
10
  from .attachment import AttachmentMixin
20
11
  from .message_maker import MessageMaker
12
+ from .message_text import TextMessageMixin
21
13
 
22
14
  if TYPE_CHECKING:
23
15
  from ...group import LegacyMUC
@@ -158,200 +150,8 @@ class MarkerMixin(MessageMaker):
158
150
  self.session.log.debug("Could not MDS mark", exc_info=e)
159
151
 
160
152
 
161
- class ContentMessageMixin(AttachmentMixin):
162
- def __default_hints(self, hints: Optional[Iterable[ProcessingHint]] = None):
163
- if hints is not None:
164
- return hints
165
- elif self.mtype == "chat":
166
- return {"markable", "store"}
167
- elif self.mtype == "groupchat":
168
- return {"markable"}
169
-
170
- def __replace_id(self, legacy_msg_id: LegacyMessageType):
171
- if self.mtype == "groupchat":
172
- return self.xmpp.store.sent.get_group_xmpp_id(
173
- self.session.user_pk, str(legacy_msg_id)
174
- ) or self._legacy_to_xmpp(legacy_msg_id)
175
- else:
176
- return self._legacy_to_xmpp(legacy_msg_id)
177
-
178
- def send_text(
179
- self,
180
- body: str,
181
- legacy_msg_id: Optional[LegacyMessageType] = None,
182
- *,
183
- when: Optional[datetime] = None,
184
- reply_to: Optional[MessageReference] = None,
185
- thread: Optional[LegacyThreadType] = None,
186
- hints: Optional[Iterable[ProcessingHint]] = None,
187
- carbon=False,
188
- archive_only=False,
189
- correction=False,
190
- correction_event_id: Optional[LegacyMessageType] = None,
191
- link_previews: Optional[list[LinkPreview]] = None,
192
- **send_kwargs,
193
- ):
194
- """
195
- Send a text message from this :term:`XMPP Entity`.
196
-
197
- :param body: Content of the message
198
- :param legacy_msg_id: If you want to be able to transport read markers from the gateway
199
- user to the legacy network, specify this
200
- :param when: when the message was sent, for a "delay" tag (:xep:`0203`)
201
- :param reply_to: Quote another message (:xep:`0461`)
202
- :param hints:
203
- :param thread:
204
- :param carbon: (only used if called on a :class:`LegacyContact`)
205
- Set this to ``True`` if this is actually a message sent **to** the
206
- :class:`LegacyContact` by the :term:`User`.
207
- Use this to synchronize outgoing history for legacy official apps.
208
- :param correction: whether this message is a correction or not
209
- :param correction_event_id: in the case where an ID is associated with the legacy
210
- 'correction event', specify it here to use it on the XMPP side. If not specified,
211
- a random ID will be used.
212
- :param link_previews: A little of sender (or server, or gateway)-generated
213
- previews of URLs linked in the body.
214
- :param archive_only: (only in groups) Do not send this message to user,
215
- but store it in the archive. Meant to be used during ``MUC.backfill()``
216
- """
217
- if carbon and not hasattr(self, "muc"):
218
- if not correction and self.xmpp.store.sent.was_sent_by_user(
219
- self.session.user_pk, str(legacy_msg_id)
220
- ):
221
- log.warning(
222
- "Carbon message for a message an XMPP has sent? This is a bug! %s",
223
- legacy_msg_id,
224
- )
225
- return
226
- if hasattr(self, "muc") and not self.is_user: # type:ignore
227
- log.warning(
228
- "send_text() called with carbon=True on a participant who is not the user",
229
- legacy_msg_id,
230
- )
231
- self.xmpp.store.sent.set_message(
232
- self.session.user_pk,
233
- str(legacy_msg_id),
234
- self.session.legacy_to_xmpp_msg_id(legacy_msg_id),
235
- )
236
- hints = self.__default_hints(hints)
237
- msg = self._make_message(
238
- mbody=body,
239
- legacy_msg_id=correction_event_id if correction else legacy_msg_id,
240
- when=when,
241
- reply_to=reply_to,
242
- hints=hints or (),
243
- carbon=carbon,
244
- thread=thread,
245
- link_previews=link_previews,
246
- )
247
- if correction:
248
- msg["replace"]["id"] = self.__replace_id(legacy_msg_id)
249
- return self._send(
250
- msg,
251
- archive_only=archive_only,
252
- carbon=carbon,
253
- legacy_msg_id=legacy_msg_id,
254
- **send_kwargs,
255
- )
256
-
257
- def correct(
258
- self,
259
- legacy_msg_id: LegacyMessageType,
260
- new_text: str,
261
- *,
262
- when: Optional[datetime] = None,
263
- reply_to: Optional[MessageReference] = None,
264
- thread: Optional[LegacyThreadType] = None,
265
- hints: Optional[Iterable[ProcessingHint]] = None,
266
- carbon=False,
267
- archive_only=False,
268
- correction_event_id: Optional[LegacyMessageType] = None,
269
- link_previews: Optional[list[LinkPreview]] = None,
270
- **send_kwargs,
271
- ):
272
- """
273
- Modify a message that was previously sent by this :term:`XMPP Entity`.
274
-
275
- Uses last message correction (:xep:`0308`)
276
-
277
- :param new_text: New content of the message
278
- :param legacy_msg_id: The legacy message ID of the message to correct
279
- :param when: when the message was sent, for a "delay" tag (:xep:`0203`)
280
- :param reply_to: Quote another message (:xep:`0461`)
281
- :param hints:
282
- :param thread:
283
- :param carbon: (only in 1:1) Reflect a message sent to this ``Contact`` by the user.
284
- Use this to synchronize outgoing history for legacy official apps.
285
- :param archive_only: (only in groups) Do not send this message to user,
286
- but store it in the archive. Meant to be used during ``MUC.backfill()``
287
- :param correction_event_id: in the case where an ID is associated with the legacy
288
- 'correction event', specify it here to use it on the XMPP side. If not specified,
289
- a random ID will be used.
290
- :param link_previews: A little of sender (or server, or gateway)-generated
291
- previews of URLs linked in the body.
292
- """
293
- self.send_text(
294
- new_text,
295
- legacy_msg_id,
296
- when=when,
297
- reply_to=reply_to,
298
- hints=hints,
299
- carbon=carbon,
300
- thread=thread,
301
- correction=True,
302
- archive_only=archive_only,
303
- correction_event_id=correction_event_id,
304
- link_previews=link_previews,
305
- **send_kwargs,
306
- )
307
-
308
- def react(
309
- self,
310
- legacy_msg_id: LegacyMessageType,
311
- emojis: Iterable[str] = (),
312
- thread: Optional[LegacyThreadType] = None,
313
- **kwargs,
314
- ):
315
- """
316
- Send a reaction (:xep:`0444`) from this :term:`XMPP Entity`.
317
-
318
- :param legacy_msg_id: The message which the reaction refers to.
319
- :param emojis: An iterable of emojis used as reactions
320
- :param thread:
321
- """
322
- msg = self._make_message(
323
- hints={"store"}, carbon=kwargs.get("carbon"), thread=thread
324
- )
325
- xmpp_id = kwargs.pop("xmpp_id", None)
326
- if not xmpp_id:
327
- xmpp_id = self._legacy_to_xmpp(legacy_msg_id)
328
- self.xmpp["xep_0444"].set_reactions(msg, to_id=xmpp_id, reactions=emojis)
329
- self._send(msg, **kwargs)
330
-
331
- def retract(
332
- self,
333
- legacy_msg_id: LegacyMessageType,
334
- thread: Optional[LegacyThreadType] = None,
335
- **kwargs,
336
- ):
337
- """
338
- Send a message retraction (:XEP:`0424`) from this :term:`XMPP Entity`.
339
-
340
- :param legacy_msg_id: Legacy ID of the message to delete
341
- :param thread:
342
- """
343
- msg = self._make_message(
344
- state=None,
345
- hints={"store"},
346
- mbody=f"/me retracted the message {legacy_msg_id}",
347
- carbon=kwargs.get("carbon"),
348
- thread=thread,
349
- )
350
- msg.enable("fallback")
351
- # namespace version mismatch between slidge and slixmpp, update me later
352
- msg["fallback"]["for"] = self.xmpp["xep_0424"].namespace[:-1] + "1"
353
- msg["retract"]["id"] = msg["replace"]["id"] = self.__replace_id(legacy_msg_id)
354
- self._send(msg, **kwargs)
153
+ class ContentMessageMixin(AttachmentMixin, TextMessageMixin):
154
+ pass
355
155
 
356
156
 
357
157
  class CarbonMessageMixin(ContentMessageMixin, MarkerMixin):
@@ -0,0 +1,211 @@
1
+ import logging
2
+ from datetime import datetime
3
+ from typing import Iterable, Optional
4
+
5
+ from ...util.types import (
6
+ LegacyMessageType,
7
+ LegacyThreadType,
8
+ LinkPreview,
9
+ MessageReference,
10
+ ProcessingHint,
11
+ )
12
+ from .message_maker import MessageMaker
13
+
14
+
15
+ class TextMessageMixin(MessageMaker):
16
+ def __default_hints(self, hints: Optional[Iterable[ProcessingHint]] = None):
17
+ if hints is not None:
18
+ return hints
19
+ elif self.mtype == "chat":
20
+ return {"markable", "store"}
21
+ elif self.mtype == "groupchat":
22
+ return {"markable"}
23
+
24
+ def _replace_id(self, legacy_msg_id: LegacyMessageType):
25
+ if self.mtype == "groupchat":
26
+ return self.xmpp.store.sent.get_group_xmpp_id(
27
+ self.session.user_pk, str(legacy_msg_id)
28
+ ) or self._legacy_to_xmpp(legacy_msg_id)
29
+ else:
30
+ return self._legacy_to_xmpp(legacy_msg_id)
31
+
32
+ def send_text(
33
+ self,
34
+ body: str,
35
+ legacy_msg_id: Optional[LegacyMessageType] = None,
36
+ *,
37
+ when: Optional[datetime] = None,
38
+ reply_to: Optional[MessageReference] = None,
39
+ thread: Optional[LegacyThreadType] = None,
40
+ hints: Optional[Iterable[ProcessingHint]] = None,
41
+ carbon=False,
42
+ archive_only=False,
43
+ correction=False,
44
+ correction_event_id: Optional[LegacyMessageType] = None,
45
+ link_previews: Optional[list[LinkPreview]] = None,
46
+ **send_kwargs,
47
+ ):
48
+ """
49
+ Send a text message from this :term:`XMPP Entity`.
50
+
51
+ :param body: Content of the message
52
+ :param legacy_msg_id: If you want to be able to transport read markers from the gateway
53
+ user to the legacy network, specify this
54
+ :param when: when the message was sent, for a "delay" tag (:xep:`0203`)
55
+ :param reply_to: Quote another message (:xep:`0461`)
56
+ :param hints:
57
+ :param thread:
58
+ :param carbon: (only used if called on a :class:`LegacyContact`)
59
+ Set this to ``True`` if this is actually a message sent **to** the
60
+ :class:`LegacyContact` by the :term:`User`.
61
+ Use this to synchronize outgoing history for legacy official apps.
62
+ :param correction: whether this message is a correction or not
63
+ :param correction_event_id: in the case where an ID is associated with the legacy
64
+ 'correction event', specify it here to use it on the XMPP side. If not specified,
65
+ a random ID will be used.
66
+ :param link_previews: A little of sender (or server, or gateway)-generated
67
+ previews of URLs linked in the body.
68
+ :param archive_only: (only in groups) Do not send this message to user,
69
+ but store it in the archive. Meant to be used during ``MUC.backfill()``
70
+ """
71
+ if carbon and not hasattr(self, "muc"):
72
+ if not correction and self.xmpp.store.sent.was_sent_by_user(
73
+ self.session.user_pk, str(legacy_msg_id)
74
+ ):
75
+ log.warning(
76
+ "Carbon message for a message an XMPP has sent? This is a bug! %s",
77
+ legacy_msg_id,
78
+ )
79
+ return
80
+ if hasattr(self, "muc") and not self.is_user: # type:ignore
81
+ log.warning(
82
+ "send_text() called with carbon=True on a participant who is not the user",
83
+ legacy_msg_id,
84
+ )
85
+ self.xmpp.store.sent.set_message(
86
+ self.session.user_pk,
87
+ str(legacy_msg_id),
88
+ self.session.legacy_to_xmpp_msg_id(legacy_msg_id),
89
+ )
90
+ hints = self.__default_hints(hints)
91
+ msg = self._make_message(
92
+ mbody=body,
93
+ legacy_msg_id=correction_event_id if correction else legacy_msg_id,
94
+ when=when,
95
+ reply_to=reply_to,
96
+ hints=hints or (),
97
+ carbon=carbon,
98
+ thread=thread,
99
+ link_previews=link_previews,
100
+ )
101
+ if correction:
102
+ msg["replace"]["id"] = self._replace_id(legacy_msg_id)
103
+ return self._send(
104
+ msg,
105
+ archive_only=archive_only,
106
+ carbon=carbon,
107
+ legacy_msg_id=legacy_msg_id,
108
+ **send_kwargs,
109
+ )
110
+
111
+ def correct(
112
+ self,
113
+ legacy_msg_id: LegacyMessageType,
114
+ new_text: str,
115
+ *,
116
+ when: Optional[datetime] = None,
117
+ reply_to: Optional[MessageReference] = None,
118
+ thread: Optional[LegacyThreadType] = None,
119
+ hints: Optional[Iterable[ProcessingHint]] = None,
120
+ carbon=False,
121
+ archive_only=False,
122
+ correction_event_id: Optional[LegacyMessageType] = None,
123
+ link_previews: Optional[list[LinkPreview]] = None,
124
+ **send_kwargs,
125
+ ):
126
+ """
127
+ Modify a message that was previously sent by this :term:`XMPP Entity`.
128
+
129
+ Uses last message correction (:xep:`0308`)
130
+
131
+ :param new_text: New content of the message
132
+ :param legacy_msg_id: The legacy message ID of the message to correct
133
+ :param when: when the message was sent, for a "delay" tag (:xep:`0203`)
134
+ :param reply_to: Quote another message (:xep:`0461`)
135
+ :param hints:
136
+ :param thread:
137
+ :param carbon: (only in 1:1) Reflect a message sent to this ``Contact`` by the user.
138
+ Use this to synchronize outgoing history for legacy official apps.
139
+ :param archive_only: (only in groups) Do not send this message to user,
140
+ but store it in the archive. Meant to be used during ``MUC.backfill()``
141
+ :param correction_event_id: in the case where an ID is associated with the legacy
142
+ 'correction event', specify it here to use it on the XMPP side. If not specified,
143
+ a random ID will be used.
144
+ :param link_previews: A little of sender (or server, or gateway)-generated
145
+ previews of URLs linked in the body.
146
+ """
147
+ self.send_text(
148
+ new_text,
149
+ legacy_msg_id,
150
+ when=when,
151
+ reply_to=reply_to,
152
+ hints=hints,
153
+ carbon=carbon,
154
+ thread=thread,
155
+ correction=True,
156
+ archive_only=archive_only,
157
+ correction_event_id=correction_event_id,
158
+ link_previews=link_previews,
159
+ **send_kwargs,
160
+ )
161
+
162
+ def react(
163
+ self,
164
+ legacy_msg_id: LegacyMessageType,
165
+ emojis: Iterable[str] = (),
166
+ thread: Optional[LegacyThreadType] = None,
167
+ **kwargs,
168
+ ):
169
+ """
170
+ Send a reaction (:xep:`0444`) from this :term:`XMPP Entity`.
171
+
172
+ :param legacy_msg_id: The message which the reaction refers to.
173
+ :param emojis: An iterable of emojis used as reactions
174
+ :param thread:
175
+ """
176
+ msg = self._make_message(
177
+ hints={"store"}, carbon=kwargs.get("carbon"), thread=thread
178
+ )
179
+ xmpp_id = kwargs.pop("xmpp_id", None)
180
+ if not xmpp_id:
181
+ xmpp_id = self._legacy_to_xmpp(legacy_msg_id)
182
+ self.xmpp["xep_0444"].set_reactions(msg, to_id=xmpp_id, reactions=emojis)
183
+ self._send(msg, **kwargs)
184
+
185
+ def retract(
186
+ self,
187
+ legacy_msg_id: LegacyMessageType,
188
+ thread: Optional[LegacyThreadType] = None,
189
+ **kwargs,
190
+ ):
191
+ """
192
+ Send a message retraction (:XEP:`0424`) from this :term:`XMPP Entity`.
193
+
194
+ :param legacy_msg_id: Legacy ID of the message to delete
195
+ :param thread:
196
+ """
197
+ msg = self._make_message(
198
+ state=None,
199
+ hints={"store"},
200
+ mbody=f"/me retracted the message {legacy_msg_id}",
201
+ carbon=kwargs.get("carbon"),
202
+ thread=thread,
203
+ )
204
+ msg.enable("fallback")
205
+ # namespace version mismatch between slidge and slixmpp, update me later
206
+ msg["fallback"]["for"] = self.xmpp["xep_0424"].namespace[:-1] + "1"
207
+ msg["retract"]["id"] = msg["replace"]["id"] = self._replace_id(legacy_msg_id)
208
+ self._send(msg, **kwargs)
209
+
210
+
211
+ log = logging.getLogger(__name__)
@@ -0,0 +1,85 @@
1
+ """Remove bogus unique constraints on room table
2
+
3
+ Revision ID: 15b0bd83407a
4
+ Revises: 45c24cc73c91
5
+ Create Date: 2024-08-28 06:57:25.022994
6
+
7
+ """
8
+
9
+ from typing import Sequence, Union
10
+
11
+ import sqlalchemy as sa
12
+ from alembic import op
13
+
14
+ import slidge.db.meta
15
+
16
+ # revision identifiers, used by Alembic.
17
+ revision: str = "15b0bd83407a"
18
+ down_revision: Union[str, None] = "45c24cc73c91"
19
+ branch_labels: Union[str, Sequence[str], None] = None
20
+ depends_on: Union[str, Sequence[str], None] = None
21
+
22
+ meta = sa.MetaData()
23
+ room_table = sa.Table(
24
+ "room",
25
+ meta,
26
+ sa.Column("id", sa.Integer(), nullable=False),
27
+ sa.Column("user_account_id", sa.Integer(), nullable=False),
28
+ sa.Column("legacy_id", sa.String(), nullable=False),
29
+ sa.Column("jid", slidge.db.meta.JIDType(), nullable=False),
30
+ sa.Column("avatar_id", sa.Integer(), nullable=True),
31
+ sa.Column("name", sa.String(), nullable=True),
32
+ sa.Column("description", sa.String(), nullable=True),
33
+ sa.Column("subject", sa.String(), nullable=True),
34
+ sa.Column("subject_date", sa.DateTime(), nullable=True),
35
+ sa.Column("subject_setter", sa.String(), nullable=True),
36
+ sa.Column("n_participants", sa.Integer(), nullable=True),
37
+ sa.Column(
38
+ "muc_type",
39
+ sa.Enum("GROUP", "CHANNEL", "CHANNEL_NON_ANONYMOUS", name="muctype"),
40
+ nullable=True,
41
+ ),
42
+ sa.Column("user_nick", sa.String(), nullable=True),
43
+ sa.Column("user_resources", sa.String(), nullable=True),
44
+ sa.Column("participants_filled", sa.Boolean(), nullable=False),
45
+ sa.Column("history_filled", sa.Boolean(), nullable=False),
46
+ sa.Column("extra_attributes", slidge.db.meta.JSONEncodedDict(), nullable=True),
47
+ sa.Column("updated", sa.Boolean(), nullable=False),
48
+ sa.Column("avatar_legacy_id", sa.String(), nullable=True),
49
+ sa.ForeignKeyConstraint(
50
+ ["avatar_id"],
51
+ ["avatar.id"],
52
+ ),
53
+ sa.ForeignKeyConstraint(
54
+ ["user_account_id"],
55
+ ["user_account.id"],
56
+ ),
57
+ sa.PrimaryKeyConstraint("id"),
58
+ )
59
+
60
+
61
+ def upgrade() -> None:
62
+ if op.get_bind().engine.name == "postgresql":
63
+ return
64
+ with op.batch_alter_table(
65
+ "room",
66
+ schema=None,
67
+ # without copy_from, the newly created table keeps the constraints
68
+ # we actually want to ditch.
69
+ copy_from=room_table,
70
+ ) as batch_op:
71
+ batch_op.create_unique_constraint(
72
+ "uq_room_user_account_id_jid", ["user_account_id", "jid"]
73
+ )
74
+ batch_op.create_unique_constraint(
75
+ "uq_room_user_account_id_legacy_id", ["user_account_id", "legacy_id"]
76
+ )
77
+
78
+
79
+ def downgrade() -> None:
80
+ # ### commands auto generated by Alembic - please adjust! ###
81
+ with op.batch_alter_table("room", schema=None) as batch_op:
82
+ batch_op.drop_constraint("uq_room_user_account_id_legacy_id", type_="unique")
83
+ batch_op.drop_constraint("uq_room_user_account_id_jid", type_="unique")
84
+
85
+ # ### end Alembic commands ###
@@ -37,7 +37,7 @@ def upgrade() -> None:
37
37
  native_enum=False,
38
38
  ),
39
39
  nullable=False,
40
- server_default=sa.text("pc"),
40
+ server_default=sa.literal("pc"),
41
41
  )
42
42
  )
43
43
 
@@ -4,8 +4,12 @@ Revision ID: 5bd48bfdffa2
4
4
  Revises: b64b1a793483
5
5
  Create Date: 2024-07-24 10:29:23.467851
6
6
 
7
+ Broken; fixed by "Remove bogus unique constraints on room table",
8
+ rev 15b0bd83407a.
9
+
7
10
  """
8
11
 
12
+ import logging
9
13
  from typing import Sequence, Union
10
14
 
11
15
  from alembic import op
@@ -26,6 +30,8 @@ def upgrade() -> None:
26
30
  schema=None,
27
31
  # without copy_from, the newly created table keeps the constraints
28
32
  # we actually want to ditch.
33
+ # LATER EDIT: this actually does not work, I should have copied the
34
+ # schema in here.
29
35
  copy_from=Room.__table__, # type:ignore
30
36
  ) as batch_op:
31
37
  batch_op.create_unique_constraint(
@@ -35,9 +41,11 @@ def upgrade() -> None:
35
41
  "uq_room_user_account_id_legacy_id", ["user_account_id", "legacy_id"]
36
42
  )
37
43
  except Exception:
38
- # happens when migration is not needed
44
+ # This only works when upgrading rev by rev because I messed up. It
39
45
  # wouldn't be necessary if the constraint was named in the first place,
40
46
  # cf https://alembic.sqlalchemy.org/en/latest/naming.html
47
+ # This is fixed by rev 15b0bd83407a
48
+ log.info("Skipping")
41
49
  pass
42
50
 
43
51
 
@@ -48,3 +56,6 @@ def downgrade() -> None:
48
56
  batch_op.drop_constraint("uq_room_user_account_id_jid", type_="unique")
49
57
 
50
58
  # ### end Alembic commands ###
59
+
60
+
61
+ log = logging.getLogger(__name__)
@@ -95,6 +95,12 @@ def upgrade() -> None:
95
95
  op.add_column("room", sa.Column("description", sa.String(), nullable=True))
96
96
  op.add_column("room", sa.Column("subject", sa.String(), nullable=True))
97
97
  op.add_column("room", sa.Column("subject_date", sa.DateTime(), nullable=True))
98
+
99
+ if op.get_bind().engine.name == "postgresql":
100
+ op.execute(
101
+ "CREATE TYPE muctype AS ENUM ('GROUP', 'CHANNEL', 'CHANNEL_NON_ANONYMOUS')"
102
+ )
103
+
98
104
  op.add_column(
99
105
  "room",
100
106
  sa.Column(
@@ -37,12 +37,13 @@ def upgrade() -> None:
37
37
 
38
38
  with op.batch_alter_table("room", schema=None) as batch_op:
39
39
  batch_op.add_column(sa.Column("avatar_legacy_id", sa.String(), nullable=True))
40
- batch_op.create_unique_constraint(
41
- "uq_room_user_account_id_jid", ["user_account_id", "jid"]
42
- )
43
- batch_op.create_unique_constraint(
44
- "uq_room_user_account_id_legacy_id", ["user_account_id", "legacy_id"]
45
- )
40
+ if op.get_bind().engine.name != "postgresql":
41
+ batch_op.create_unique_constraint(
42
+ "uq_room_user_account_id_jid", ["user_account_id", "jid"]
43
+ )
44
+ batch_op.create_unique_constraint(
45
+ "uq_room_user_account_id_legacy_id", ["user_account_id", "legacy_id"]
46
+ )
46
47
 
47
48
  for room_pk, avatar_legacy_id in room_avatars:
48
49
  conn.execute(
@@ -24,6 +24,10 @@ def upgrade() -> None:
24
24
  # since we don't want source to be nullable, we drop all rows first.
25
25
  # This is what you get by using alpha versions!
26
26
  op.execute(sa.delete(ArchivedMessage))
27
+
28
+ if op.get_bind().engine.name == "postgresql":
29
+ op.execute("CREATE TYPE archivedmessagesource AS ENUM ('LIVE', 'BACKFILL')")
30
+
27
31
  # ### commands auto generated by Alembic - please adjust! ###
28
32
 
29
33
  with op.batch_alter_table("mam", schema=None) as batch_op:
slidge/db/models.py CHANGED
@@ -156,7 +156,9 @@ class Contact(Base):
156
156
 
157
157
  is_friend: Mapped[bool] = mapped_column(default=False)
158
158
  added_to_roster: Mapped[bool] = mapped_column(default=False)
159
- sent_order: Mapped[list["ContactSent"]] = relationship(back_populates="contact")
159
+ sent_order: Mapped[list["ContactSent"]] = relationship(
160
+ back_populates="contact", cascade="all, delete-orphan"
161
+ )
160
162
 
161
163
  extra_attributes: Mapped[Optional[JSONSerializable]] = mapped_column(
162
164
  default=None, nullable=True
@@ -315,7 +317,7 @@ class LegacyIdsMulti(Base):
315
317
 
316
318
  legacy_id: Mapped[str] = mapped_column(nullable=False)
317
319
  xmpp_ids: Mapped[list["XmppIdsMulti"]] = relationship(
318
- back_populates="legacy_ids_multi"
320
+ back_populates="legacy_ids_multi", cascade="all, delete-orphan"
319
321
  )
320
322
 
321
323