slidge 0.2.0a10__py3-none-any.whl → 0.2.0b1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
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