slidge 0.3.0a2__py3-none-any.whl → 0.3.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.
- slidge/contact/contact.py +2 -2
- slidge/core/gateway.py +3 -4
- slidge/core/mixins/attachment.py +36 -2
- slidge/core/mixins/avatar.py +22 -5
- slidge/core/session.py +6 -2
- slidge/db/alembic/versions/cef02a8b1451_initial_schema.py +361 -0
- slidge/db/models.py +1 -0
- slidge/group/participant.py +1 -1
- slidge/group/room.py +26 -52
- slidge/migration.py +14 -5
- {slidge-0.3.0a2.dist-info → slidge-0.3.0b1.dist-info}/METADATA +1 -1
- {slidge-0.3.0a2.dist-info → slidge-0.3.0b1.dist-info}/RECORD +16 -38
- {slidge-0.3.0a2.dist-info → slidge-0.3.0b1.dist-info}/WHEEL +1 -1
- slidge/db/alembic/versions/0337c90c0b96_unify_legacy_xmpp_id_mappings.py +0 -183
- slidge/db/alembic/versions/04cf35e3cf85_add_participant_nickname_no_illegal.py +0 -33
- slidge/db/alembic/versions/09f27f098baa_add_missing_attributes_in_room.py +0 -36
- slidge/db/alembic/versions/15b0bd83407a_remove_bogus_unique_constraints_on_room_.py +0 -85
- slidge/db/alembic/versions/2461390c0af2_store_contacts_caps_verstring_in_db.py +0 -36
- slidge/db/alembic/versions/29f5280c61aa_store_subject_setter_in_room.py +0 -37
- slidge/db/alembic/versions/2b1f45ab7379_store_room_subject_setter_by_nickname.py +0 -41
- slidge/db/alembic/versions/3071e0fa69d4_add_contact_client_type.py +0 -52
- slidge/db/alembic/versions/45c24cc73c91_add_bob.py +0 -42
- slidge/db/alembic/versions/4dbd23a3f868_new_avatar_store.py +0 -105
- slidge/db/alembic/versions/54ce3cde350c_use_hash_for_avatar_filenames.py +0 -50
- slidge/db/alembic/versions/58b98dacf819_refactor.py +0 -118
- slidge/db/alembic/versions/5bd48bfdffa2_lift_room_legacy_id_constraint.py +0 -61
- slidge/db/alembic/versions/75a62b74b239_ditch_hats_table.py +0 -74
- slidge/db/alembic/versions/82a4af84b679_add_muc_history_filled.py +0 -48
- slidge/db/alembic/versions/8b993243a536_add_vcard_content_to_contact_table.py +0 -43
- slidge/db/alembic/versions/8d2ced764698_rely_on_db_to_store_contacts_rooms_and_.py +0 -139
- slidge/db/alembic/versions/aa9d82a7f6ef_db_creation.py +0 -50
- slidge/db/alembic/versions/abba1ae0edb3_store_avatar_legacy_id_in_the_contact_.py +0 -79
- slidge/db/alembic/versions/b33993e87db3_move_everything_to_persistent_db.py +0 -214
- slidge/db/alembic/versions/b64b1a793483_add_source_and_legacy_id_for_archived_.py +0 -52
- slidge/db/alembic/versions/c4a8ec35a0e8_per_room_user_nick.py +0 -34
- slidge/db/alembic/versions/e91195719c2c_store_users_avatars_persistently.py +0 -26
- {slidge-0.3.0a2.dist-info → slidge-0.3.0b1.dist-info}/entry_points.txt +0 -0
- {slidge-0.3.0a2.dist-info → slidge-0.3.0b1.dist-info}/licenses/LICENSE +0 -0
- {slidge-0.3.0a2.dist-info → slidge-0.3.0b1.dist-info}/top_level.txt +0 -0
slidge/contact/contact.py
CHANGED
@@ -95,7 +95,7 @@ class LegacyContact(
|
|
95
95
|
super().__init__()
|
96
96
|
|
97
97
|
@property
|
98
|
-
def jid(self):
|
98
|
+
def jid(self): # type:ignore[override]
|
99
99
|
jid = JID(self.stored.jid)
|
100
100
|
jid.resource = self.RESOURCE
|
101
101
|
return jid
|
@@ -298,7 +298,7 @@ class LegacyContact(
|
|
298
298
|
)
|
299
299
|
self.commit()
|
300
300
|
for p in self.participants:
|
301
|
-
p.nickname = n
|
301
|
+
p.nickname = n or str(self.legacy_id)
|
302
302
|
|
303
303
|
def _post_avatar_update(self, cached_avatar) -> None:
|
304
304
|
if self.is_friend and self.added_to_roster:
|
slidge/core/gateway.py
CHANGED
@@ -472,7 +472,7 @@ class BaseGateway(
|
|
472
472
|
)
|
473
473
|
|
474
474
|
@property # type: ignore
|
475
|
-
def jid(self):
|
475
|
+
def jid(self): # type:ignore[override]
|
476
476
|
# Override to avoid slixmpp deprecation warnings.
|
477
477
|
return self.boundjid
|
478
478
|
|
@@ -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,
|
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:
|
slidge/core/mixins/attachment.py
CHANGED
@@ -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(
|
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:
|
@@ -400,6 +403,37 @@ class AttachmentMixin(TextMessageMixin):
|
|
400
403
|
:param when: when the file was sent, for a "delay" tag (:xep:`0203`)
|
401
404
|
:param thread:
|
402
405
|
"""
|
406
|
+
coro = self.__send_file(
|
407
|
+
attachment,
|
408
|
+
legacy_msg_id,
|
409
|
+
reply_to=reply_to,
|
410
|
+
when=when,
|
411
|
+
thread=thread,
|
412
|
+
**kwargs,
|
413
|
+
)
|
414
|
+
if self.session is NotImplemented:
|
415
|
+
return await coro
|
416
|
+
elif not isinstance(attachment, LegacyAttachment):
|
417
|
+
return await coro
|
418
|
+
elif attachment.legacy_file_id is None:
|
419
|
+
return await coro
|
420
|
+
else:
|
421
|
+
# prevents race conditions where we download the same thing several time
|
422
|
+
# and end up attempting to insert it twice in the DB, raising an
|
423
|
+
# IntegrityError.
|
424
|
+
async with self.session.lock(("attachment", attachment.legacy_file_id)):
|
425
|
+
return await coro
|
426
|
+
|
427
|
+
async def __send_file(
|
428
|
+
self,
|
429
|
+
attachment: LegacyAttachment | Path | str,
|
430
|
+
legacy_msg_id: Optional[LegacyMessageType] = None,
|
431
|
+
*,
|
432
|
+
reply_to: Optional[MessageReference] = None,
|
433
|
+
when: Optional[datetime] = None,
|
434
|
+
thread: Optional[LegacyThreadType] = None,
|
435
|
+
**kwargs,
|
436
|
+
) -> tuple[Optional[str], list[Message]]:
|
403
437
|
store_multi = kwargs.pop("store_multi", True)
|
404
438
|
carbon = kwargs.pop("carbon", False)
|
405
439
|
mto = kwargs.pop("mto", None)
|
slidge/core/mixins/avatar.py
CHANGED
@@ -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
|
@@ -122,11 +123,27 @@ class AvatarMixin(UpdateInfoMixin):
|
|
122
123
|
else:
|
123
124
|
avatar.path.unlink()
|
124
125
|
|
125
|
-
if cached_avatar is None
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
126
|
+
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
|
+
)
|
142
|
+
self.stored = orm.merge(self.stored)
|
143
|
+
self.stored.avatar = stored_avatar
|
144
|
+
orm.add(self.stored)
|
145
|
+
orm.commit()
|
146
|
+
|
130
147
|
self._post_avatar_update(cached_avatar)
|
131
148
|
|
132
149
|
def get_cached_avatar(self) -> Optional["CachedAvatar"]:
|
slidge/core/session.py
CHANGED
@@ -24,6 +24,7 @@ from ..db.models import Contact, GatewayUser
|
|
24
24
|
from ..group.bookmarks import LegacyBookmarks
|
25
25
|
from ..group.room import LegacyMUC
|
26
26
|
from ..util import ABCSubclassableOnceAtMost
|
27
|
+
from ..util.lock import NamedLockMixin
|
27
28
|
from ..util.types import (
|
28
29
|
LegacyGroupIdType,
|
29
30
|
LegacyMessageType,
|
@@ -50,7 +51,9 @@ class CachedPresence(NamedTuple):
|
|
50
51
|
|
51
52
|
|
52
53
|
class BaseSession(
|
53
|
-
Generic[LegacyMessageType, RecipientType],
|
54
|
+
Generic[LegacyMessageType, RecipientType],
|
55
|
+
NamedLockMixin,
|
56
|
+
metaclass=ABCSubclassableOnceAtMost,
|
54
57
|
):
|
55
58
|
"""
|
56
59
|
The session of a registered :term:`User`.
|
@@ -95,6 +98,7 @@ class BaseSession(
|
|
95
98
|
_bookmarks_cls: Type[LegacyBookmarks]
|
96
99
|
|
97
100
|
def __init__(self, user: GatewayUser) -> None:
|
101
|
+
super().__init__()
|
98
102
|
self.user = user
|
99
103
|
self.log = logging.getLogger(user.jid.bare)
|
100
104
|
|
@@ -704,8 +708,8 @@ class BaseSession(
|
|
704
708
|
log.warning("User not found during unregistration")
|
705
709
|
return
|
706
710
|
|
711
|
+
await cls.xmpp.unregister(session)
|
707
712
|
with cls.xmpp.store.session() as orm:
|
708
|
-
await cls.xmpp.unregister(session.user)
|
709
713
|
orm.delete(session.user)
|
710
714
|
orm.commit()
|
711
715
|
|
@@ -0,0 +1,361 @@
|
|
1
|
+
"""Initial schema
|
2
|
+
|
3
|
+
Revision ID: cef02a8b1451
|
4
|
+
Revises:
|
5
|
+
Create Date: 2025-08-28 12:48:16.890606
|
6
|
+
|
7
|
+
"""
|
8
|
+
|
9
|
+
from typing import Sequence, Union
|
10
|
+
|
11
|
+
import sqlalchemy as sa
|
12
|
+
from alembic import op
|
13
|
+
|
14
|
+
import slidge
|
15
|
+
|
16
|
+
# revision identifiers, used by Alembic.
|
17
|
+
revision: str = "cef02a8b1451"
|
18
|
+
down_revision: Union[str, None] = None
|
19
|
+
branch_labels: Union[str, Sequence[str], None] = None
|
20
|
+
depends_on: Union[str, Sequence[str], None] = None
|
21
|
+
|
22
|
+
|
23
|
+
def upgrade() -> None:
|
24
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
25
|
+
op.create_table(
|
26
|
+
"avatar",
|
27
|
+
sa.Column("id", sa.Integer(), nullable=False),
|
28
|
+
sa.Column("hash", sa.String(), nullable=False),
|
29
|
+
sa.Column("height", sa.Integer(), nullable=False),
|
30
|
+
sa.Column("width", sa.Integer(), nullable=False),
|
31
|
+
sa.Column("legacy_id", sa.String(), nullable=True),
|
32
|
+
sa.Column("url", sa.String(), nullable=True),
|
33
|
+
sa.Column("etag", sa.String(), nullable=True),
|
34
|
+
sa.Column("last_modified", sa.String(), nullable=True),
|
35
|
+
sa.PrimaryKeyConstraint("id", name=op.f("pk_avatar")),
|
36
|
+
sa.UniqueConstraint("hash", name=op.f("uq_avatar_hash")),
|
37
|
+
sa.UniqueConstraint("legacy_id", name=op.f("uq_avatar_legacy_id")),
|
38
|
+
)
|
39
|
+
op.create_table(
|
40
|
+
"bob",
|
41
|
+
sa.Column("id", sa.Integer(), nullable=False),
|
42
|
+
sa.Column("file_name", sa.String(), nullable=False),
|
43
|
+
sa.Column("sha_1", sa.String(), nullable=False),
|
44
|
+
sa.Column("sha_256", sa.String(), nullable=False),
|
45
|
+
sa.Column("sha_512", sa.String(), nullable=False),
|
46
|
+
sa.Column("content_type", sa.String(), nullable=False),
|
47
|
+
sa.PrimaryKeyConstraint("id", name=op.f("pk_bob")),
|
48
|
+
sa.UniqueConstraint("sha_1", name=op.f("uq_bob_sha_1")),
|
49
|
+
sa.UniqueConstraint("sha_256", name=op.f("uq_bob_sha_256")),
|
50
|
+
sa.UniqueConstraint("sha_512", name=op.f("uq_bob_sha_512")),
|
51
|
+
)
|
52
|
+
op.create_table(
|
53
|
+
"user_account",
|
54
|
+
sa.Column("id", sa.Integer(), nullable=False),
|
55
|
+
sa.Column("jid", slidge.db.meta.JIDType(), nullable=False),
|
56
|
+
sa.Column(
|
57
|
+
"registration_date",
|
58
|
+
sa.DateTime(),
|
59
|
+
server_default=sa.text("(CURRENT_TIMESTAMP)"),
|
60
|
+
nullable=False,
|
61
|
+
),
|
62
|
+
sa.Column(
|
63
|
+
"legacy_module_data", slidge.db.meta.JSONEncodedDict(), nullable=False
|
64
|
+
),
|
65
|
+
sa.Column("preferences", slidge.db.meta.JSONEncodedDict(), nullable=False),
|
66
|
+
sa.Column("avatar_hash", sa.String(), nullable=True),
|
67
|
+
sa.PrimaryKeyConstraint("id", name=op.f("pk_user_account")),
|
68
|
+
sa.UniqueConstraint("jid", name=op.f("uq_user_account_jid")),
|
69
|
+
)
|
70
|
+
op.create_table(
|
71
|
+
"attachment",
|
72
|
+
sa.Column("id", sa.Integer(), nullable=False),
|
73
|
+
sa.Column("user_account_id", sa.Integer(), nullable=False),
|
74
|
+
sa.Column("legacy_file_id", sa.String(), nullable=True),
|
75
|
+
sa.Column("url", sa.String(), nullable=False),
|
76
|
+
sa.Column("sims", sa.String(), nullable=True),
|
77
|
+
sa.Column("sfs", sa.String(), nullable=True),
|
78
|
+
sa.ForeignKeyConstraint(
|
79
|
+
["user_account_id"],
|
80
|
+
["user_account.id"],
|
81
|
+
name=op.f("fk_attachment_user_account_id_user_account"),
|
82
|
+
),
|
83
|
+
sa.PrimaryKeyConstraint("id", name=op.f("pk_attachment")),
|
84
|
+
sa.UniqueConstraint(
|
85
|
+
"user_account_id",
|
86
|
+
"legacy_file_id",
|
87
|
+
name=op.f("uq_attachment_user_account_id"),
|
88
|
+
),
|
89
|
+
)
|
90
|
+
with op.batch_alter_table("attachment", schema=None) as batch_op:
|
91
|
+
batch_op.create_index(
|
92
|
+
batch_op.f("ix_attachment_legacy_file_id"), ["legacy_file_id"], unique=False
|
93
|
+
)
|
94
|
+
batch_op.create_index(batch_op.f("ix_attachment_url"), ["url"], unique=False)
|
95
|
+
|
96
|
+
op.create_table(
|
97
|
+
"contact",
|
98
|
+
sa.Column("id", sa.Integer(), nullable=False),
|
99
|
+
sa.Column("user_account_id", sa.Integer(), nullable=False),
|
100
|
+
sa.Column("legacy_id", sa.String(), nullable=False),
|
101
|
+
sa.Column("jid", slidge.db.meta.JIDType(), nullable=False),
|
102
|
+
sa.Column("avatar_id", sa.Integer(), nullable=True),
|
103
|
+
sa.Column("nick", sa.String(), nullable=True),
|
104
|
+
sa.Column("cached_presence", sa.Boolean(), nullable=False),
|
105
|
+
sa.Column("last_seen", sa.DateTime(), nullable=True),
|
106
|
+
sa.Column("ptype", sa.String(), nullable=True),
|
107
|
+
sa.Column("pstatus", sa.String(), nullable=True),
|
108
|
+
sa.Column("pshow", sa.String(), nullable=True),
|
109
|
+
sa.Column("caps_ver", sa.String(), nullable=True),
|
110
|
+
sa.Column("is_friend", sa.Boolean(), nullable=False),
|
111
|
+
sa.Column("added_to_roster", sa.Boolean(), nullable=False),
|
112
|
+
sa.Column("extra_attributes", slidge.db.meta.JSONEncodedDict(), nullable=True),
|
113
|
+
sa.Column("updated", sa.Boolean(), nullable=False),
|
114
|
+
sa.Column("vcard", sa.String(), nullable=True),
|
115
|
+
sa.Column("vcard_fetched", sa.Boolean(), nullable=False),
|
116
|
+
sa.Column(
|
117
|
+
"client_type",
|
118
|
+
sa.Enum(
|
119
|
+
"bot",
|
120
|
+
"console",
|
121
|
+
"game",
|
122
|
+
"handheld",
|
123
|
+
"pc",
|
124
|
+
"phone",
|
125
|
+
"sms",
|
126
|
+
"tablet",
|
127
|
+
"web",
|
128
|
+
native_enum=False,
|
129
|
+
),
|
130
|
+
nullable=False,
|
131
|
+
),
|
132
|
+
sa.ForeignKeyConstraint(
|
133
|
+
["avatar_id"], ["avatar.id"], name=op.f("fk_contact_avatar_id_avatar")
|
134
|
+
),
|
135
|
+
sa.ForeignKeyConstraint(
|
136
|
+
["user_account_id"],
|
137
|
+
["user_account.id"],
|
138
|
+
name=op.f("fk_contact_user_account_id_user_account"),
|
139
|
+
),
|
140
|
+
sa.PrimaryKeyConstraint("id", name=op.f("pk_contact")),
|
141
|
+
sa.UniqueConstraint(
|
142
|
+
"user_account_id", "jid", name=op.f("uq_contact_user_account_id")
|
143
|
+
),
|
144
|
+
sa.UniqueConstraint(
|
145
|
+
"user_account_id", "legacy_id", name=op.f("uq_contact_user_account_id")
|
146
|
+
),
|
147
|
+
)
|
148
|
+
op.create_table(
|
149
|
+
"room",
|
150
|
+
sa.Column("id", sa.Integer(), nullable=False),
|
151
|
+
sa.Column("user_account_id", sa.Integer(), nullable=False),
|
152
|
+
sa.Column("legacy_id", sa.String(), nullable=False),
|
153
|
+
sa.Column("jid", slidge.db.meta.JIDType(), nullable=False),
|
154
|
+
sa.Column("avatar_id", sa.Integer(), nullable=True),
|
155
|
+
sa.Column("name", sa.String(), nullable=True),
|
156
|
+
sa.Column("description", sa.String(), nullable=True),
|
157
|
+
sa.Column("subject", sa.String(), nullable=True),
|
158
|
+
sa.Column("subject_date", sa.DateTime(), nullable=True),
|
159
|
+
sa.Column("subject_setter", sa.String(), nullable=True),
|
160
|
+
sa.Column("n_participants", sa.Integer(), nullable=True),
|
161
|
+
sa.Column(
|
162
|
+
"muc_type",
|
163
|
+
sa.Enum("GROUP", "CHANNEL", "CHANNEL_NON_ANONYMOUS", name="muctype"),
|
164
|
+
nullable=False,
|
165
|
+
),
|
166
|
+
sa.Column("user_nick", sa.String(), nullable=True),
|
167
|
+
sa.Column("user_resources", sa.String(), nullable=True),
|
168
|
+
sa.Column("participants_filled", sa.Boolean(), nullable=False),
|
169
|
+
sa.Column("history_filled", sa.Boolean(), nullable=False),
|
170
|
+
sa.Column("extra_attributes", slidge.db.meta.JSONEncodedDict(), nullable=True),
|
171
|
+
sa.Column("updated", sa.Boolean(), nullable=False),
|
172
|
+
sa.ForeignKeyConstraint(
|
173
|
+
["avatar_id"], ["avatar.id"], name=op.f("fk_room_avatar_id_avatar")
|
174
|
+
),
|
175
|
+
sa.ForeignKeyConstraint(
|
176
|
+
["user_account_id"],
|
177
|
+
["user_account.id"],
|
178
|
+
name=op.f("fk_room_user_account_id_user_account"),
|
179
|
+
),
|
180
|
+
sa.PrimaryKeyConstraint("id", name=op.f("pk_room")),
|
181
|
+
sa.UniqueConstraint(
|
182
|
+
"user_account_id", "jid", name="uq_room_user_account_id_jid"
|
183
|
+
),
|
184
|
+
sa.UniqueConstraint(
|
185
|
+
"user_account_id", "legacy_id", name="uq_room_user_account_id_legacy_id"
|
186
|
+
),
|
187
|
+
)
|
188
|
+
op.create_table(
|
189
|
+
"contact_sent",
|
190
|
+
sa.Column("id", sa.Integer(), nullable=False),
|
191
|
+
sa.Column("contact_id", sa.Integer(), nullable=False),
|
192
|
+
sa.Column("msg_id", sa.String(), nullable=False),
|
193
|
+
sa.ForeignKeyConstraint(
|
194
|
+
["contact_id"],
|
195
|
+
["contact.id"],
|
196
|
+
name=op.f("fk_contact_sent_contact_id_contact"),
|
197
|
+
),
|
198
|
+
sa.PrimaryKeyConstraint("id", name=op.f("pk_contact_sent")),
|
199
|
+
sa.UniqueConstraint(
|
200
|
+
"contact_id", "msg_id", name=op.f("uq_contact_sent_contact_id")
|
201
|
+
),
|
202
|
+
)
|
203
|
+
op.create_table(
|
204
|
+
"direct_msg",
|
205
|
+
sa.Column("foreign_key", sa.Integer(), nullable=False),
|
206
|
+
sa.Column("id", sa.Integer(), nullable=False),
|
207
|
+
sa.Column("legacy_id", sa.String(), nullable=False),
|
208
|
+
sa.Column("xmpp_id", sa.String(), nullable=False),
|
209
|
+
sa.ForeignKeyConstraint(
|
210
|
+
["foreign_key"],
|
211
|
+
["contact.id"],
|
212
|
+
name=op.f("fk_direct_msg_foreign_key_contact"),
|
213
|
+
),
|
214
|
+
sa.PrimaryKeyConstraint("id", name=op.f("pk_direct_msg")),
|
215
|
+
)
|
216
|
+
with op.batch_alter_table("direct_msg", schema=None) as batch_op:
|
217
|
+
batch_op.create_index(
|
218
|
+
"ix_direct_msg_legacy_id", ["legacy_id", "foreign_key"], unique=False
|
219
|
+
)
|
220
|
+
|
221
|
+
op.create_table(
|
222
|
+
"direct_thread",
|
223
|
+
sa.Column("foreign_key", sa.Integer(), nullable=False),
|
224
|
+
sa.Column("id", sa.Integer(), nullable=False),
|
225
|
+
sa.Column("legacy_id", sa.String(), nullable=False),
|
226
|
+
sa.Column("xmpp_id", sa.String(), nullable=False),
|
227
|
+
sa.ForeignKeyConstraint(
|
228
|
+
["foreign_key"],
|
229
|
+
["contact.id"],
|
230
|
+
name=op.f("fk_direct_thread_foreign_key_contact"),
|
231
|
+
),
|
232
|
+
sa.PrimaryKeyConstraint("id", name=op.f("pk_direct_thread")),
|
233
|
+
)
|
234
|
+
with op.batch_alter_table("direct_thread", schema=None) as batch_op:
|
235
|
+
batch_op.create_index(
|
236
|
+
"ix_direct_direct_thread_id", ["legacy_id", "foreign_key"], unique=False
|
237
|
+
)
|
238
|
+
|
239
|
+
op.create_table(
|
240
|
+
"group_msg",
|
241
|
+
sa.Column("foreign_key", sa.Integer(), nullable=False),
|
242
|
+
sa.Column("id", sa.Integer(), nullable=False),
|
243
|
+
sa.Column("legacy_id", sa.String(), nullable=False),
|
244
|
+
sa.Column("xmpp_id", sa.String(), nullable=False),
|
245
|
+
sa.ForeignKeyConstraint(
|
246
|
+
["foreign_key"], ["room.id"], name=op.f("fk_group_msg_foreign_key_room")
|
247
|
+
),
|
248
|
+
sa.PrimaryKeyConstraint("id", name=op.f("pk_group_msg")),
|
249
|
+
)
|
250
|
+
with op.batch_alter_table("group_msg", schema=None) as batch_op:
|
251
|
+
batch_op.create_index(
|
252
|
+
"ix_group_msg_legacy_id", ["legacy_id", "foreign_key"], unique=False
|
253
|
+
)
|
254
|
+
|
255
|
+
op.create_table(
|
256
|
+
"group_thread",
|
257
|
+
sa.Column("foreign_key", sa.Integer(), nullable=False),
|
258
|
+
sa.Column("id", sa.Integer(), nullable=False),
|
259
|
+
sa.Column("legacy_id", sa.String(), nullable=False),
|
260
|
+
sa.Column("xmpp_id", sa.String(), nullable=False),
|
261
|
+
sa.ForeignKeyConstraint(
|
262
|
+
["foreign_key"], ["room.id"], name=op.f("fk_group_thread_foreign_key_room")
|
263
|
+
),
|
264
|
+
sa.PrimaryKeyConstraint("id", name=op.f("pk_group_thread")),
|
265
|
+
)
|
266
|
+
with op.batch_alter_table("group_thread", schema=None) as batch_op:
|
267
|
+
batch_op.create_index(
|
268
|
+
"ix_direct_group_thread_id", ["legacy_id", "foreign_key"], unique=False
|
269
|
+
)
|
270
|
+
|
271
|
+
op.create_table(
|
272
|
+
"mam",
|
273
|
+
sa.Column("id", sa.Integer(), nullable=False),
|
274
|
+
sa.Column("room_id", sa.Integer(), nullable=False),
|
275
|
+
sa.Column("stanza_id", sa.String(), nullable=False),
|
276
|
+
sa.Column("timestamp", sa.DateTime(), nullable=False),
|
277
|
+
sa.Column("author_jid", slidge.db.meta.JIDType(), nullable=False),
|
278
|
+
sa.Column(
|
279
|
+
"source",
|
280
|
+
sa.Enum("LIVE", "BACKFILL", name="archivedmessagesource"),
|
281
|
+
nullable=False,
|
282
|
+
),
|
283
|
+
sa.Column("legacy_id", sa.String(), nullable=True),
|
284
|
+
sa.Column("stanza", sa.String(), nullable=False),
|
285
|
+
sa.ForeignKeyConstraint(
|
286
|
+
["room_id"], ["room.id"], name=op.f("fk_mam_room_id_room")
|
287
|
+
),
|
288
|
+
sa.PrimaryKeyConstraint("id", name=op.f("pk_mam")),
|
289
|
+
sa.UniqueConstraint("room_id", "stanza_id", name=op.f("uq_mam_room_id")),
|
290
|
+
)
|
291
|
+
op.create_table(
|
292
|
+
"participant",
|
293
|
+
sa.Column("id", sa.Integer(), nullable=False),
|
294
|
+
sa.Column("room_id", sa.Integer(), nullable=False),
|
295
|
+
sa.Column("contact_id", sa.Integer(), nullable=True),
|
296
|
+
sa.Column("is_user", sa.Boolean(), nullable=False),
|
297
|
+
sa.Column(
|
298
|
+
"affiliation",
|
299
|
+
sa.Enum("outcast", "member", "admin", "owner", "none", native_enum=False),
|
300
|
+
nullable=False,
|
301
|
+
),
|
302
|
+
sa.Column(
|
303
|
+
"role",
|
304
|
+
sa.Enum("moderator", "participant", "visitor", "none", native_enum=False),
|
305
|
+
nullable=False,
|
306
|
+
),
|
307
|
+
sa.Column("presence_sent", sa.Boolean(), nullable=False),
|
308
|
+
sa.Column("resource", sa.String(), nullable=False),
|
309
|
+
sa.Column("nickname", sa.String(), nullable=False),
|
310
|
+
sa.Column("nickname_no_illegal", sa.String(), nullable=False),
|
311
|
+
sa.Column("hats", sa.JSON(), nullable=False),
|
312
|
+
sa.Column("extra_attributes", slidge.db.meta.JSONEncodedDict(), nullable=True),
|
313
|
+
sa.ForeignKeyConstraint(
|
314
|
+
["contact_id"],
|
315
|
+
["contact.id"],
|
316
|
+
name=op.f("fk_participant_contact_id_contact"),
|
317
|
+
),
|
318
|
+
sa.ForeignKeyConstraint(
|
319
|
+
["room_id"], ["room.id"], name=op.f("fk_participant_room_id_room")
|
320
|
+
),
|
321
|
+
sa.PrimaryKeyConstraint("id", name=op.f("pk_participant")),
|
322
|
+
sa.UniqueConstraint(
|
323
|
+
"room_id", "contact_id", name=op.f("uq_participant_room_id")
|
324
|
+
),
|
325
|
+
sa.UniqueConstraint("room_id", "resource", name=op.f("uq_participant_room_id")),
|
326
|
+
)
|
327
|
+
# ### end Alembic commands ###
|
328
|
+
|
329
|
+
|
330
|
+
def downgrade() -> None:
|
331
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
332
|
+
op.drop_table("participant")
|
333
|
+
op.drop_table("mam")
|
334
|
+
with op.batch_alter_table("group_thread", schema=None) as batch_op:
|
335
|
+
batch_op.drop_index("ix_direct_group_thread_id")
|
336
|
+
|
337
|
+
op.drop_table("group_thread")
|
338
|
+
with op.batch_alter_table("group_msg", schema=None) as batch_op:
|
339
|
+
batch_op.drop_index("ix_group_msg_legacy_id")
|
340
|
+
|
341
|
+
op.drop_table("group_msg")
|
342
|
+
with op.batch_alter_table("direct_thread", schema=None) as batch_op:
|
343
|
+
batch_op.drop_index("ix_direct_direct_thread_id")
|
344
|
+
|
345
|
+
op.drop_table("direct_thread")
|
346
|
+
with op.batch_alter_table("direct_msg", schema=None) as batch_op:
|
347
|
+
batch_op.drop_index("ix_direct_msg_legacy_id")
|
348
|
+
|
349
|
+
op.drop_table("direct_msg")
|
350
|
+
op.drop_table("contact_sent")
|
351
|
+
op.drop_table("room")
|
352
|
+
op.drop_table("contact")
|
353
|
+
with op.batch_alter_table("attachment", schema=None) as batch_op:
|
354
|
+
batch_op.drop_index(batch_op.f("ix_attachment_url"))
|
355
|
+
batch_op.drop_index(batch_op.f("ix_attachment_legacy_file_id"))
|
356
|
+
|
357
|
+
op.drop_table("attachment")
|
358
|
+
op.drop_table("user_account")
|
359
|
+
op.drop_table("bob")
|
360
|
+
op.drop_table("avatar")
|
361
|
+
# ### end Alembic commands ###
|
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"))
|