slidge 0.2.0a9__py3-none-any.whl → 0.2.0b0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. slidge/__main__.py +2 -3
  2. slidge/__version__.py +1 -1
  3. slidge/command/adhoc.py +1 -1
  4. slidge/command/base.py +4 -4
  5. slidge/command/user.py +5 -1
  6. slidge/contact/roster.py +9 -0
  7. slidge/core/config.py +0 -3
  8. slidge/core/dispatcher/__init__.py +3 -0
  9. slidge/core/{gateway → dispatcher}/caps.py +6 -4
  10. slidge/core/{gateway → dispatcher}/disco.py +11 -17
  11. slidge/core/dispatcher/message/__init__.py +10 -0
  12. slidge/core/dispatcher/message/chat_state.py +40 -0
  13. slidge/core/dispatcher/message/marker.py +62 -0
  14. slidge/core/dispatcher/message/message.py +397 -0
  15. slidge/core/dispatcher/muc/__init__.py +12 -0
  16. slidge/core/dispatcher/muc/admin.py +98 -0
  17. slidge/core/{gateway → dispatcher/muc}/mam.py +26 -15
  18. slidge/core/dispatcher/muc/misc.py +121 -0
  19. slidge/core/dispatcher/muc/owner.py +96 -0
  20. slidge/core/{gateway → dispatcher/muc}/ping.py +10 -15
  21. slidge/core/dispatcher/presence.py +177 -0
  22. slidge/core/{gateway → dispatcher}/registration.py +23 -2
  23. slidge/core/{gateway → dispatcher}/search.py +9 -14
  24. slidge/core/dispatcher/session_dispatcher.py +84 -0
  25. slidge/core/dispatcher/util.py +174 -0
  26. slidge/core/{gateway/vcard_temp.py → dispatcher/vcard.py} +26 -12
  27. slidge/core/{gateway/base.py → gateway.py} +42 -137
  28. slidge/core/mixins/attachment.py +24 -8
  29. slidge/core/mixins/base.py +2 -2
  30. slidge/core/mixins/lock.py +10 -8
  31. slidge/core/mixins/message.py +9 -203
  32. slidge/core/mixins/message_text.py +211 -0
  33. slidge/core/pubsub.py +2 -1
  34. slidge/core/session.py +28 -2
  35. slidge/db/alembic/versions/15b0bd83407a_remove_bogus_unique_constraints_on_room_.py +83 -0
  36. slidge/db/alembic/versions/45c24cc73c91_add_bob.py +42 -0
  37. slidge/db/alembic/versions/5bd48bfdffa2_lift_room_legacy_id_constraint.py +12 -1
  38. slidge/db/models.py +16 -1
  39. slidge/db/store.py +144 -11
  40. slidge/group/bookmarks.py +23 -1
  41. slidge/group/participant.py +5 -5
  42. slidge/group/room.py +10 -1
  43. slidge/{core/gateway → slixfix}/delivery_receipt.py +1 -1
  44. slidge/util/test.py +9 -5
  45. slidge/util/types.py +6 -0
  46. slidge/util/util.py +5 -2
  47. {slidge-0.2.0a9.dist-info → slidge-0.2.0b0.dist-info}/METADATA +2 -1
  48. {slidge-0.2.0a9.dist-info → slidge-0.2.0b0.dist-info}/RECORD +51 -40
  49. slidge-0.2.0b0.dist-info/entry_points.txt +3 -0
  50. slidge/core/gateway/__init__.py +0 -3
  51. slidge/core/gateway/muc_admin.py +0 -35
  52. slidge/core/gateway/presence.py +0 -95
  53. slidge/core/gateway/session_dispatcher.py +0 -895
  54. slidge-0.2.0a9.dist-info/entry_points.txt +0 -3
  55. {slidge-0.2.0a9.dist-info → slidge-0.2.0b0.dist-info}/LICENSE +0 -0
  56. {slidge-0.2.0a9.dist-info → slidge-0.2.0b0.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,205 +150,19 @@ 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:
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
- self.xmpp.store.sent.set_message(
227
- self.session.user_pk,
228
- str(legacy_msg_id),
229
- self.session.legacy_to_xmpp_msg_id(legacy_msg_id),
230
- )
231
- hints = self.__default_hints(hints)
232
- msg = self._make_message(
233
- mbody=body,
234
- legacy_msg_id=correction_event_id if correction else legacy_msg_id,
235
- when=when,
236
- reply_to=reply_to,
237
- hints=hints or (),
238
- carbon=carbon,
239
- thread=thread,
240
- link_previews=link_previews,
241
- )
242
- if correction:
243
- msg["replace"]["id"] = self.__replace_id(legacy_msg_id)
244
- return self._send(
245
- msg,
246
- archive_only=archive_only,
247
- carbon=carbon,
248
- legacy_msg_id=legacy_msg_id,
249
- **send_kwargs,
250
- )
251
-
252
- def correct(
253
- self,
254
- legacy_msg_id: LegacyMessageType,
255
- new_text: str,
256
- *,
257
- when: Optional[datetime] = None,
258
- reply_to: Optional[MessageReference] = None,
259
- thread: Optional[LegacyThreadType] = None,
260
- hints: Optional[Iterable[ProcessingHint]] = None,
261
- carbon=False,
262
- archive_only=False,
263
- correction_event_id: Optional[LegacyMessageType] = None,
264
- link_previews: Optional[list[LinkPreview]] = None,
265
- **send_kwargs,
266
- ):
267
- """
268
- Modify a message that was previously sent by this :term:`XMPP Entity`.
269
-
270
- Uses last message correction (:xep:`0308`)
271
-
272
- :param new_text: New content of the message
273
- :param legacy_msg_id: The legacy message ID of the message to correct
274
- :param when: when the message was sent, for a "delay" tag (:xep:`0203`)
275
- :param reply_to: Quote another message (:xep:`0461`)
276
- :param hints:
277
- :param thread:
278
- :param carbon: (only in 1:1) Reflect a message sent to this ``Contact`` by the user.
279
- Use this to synchronize outgoing history for legacy official apps.
280
- :param archive_only: (only in groups) Do not send this message to user,
281
- but store it in the archive. Meant to be used during ``MUC.backfill()``
282
- :param correction_event_id: in the case where an ID is associated with the legacy
283
- 'correction event', specify it here to use it on the XMPP side. If not specified,
284
- a random ID will be used.
285
- :param link_previews: A little of sender (or server, or gateway)-generated
286
- previews of URLs linked in the body.
287
- """
288
- self.send_text(
289
- new_text,
290
- legacy_msg_id,
291
- when=when,
292
- reply_to=reply_to,
293
- hints=hints,
294
- carbon=carbon,
295
- thread=thread,
296
- correction=True,
297
- archive_only=archive_only,
298
- correction_event_id=correction_event_id,
299
- link_previews=link_previews,
300
- **send_kwargs,
301
- )
302
-
303
- def react(
304
- self,
305
- legacy_msg_id: LegacyMessageType,
306
- emojis: Iterable[str] = (),
307
- thread: Optional[LegacyThreadType] = None,
308
- **kwargs,
309
- ):
310
- """
311
- Send a reaction (:xep:`0444`) from this :term:`XMPP Entity`.
312
-
313
- :param legacy_msg_id: The message which the reaction refers to.
314
- :param emojis: An iterable of emojis used as reactions
315
- :param thread:
316
- """
317
- msg = self._make_message(
318
- hints={"store"}, carbon=kwargs.get("carbon"), thread=thread
319
- )
320
- xmpp_id = kwargs.pop("xmpp_id", None)
321
- if not xmpp_id:
322
- xmpp_id = self._legacy_to_xmpp(legacy_msg_id)
323
- self.xmpp["xep_0444"].set_reactions(msg, to_id=xmpp_id, reactions=emojis)
324
- self._send(msg, **kwargs)
325
-
326
- def retract(
327
- self,
328
- legacy_msg_id: LegacyMessageType,
329
- thread: Optional[LegacyThreadType] = None,
330
- **kwargs,
331
- ):
332
- """
333
- Send a message retraction (:XEP:`0424`) from this :term:`XMPP Entity`.
334
-
335
- :param legacy_msg_id: Legacy ID of the message to delete
336
- :param thread:
337
- """
338
- msg = self._make_message(
339
- state=None,
340
- hints={"store"},
341
- mbody=f"/me retracted the message {legacy_msg_id}",
342
- carbon=kwargs.get("carbon"),
343
- thread=thread,
344
- )
345
- msg.enable("fallback")
346
- # namespace version mismatch between slidge and slixmpp, update me later
347
- msg["fallback"]["for"] = self.xmpp["xep_0424"].namespace[:-1] + "1"
348
- msg["retract"]["id"] = msg["replace"]["id"] = self.__replace_id(legacy_msg_id)
349
- self._send(msg, **kwargs)
153
+ class ContentMessageMixin(AttachmentMixin, TextMessageMixin):
154
+ pass
350
155
 
351
156
 
352
157
  class CarbonMessageMixin(ContentMessageMixin, MarkerMixin):
353
158
  def _privileged_send(self, msg: Message):
354
159
  i = msg.get_id()
355
- if not i:
356
- i = str(uuid.uuid4())
160
+ if i:
161
+ self.session.ignore_messages.add(i)
162
+ else:
163
+ i = "slidge-carbon-" + str(uuid.uuid4())
357
164
  msg.set_id(i)
358
165
  msg.del_origin_id()
359
- self.session.ignore_messages.add(i)
360
166
  try:
361
167
  self.xmpp["xep_0356"].send_privileged_message(msg)
362
168
  except PermissionError:
@@ -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__)
slidge/core/pubsub.py CHANGED
@@ -25,8 +25,9 @@ from ..db.store import ContactStore, SlidgeStore
25
25
  from .mixins.lock import NamedLockMixin
