slidge 0.2.0a3__tar.gz → 0.2.0a4__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. {slidge-0.2.0a3 → slidge-0.2.0a4}/PKG-INFO +1 -1
  2. {slidge-0.2.0a3 → slidge-0.2.0a4}/pyproject.toml +1 -1
  3. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/__version__.py +1 -1
  4. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/command/admin.py +7 -1
  5. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/contact/contact.py +2 -2
  6. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/contact/roster.py +41 -51
  7. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/gateway/base.py +1 -1
  8. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/gateway/vcard_temp.py +1 -1
  9. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/pubsub.py +11 -9
  10. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/avatar.py +5 -0
  11. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/store.py +25 -6
  12. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/group/bookmarks.py +34 -47
  13. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/group/participant.py +15 -7
  14. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/group/room.py +3 -1
  15. slidge-0.2.0a4/slidge/util/db.py +5 -0
  16. {slidge-0.2.0a3 → slidge-0.2.0a4}/LICENSE +0 -0
  17. {slidge-0.2.0a3 → slidge-0.2.0a4}/README.md +0 -0
  18. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/__init__.py +0 -0
  19. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/__main__.py +0 -0
  20. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/command/__init__.py +0 -0
  21. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/command/adhoc.py +0 -0
  22. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/command/base.py +0 -0
  23. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/command/categories.py +0 -0
  24. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/command/chat_command.py +0 -0
  25. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/command/register.py +0 -0
  26. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/command/user.py +0 -0
  27. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/contact/__init__.py +0 -0
  28. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/__init__.py +0 -0
  29. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/config.py +0 -0
  30. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/gateway/__init__.py +0 -0
  31. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/gateway/caps.py +0 -0
  32. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/gateway/delivery_receipt.py +0 -0
  33. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/gateway/disco.py +0 -0
  34. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/gateway/mam.py +0 -0
  35. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/gateway/muc_admin.py +0 -0
  36. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/gateway/ping.py +0 -0
  37. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/gateway/presence.py +0 -0
  38. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/gateway/registration.py +0 -0
  39. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/gateway/search.py +0 -0
  40. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/gateway/session_dispatcher.py +0 -0
  41. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/mixins/__init__.py +0 -0
  42. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/mixins/attachment.py +0 -0
  43. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/mixins/avatar.py +0 -0
  44. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/mixins/base.py +0 -0
  45. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/mixins/db.py +0 -0
  46. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/mixins/disco.py +0 -0
  47. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/mixins/lock.py +0 -0
  48. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/mixins/message.py +0 -0
  49. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/mixins/message_maker.py +0 -0
  50. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/mixins/presence.py +0 -0
  51. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/mixins/recipient.py +0 -0
  52. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/core/session.py +0 -0
  53. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/__init__.py +0 -0
  54. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/alembic/__init__.py +0 -0
  55. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/alembic/env.py +0 -0
  56. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/alembic/old_user_store.py +0 -0
  57. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/alembic/script.py.mako +0 -0
  58. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/alembic/versions/09f27f098baa_add_missing_attributes_in_room.py +0 -0
  59. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/alembic/versions/2461390c0af2_store_contacts_caps_verstring_in_db.py +0 -0
  60. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/alembic/versions/29f5280c61aa_store_subject_setter_in_room.py +0 -0
  61. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/alembic/versions/2b1f45ab7379_store_room_subject_setter_by_nickname.py +0 -0
  62. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/alembic/versions/5bd48bfdffa2_lift_room_legacy_id_constraint.py +0 -0
  63. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/alembic/versions/82a4af84b679_add_muc_history_filled.py +0 -0
  64. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/alembic/versions/8b993243a536_add_vcard_content_to_contact_table.py +0 -0
  65. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/alembic/versions/8d2ced764698_rely_on_db_to_store_contacts_rooms_and_.py +0 -0
  66. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/alembic/versions/aa9d82a7f6ef_db_creation.py +0 -0
  67. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/alembic/versions/b33993e87db3_move_everything_to_persistent_db.py +0 -0
  68. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/alembic/versions/b64b1a793483_add_source_and_legacy_id_for_archived_.py +0 -0
  69. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/alembic/versions/c4a8ec35a0e8_per_room_user_nick.py +0 -0
  70. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/alembic/versions/e91195719c2c_store_users_avatars_persistently.py +0 -0
  71. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/meta.py +0 -0
  72. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/db/models.py +0 -0
  73. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/group/__init__.py +0 -0
  74. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/group/archive.py +0 -0
  75. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/main.py +0 -0
  76. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/migration.py +0 -0
  77. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/py.typed +0 -0
  78. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/__init__.py +0 -0
  79. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/link_preview/__init__.py +0 -0
  80. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/link_preview/link_preview.py +0 -0
  81. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/link_preview/stanza.py +0 -0
  82. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/roster.py +0 -0
  83. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0077/__init__.py +0 -0
  84. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0077/register.py +0 -0
  85. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0077/stanza.py +0 -0
  86. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0100/__init__.py +0 -0
  87. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0100/gateway.py +0 -0
  88. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0100/stanza.py +0 -0
  89. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0153/__init__.py +0 -0
  90. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0153/stanza.py +0 -0
  91. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0153/vcard_avatar.py +0 -0
  92. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0264/__init__.py +0 -0
  93. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0264/stanza.py +0 -0
  94. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0264/thumbnail.py +0 -0
  95. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0292/__init__.py +0 -0
  96. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0292/vcard4.py +0 -0
  97. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0313/__init__.py +0 -0
  98. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0313/mam.py +0 -0
  99. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0313/stanza.py +0 -0
  100. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0317/__init__.py +0 -0
  101. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0317/hats.py +0 -0
  102. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0317/stanza.py +0 -0
  103. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0356_old/__init__.py +0 -0
  104. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0356_old/privilege.py +0 -0
  105. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0356_old/stanza.py +0 -0
  106. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0424/__init__.py +0 -0
  107. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0424/retraction.py +0 -0
  108. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0424/stanza.py +0 -0
  109. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0490/__init__.py +0 -0
  110. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0490/mds.py +0 -0
  111. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/slixfix/xep_0490/stanza.py +0 -0
  112. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/util/__init__.py +0 -0
  113. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/util/archive_msg.py +0 -0
  114. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/util/conf.py +0 -0
  115. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/util/test.py +0 -0
  116. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/util/types.py +0 -0
  117. {slidge-0.2.0a3 → slidge-0.2.0a4}/slidge/util/util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: slidge
