slidge 0.2.0a9__py3-none-any.whl → 0.2.0a10__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 (44) hide show
  1. slidge/__version__.py +1 -1
  2. slidge/command/adhoc.py +1 -1
  3. slidge/command/base.py +4 -4
  4. slidge/contact/roster.py +7 -0
  5. slidge/core/dispatcher/__init__.py +3 -0
  6. slidge/core/{gateway → dispatcher}/caps.py +6 -4
  7. slidge/core/{gateway → dispatcher}/disco.py +11 -17
  8. slidge/core/dispatcher/message/__init__.py +10 -0
  9. slidge/core/dispatcher/message/chat_state.py +40 -0
  10. slidge/core/dispatcher/message/marker.py +67 -0
  11. slidge/core/dispatcher/message/message.py +397 -0
  12. slidge/core/dispatcher/muc/__init__.py +12 -0
  13. slidge/core/dispatcher/muc/admin.py +98 -0
  14. slidge/core/{gateway → dispatcher/muc}/mam.py +26 -15
  15. slidge/core/dispatcher/muc/misc.py +118 -0
  16. slidge/core/dispatcher/muc/owner.py +96 -0
  17. slidge/core/{gateway → dispatcher/muc}/ping.py +10 -15
  18. slidge/core/dispatcher/presence.py +177 -0
  19. slidge/core/{gateway → dispatcher}/registration.py +23 -2
  20. slidge/core/{gateway → dispatcher}/search.py +9 -14
  21. slidge/core/dispatcher/session_dispatcher.py +84 -0
  22. slidge/core/dispatcher/util.py +174 -0
  23. slidge/core/{gateway/vcard_temp.py → dispatcher/vcard.py} +26 -12
  24. slidge/core/{gateway/base.py → gateway.py} +42 -137
  25. slidge/core/mixins/base.py +2 -2
  26. slidge/core/mixins/message.py +10 -4
  27. slidge/core/pubsub.py +2 -1
  28. slidge/core/session.py +28 -2
  29. slidge/db/alembic/versions/45c24cc73c91_add_bob.py +42 -0
  30. slidge/db/models.py +13 -0
  31. slidge/db/store.py +128 -2
  32. slidge/{core/gateway → slixfix}/delivery_receipt.py +1 -1
  33. slidge/util/test.py +5 -1
  34. slidge/util/types.py +6 -0
  35. slidge/util/util.py +5 -2
  36. {slidge-0.2.0a9.dist-info → slidge-0.2.0a10.dist-info}/METADATA +2 -1
  37. {slidge-0.2.0a9.dist-info → slidge-0.2.0a10.dist-info}/RECORD +40 -31
  38. slidge/core/gateway/__init__.py +0 -3
  39. slidge/core/gateway/muc_admin.py +0 -35
  40. slidge/core/gateway/presence.py +0 -95
  41. slidge/core/gateway/session_dispatcher.py +0 -895
  42. {slidge-0.2.0a9.dist-info → slidge-0.2.0a10.dist-info}/LICENSE +0 -0
  43. {slidge-0.2.0a9.dist-info → slidge-0.2.0a10.dist-info}/WHEEL +0 -0
  44. {slidge-0.2.0a9.dist-info → slidge-0.2.0a10.dist-info}/entry_points.txt +0 -0
@@ -6,8 +6,8 @@ from slixmpp import JID
6
6
  from ...util.types import MessageOrPresenceTypeVar
7
7
 
8
8
  if TYPE_CHECKING:
9
- from slidge.core.gateway import BaseGateway
10
- from slidge.core.session import BaseSession
9
+ from ..gateway import BaseGateway
10
+ from ..session import BaseSession
11
11
 
12
12
 
13
13
  class MetaBase(ABCMeta):
@@ -214,7 +214,7 @@ class ContentMessageMixin(AttachmentMixin):
214
214
  :param archive_only: (only in groups) Do not send this message to user,
215
215
  but store it in the archive. Meant to be used during ``MUC.backfill()``