26
26
 
27
27
  if TYPE_CHECKING:
28
+ from slidge.core.gateway import BaseGateway
29
+
28
30
  from ..contact.contact import LegacyContact
29
- from ..core.gateway.base import BaseGateway
30
31
 
31
32
  VCARD4_NAMESPACE = "urn:xmpp:vcard4"
32
33
 
slidge/core/session.py CHANGED
@@ -31,6 +31,7 @@ from ..util.types import (
31
31
  PseudoPresenceShow,
32
32
  RecipientType,
33
33
  ResourceDict,
34
+ Sticker,
34
35
  )
35
36
  from ..util.util import deprecated
36
37
 
@@ -225,6 +226,31 @@ class BaseSession(
225
226
 
226
227
  send_file = deprecated("BaseSession.send_file", on_file)
227
228
 
229
+ async def on_sticker(
230
+ self,
231
+ chat: RecipientType,
232
+ sticker: Sticker,
233
+ *,
234
+ reply_to_msg_id: Optional[LegacyMessageType] = None,
235
+ reply_to_fallback_text: Optional[str] = None,
236
+ reply_to: Optional[Union["LegacyContact", "LegacyParticipant"]] = None,
237
+ thread: Optional[LegacyThreadType] = None,
238
+ ) -> Optional[LegacyMessageType]:
239
+ """
240
+ Triggered when the user sends a file using HTTP Upload (:xep:`0363`)
241
+
242
+ :param chat: See :meth:`.BaseSession.on_text`
243
+ :param sticker: The sticker sent by the user.
244
+ :param reply_to_msg_id: See :meth:`.BaseSession.on_text`
245
+ :param reply_to_fallback_text: See :meth:`.BaseSession.on_text`
246
+ :param reply_to: See :meth:`.BaseSession.on_text`
247
+ :param thread:
248
+
249
+ :return: An ID of some sort that can be used later to ack and mark the message
250
+ as read by the user
251
+ """
252
+ raise NotImplementedError
253
+
228
254
  async def on_active(
229
255
  self, chat: RecipientType, thread: Optional[LegacyThreadType] = None
230
256
  ):
@@ -729,8 +755,8 @@ class BaseSession(
729
755
  self.xmpp.re_login(self)
730
756
 
731
757
  async def get_contact_or_group_or_participant(self, jid: JID, create=True):
732
- if jid.bare in (contacts := self.contacts.known_contacts(only_friends=False)):
733
- return contacts[jid.bare]
758
+ if (contact := self.contacts.by_jid_only_if_exists(jid)) is not None:
759
+ return contact
734
760
  if (muc := self.bookmarks.by_jid_only_if_exists(JID(jid.bare))) is not None:
735
761
  return await self.__get_muc_or_participant(muc, jid)
736
762
  else:
@@ -0,0 +1,83 @@
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
+ with op.batch_alter_table(
63
+ "room",
64
+ schema=None,
65
+ # without copy_from, the newly created table keeps the constraints
66
+ # we actually want to ditch.
67
+ copy_from=room_table,
68
+ ) as batch_op:
69
+ batch_op.create_unique_constraint(
70
+ "uq_room_user_account_id_jid", ["user_account_id", "jid"]
71
+ )
72
+ batch_op.create_unique_constraint(
73
+ "uq_room_user_account_id_legacy_id", ["user_account_id", "legacy_id"]
74
+ )
75
+
76
+
77
+ def downgrade() -> None:
78
+ # ### commands auto generated by Alembic - please adjust! ###
79
+ with op.batch_alter_table("room", schema=None) as batch_op:
80
+ batch_op.drop_constraint("uq_room_user_account_id_legacy_id", type_="unique")
81
+ batch_op.drop_constraint("uq_room_user_account_id_jid", type_="unique")
82
+
83
+ # ### end Alembic commands ###
@@ -0,0 +1,42 @@
1
+ """Add BoB
2
+
3
+ Revision ID: 45c24cc73c91
4
+ Revises: 3071e0fa69d4
5
+ Create Date: 2024-08-01 22:30:07.073935
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 = "45c24cc73c91"
16
+ down_revision: Union[str, None] = "3071e0fa69d4"
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
+ # ### commands auto generated by Alembic - please adjust! ###
23
+ op.create_table(
24
+ "bob",
25
+ sa.Column("id", sa.Integer(), nullable=False),
26
+ sa.Column("file_name", sa.String(), nullable=False),
27
+ sa.Column("sha_1", sa.String(), nullable=False),
28
+ sa.Column("sha_256", sa.String(), nullable=False),
29
+ sa.Column("sha_512", sa.String(), nullable=False),
30
+ sa.Column("content_type", sa.String(), nullable=False),
31
+ sa.PrimaryKeyConstraint("id"),
32
+ sa.UniqueConstraint("sha_1"),
33
+ sa.UniqueConstraint("sha_256"),
34
+ sa.UniqueConstraint("sha_512"),
35
+ )
36
+ # ### end Alembic commands ###
37
+
38
+
39
+ def downgrade() -> None:
40
+ # ### commands auto generated by Alembic - please adjust! ###
41
+ op.drop_table("bob")
42
+ # ### end Alembic commands ###
@@ -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__)