3
- Version: 0.2.0a3
3
+ Version: 0.2.0a4
4
4
  Summary: XMPP bridging framework
5
5
  Home-page: https://sr.ht/~nicoco/slidge/
6
6
  License: AGPL-3.0-or-later
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "slidge"
3
- version = "0.2.0alpha3"
3
+ version = "0.2.0alpha4"
4
4
  description = "XMPP bridging framework"
5
5
  authors = ["Nicolas Cedilnik <nicoco@nicoco.fr>"]
6
6
  readme = "README.md"
@@ -2,4 +2,4 @@ from slidge.util.util import get_version # noqa: F401
2
2
 
3
3
  # this is modified before publish, but if someone cloned from the repo,
4
4
  # it can help
5
- __version__ = "0.2.0alpha3"
5
+ __version__ = "0.2.0alpha4"
@@ -1,5 +1,6 @@
1
1
  # Commands only accessible for slidge admins
2
2
  import functools
3
+ import importlib
3
4
  import logging
4
5
  from datetime import datetime
5
6
  from typing import Any, Optional
@@ -7,6 +8,7 @@ from typing import Any, Optional
7
8
  from slixmpp import JID
8
9
  from slixmpp.exceptions import XMPPError
9
10
 
11
+ from ..core import config
10
12
  from ..util.types import AnyBaseSession
11
13
  from .base import (
12
14
  Command,
@@ -90,8 +92,12 @@ class SlidgeInfo(AdminCommand):
90
92
  [a for a in (days_ago, hours_ago, minutes_ago, seconds_ago) if a]
91
93
  )
92
94
 
95
+ legacy_module = importlib.import_module(config.LEGACY_MODULE)
96
+ version = getattr(legacy_module, "__version__", "No version")
97
+
93
98
  return (
94
- f"{self.xmpp.COMPONENT_NAME} version {__version__}\n"
99
+ f"{self.xmpp.COMPONENT_NAME} (slidge core {__version__},"
100
+ f" {config.LEGACY_MODULE} {version})\n"
95
101
  f"Up since {start:%Y-%m-%d %H:%M} ({ago} ago)"
96
102
  )