216
216
  """
217
- if carbon:
217
+ if carbon and not hasattr(self, "muc"):
218
218
  if not correction and self.xmpp.store.sent.was_sent_by_user(
219
219
  self.session.user_pk, str(legacy_msg_id)
220
220
  ):
@@ -223,6 +223,11 @@ class ContentMessageMixin(AttachmentMixin):
223
223
  legacy_msg_id,
224
224
  )
225
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
+ )
226
231
  self.xmpp.store.sent.set_message(
227
232
  self.session.user_pk,
228
233
  str(legacy_msg_id),
@@ -352,11 +357,12 @@ class ContentMessageMixin(AttachmentMixin):
352
357
  class CarbonMessageMixin(ContentMessageMixin, MarkerMixin):
353
358
  def _privileged_send(self, msg: Message):
354
359
  i = msg.get_id()
355
- if not i:
356
- i = str(uuid.uuid4())
360
+ if i:
361
+ self.session.ignore_messages.add(i)
362
+ else:
363
+ i = "slidge-carbon-" + str(uuid.uuid4())
357
364
  msg.set_id(i)
358
365
  msg.del_origin_id()
359
- self.session.ignore_messages.add(i)
360
366
  try:
361
367
  self.xmpp["xep_0356"].send_privileged_message(msg)
362
368
  except PermissionError:
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,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 ###
slidge/db/models.py CHANGED
@@ -386,3 +386,16 @@ class Participant(Base):
386
386
  )
387
387
 
388
388
  extra_attributes: Mapped[Optional[JSONSerializable]] = mapped_column(default=None)
389
+
390
+
391
+ class Bob(Base):
392
+ __tablename__ = "bob"
393
+
394
+ id: Mapped[int] = mapped_column(primary_key=True)
395
+ file_name: Mapped[str] = mapped_column(nullable=False)
396
+
397
+ sha_1: Mapped[str] = mapped_column(nullable=False, unique=True)
398
+ sha_256: Mapped[str] = mapped_column(nullable=False, unique=True)
399
+ sha_512: Mapped[str] = mapped_column(nullable=False, unique=True)
400
+
401
+ content_type: Mapped[Optional[str]] = mapped_column(nullable=False)
slidge/db/store.py CHANGED
@@ -1,27 +1,33 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import hashlib
3
4
  import json
4
5
  import logging
6
+ import uuid
5
7
  from contextlib import contextmanager
6
8
  from datetime import datetime, timedelta, timezone
9
+ from mimetypes import guess_extension
7
10
  from typing import TYPE_CHECKING, Collection, Iterator, Optional, Type
8
11
 
9
12
  from slixmpp import JID, Iq, Message, Presence
10
13
  from slixmpp.exceptions import XMPPError
14
+ from slixmpp.plugins.xep_0231.stanza import BitsOfBinary
11
15
  from sqlalchemy import Engine, delete, select, update
12
- from sqlalchemy.orm import Session, attributes
16
+ from sqlalchemy.orm import Session, attributes, load_only
13
17
  from sqlalchemy.sql.functions import count
14
18
 
19
+ from ..core import config
15
20
  from ..util.archive_msg import HistoryMessage
16
21
  from ..util.types import URL, CachedPresence, ClientType
17
22
  from ..util.types import Hat as HatTuple
18
- from ..util.types import MamMetadata, MucAffiliation, MucRole
23
+ from ..util.types import MamMetadata, MucAffiliation, MucRole, Sticker
19
24
  from .meta import Base
20
25
  from .models import (
21
26
  ArchivedMessage,
22
27
  ArchivedMessageSource,
23
28
  Attachment,
24
29
  Avatar,
30
+ Bob,
25
31
  Contact,
26
32
  ContactSent,
27
33
  GatewayUser,
@@ -87,6 +93,7 @@ class SlidgeStore(EngineMixin):
87
93
  self.rooms = RoomStore(engine)
88
94
  self.sent = SentStore(engine)
89
95
  self.participants = ParticipantStore(engine)
96
+ self.bob = BobStore(engine)
90
97
 
91
98
 
92
99
  class UserStore(EngineMixin):
@@ -973,6 +980,15 @@ class RoomStore(UpdatedMixin):
973
980
  select(Room).where(Room.user_account_id == user_pk)
974
981
  ).scalars()
975
982
 
983
+ def get_all_jid_and_names(self, user_pk: int) -> Iterator[Room]:
984
+ with self.session() as session:
985
+ yield from session.scalars(
986
+ select(Room)
987
+ .filter(Room.user_account_id == user_pk)
988
+ .options(load_only(Room.jid, Room.name))
989
+ .order_by(Room.name)
990
+ ).all()
991
+
976
992
 
977
993
  class ParticipantStore(EngineMixin):
978
994
  def __init__(self, *a, **kw):
@@ -1120,5 +1136,115 @@ class ParticipantStore(EngineMixin):
1120
1136
  ).scalar()
1121
1137
 
1122
1138
 
1139
+ class BobStore(EngineMixin):
1140
+ _ATTR_MAP = {
1141
+ "sha-1": "sha_1",
1142
+ "sha1": "sha_1",
1143
+ "sha-256": "sha_256",
1144
+ "sha256": "sha_256",
1145
+ "sha-512": "sha_512",
1146
+ "sha512": "sha_512",
1147
+ }
1148
+
1149
+ _ALG_MAP = {
1150
+ "sha_1": hashlib.sha1,
1151
+ "sha_256": hashlib.sha256,
1152
+ "sha_512": hashlib.sha512,
1153
+ }
1154
+
1155
+ def __init__(self, *a, **k):
1156
+ super().__init__(*a, **k)
1157
+ self.root_dir = config.HOME_DIR / "slidge_stickers"
1158
+ self.root_dir.mkdir(exist_ok=True)
1159
+
1160
+ @staticmethod
1161
+ def __split_cid(cid: str) -> list[str]:
1162
+ return cid.removesuffix("@bob.xmpp.org").split("+")
1163
+
1164
+ def __get_condition(self, cid: str):
1165
+ alg_name, digest = self.__split_cid(cid)
1166
+ attr = self._ATTR_MAP.get(alg_name)
1167
+ if attr is None:
1168
+ log.warning("Unknown hash algo: %s", alg_name)
1169
+ return None
1170
+ return getattr(Bob, attr) == digest
1171
+
1172
+ def get(self, cid: str) -> Bob | None:
1173
+ with self.session() as session:
1174
+ try:
1175
+ return session.query(Bob).filter(self.__get_condition(cid)).scalar()
1176
+ except ValueError:
1177
+ log.warning("Cannot get Bob with CID: %s", cid)
1178
+ return None
1179
+
1180
+ def get_sticker(self, cid: str) -> Sticker | None:
1181
+ bob = self.get(cid)
1182
+ if bob is None:
1183
+ return None
1184
+ return Sticker(
1185
+ self.root_dir / bob.file_name,
1186
+ bob.content_type,
1187
+ {h: getattr(bob, h) for h in self._ALG_MAP},
1188
+ )
1189
+
1190
+ def get_bob(self, _jid, _node, _ifrom, cid: str) -> BitsOfBinary | None:
1191
+ stored = self.get(cid)
1192
+ if stored is None:
1193
+ return None
1194
+ bob = BitsOfBinary()
1195
+ bob["data"] = (self.root_dir / stored.file_name).read_bytes()
1196
+ if stored.content_type is not None:
1197
+ bob["type"] = stored.content_type
1198
+ bob["cid"] = cid
1199
+ return bob
1200
+
1201
+ def del_bob(self, _jid, _node, _ifrom, cid: str) -> None:
1202
+ with self.session() as orm:
1203
+ try:
1204
+ file_name = orm.scalar(
1205
+ delete(Bob)
1206
+ .where(self.__get_condition(cid))
1207
+ .returning(Bob.file_name)
1208
+ )
1209
+ except ValueError:
1210
+ log.warning("Cannot delete Bob with CID: %s", cid)
1211
+ return None
1212
+ if file_name is None:
1213
+ log.warning("No BoB with CID: %s", cid)
1214
+ return None
1215
+ (self.root_dir / file_name).unlink()
1216
+ orm.commit()
1217
+
1218
+ def set_bob(self, _jid, _node, _ifrom, bob: BitsOfBinary) -> None:
1219
+ cid = bob["cid"]
1220
+ try:
1221
+ alg_name, digest = self.__split_cid(cid)
1222
+ except ValueError:
1223
+ log.warning("Cannot set Bob with CID: %s", cid)
1224
+ return
1225
+ attr = self._ATTR_MAP.get(alg_name)
1226
+ if attr is None:
1227
+ log.warning("Cannot set BoB with unknown hash algo: %s", alg_name)
1228
+ return None
1229
+ with self.session() as orm:
1230
+ existing = self.get(bob["cid"])
1231
+ if existing is not None:
1232
+ log.debug("Bob already known")
1233
+ return
1234
+ bytes_ = bob["data"]
1235
+ path = self.root_dir / uuid.uuid4().hex
1236
+ if bob["type"]:
1237
+ path = path.with_suffix(guess_extension(bob["type"]) or "")
1238
+ path.write_bytes(bytes_)
1239
+ hashes = {k: v(bytes_).hexdigest() for k, v in self._ALG_MAP.items()}
1240
+ if hashes[attr] != digest:
1241
+ raise ValueError(
1242
+ "The given CID does not correspond to the result of our hash"
1243
+ )
1244
+ row = Bob(file_name=path.name, content_type=bob["type"] or None, **hashes)
1245
+ orm.add(row)
1246
+ orm.commit()
1247
+
1248
+
1123
1249
  log = logging.getLogger(__name__)
1124
1250
  _session: Optional[Session] = None
@@ -11,7 +11,7 @@ from slixmpp import JID, Message
11
11
  from slixmpp.types import MessageTypes
12
12
 
13
13
  if TYPE_CHECKING:
14
- from .base import BaseGateway
14
+ from slidge.core.gateway import BaseGateway
15
15
 
16
16
 
17
17
  class DeliveryReceipt:
slidge/util/test.py CHANGED
@@ -287,7 +287,11 @@ class SlidgeTest(SlixTestPlus):
287
287
  session.execute(delete(Contact))
288
288
  session.commit()
289
289
 
290
- self.run_coro(self.xmpp._on_user_register(Iq(sfrom="romeo@montague.lit/gajim")))
290
+ self.run_coro(
291
+ self.xmpp._BaseGateway__dispatcher._on_user_register(
292
+ Iq(sfrom="romeo@montague.lit/gajim")
293
+ )
294
+ )
291
295
  welcome = self.next_sent()
292
296
  assert welcome["body"]
293
297
  stanza = self.next_sent()
slidge/util/types.py CHANGED
@@ -207,3 +207,9 @@ class CachedPresence(NamedTuple):
207
207
  ptype: Optional[PresenceTypes] = None
208
208
  pstatus: Optional[str] = None
209
209
  pshow: Optional[PresenceShows] = None
210
+
211
+
212
+ class Sticker(NamedTuple):
213
+ path: Path
214
+ content_type: Optional[str]
215
+ hashes: dict[str, str]
slidge/util/util.py CHANGED
@@ -7,7 +7,7 @@ from abc import ABCMeta
7
7
  from functools import wraps
8
8
  from pathlib import Path
9
9
  from time import time
10
- from typing import TYPE_CHECKING, Callable, NamedTuple, Optional, Type
10
+ from typing import TYPE_CHECKING, Callable, NamedTuple, Optional, Type, TypeVar
11
11
 
12
12
  from .types import Mention, ResourceDict
13
13
 
@@ -276,7 +276,10 @@ def deprecated(name: str, new: Callable):
276
276
  return wrapped
277
277
 
278
278
 
279
- def dict_to_named_tuple(data: dict, cls: Type[NamedTuple]):
279
+ T = TypeVar("T", bound=NamedTuple)
280
+
281
+
282
+ def dict_to_named_tuple(data: dict, cls: Type[T]) -> T:
280
283
  return cls(*(data.get(f) for f in cls._fields)) # type:ignore
281
284
 
282
285
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: slidge
3
- Version: 0.2.0a9
3
+ Version: 0.2.0a10
4
4
  Summary: XMPP bridging framework
5
5
  Home-page: https://sr.ht/~nicoco/slidge/
6
6
  License: AGPL-3.0-or-later
@@ -16,6 +16,7 @@ Requires-Dist: ConfigArgParse (>=1.5.3,<2.0.0)
16
16
  Requires-Dist: Pillow (>=10,<11)
17
17
  Requires-Dist: aiohttp[speedups] (>=3.8.3,<4.0.0)
18
18
  Requires-Dist: alembic (>=1.13.1,<2.0.0)
19
+ Requires-Dist: defusedxml (>=0.7.1,<0.8.0)
19
20
  Requires-Dist: pickle-secure (>=0.99.9,<0.100.0)
20
21
  Requires-Dist: python-magic (>=0.4.27,<0.5.0)
21
22
  Requires-Dist: qrcode (>=7.4.1,<8.0.0)
@@ -1,45 +1,52 @@
1
1
  slidge/__init__.py,sha256=S0tUjqpZlzsr8G4Y_1Xt-KCYB07qaknTB0OwHU8k29U,1587
2
2
  slidge/__main__.py,sha256=Y12eh1TD_C5MB50KgEAuMffGnRFCvKYFKHD4UYSmHA0,72
3
- slidge/__version__.py,sha256=9y4M-LYXgK7-PIasL6QWLN6L5LRaek-yXy_SekzwWrg,170
3
+ slidge/__version__.py,sha256=05G747WHKOvpl1x4M5U-3t3qszlgbNfnUxAxrATG8ck,171
4
4
  slidge/command/__init__.py,sha256=UYf1mjCYbZ5G7PIgaFTWSQRAzEJkQ6dTH8Fu_e_XnO0,613
5
- slidge/command/adhoc.py,sha256=5xLLoWyUJqCJB7kAwD2VKYTl_7MObCsgdz-qg_WkWGs,9417
5
+ slidge/command/adhoc.py,sha256=9PsTsGMPKAK_YXQpwdcH9SSDki8YQ49OZ5p65W5HA6k,9412
6
6
  slidge/command/admin.py,sha256=x_kJ0TJhzf6d3OBIOXFjudZFO8bRYUG919td7OjMCug,6008
7
- slidge/command/base.py,sha256=xTlzxAbTWTpbFgQ0FxKjmp3ZImzempwJvGn9UiVUUTc,13044
7
+ slidge/command/base.py,sha256=7NSzPZdBLZElrm3smzvFKgP0GUggxXdkhclxIKCjtT8,13036
8
8
  slidge/command/categories.py,sha256=BJCfaga2qoAxnHfgHD7I_RKZuBA5nnNOukkWHJwsUFE,99
9
9
  slidge/command/chat_command.py,sha256=VBs6IuDka1IyyMzz0ZyE9zMImaEzUZLcnffxq_vwb4M,10565
10
10
  slidge/command/register.py,sha256=fzPcGUoJtainnDOiC13gWV-uYLuJcsmdKGJ-jXT1qIo,6697
11
11
  slidge/command/user.py,sha256=uFheYOprhypkHEEl6qSTEM7T2N28xXaDi7v1he-AET8,11512
12
12
  slidge/contact/__init__.py,sha256=WMMaHk7UW7YT9EH2LtPdkU0bHQaOp4ikBhbBQskmoc8,191
13
13
  slidge/contact/contact.py,sha256=kKtJ9NPLS9DPVyyahx_K-Mtp5k5UQdQJZavC1XCmWlc,23104
14
- slidge/contact/roster.py,sha256=YF5NiParDKYNqW52fu1xSVW1skR-guy7YzIQ5kDYoDk,9874
14
+ slidge/contact/roster.py,sha256=AQTfmM4hrlxkXSM7ZX-C8P9NDN5RqNMNuPrSjt_3MJM,10223
15
15
  slidge/core/__init__.py,sha256=RG7Jj5JCJERjhqJ31lOLYV-7bH_oblClQD1KF9LsTXo,68
16
16
  slidge/core/config.py,sha256=leNcN_TI0Ka1hhzOHx7cBW3fNj5xZwsiv9l8AfRY_vU,7630
17
- slidge/core/gateway/__init__.py,sha256=rZckY2gAE-mon77_DSsAW1XtWqhBAETE2d4FqZ8pJXk,58
18
- slidge/core/gateway/base.py,sha256=Dxy39bAgOvJ-vN1RA9PU821YYuvkp_V06y_-vUDW7bU,38752
19
- slidge/core/gateway/caps.py,sha256=jemB4tB_2MTAxqQw5Bs4b7qNQ8gLPuAve0aoH6TzLEs,1937
20
- slidge/core/gateway/delivery_receipt.py,sha256=AT_9gvZrtWpSRsDJcYjE8CmF7TW-YBbUPdqNW5zWAdo,1352
21
- slidge/core/gateway/disco.py,sha256=uazgDXSDb5KrardjPCvElItARcxkeBRohtx82A2BlCQ,2203
22
- slidge/core/gateway/mam.py,sha256=ZUZXX7YcpK1WHq8RlgYrXo2zrLm5pOM1sVzON61mXYQ,2418
23
- slidge/core/gateway/muc_admin.py,sha256=PslX1gZK_PhY2VaeAPP1nEzThMaBBGPRgs-wiJ35zJQ,1033
24
- slidge/core/gateway/ping.py,sha256=_zzPkjqvxjTxLNP1jbj0WVLMaybxbYqrKDRM5jHSDjs,1729
25
- slidge/core/gateway/presence.py,sha256=Ls8IY4uNQaW8F3F1CpRhfyFIVbd_py_VkZyJKMMei8s,2732
26
- slidge/core/gateway/registration.py,sha256=JXwIQ-QqZCPXEmCU2G8FvIYDGvD8L8CqGb_Qkbycgt0,2303
27
- slidge/core/gateway/search.py,sha256=08ds6gvzX3EnTH-AU8X8J8JKEKYaSrRGTFwwClTT-Rc,3495
28
- slidge/core/gateway/session_dispatcher.py,sha256=FBCbMNNa3SQCd2n_NEdD5q7cjdEgUHGuI_DIWh5cTUY,33202
29
- slidge/core/gateway/vcard_temp.py,sha256=cnzHZO6qF8OUWSvBieEdNAV_Ndv1ixZOzBCBXy2Vopw,4637
17
+ slidge/core/dispatcher/__init__.py,sha256=1EXcjXietUKlxEqdrCWCV3xZ3q_DSsjHoqWrPMbtYao,84
18
+ slidge/core/dispatcher/caps.py,sha256=vzCAXo_bhALuLEpJWtyJTzVfWx96g1AsWD8_wkoDl0Y,2028
19
+ slidge/core/dispatcher/disco.py,sha256=j56VY9NIFzwPEWFKQQZ7YIqS9GdD-ZaF_K8a2L-JvRk,2006
20
+ slidge/core/dispatcher/message/__init__.py,sha256=vpDGOc_U9XvkUU_ws9n9-5M2NPJ87XGTVpuIxM7Z99k,223
21
+ slidge/core/dispatcher/message/chat_state.py,sha256=sCdEpzbgmvBmTovNOCv9uY6v0eJZcWVvDYAGlAV3FJ4,1735
22
+ slidge/core/dispatcher/message/marker.py,sha256=VbD1-2QeOCC4EbrS-wpJxHwIcmvPF4Q4qd0eiv95c7I,2451
23
+ slidge/core/dispatcher/message/message.py,sha256=HwauW2kGionLyDWG01OSa9a14gYzoovJuJvGbfB4nt4,15296
24
+ slidge/core/dispatcher/muc/__init__.py,sha256=V8URHLJ_y7mk-7Id6FzRuczb1Uq_Z69fhxvzHuVLH1w,269
25
+ slidge/core/dispatcher/muc/admin.py,sha256=s21V2LEqc0e_DIpipEhhQdpae762lW1lVqj4wjFhX8M,3364
26
+ slidge/core/dispatcher/muc/mam.py,sha256=1ROVP4ZPEVEH-HR5qRV4YwHz-V15uu5gyhv1ZwwKhk8,2821
27
+ slidge/core/dispatcher/muc/misc.py,sha256=L5I2nt23qvQ-2qS5qgW3hSg6Z7DKnGvwxgXqn_WLvpQ,3943
28
+ slidge/core/dispatcher/muc/owner.py,sha256=Vwwz15fdLq40XTnyDcMmRtMOXdY3T3_BwpSV3Nr8FNw,3290
29
+ slidge/core/dispatcher/muc/ping.py,sha256=lb1VQPhiUPZ19KhbofRXMVCcY6wwQ2w-asnqtANaAwA,1660
30
+ slidge/core/dispatcher/presence.py,sha256=ZxAmC34yxKxbk_-h6g_S8pTssL7ovULm3q2ishpYaB4,6393
31
+ slidge/core/dispatcher/registration.py,sha256=Xmbw9NF3LUppCOa3XzreopdKDitZnwl_5HE-kds74n8,3155
32
+ slidge/core/dispatcher/search.py,sha256=9cGj0wwvyYlP_Yk440Y12sgo4Y1p-JWUDSJP5Zxch0M,3296
33
+ slidge/core/dispatcher/session_dispatcher.py,sha256=_njTftgpUKKMP-hgAo99Hu0YrIa6E9OTzSYdiMW000w,2844
34
+ slidge/core/dispatcher/util.py,sha256=x_vC7OXcaDaSz3RPPGnK9fOvimmMaKPM3RkgmHvU0Qw,5676
35
+ slidge/core/dispatcher/vcard.py,sha256=Rmx-wCz6Lps0mXCO48HppNQlS3GOgMuzuw9hZYBdlVU,5130
36
+ slidge/core/gateway.py,sha256=NhIgxZKPnOpwsx50OKgyZyk9nfU8ZlUSMddwIDIhFcw,36351
30
37
  slidge/core/mixins/__init__.py,sha256=muReAzgvENgMvlfm0Fpe6BQFfm2EMjoDe9ZhGgo6Vig,627
31
38
  slidge/core/mixins/attachment.py,sha256=5Xa_GkSL_rRTC45TRjW98jztk__4M5P-3EG4IF91K0c,19022
32
39
  slidge/core/mixins/avatar.py,sha256=kGIIZzLSNuxF9bIvt5Bv03_uT_pU5QV1kS7cRu6-GUA,7874
33
- slidge/core/mixins/base.py,sha256=9hjf2Pw5r0poSi1Abv-_znk83Kngsu9EXTf05gpFDdI,768
40
+ slidge/core/mixins/base.py,sha256=MOd-pas38_52VawQVlxWtBtmTKC6My9G0ZaCeQxOJbs,748
34
41
  slidge/core/mixins/db.py,sha256=5Qpegd7D8e5TLXLLINYcf_DuVdN-7wNmsfztUuFYPcU,442
35
42
  slidge/core/mixins/disco.py,sha256=jk3Z1B6zTuisHv8VKNRJodIo0ee5btYHh2ZrlflPj_Q,3670
36
43
  slidge/core/mixins/lock.py,sha256=mVzwVVEoq1hrAMgGLh4K84BTLt7JTJ33B8HSGSorTdY,913
37
- slidge/core/mixins/message.py,sha256=jJz_peNQmDf0uVQcI7TWG7oUaSGjUL8eiulNicGgWhI,15071
44
+ slidge/core/mixins/message.py,sha256=6X0MskF1fC9Ih8aLRfdqNe7H3jpnFGEJb0EykRKze0c,15384
38
45
  slidge/core/mixins/message_maker.py,sha256=TcCutHi0sIwL6beJNkN7XyR0aDIbA0xZyxd2Gc9ulG4,6022
39
46
  slidge/core/mixins/presence.py,sha256=yywo6KAw8C7GaZSMrSMuioNfhW08MrnobHt8XbHd0q8,7891
40
47
  slidge/core/mixins/recipient.py,sha256=U-YppozUO8pA94jmD3-qmhkykTebPNaOVWc3JDPC9w8,1302
41
- slidge/core/pubsub.py,sha256=ITOhgUKdYh6oJBpmZ8nevDQlYT4WJMC-k7Z76YchXqY,11906
42
- slidge/core/session.py,sha256=iYRdG_CZYiH-a4A69vqKLf-vnSF_N-XnxEF1veBMCWk,27182
48
+ slidge/core/pubsub.py,sha256=oTiS5KFQJAmsgkhOsvfvthT-LkuZGQSCrrUG0JskNkI,11907
49
+ slidge/core/session.py,sha256=nQexpCd1jlHOhQPnFI4ri-5odp3N2pU5HO4l7WFetZY,28148
43
50
  slidge/db/__init__.py,sha256=EBDH1JSEhgqYcli2Bw11CRC749wJk8AOucgBzmhDSvU,105
44
51
  slidge/db/alembic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
52
  slidge/db/alembic/env.py,sha256=hsBlRNs0zF5diSHGRSa8Fi3qRVQDA2rJdR41AEIdvxc,1642
@@ -50,6 +57,7 @@ slidge/db/alembic/versions/2461390c0af2_store_contacts_caps_verstring_in_db.py,s
50
57
  slidge/db/alembic/versions/29f5280c61aa_store_subject_setter_in_room.py,sha256=f8TFS28CXjGhvIn41UYMoHYeODfqhKfo4O7gk-JwA1E,1134
51
58
  slidge/db/alembic/versions/2b1f45ab7379_store_room_subject_setter_by_nickname.py,sha256=CMVP2wFz6s7t57eWdSaGtck8BXzfVPJhHE5AoWi34tI,1359
52
59
  slidge/db/alembic/versions/3071e0fa69d4_add_contact_client_type.py,sha256=O5BY1vpbtuYT5j6i3EMuuJAf6loIYT1kco8c-c6TF5g,1391
60
+ slidge/db/alembic/versions/45c24cc73c91_add_bob.py,sha256=UjMySZ5LaInyPt0KbAxx0rF4GQhZh8CwBeqHtNPdG1c,1249
53
61
  slidge/db/alembic/versions/5bd48bfdffa2_lift_room_legacy_id_constraint.py,sha256=cObfqUzqdNezIeJdHe7YKFwRwtelXk8y1PwZ75chXDc,1629
54
62
  slidge/db/alembic/versions/82a4af84b679_add_muc_history_filled.py,sha256=g37po0ydp8ZmzJrE5oFV7GscnploxjCtPDpw28SqVGk,1429
55
63
  slidge/db/alembic/versions/8b993243a536_add_vcard_content_to_contact_table.py,sha256=18tG8B03Kq8Qz_-mMd28Beed6jow8XNTtrz7gT5QY3g,1210
@@ -62,8 +70,8 @@ slidge/db/alembic/versions/c4a8ec35a0e8_per_room_user_nick.py,sha256=jjQmlRv6nqd
62
70
  slidge/db/alembic/versions/e91195719c2c_store_users_avatars_persistently.py,sha256=8Ga3VFgKrzMs_-B8OPtfP-0rey_MFaDg-QGtSbaft3o,640
63
71
  slidge/db/avatar.py,sha256=FfRt2Vu11ZKD9F3x1_drawvUd-TDE3mp7SE3BZ9hOOg,6467
64
72
  slidge/db/meta.py,sha256=v1Jf-npZ28QwdGpsLQWLBHEbEP3-jnPrygRg05tJ_Iw,1831
65
- slidge/db/models.py,sha256=yO4hM0VE1cQdDqWiZU1YW5ZjzwSnHUTavkGbkAMEB9A,13297
66
- slidge/db/store.py,sha256=jBkjTVXIg_N558rEfaDWzQ7mnIYMp2ziTk0o9KRVioo,42071
73
+ slidge/db/models.py,sha256=bsZCEtBDkvwiZiJNyp0cqxLHphtCUBIGnOPIaaG9opc,13738
74
+ slidge/db/store.py,sha256=1p-wAgG4K_QUehnmqRz-zvmW_PbXYYVq5qYMViF0cNY,46432
67
75
  slidge/group/__init__.py,sha256=yFt7cHqeaKIMN6f9ZyhhspOcJJvBtLedGv-iICG7lto,258
68
76
  slidge/group/archive.py,sha256=xGPkdSk8-BT6t6lNVo1FEwiFVAttoxCma8Tsyk5r8Kg,5279
69
77
  slidge/group/bookmarks.py,sha256=_LDf7A7aWkwPH88v7c-mOp8VJs3gSFM1-uCqSb4ThO8,5825
@@ -73,6 +81,7 @@ slidge/main.py,sha256=8oND7xpR3eLw7b62fT61UhYlmNp_9gv3tNz2N3xR7-c,6232
73
81
  slidge/migration.py,sha256=4BJmPIRB56_WIhRTqBFIIBXuvnhhBjjOMl4CE7jY6oc,1541
74
82
  slidge/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
83
  slidge/slixfix/__init__.py,sha256=7GevigEt68hwgwHqXcsFogN5jRXRHPeqR6kwODCH4hc,3055
84
+ slidge/slixfix/delivery_receipt.py,sha256=3bWdZH3-X3CZJXmnI_TpjkTUUK-EY4Ktm78lW0-40fc,1366
76
85
  slidge/slixfix/link_preview/__init__.py,sha256=TDPTSEH5FQxgGpQpQIde-D72AHg-6YVWG-tOj4KpKmU,290
77
86
  slidge/slixfix/link_preview/link_preview.py,sha256=9PgdfnoyVMHnXS0w5OFp0wz3ku96Ck-HtRXbVUlDi1U,448
78
87
  slidge/slixfix/link_preview/stanza.py,sha256=YAXoNw2MD0a3nzvldGKlvSemjUMbUEG23regzmj4Ntc,2664
@@ -110,11 +119,11 @@ slidge/util/__init__.py,sha256=BELovoTMPcPPGz3D48esBr8A4BRRHXTvavfgnArBgEc,301
110
119
  slidge/util/archive_msg.py,sha256=xXAR0BI5r3d6KKWjae9594izCOv6iI03z2WLuTecNw8,1724
111
120
  slidge/util/conf.py,sha256=1j2OnOsCBar1tOObErhXR5RC3Vl3faliOZ1U8J3My58,6613
112
121
  slidge/util/db.py,sha256=4LxZj8oBYgiSnyBUnF_ALjr0TblkfNQq_p28sCfkHMY,242
113
- slidge/util/test.py,sha256=S8Kp5uJlWYPvnw8HMHUPlbrvsqwdBLs9MI99svMfjLg,13832
114
- slidge/util/types.py,sha256=o_5rbwfL_3e73JPT1t9o3kyDpJscFHzn4_bt8i3LoSk,5386
115
- slidge/util/util.py,sha256=8JeE0QObNGQr_Tw4OFPwQSz_EB_zh_0t9IJmNNhW0ic,9114
116
- slidge-0.2.0a9.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
117
- slidge-0.2.0a9.dist-info/METADATA,sha256=UYbPeUa9y7-m4f1ulm4CFYAdKYoGbf53gC-n_lf6aoI,4962
118
- slidge-0.2.0a9.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
119
- slidge-0.2.0a9.dist-info/entry_points.txt,sha256=SNl72KSocF5plsu_67xyH6wVWfGTXQbzkQgXbLtzDrQ,47
120
- slidge-0.2.0a9.dist-info/RECORD,,
122
+ slidge/util/test.py,sha256=movqj7rxDPZG4RF46CN1z73PSYAHIc_LuudquGRwLVU,13909
123
+ slidge/util/types.py,sha256=R_xfS5mRL0XUJIoDpnaAkZlTOoLPerduXBFftaVwIAI,5489
124
+ slidge/util/util.py,sha256=DyJWO2pmE-RiB9Rsy6TUTcvB-BDlmLZBW4PELx4arFQ,9156
125
+ slidge-0.2.0a10.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
126
+ slidge-0.2.0a10.dist-info/METADATA,sha256=_sFwLHhxETI7mHO1Hoetd6FVtNVYpyHHnboPxJucnkU,5006
127
+ slidge-0.2.0a10.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
128
+ slidge-0.2.0a10.dist-info/entry_points.txt,sha256=SNl72KSocF5plsu_67xyH6wVWfGTXQbzkQgXbLtzDrQ,47
129
+ slidge-0.2.0a10.dist-info/RECORD,,
@@ -1,3 +0,0 @@
1
- from .base import BaseGateway
2
-
3
- __all__ = ("BaseGateway",)
@@ -1,35 +0,0 @@
1
- from typing import TYPE_CHECKING
2
-
3
- from slixmpp import CoroutineCallback, Iq, StanzaPath
4
- from slixmpp.exceptions import XMPPError
5
-
6
- if TYPE_CHECKING:
7
- from .base import BaseGateway
8
-
9
-
10
- class MucAdmin:
11
- def __init__(self, xmpp: "BaseGateway"):
12
- self.xmpp = xmpp
13
- xmpp.register_handler(
14
- CoroutineCallback(
15
- "muc#admin",
16
- StanzaPath("iq@type=get/mucadmin_query"),
17
- self._handle_admin, # type: ignore
18
- )
19
- )
20
-
21
- async def _handle_admin(self, iq: Iq):
22
- muc = await self.xmpp.get_muc_from_stanza(iq)
23
-
24
- affiliation = iq["mucadmin_query"]["item"]["affiliation"]
25
-
26
- if not affiliation:
27
- raise XMPPError("bad-request")
28
-
29
- reply = iq.reply()
30
- reply.enable("mucadmin_query")
31
- async for participant in muc.get_participants():
32
- if not participant.affiliation == affiliation:
33
- continue
34
- reply["mucadmin_query"].append(participant.mucadmin_item())
35
- reply.send()