slidge 0.1.3__py3-none-any.whl → 0.2.0a1__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 (74) hide show
  1. slidge/__init__.py +3 -5
  2. slidge/__main__.py +2 -196
  3. slidge/__version__.py +5 -0
  4. slidge/command/adhoc.py +8 -1
  5. slidge/command/admin.py +6 -7
  6. slidge/command/base.py +1 -2
  7. slidge/command/register.py +32 -16
  8. slidge/command/user.py +85 -6
  9. slidge/contact/contact.py +165 -49
  10. slidge/contact/roster.py +122 -47
  11. slidge/core/config.py +14 -11
  12. slidge/core/gateway/base.py +148 -36
  13. slidge/core/gateway/caps.py +7 -5
  14. slidge/core/gateway/disco.py +2 -4
  15. slidge/core/gateway/mam.py +1 -4
  16. slidge/core/gateway/muc_admin.py +1 -1
  17. slidge/core/gateway/ping.py +2 -3
  18. slidge/core/gateway/presence.py +1 -1
  19. slidge/core/gateway/registration.py +32 -21
  20. slidge/core/gateway/search.py +3 -5
  21. slidge/core/gateway/session_dispatcher.py +120 -57
  22. slidge/core/gateway/vcard_temp.py +7 -5
  23. slidge/core/mixins/__init__.py +11 -1
  24. slidge/core/mixins/attachment.py +32 -14
  25. slidge/core/mixins/avatar.py +90 -25
  26. slidge/core/mixins/base.py +8 -2
  27. slidge/core/mixins/db.py +18 -0
  28. slidge/core/mixins/disco.py +0 -10
  29. slidge/core/mixins/message.py +18 -8
  30. slidge/core/mixins/message_maker.py +17 -9
  31. slidge/core/mixins/presence.py +17 -4
  32. slidge/core/pubsub.py +54 -220
  33. slidge/core/session.py +69 -34
  34. slidge/db/__init__.py +4 -0
  35. slidge/db/alembic/env.py +64 -0
  36. slidge/db/alembic/script.py.mako +26 -0
  37. slidge/db/alembic/versions/09f27f098baa_add_missing_attributes_in_room.py +36 -0
  38. slidge/db/alembic/versions/2461390c0af2_store_contacts_caps_verstring_in_db.py +36 -0
  39. slidge/db/alembic/versions/29f5280c61aa_store_subject_setter_in_room.py +37 -0
  40. slidge/db/alembic/versions/2b1f45ab7379_store_room_subject_setter_by_nickname.py +41 -0
  41. slidge/db/alembic/versions/82a4af84b679_add_muc_history_filled.py +48 -0
  42. slidge/db/alembic/versions/8d2ced764698_rely_on_db_to_store_contacts_rooms_and_.py +133 -0
  43. slidge/db/alembic/versions/aa9d82a7f6ef_db_creation.py +85 -0
  44. slidge/db/alembic/versions/b33993e87db3_move_everything_to_persistent_db.py +214 -0
  45. slidge/db/alembic/versions/b64b1a793483_add_source_and_legacy_id_for_archived_.py +48 -0
  46. slidge/db/alembic/versions/c4a8ec35a0e8_per_room_user_nick.py +34 -0
  47. slidge/db/alembic/versions/e91195719c2c_store_users_avatars_persistently.py +26 -0
  48. slidge/db/avatar.py +235 -0
  49. slidge/db/meta.py +65 -0
  50. slidge/db/models.py +375 -0
  51. slidge/db/store.py +1078 -0
  52. slidge/group/archive.py +58 -14
  53. slidge/group/bookmarks.py +72 -57
  54. slidge/group/participant.py +87 -28
  55. slidge/group/room.py +369 -211
  56. slidge/main.py +201 -0
  57. slidge/migration.py +30 -0
  58. slidge/slixfix/__init__.py +35 -2
  59. slidge/slixfix/roster.py +11 -4
  60. slidge/slixfix/xep_0292/vcard4.py +3 -0
  61. slidge/util/archive_msg.py +2 -1
  62. slidge/util/db.py +1 -47
  63. slidge/util/test.py +71 -4
  64. slidge/util/types.py +29 -4
  65. slidge/util/util.py +22 -0
  66. {slidge-0.1.3.dist-info → slidge-0.2.0a1.dist-info}/METADATA +4 -4
  67. slidge-0.2.0a1.dist-info/RECORD +114 -0
  68. slidge/core/cache.py +0 -183
  69. slidge/util/schema.sql +0 -126
  70. slidge/util/sql.py +0 -508
  71. slidge-0.1.3.dist-info/RECORD +0 -96
  72. {slidge-0.1.3.dist-info → slidge-0.2.0a1.dist-info}/LICENSE +0 -0
  73. {slidge-0.1.3.dist-info → slidge-0.2.0a1.dist-info}/WHEEL +0 -0
  74. {slidge-0.1.3.dist-info → slidge-0.2.0a1.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,64 @@
1
+ from alembic import context
2
+
3
+ from slidge import global_config
4
+ from slidge.db.meta import Base, get_engine
5
+
6
+ config = context.config
7
+
8
+ target_metadata = Base.metadata
9
+
10
+
11
+ def run_migrations_offline() -> None:
12
+ """Run migrations in 'offline' mode.
13
+
14
+ This configures the context with just a URL
15
+ and not an Engine, though an Engine is acceptable
16
+ here as well. By skipping the Engine creation
17
+ we don't even need a DBAPI to be available.
18
+
19
+ Calls to context.execute() here emit the given string to the
20
+ script output.
21
+
22
+ """
23
+ url = config.get_main_option("sqlalchemy.url")
24
+ context.configure(
25
+ url=url,
26
+ target_metadata=target_metadata,
27
+ literal_binds=True,
28
+ dialect_opts={"paramstyle": "named"},
29
+ render_as_batch=True,
30
+ )
31
+
32
+ with context.begin_transaction():
33
+ context.run_migrations()
34
+
35
+
36
+ def run_migrations_online() -> None:
37
+ """Run migrations in 'online' mode.
38
+
39
+ In this scenario we need to create an Engine
40
+ and associate a connection with the context.
41
+
42
+ """
43
+ try:
44
+ # in prod
45
+ connectable = get_engine(global_config.DB_URL)
46
+ except AttributeError:
47
+ # during dev, to generate migrations
48
+ connectable = get_engine("sqlite+pysqlite:///dev/slidge.sqlite")
49
+
50
+ with connectable.connect() as connection:
51
+ context.configure(
52
+ connection=connection,
53
+ target_metadata=target_metadata,
54
+ render_as_batch=True,
55
+ )
56
+
57
+ with context.begin_transaction():
58
+ context.run_migrations()
59
+
60
+
61
+ if context.is_offline_mode():
62
+ run_migrations_offline()
63
+ else:
64
+ run_migrations_online()
@@ -0,0 +1,26 @@
1
+ """${message}
2
+
3
+ Revision ID: ${up_revision}
4
+ Revises: ${down_revision | comma,n}
5
+ Create Date: ${create_date}
6
+
7
+ """
8
+ from typing import Sequence, Union
9
+
10
+ from alembic import op
11
+ import sqlalchemy as sa
12
+ ${imports if imports else ""}
13
+
14
+ # revision identifiers, used by Alembic.
15
+ revision: str = ${repr(up_revision)}
16
+ down_revision: Union[str, None] = ${repr(down_revision)}
17
+ branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
18
+ depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
19
+
20
+
21
+ def upgrade() -> None:
22
+ ${upgrades if upgrades else "pass"}
23
+
24
+
25
+ def downgrade() -> None:
26
+ ${downgrades if downgrades else "pass"}
@@ -0,0 +1,36 @@
1
+ """Add n_participants attributes to Room
2
+
3
+ Should have been part of another commit, but I messed up some rebase
4
+
5
+ Revision ID: 09f27f098baa
6
+ Revises: 29f5280c61aa
7
+ Create Date: 2024-07-11 10:54:21.155871
8
+
9
+ """
10
+
11
+ from typing import Sequence, Union
12
+
13
+ import sqlalchemy as sa
14
+ from alembic import op
15
+
16
+ # revision identifiers, used by Alembic.
17
+ revision: str = "09f27f098baa"
18
+ down_revision: Union[str, None] = "29f5280c61aa"
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
+ with op.batch_alter_table("room", schema=None) as batch_op:
26
+ batch_op.add_column(sa.Column("n_participants", sa.Integer(), nullable=True))
27
+
28
+ # ### end Alembic commands ###
29
+
30
+
31
+ def downgrade() -> None:
32
+ # ### commands auto generated by Alembic - please adjust! ###
33
+ with op.batch_alter_table("room", schema=None) as batch_op:
34
+ batch_op.drop_column("n_participants")
35
+
36
+ # ### end Alembic commands ###
@@ -0,0 +1,36 @@
1
+ """Store contacts caps verstring in DB
2
+
3
+ Revision ID: 2461390c0af2
4
+ Revises: 2b1f45ab7379
5
+ Create Date: 2024-07-20 08:00:11.675735
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 = "2461390c0af2"
16
+ down_revision: Union[str, None] = "2b1f45ab7379"
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
+ with op.batch_alter_table("contact", schema=None) as batch_op:
24
+ batch_op.add_column(sa.Column("caps_ver_bare", sa.String(), nullable=True))
25
+ batch_op.add_column(sa.Column("caps_ver", sa.String(), nullable=True))
26
+
27
+ # ### end Alembic commands ###
28
+
29
+
30
+ def downgrade() -> None:
31
+ # ### commands auto generated by Alembic - please adjust! ###
32
+ with op.batch_alter_table("contact", schema=None) as batch_op:
33
+ batch_op.drop_column("caps_ver")
34
+ batch_op.drop_column("caps_ver_bare")
35
+
36
+ # ### end Alembic commands ###
@@ -0,0 +1,37 @@
1
+ """Store subject setter in Room
2
+
3
+ Revision ID: 29f5280c61aa
4
+ Revises: 8d2ced764698
5
+ Create Date: 2024-07-10 13:09:25.181594
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 = "29f5280c61aa"
16
+ down_revision: Union[str, None] = "8d2ced764698"
17
+ branch_labels: Union[str, Sequence[str], None] = None
18
+ depends_on: Union[str, Sequence[str], None] = None
19
+
20
+
21
+ def upgrade() -> None:
22
+ with op.batch_alter_table("room", schema=None) as batch_op:
23
+ batch_op.add_column(sa.Column("subject_setter_id", sa.Integer(), nullable=True))
24
+ # we give this constraint a name a workaround for
25
+ # https://github.com/sqlalchemy/alembic/issues/1195
26
+ batch_op.create_foreign_key(
27
+ "subject_setter_id_foreign_key",
28
+ "participant",
29
+ ["subject_setter_id"],
30
+ ["id"],
31
+ )
32
+
33
+
34
+ def downgrade() -> None:
35
+ with op.batch_alter_table("room", schema=None) as batch_op:
36
+ batch_op.drop_constraint("subject_setter_id_foreign_key", type_="foreignkey")
37
+ batch_op.drop_column("subject_setter_id")
@@ -0,0 +1,41 @@
1
+ """Store room subject setter by nickname
2
+
3
+ Revision ID: 2b1f45ab7379
4
+ Revises: c4a8ec35a0e8
5
+ Create Date: 2024-07-20 00:14:36.882689
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 = "2b1f45ab7379"
16
+ down_revision: Union[str, None] = "c4a8ec35a0e8"
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
+ with op.batch_alter_table("room", schema=None) as batch_op:
24
+ batch_op.add_column(sa.Column("subject_setter", sa.String(), nullable=True))
25
+ batch_op.drop_constraint("subject_setter_id_foreign_key", type_="foreignkey")
26
+ batch_op.drop_column("subject_setter_id")
27
+ # ### end Alembic commands ###
28
+
29
+
30
+ def downgrade() -> None:
31
+ # ### commands auto generated by Alembic - please adjust! ###
32
+ with op.batch_alter_table("room", schema=None) as batch_op:
33
+ batch_op.add_column(sa.Column("subject_setter_id", sa.INTEGER(), nullable=True))
34
+ batch_op.create_foreign_key(
35
+ "subject_setter_id_foreign_key",
36
+ "participant",
37
+ ["subject_setter_id"],
38
+ ["id"],
39
+ )
40
+ batch_op.drop_column("subject_setter")
41
+ # ### end Alembic commands ###
@@ -0,0 +1,48 @@
1
+ """Add MUC.history_filled
2
+
3
+ Also drop caps_ver_bare column that should never have been added.
4
+
5
+ Revision ID: 82a4af84b679
6
+ Revises: 2461390c0af2
7
+ Create Date: 2024-07-22 07:01:05.352737
8
+
9
+ """
10
+
11
+ from typing import Sequence, Union
12
+
13
+ import sqlalchemy as sa
14
+ from alembic import op
15
+
16
+ # revision identifiers, used by Alembic.
17
+ revision: str = "82a4af84b679"
18
+ down_revision: Union[str, None] = "2461390c0af2"
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
+ with op.batch_alter_table("contact", schema=None) as batch_op:
26
+ batch_op.drop_column("caps_ver_bare")
27
+
28
+ with op.batch_alter_table("room", schema=None) as batch_op:
29
+ batch_op.add_column(
30
+ sa.Column(
31
+ "history_filled",
32
+ sa.Boolean(),
33
+ nullable=False,
34
+ server_default=sa.False_(), # manually added
35
+ )
36
+ )
37
+ # ### end Alembic commands ###
38
+
39
+
40
+ def downgrade() -> None:
41
+ # ### commands auto generated by Alembic - please adjust! ###
42
+ with op.batch_alter_table("room", schema=None) as batch_op:
43
+ batch_op.drop_column("history_filled")
44
+
45
+ with op.batch_alter_table("contact", schema=None) as batch_op:
46
+ batch_op.add_column(sa.Column("caps_ver_bare", sa.VARCHAR(), nullable=True))
47
+
48
+ # ### end Alembic commands ###
@@ -0,0 +1,133 @@
1
+ """Rely on DB to store contacts, rooms and participants
2
+
3
+ Revision ID: 8d2ced764698
4
+ Revises: b33993e87db3
5
+ Create Date: 2024-07-08 14:39:47.022088
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 = "8d2ced764698"
18
+ down_revision: Union[str, None] = "b33993e87db3"
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
+ op.create_table(
25
+ "hat",
26
+ sa.Column("id", sa.Integer(), nullable=False),
27
+ sa.Column("title", sa.String(), nullable=False),
28
+ sa.Column("uri", sa.String(), nullable=False),
29
+ sa.PrimaryKeyConstraint("id"),
30
+ sa.UniqueConstraint("title", "uri"),
31
+ )
32
+ op.create_table(
33
+ "contact_sent",
34
+ sa.Column("id", sa.Integer(), nullable=False),
35
+ sa.Column("contact_id", sa.Integer(), nullable=False),
36
+ sa.Column("msg_id", sa.String(), nullable=False),
37
+ sa.ForeignKeyConstraint(
38
+ ["contact_id"],
39
+ ["contact.id"],
40
+ ),
41
+ sa.PrimaryKeyConstraint("id"),
42
+ sa.UniqueConstraint("contact_id", "msg_id"),
43
+ )
44
+ op.create_table(
45
+ "participant",
46
+ sa.Column("id", sa.Integer(), nullable=False),
47
+ sa.Column("room_id", sa.Integer(), nullable=False),
48
+ sa.Column("contact_id", sa.Integer(), nullable=True),
49
+ sa.Column("is_user", sa.Boolean(), nullable=False),
50
+ sa.Column(
51
+ "affiliation",
52
+ sa.Enum("outcast", "member", "admin", "owner", "none", native_enum=False),
53
+ nullable=False,
54
+ ),
55
+ sa.Column(
56
+ "role",
57
+ sa.Enum("moderator", "participant", "visitor", "none", native_enum=False),
58
+ nullable=False,
59
+ ),
60
+ sa.Column("presence_sent", sa.Boolean(), nullable=False),
61
+ sa.Column("resource", sa.String(), nullable=True),
62
+ sa.Column("nickname", sa.String(), nullable=True),
63
+ sa.Column("extra_attributes", slidge.db.meta.JSONEncodedDict(), nullable=True),
64
+ sa.ForeignKeyConstraint(
65
+ ["contact_id"],
66
+ ["contact.id"],
67
+ ),
68
+ sa.ForeignKeyConstraint(
69
+ ["room_id"],
70
+ ["room.id"],
71
+ ),
72
+ sa.PrimaryKeyConstraint("id"),
73
+ )
74
+ op.create_table(
75
+ "participant_hats",
76
+ sa.Column("participant_id", sa.Integer(), nullable=False),
77
+ sa.Column("hat_id", sa.Integer(), nullable=False),
78
+ sa.ForeignKeyConstraint(
79
+ ["hat_id"],
80
+ ["hat.id"],
81
+ ),
82
+ sa.ForeignKeyConstraint(
83
+ ["participant_id"],
84
+ ["participant.id"],
85
+ ),
86
+ sa.PrimaryKeyConstraint("participant_id", "hat_id"),
87
+ )
88
+ op.add_column("contact", sa.Column("is_friend", sa.Boolean(), nullable=False))
89
+ op.add_column("contact", sa.Column("added_to_roster", sa.Boolean(), nullable=False))
90
+ op.add_column(
91
+ "contact",
92
+ sa.Column("extra_attributes", slidge.db.meta.JSONEncodedDict(), nullable=True),
93
+ )
94
+ op.add_column("contact", sa.Column("updated", sa.Boolean(), nullable=False))
95
+ op.add_column("room", sa.Column("description", sa.String(), nullable=True))
96
+ op.add_column("room", sa.Column("subject", sa.String(), nullable=True))
97
+ op.add_column("room", sa.Column("subject_date", sa.DateTime(), nullable=True))
98
+ op.add_column(
99
+ "room",
100
+ sa.Column(
101
+ "muc_type",
102
+ sa.Enum("GROUP", "CHANNEL", "CHANNEL_NON_ANONYMOUS", name="muctype"),
103
+ nullable=True,
104
+ ),
105
+ )
106
+ op.add_column("room", sa.Column("user_resources", sa.String(), nullable=True))
107
+ op.add_column(
108
+ "room", sa.Column("participants_filled", sa.Boolean(), nullable=False)
109
+ )
110
+ op.add_column(
111
+ "room",
112
+ sa.Column("extra_attributes", slidge.db.meta.JSONEncodedDict(), nullable=True),
113
+ )
114
+ op.add_column("room", sa.Column("updated", sa.Boolean(), nullable=False))
115
+
116
+
117
+ def downgrade() -> None:
118
+ op.drop_column("room", "updated")
119
+ op.drop_column("room", "extra_attributes")
120
+ op.drop_column("room", "participants_filled")
121
+ op.drop_column("room", "user_resources")
122
+ op.drop_column("room", "muc_type")
123
+ op.drop_column("room", "subject_date")
124
+ op.drop_column("room", "subject")
125
+ op.drop_column("room", "description")
126
+ op.drop_column("contact", "updated")
127
+ op.drop_column("contact", "extra_attributes")
128
+ op.drop_column("contact", "added_to_roster")
129
+ op.drop_column("contact", "is_friend")
130
+ op.drop_table("participant_hats")
131
+ op.drop_table("participant")
132
+ op.drop_table("contact_sent")
133
+ op.drop_table("hat")
@@ -0,0 +1,85 @@
1
+ """DB Creation
2
+
3
+ Including a migration from the user_store shelf
4
+
5
+ Revision ID: aa9d82a7f6ef
6
+ Revises:
7
+ Create Date: 2024-04-17 20:57:01.357041
8
+
9
+ """
10
+
11
+ import logging
12
+ from datetime import datetime
13
+ from typing import Sequence, Union
14
+
15
+ import sqlalchemy as sa
16
+ from alembic import op
17
+
18
+ import slidge.db.meta
19
+
20
+ # revision identifiers, used by Alembic.
21
+ revision: str = "aa9d82a7f6ef"
22
+ down_revision: Union[str, None] = None
23
+ branch_labels: Union[str, Sequence[str], None] = None
24
+ depends_on: Union[str, Sequence[str], None] = None
25
+
26
+
27
+ def upgrade() -> None:
28
+ # ### commands auto generated by Alembic - please adjust! ###
29
+ accounts = op.create_table(
30
+ "user_account",
31
+ sa.Column("id", sa.Integer(), nullable=False),
32
+ sa.Column("jid", slidge.db.meta.JIDType(), nullable=False),
33
+ sa.Column(
34
+ "registration_date",
35
+ sa.DateTime(),
36
+ server_default=sa.text("(CURRENT_TIMESTAMP)"),
37
+ nullable=False,
38
+ ),
39
+ sa.Column(
40
+ "legacy_module_data", slidge.db.meta.JSONEncodedDict(), nullable=False
41
+ ),
42
+ sa.Column("preferences", slidge.db.meta.JSONEncodedDict(), nullable=False),
43
+ sa.PrimaryKeyConstraint("id"),
44
+ sa.UniqueConstraint("jid"),
45
+ )
46
+ # ### end Alembic commands ###
47
+ try:
48
+ migrate_from_shelf(accounts)
49
+ except Exception:
50
+ downgrade()
51
+ raise
52
+
53
+
54
+ def downgrade() -> None:
55
+ # ### commands auto generated by Alembic - please adjust! ###
56
+ op.drop_table("user_account")
57
+ # ### end Alembic commands ###
58
+
59
+
60
+ def migrate_from_shelf(accounts: sa.Table) -> None:
61
+ try:
62
+ from slidge.util.db import user_store
63
+ except ImportError:
64
+ return
65
+ try:
66
+ users = list(user_store.get_all())
67
+ except AttributeError:
68
+ return
69
+ logging.info("Migrating %s users from the deprecated user_store shelf", len(users))
70
+ op.bulk_insert(
71
+ accounts,
72
+ [
73
+ {
74
+ "jid": user.jid,
75
+ "registration_date": (
76
+ user.registration_date
77
+ if user.registration_date is not None
78
+ else datetime.now()
79
+ ),
80
+ "legacy_module_data": user.registration_form,
81
+ "preferences": {},
82
+ }
83
+ for user in users
84
+ ],
85
+ )