97
103
 
@@ -129,8 +129,8 @@ class LegacyContact(
129
129
  self._vcard_fetched = False
130
130
  self._vcard: str | None = None
131
131
 
132
- async def get_vcard(self) -> VCard4 | None:
133
- if not self._vcard_fetched:
132
+ async def get_vcard(self, fetch=True) -> VCard4 | None:
133
+ if fetch and not self._vcard_fetched:
134
134
  await self.fetch_vcard()
135
135
  if self._vcard is None:
136
136
  return None
@@ -8,6 +8,7 @@ from slixmpp.exceptions import IqError, XMPPError
8
8
  from slixmpp.jid import JID_UNESCAPE_TRANSFORMATIONS, _unescape_node
9
9
 
10
10
  from ..core.mixins.lock import NamedLockMixin
11
+ from ..db.models import Contact
11
12
  from ..db.store import ContactStore
12
13
  from ..util import SubclassableOnce
13
14
  from ..util.types import LegacyContactType, LegacyUserIdType
@@ -63,37 +64,6 @@ class LegacyRoster(
63
64
  for stored in self.__store.get_all(user_pk=self.session.user_pk):
64
65
  yield self._contact_cls.from_store(self.session, stored)
65
66
 
66
- async def __finish_init_contact(
67
- self, legacy_id: LegacyUserIdType, jid_username: str, *args, **kwargs
68
- ):
69
- async with self.lock(("finish", legacy_id)):
70
- with self.__store.session():
71
- stored = self.__store.get_by_legacy_id(
72
- self.session.user_pk, str(legacy_id)
73
- )
74
- if stored is not None:
75
- if stored.updated:
76
- return self._contact_cls.from_store(self.session, stored)
77
- c: LegacyContact = self._contact_cls(
78
- self.session, legacy_id, jid_username, *args, **kwargs
79
- )
80
- c.contact_pk = stored.id
81
- else:
82
- c = self._contact_cls(
83
- self.session, legacy_id, jid_username, *args, **kwargs
84
- )
85
- try:
86
- with c.updating_info():
87
- await c.avatar_wrap_update_info()
88
- except Exception as e:
89
- raise XMPPError("internal-server-error", str(e))
90
- c._caps_ver = await c.get_caps_ver(c.jid)
91
- need_avatar = c.contact_pk is None
92
- c.contact_pk = self.__store.update(c, commit=not self.__filling)
93
- if need_avatar:
94
- c._post_avatar_update()
95
- return c
96
-
97
67
  def known_contacts(self, only_friends=True) -> dict[str, LegacyContactType]:
98
68
  if only_friends:
99
69
  return {c.jid.bare: c for c in self if c.is_friend}
@@ -112,17 +82,15 @@ class LegacyRoster(
112
82
  # """
113
83
  username = contact_jid.node
114
84
  async with self.lock(("username", username)):
115
- with self.__store.session():
116
- stored = self.__store.get_by_jid(self.session.user_pk, contact_jid)
117
- if stored is not None and stored.updated:
118
- return self._contact_cls.from_store(self.session, stored)
119
-
120
85
  legacy_id = await self.jid_username_to_legacy_id(username)
121
86
  log.debug("Contact %s not found", contact_jid)
122
87
  if self.get_lock(("legacy_id", legacy_id)):
123
88
  log.debug("Already updating %s", contact_jid)
124
89
  return await self.by_legacy_id(legacy_id)
125
- return await self.__finish_init_contact(legacy_id, username)
90
+
91
+ with self.__store.session():
92
+ stored = self.__store.get_by_jid(self.session.user_pk, contact_jid)
93
+ return await self.__update_contact(stored, legacy_id, username)
126
94
 
127
95
  async def by_legacy_id(
128
96
  self, legacy_id: LegacyUserIdType, *args, **kwargs
@@ -145,26 +113,48 @@ class LegacyRoster(
145
113
  if legacy_id == self.user_legacy_id:
146
114
  raise ContactIsUser
147
115
  async with self.lock(("legacy_id", legacy_id)):
148
- with self.__store.session():
149
- stored = self.__store.get_by_legacy_id(
150
- self.session.user_pk, str(legacy_id)
151
- )
152
- if stored is not None and stored.updated:
153
- return self._contact_cls.from_store(
154
- self.session, stored, *args, **kwargs
155
- )
156
-
157
116
  username = await self.legacy_id_to_jid_username(legacy_id)
158
- log.debug("Contact %s not found", legacy_id)
159
117
  if self.get_lock(("username", username)):
160
118
  log.debug("Already updating %s", username)
161
119
  jid = JID()
162
120
  jid.node = username
163
121
  jid.domain = self.session.xmpp.boundjid.bare
164
122
  return await self.by_jid(jid)
165
- return await self.__finish_init_contact(
166
- legacy_id, username, *args, **kwargs
167
- )
123
+
124
+ with self.__store.session():
125
+ stored = self.__store.get_by_legacy_id(
126
+ self.session.user_pk, str(legacy_id)
127
+ )
128
+ return await self.__update_contact(
129
+ stored, legacy_id, username, *args, **kwargs
130
+ )
131
+
132
+ async def __update_contact(
133
+ self,
134
+ stored: Contact | None,
135
+ legacy_id: LegacyUserIdType,
136
+ username: str,
137
+ *a,
138
+ **kw,
139
+ ) -> LegacyContactType:
140
+ if stored is None:
141
+ contact = self._contact_cls(self.session, legacy_id, username, *a, **kw)
142
+ else:
143
+ contact = self._contact_cls.from_store(self.session, stored, *a, **kw)
144
+ if stored.updated:
145
+ return contact
146
+
147
+ try:
148
+ with contact.updating_info():
149
+ await contact.avatar_wrap_update_info()
150
+ except Exception as e:
151
+ raise XMPPError("internal-server-error", str(e))
152
+ contact._caps_ver = await contact.get_caps_ver(contact.jid)
153
+ need_avatar = contact.contact_pk is None
154
+ contact.contact_pk = self.__store.update(contact, commit=not self.__filling)
155
+ if need_avatar:
156
+ contact._post_avatar_update()
157
+ return contact
168
158
 
169
159
  async def by_stanza(self, s) -> LegacyContact:
170
160
  # """
@@ -225,7 +215,7 @@ class LegacyRoster(
225
215
  item = contact.get_roster_item()
226
216
  old = user_roster.get(contact.jid.bare)
227
217
  if old is not None and all(
228
- old[k] == item[contact.jid.bare][k]
218
+ old[k] == item[contact.jid.bare].get(k)
229
219
  for k in ("subscription", "groups", "name")
230
220
  ):
231
221
  self.log.debug("No need to update roster")
@@ -315,7 +315,7 @@ class BaseGateway(
315
315
 
316
316
  from ...group.room import LegacyMUC
317
317
 
318
- LegacyMUC.get_unique_subclass().xmpp = self
318
+ LegacyMUC.get_self_or_unique_subclass().xmpp = self
319
319
 
320
320
  self.get_session_from_stanza: Callable[
321
321
  [Union[Message, Presence, Iq]], BaseSession
@@ -86,7 +86,7 @@ class VCardTemp:
86
86
  avatar = entity.get_avatar()
87
87
  type_ = "image/png"
88
88
  if isinstance(entity, LegacyContact):
89
- vcard = await entity.get_vcard()
89
+ vcard = await entity.get_vcard(fetch=False)
90
90
  else:
91
91
  vcard = None
92
92
  v = self.xmpp.plugin["xep_0054"].make_vcard()
@@ -22,6 +22,7 @@ from slixmpp.types import JidStr, OptJidStr
22
22
 
23
23
  from ..db.avatar import CachedAvatar, avatar_cache
24
24
  from ..db.store import ContactStore, SlidgeStore
25
+ from ..util.types import URL
25
26
  from .mixins.lock import NamedLockMixin
26
27
 
27
28
  if TYPE_CHECKING:
@@ -171,14 +172,13 @@ class PubSubComponent(NamedLockMixin, BasePlugin):
171
172
  except XMPPError:
172
173
  pass
173
174
  else:
174
- if pep_avatar.metadata is None:
175
- raise XMPPError("internal-server-error", "Avatar but no metadata?")
176
- await self.__broadcast(
177
- data=pep_avatar.metadata,
178
- from_=p.get_to(),
179
- to=from_,
180
- id=pep_avatar.metadata["info"]["id"],
181
- )
175
+ if pep_avatar.metadata is not None:
176
+ await self.__broadcast(
177
+ data=pep_avatar.metadata,
178
+ from_=p.get_to(),
179
+ to=from_,
180
+ id=pep_avatar.metadata["info"]["id"],
181
+ )
182
182
  if UserNick.namespace + "+notify" in features:
183
183
  try:
184
184
  pep_nick = await self._get_authorized_nick(p)
@@ -222,7 +222,9 @@ class PubSubComponent(NamedLockMixin, BasePlugin):
222
222
  item = PepAvatar()
223
223
  avatar_id = entity.avatar_id
224
224
  if avatar_id is not None:
225
- stored = avatar_cache.get(str(avatar_id))
225
+ stored = avatar_cache.get(
226
+ avatar_id if isinstance(avatar_id, URL) else str(avatar_id)
227
+ )
226
228
  assert stored is not None
227
229
  item.set_avatar_from_cache(stored)
228
230
  return item
@@ -206,6 +206,11 @@ class AvatarCache:
206
206
  stored = orm.execute(select(Avatar).where(Avatar.hash == hash_)).scalar()
207
207
 
208
208
  if stored is not None:
209
+ if unique_id is not None:
210
+ log.warning("Updating 'unique' IDs of a known avatar.")
211
+ stored.legacy_id = str(unique_id)
212
+ orm.add(stored)
213
+ orm.commit()
209
214
  return CachedAvatar.from_store(stored, self.dir)
210
215
 
211
216
  stored = Avatar(
@@ -162,12 +162,20 @@ class AvatarStore(EngineMixin):
162
162
  class SentStore(EngineMixin):
163
163
  def set_message(self, user_pk: int, legacy_id: str, xmpp_id: str) -> None:
164
164
  with self.session() as session:
165
- msg = XmppToLegacyIds(
166
- user_account_id=user_pk,
167
- legacy_id=legacy_id,
168
- xmpp_id=xmpp_id,
169
- type=XmppToLegacyEnum.DM,
165
+ msg = (
166
+ session.query(XmppToLegacyIds)
167
+ .filter(XmppToLegacyIds.user_account_id == user_pk)
168
+ .filter(XmppToLegacyIds.legacy_id == legacy_id)
169
+ .filter(XmppToLegacyIds.xmpp_id == xmpp_id)
170
+ .scalar()
170
171
  )
172
+ if msg is None:
173
+ msg = XmppToLegacyIds(user_account_id=user_pk)
174
+ else:
175
+ log.debug("Resetting a DM from sent store")
176
+ msg.legacy_id = legacy_id
177
+ msg.xmpp_id = xmpp_id
178
+ msg.type = XmppToLegacyEnum.DM
171
179
  session.add(msg)
172
180
  session.commit()
173
181
 
@@ -625,6 +633,7 @@ class MAMStore(EngineMixin):
625
633
  with self.session() as session:
626
634
  after_timestamp = (
627
635
  session.query(ArchivedMessage.timestamp)
636
+ .filter(ArchivedMessage.room_id == room_pk)
628
637
  .filter(ArchivedMessage.legacy_id == after_id)
629
638
  .scalar()
630
639
  )
@@ -778,7 +787,10 @@ class RoomStore(UpdatedMixin):
778
787
  with self.session() as session:
779
788
  session.execute(
780
789
  update(Room).values(
781
- subject_setter=None, user_resources=None, history_filled=False
790
+ subject_setter=None,
791
+ user_resources=None,
792
+ history_filled=False,
793
+ participants_filled=False,
782
794
  )
783
795
  )
784
796
  session.commit()
@@ -890,6 +902,13 @@ class RoomStore(UpdatedMixin):
890
902
  )
891
903
  session.commit()
892
904
 
905
+ def update_user_nick(self, room_pk, nick: str) -> None:
906
+ with self.session() as session:
907
+ session.execute(
908
+ update(Room).where(Room.id == room_pk).values(user_nick=nick)
909
+ )
910
+ session.commit()
911
+
893
912
  def delete(self, room_pk: int) -> None:
894
913
  with self.session() as session:
895
914
  session.execute(delete(Room).where(Room.id == room_pk))
@@ -8,6 +8,7 @@ from slixmpp.jid import _unescape_node
8
8
 
9
9
  from ..contact.roster import ESCAPE_TABLE
10
10
  from ..core.mixins.lock import NamedLockMixin
11
+ from ..db.models import Room
11
12
  from ..util import SubclassableOnce
12
13
  from ..util.types import LegacyGroupIdType, LegacyMUCType
13
14
  from .archive import MessageArchive
@@ -57,29 +58,6 @@ class LegacyBookmarks(
57
58
  def __repr__(self):
58
59
  return f"<Bookmarks of {self.user_jid}>"
59
60
 
60
- async def __finish_init_muc(self, legacy_id: LegacyGroupIdType, jid: JID):
61
- with self.__store.session():
62
- stored = self.__store.get_by_legacy_id(self.session.user_pk, str(legacy_id))
63
- if stored is not None:
64
- if stored.updated:
65
- return self._muc_class.from_store(self.session, stored)
66
- muc = self._muc_class(self.session, legacy_id=legacy_id, jid=jid)
67
- muc.pk = stored.id
68
- else:
69
- muc = self._muc_class(self.session, legacy_id=legacy_id, jid=jid)
70
-
71
- try:
72
- with muc.updating_info():
73
- await muc.avatar_wrap_update_info()
74
- except Exception as e:
75
- raise XMPPError("internal-server-error", str(e))
76
- if not muc.user_nick:
77
- muc.user_nick = self._user_nick
78
- self.log.debug("MUC created: %r", muc)
79
- muc.pk = self.__store.update(muc)
80
- muc.archive = MessageArchive(muc.pk, self.xmpp.store.mam)
81
- return muc
82
-
83
61
  async def legacy_id_to_jid_local_part(self, legacy_id: LegacyGroupIdType):
84
62
  return await self.legacy_id_to_jid_username(legacy_id)
85
63
 
@@ -110,24 +88,16 @@ class LegacyBookmarks(
110
88
  async def by_jid(self, jid: JID) -> LegacyMUCType:
111
89
  if jid.resource:
112
90
  jid = JID(jid.bare)
113
- bare = jid.bare
114
- async with self.lock(("bare", bare)):
115
- assert isinstance(jid.username, str)
116
- legacy_id = await self.jid_local_part_to_legacy_id(jid.username)
91
+ async with self.lock(("bare", jid.bare)):
92
+ assert isinstance(jid.local, str)
93
+ legacy_id = await self.jid_local_part_to_legacy_id(jid.local)
117
94
  if self.get_lock(("legacy_id", legacy_id)):
118
95
  self.log.debug("Not instantiating %s after all", jid)
119
96
  return await self.by_legacy_id(legacy_id)
120
97
 
121
98
  with self.__store.session():
122
99
  stored = self.__store.get_by_jid(self.session.user_pk, jid)
123
- if stored is not None and stored.updated:
124
- return self._muc_class.from_store(self.session, stored)
125
-
126
- self.log.debug("Attempting to instantiate a new MUC for JID %s", jid)
127
- local_part = jid.node
128
-
129
- self.log.debug("%r is group %r", local_part, legacy_id)
130
- return await self.__finish_init_muc(legacy_id, JID(bare))
100
+ return await self.__update_muc(stored, legacy_id, jid)
131
101
 
132
102
  def by_jid_only_if_exists(self, jid: JID) -> Optional[LegacyMUCType]:
133
103
  with self.__store.session():
@@ -138,22 +108,39 @@ class LegacyBookmarks(
138
108
 
139
109
  async def by_legacy_id(self, legacy_id: LegacyGroupIdType) -> LegacyMUCType:
140
110
  async with self.lock(("legacy_id", legacy_id)):
141
- with self.__store.session():
142
- stored = self.__store.get_by_legacy_id(
143
- self.session.user_pk, str(legacy_id)
144
- )
145
- if stored is not None and stored.updated:
146
- return self._muc_class.from_store(self.session, stored)
147
- self.log.debug("Create new MUC instance for legacy ID %s", legacy_id)
148
111
  local = await self.legacy_id_to_jid_local_part(legacy_id)
149
- bare = f"{local}@{self.xmpp.boundjid}"
150
- jid = JID(bare)
151
- if self.get_lock(("bare", bare)):
112
+ jid = JID(f"{local}@{self.xmpp.boundjid}")
113
+ if self.get_lock(("bare", jid.bare)):
152
114
  self.log.debug("Not instantiating %s after all", legacy_id)
153
115
  return await self.by_jid(jid)
154
- muc = await self.__finish_init_muc(legacy_id, jid)
155
116
 
156
- return muc
117
+ with self.__store.session():
118
+ stored = self.__store.get_by_legacy_id(
119
+ self.session.user_pk, str(legacy_id)
120
+ )
121
+ return await self.__update_muc(stored, legacy_id, jid)
122
+
123
+ async def __update_muc(
124
+ self, stored: Room | None, legacy_id: LegacyGroupIdType, jid: JID
125
+ ):
126
+ if stored is None:
127
+ muc = self._muc_class(self.session, legacy_id=legacy_id, jid=jid)
128
+ else:
129
+ muc = self._muc_class.from_store(self.session, stored)
130
+ if stored.updated:
131
+ return muc
132
+
133
+ try:
134
+ with muc.updating_info():
135
+ await muc.avatar_wrap_update_info()
136
+ except Exception as e:
137
+ raise XMPPError("internal-server-error", str(e))
138
+ if not muc.user_nick:
139
+ muc.user_nick = self._user_nick
140
+ self.log.debug("MUC created: %r", muc)
141
+ muc.pk = self.__store.update(muc)
142
+ muc.archive = MessageArchive(muc.pk, self.xmpp.store.mam)
143
+ return muc
157
144
 
158
145
  @abc.abstractmethod
159
146
  async def fill(self):
@@ -450,13 +450,21 @@ class LegacyParticipant(
450
450
  return super().get_disco_info()
451
451
 
452
452
  def moderate(self, legacy_msg_id: LegacyMessageType, reason: Optional[str] = None):
453
- m = self.muc.get_system_participant()._make_message()
454
- m["apply_to"]["id"] = self._legacy_to_xmpp(legacy_msg_id)
455
- m["apply_to"]["moderated"].enable("retract")
456
- m["apply_to"]["moderated"]["by"] = self.jid
457
- if reason:
458
- m["apply_to"]["moderated"]["reason"] = reason
459
- self._send(m)
453
+ xmpp_id = self._legacy_to_xmpp(legacy_msg_id)
454
+ multi = self.xmpp.store.multi.get_xmpp_ids(self.session.user_pk, xmpp_id)
455
+ if multi is None:
456
+ msg_ids = [xmpp_id]
457
+ else:
458
+ msg_ids = multi + [xmpp_id]
459
+
460
+ for i in msg_ids:
461
+ m = self.muc.get_system_participant()._make_message()
462
+ m["apply_to"]["id"] = i
463
+ m["apply_to"]["moderated"].enable("retract")
464
+ m["apply_to"]["moderated"]["by"] = self.jid
465
+ if reason:
466
+ m["apply_to"]["moderated"]["reason"] = reason
467
+ self._send(m)
460
468
 
461
469
  def set_room_subject(
462
470
  self,
@@ -206,6 +206,8 @@ class LegacyMUC(
206
206
  @user_nick.setter
207
207
  def user_nick(self, nick: str):
208
208
  self._user_nick = nick
209
+ if not self._updating_info:
210
+ self.__store.update_user_nick(self.pk, nick)
209
211
 
210
212
  def add_user_resource(self, resource: str) -> None:
211
213
  self._user_resources.add(resource)
@@ -1195,7 +1197,7 @@ class LegacyMUC(
1195
1197
  )
1196
1198
  muc.pk = stored.id
1197
1199
  muc.type = stored.muc_type # type: ignore
1198
- muc.user_nick = stored.user_nick
1200
+ muc._user_nick = stored.user_nick
1199
1201
  if stored.name:
1200
1202
  muc.DISCO_NAME = stored.name
1201
1203
  if stored.description:
@@ -0,0 +1,5 @@
1
+ # here to allow migration of the user store from v0.1
2
+ # since it relies on shelf, which relies on pickle, we need to keep objects
3
+ # importable where they were when the shelf was written
4
+
5
+ from ..db.alembic.old_user_store import * # noqa:F403
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes