slidge 0.2.12__py3-none-any.whl → 0.3.0a0__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/__init__.py +5 -2
- slidge/command/adhoc.py +9 -3
- slidge/command/admin.py +16 -12
- slidge/command/base.py +16 -12
- slidge/command/chat_command.py +25 -16
- slidge/command/user.py +7 -8
- slidge/contact/contact.py +119 -209
- slidge/contact/roster.py +106 -105
- slidge/core/config.py +2 -43
- slidge/core/dispatcher/caps.py +9 -2
- slidge/core/dispatcher/disco.py +13 -3
- slidge/core/dispatcher/message/__init__.py +1 -1
- slidge/core/dispatcher/message/chat_state.py +17 -8
- slidge/core/dispatcher/message/marker.py +7 -5
- slidge/core/dispatcher/message/message.py +117 -92
- slidge/core/dispatcher/muc/__init__.py +1 -1
- slidge/core/dispatcher/muc/admin.py +4 -4
- slidge/core/dispatcher/muc/mam.py +10 -6
- slidge/core/dispatcher/muc/misc.py +4 -2
- slidge/core/dispatcher/muc/owner.py +5 -3
- slidge/core/dispatcher/muc/ping.py +3 -1
- slidge/core/dispatcher/presence.py +21 -15
- slidge/core/dispatcher/registration.py +20 -12
- slidge/core/dispatcher/search.py +7 -3
- slidge/core/dispatcher/session_dispatcher.py +13 -5
- slidge/core/dispatcher/util.py +37 -27
- slidge/core/dispatcher/vcard.py +7 -4
- slidge/core/gateway.py +168 -84
- slidge/core/mixins/__init__.py +1 -11
- slidge/core/mixins/attachment.py +163 -148
- slidge/core/mixins/avatar.py +100 -177
- slidge/core/mixins/db.py +50 -2
- slidge/core/mixins/message.py +19 -17
- slidge/core/mixins/message_maker.py +29 -15
- slidge/core/mixins/message_text.py +38 -30
- slidge/core/mixins/presence.py +91 -35
- slidge/core/pubsub.py +42 -47
- slidge/core/session.py +88 -57
- slidge/db/alembic/versions/0337c90c0b96_unify_legacy_xmpp_id_mappings.py +183 -0
- slidge/db/alembic/versions/4dbd23a3f868_new_avatar_store.py +56 -0
- slidge/db/alembic/versions/54ce3cde350c_use_hash_for_avatar_filenames.py +50 -0
- slidge/db/alembic/versions/58b98dacf819_refactor.py +118 -0
- slidge/db/alembic/versions/75a62b74b239_ditch_hats_table.py +74 -0
- slidge/db/avatar.py +150 -119
- slidge/db/meta.py +33 -22
- slidge/db/models.py +68 -117
- slidge/db/store.py +412 -1094
- slidge/group/archive.py +61 -54
- slidge/group/bookmarks.py +74 -55
- slidge/group/participant.py +135 -142
- slidge/group/room.py +315 -312
- slidge/main.py +28 -18
- slidge/migration.py +2 -12
- slidge/slixfix/__init__.py +20 -4
- slidge/slixfix/delivery_receipt.py +6 -4
- slidge/slixfix/link_preview/link_preview.py +1 -1
- slidge/slixfix/link_preview/stanza.py +1 -1
- slidge/slixfix/roster.py +5 -7
- slidge/slixfix/xep_0077/register.py +8 -8
- slidge/slixfix/xep_0077/stanza.py +7 -7
- slidge/slixfix/xep_0100/gateway.py +12 -13
- slidge/slixfix/xep_0153/vcard_avatar.py +1 -1
- slidge/slixfix/xep_0292/vcard4.py +1 -1
- slidge/util/archive_msg.py +11 -5
- slidge/util/conf.py +23 -20
- slidge/util/jid_escaping.py +1 -1
- slidge/{core/mixins → util}/lock.py +6 -6
- slidge/util/test.py +30 -29
- slidge/util/types.py +22 -18
- slidge/util/util.py +19 -22
- {slidge-0.2.12.dist-info → slidge-0.3.0a0.dist-info}/METADATA +1 -1
- slidge-0.3.0a0.dist-info/RECORD +117 -0
- {slidge-0.2.12.dist-info → slidge-0.3.0a0.dist-info}/WHEEL +1 -1
- slidge-0.2.12.dist-info/RECORD +0 -112
- {slidge-0.2.12.dist-info → slidge-0.3.0a0.dist-info}/entry_points.txt +0 -0
- {slidge-0.2.12.dist-info → slidge-0.3.0a0.dist-info}/licenses/LICENSE +0 -0
- {slidge-0.2.12.dist-info → slidge-0.3.0a0.dist-info}/top_level.txt +0 -0
@@ -16,7 +16,9 @@ from ..util import DispatcherMixin, exceptions_to_xmpp_errors
|
|
16
16
|
|
17
17
|
|
18
18
|
class MessageContentMixin(DispatcherMixin):
|
19
|
-
|
19
|
+
__slots__: list[str] = []
|
20
|
+
|
21
|
+
def __init__(self, xmpp) -> None:
|
20
22
|
super().__init__(xmpp)
|
21
23
|
xmpp.add_event_handler("legacy_message", self.on_legacy_message)
|
22
24
|
xmpp.add_event_handler("message_correction", self.on_message_correction)
|
@@ -28,7 +30,7 @@ class MessageContentMixin(DispatcherMixin):
|
|
28
30
|
await self.on_legacy_message(msg)
|
29
31
|
|
30
32
|
@exceptions_to_xmpp_errors
|
31
|
-
async def on_legacy_message(self, msg: Message):
|
33
|
+
async def on_legacy_message(self, msg: Message) -> None:
|
32
34
|
"""
|
33
35
|
Meant to be called from :class:`BaseGateway` only.
|
34
36
|
|
@@ -65,16 +67,27 @@ class MessageContentMixin(DispatcherMixin):
|
|
65
67
|
if src is not None and src.startswith("cid:"):
|
66
68
|
cid = src.removeprefix("cid:")
|
67
69
|
|
68
|
-
session,
|
70
|
+
session, recipient, thread = await self._get_session_recipient_thread(msg)
|
69
71
|
|
70
72
|
if msg.get_plugin("oob", check=True) is not None:
|
71
73
|
url = msg["oob"]["url"]
|
74
|
+
elif (
|
75
|
+
"reference" in msg
|
76
|
+
and "sims" in msg["reference"]
|
77
|
+
and "sources" in msg["reference"]["sims"]
|
78
|
+
):
|
79
|
+
for source in msg["reference"]["sims"]["sources"]["substanzas"]:
|
80
|
+
if source["uri"].startswith("http"):
|
81
|
+
url = source["uri"]
|
82
|
+
break
|
83
|
+
else:
|
84
|
+
url = None
|
72
85
|
else:
|
73
86
|
url = None
|
74
87
|
|
75
88
|
if msg.get_plugin("reply", check=True):
|
76
89
|
text, reply_to_msg_id, reply_to, reply_fallback = await self.__get_reply(
|
77
|
-
msg, session,
|
90
|
+
msg, session, recipient
|
78
91
|
)
|
79
92
|
else:
|
80
93
|
text = msg["body"]
|
@@ -93,7 +106,7 @@ class MessageContentMixin(DispatcherMixin):
|
|
93
106
|
legacy_msg_id = await self.__send_url(
|
94
107
|
url,
|
95
108
|
session,
|
96
|
-
|
109
|
+
recipient,
|
97
110
|
reply_to_msg_id=reply_to_msg_id,
|
98
111
|
reply_to_fallback_text=reply_fallback,
|
99
112
|
reply_to=reply_to,
|
@@ -104,19 +117,19 @@ class MessageContentMixin(DispatcherMixin):
|
|
104
117
|
msg.get_from(),
|
105
118
|
cid,
|
106
119
|
session,
|
107
|
-
|
120
|
+
recipient,
|
108
121
|
reply_to_msg_id=reply_to_msg_id,
|
109
122
|
reply_to_fallback_text=reply_fallback,
|
110
123
|
reply_to=reply_to,
|
111
124
|
thread=thread,
|
112
125
|
)
|
113
126
|
elif text:
|
114
|
-
if isinstance(
|
115
|
-
mentions = {"mentions": await
|
127
|
+
if isinstance(recipient, LegacyMUC):
|
128
|
+
mentions = {"mentions": await recipient.parse_mentions(text)}
|
116
129
|
else:
|
117
130
|
mentions = {}
|
118
131
|
legacy_msg_id = await session.on_text(
|
119
|
-
|
132
|
+
recipient,
|
120
133
|
text,
|
121
134
|
reply_to_msg_id=reply_to_msg_id,
|
122
135
|
reply_to_fallback_text=reply_fallback,
|
@@ -129,43 +142,49 @@ class MessageContentMixin(DispatcherMixin):
|
|
129
142
|
log.debug("Ignoring %s", msg.get_id())
|
130
143
|
return
|
131
144
|
|
132
|
-
if isinstance(
|
133
|
-
await
|
134
|
-
if legacy_msg_id is not None:
|
135
|
-
self.xmpp.store.sent.set_group_message(
|
136
|
-
session.user_pk, str(legacy_msg_id), msg.get_id()
|
137
|
-
)
|
145
|
+
if isinstance(recipient, LegacyMUC):
|
146
|
+
await recipient.echo(msg, legacy_msg_id)
|
138
147
|
else:
|
139
148
|
self.__ack(msg)
|
140
|
-
|
141
|
-
|
142
|
-
|
149
|
+
|
150
|
+
if legacy_msg_id is None:
|
151
|
+
return
|
152
|
+
|
153
|
+
with self.xmpp.store.session() as orm:
|
154
|
+
self.xmpp.store.id_map.set_msg(
|
155
|
+
orm,
|
156
|
+
recipient.stored.id,
|
157
|
+
str(legacy_msg_id),
|
158
|
+
[msg.get_id()],
|
159
|
+
recipient.is_group,
|
160
|
+
)
|
161
|
+
if session.MESSAGE_IDS_ARE_THREAD_IDS and (t := msg["thread"]):
|
162
|
+
self.xmpp.store.id_map.set_thread(
|
163
|
+
orm, recipient.stored.id, t, str(legacy_msg_id), recipient.is_group
|
143
164
|
)
|
144
|
-
|
145
|
-
self.xmpp.store.sent.set_thread(
|
146
|
-
session.user_pk, t, str(legacy_msg_id)
|
147
|
-
)
|
165
|
+
orm.commit()
|
148
166
|
|
149
167
|
@exceptions_to_xmpp_errors
|
150
|
-
async def on_message_correction(self, msg: Message):
|
168
|
+
async def on_message_correction(self, msg: Message) -> None:
|
151
169
|
if msg.get_plugin("retract", check=True) is not None:
|
152
170
|
# ignore message retraction fallback (fallback=last msg correction)
|
153
171
|
return
|
154
|
-
session,
|
172
|
+
session, recipient, thread = await self._get_session_recipient_thread(msg)
|
155
173
|
xmpp_id = msg["replace"]["id"]
|
156
|
-
if isinstance(
|
157
|
-
|
158
|
-
|
159
|
-
|
174
|
+
if isinstance(recipient, LegacyMUC):
|
175
|
+
with self.xmpp.store.session() as orm:
|
176
|
+
legacy_id_str = self.xmpp.store.id_map.get_legacy(
|
177
|
+
orm, recipient.stored.id, xmpp_id, True
|
178
|
+
)
|
160
179
|
if legacy_id_str is None:
|
161
|
-
legacy_id = self._xmpp_msg_id_to_legacy(session, xmpp_id)
|
180
|
+
legacy_id = self._xmpp_msg_id_to_legacy(session, xmpp_id, recipient)
|
162
181
|
else:
|
163
182
|
legacy_id = self.xmpp.LEGACY_MSG_ID_TYPE(legacy_id_str)
|
164
183
|
else:
|
165
|
-
legacy_id = self._xmpp_msg_id_to_legacy(session, xmpp_id)
|
184
|
+
legacy_id = self._xmpp_msg_id_to_legacy(session, xmpp_id, recipient)
|
166
185
|
|
167
|
-
if isinstance(
|
168
|
-
mentions = await
|
186
|
+
if isinstance(recipient, LegacyMUC):
|
187
|
+
mentions = await recipient.parse_mentions(msg["body"])
|
169
188
|
else:
|
170
189
|
mentions = None
|
171
190
|
|
@@ -177,22 +196,18 @@ class MessageContentMixin(DispatcherMixin):
|
|
177
196
|
if legacy_id is None:
|
178
197
|
log.debug("Did not find legacy ID to correct")
|
179
198
|
new_legacy_msg_id = await session.on_text(
|
180
|
-
|
199
|
+
recipient,
|
181
200
|
"Correction:" + msg["body"],
|
182
201
|
thread=thread,
|
183
202
|
mentions=mentions,
|
184
203
|
link_previews=link_previews,
|
185
204
|
)
|
186
|
-
elif (
|
187
|
-
|
188
|
-
and config.CORRECTION_EMPTY_BODY_AS_RETRACTION
|
189
|
-
and entity.RETRACTION
|
190
|
-
):
|
191
|
-
await session.on_retract(entity, legacy_id, thread=thread)
|
205
|
+
elif not msg["body"].strip() and recipient.RETRACTION:
|
206
|
+
await session.on_retract(recipient, legacy_id, thread=thread)
|
192
207
|
new_legacy_msg_id = None
|
193
|
-
elif
|
208
|
+
elif recipient.CORRECTION:
|
194
209
|
new_legacy_msg_id = await session.on_correct(
|
195
|
-
|
210
|
+
recipient,
|
196
211
|
msg["body"],
|
197
212
|
legacy_id,
|
198
213
|
thread=thread,
|
@@ -204,60 +219,59 @@ class MessageContentMixin(DispatcherMixin):
|
|
204
219
|
"Last message correction is not supported by this legacy service. "
|
205
220
|
"Slidge will send your correction as new message."
|
206
221
|
)
|
207
|
-
if
|
208
|
-
config.LAST_MESSAGE_CORRECTION_RETRACTION_WORKAROUND
|
209
|
-
and entity.RETRACTION
|
210
|
-
and legacy_id is not None
|
211
|
-
):
|
222
|
+
if recipient.RETRACTION and legacy_id is not None:
|
212
223
|
if legacy_id is not None:
|
213
224
|
session.send_gateway_message(
|
214
225
|
"Slidge will attempt to retract the original message you wanted"
|
215
226
|
" to edit."
|
216
227
|
)
|
217
|
-
await session.on_retract(
|
228
|
+
await session.on_retract(recipient, legacy_id, thread=thread)
|
218
229
|
|
219
230
|
new_legacy_msg_id = await session.on_text(
|
220
|
-
|
231
|
+
recipient,
|
221
232
|
"Correction: " + msg["body"],
|
222
233
|
thread=thread,
|
223
234
|
mentions=mentions,
|
224
235
|
link_previews=link_previews,
|
225
236
|
)
|
226
237
|
|
227
|
-
if isinstance(
|
228
|
-
|
229
|
-
self.xmpp.store.sent.set_group_message(
|
230
|
-
session.user_pk, new_legacy_msg_id, msg.get_id()
|
231
|
-
)
|
232
|
-
await entity.echo(msg, new_legacy_msg_id)
|
238
|
+
if isinstance(recipient, LegacyMUC):
|
239
|
+
await recipient.echo(msg, new_legacy_msg_id)
|
233
240
|
else:
|
234
241
|
self.__ack(msg)
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
242
|
+
if new_legacy_msg_id is None:
|
243
|
+
return
|
244
|
+
with self.xmpp.store.session() as orm:
|
245
|
+
self.xmpp.store.id_map.set_msg(
|
246
|
+
orm,
|
247
|
+
recipient.stored.id,
|
248
|
+
new_legacy_msg_id,
|
249
|
+
msg.get_id(),
|
250
|
+
recipient.is_group,
|
251
|
+
)
|
252
|
+
orm.commit()
|
239
253
|
|
240
254
|
@exceptions_to_xmpp_errors
|
241
255
|
async def on_message_retract(self, msg: Message):
|
242
|
-
session,
|
243
|
-
if not
|
256
|
+
session, recipient, thread = await self._get_session_recipient_thread(msg)
|
257
|
+
if not recipient.RETRACTION:
|
244
258
|
raise XMPPError(
|
245
259
|
"bad-request",
|
246
260
|
"This legacy service does not support message retraction.",
|
247
261
|
)
|
248
262
|
xmpp_id: str = msg["retract"]["id"]
|
249
|
-
legacy_id = self._xmpp_msg_id_to_legacy(session, xmpp_id)
|
263
|
+
legacy_id = self._xmpp_msg_id_to_legacy(session, xmpp_id, recipient)
|
250
264
|
if legacy_id:
|
251
|
-
await session.on_retract(
|
252
|
-
if isinstance(
|
253
|
-
await
|
265
|
+
await session.on_retract(recipient, legacy_id, thread=thread)
|
266
|
+
if isinstance(recipient, LegacyMUC):
|
267
|
+
await recipient.echo(msg, None)
|
254
268
|
else:
|
255
269
|
log.debug("Ignored retraction from user")
|
256
270
|
self.__ack(msg)
|
257
271
|
|
258
272
|
@exceptions_to_xmpp_errors
|
259
273
|
async def on_reactions(self, msg: Message):
|
260
|
-
session,
|
274
|
+
session, recipient, thread = await self._get_session_recipient_thread(msg)
|
261
275
|
react_to: str = msg["reactions"]["id"]
|
262
276
|
|
263
277
|
special_msg = session.SPECIAL_MSG_ID_PREFIX and react_to.startswith(
|
@@ -267,7 +281,7 @@ class MessageContentMixin(DispatcherMixin):
|
|
267
281
|
if special_msg:
|
268
282
|
legacy_id = react_to
|
269
283
|
else:
|
270
|
-
legacy_id = self._xmpp_msg_id_to_legacy(session, react_to)
|
284
|
+
legacy_id = self._xmpp_msg_id_to_legacy(session, react_to, recipient)
|
271
285
|
|
272
286
|
if not legacy_id:
|
273
287
|
log.debug("Ignored reaction from user")
|
@@ -280,58 +294,65 @@ class MessageContentMixin(DispatcherMixin):
|
|
280
294
|
remove_emoji_variation_selector_16(r["value"]) for r in msg["reactions"]
|
281
295
|
]
|
282
296
|
error_msg = None
|
283
|
-
|
297
|
+
recipient = recipient
|
284
298
|
|
285
299
|
if not special_msg:
|
286
|
-
if
|
300
|
+
if recipient.REACTIONS_SINGLE_EMOJI and len(emojis) > 1:
|
287
301
|
error_msg = "Maximum 1 emoji/message"
|
288
302
|
|
289
|
-
if not error_msg and (
|
303
|
+
if not error_msg and (
|
304
|
+
subset := await recipient.available_emojis(legacy_id)
|
305
|
+
):
|
290
306
|
if not set(emojis).issubset(subset):
|
291
307
|
error_msg = f"You can only react with the following emojis: {''.join(subset)}"
|
292
308
|
|
293
309
|
if error_msg:
|
294
310
|
session.send_gateway_message(error_msg)
|
295
|
-
if not isinstance(
|
311
|
+
if not isinstance(recipient, LegacyMUC):
|
296
312
|
# no need to carbon for groups, we just don't echo the stanza
|
297
|
-
|
298
|
-
await session.on_react(
|
313
|
+
recipient.react(legacy_id, carbon=True)
|
314
|
+
await session.on_react(recipient, legacy_id, [], thread=thread)
|
299
315
|
raise XMPPError(
|
300
|
-
"policy-violation",
|
316
|
+
"policy-violation",
|
301
317
|
text=error_msg,
|
302
318
|
)
|
303
319
|
|
304
|
-
await session.on_react(
|
305
|
-
if isinstance(
|
306
|
-
await
|
320
|
+
await session.on_react(recipient, legacy_id, emojis, thread=thread)
|
321
|
+
if isinstance(recipient, LegacyMUC):
|
322
|
+
await recipient.echo(msg, None)
|
307
323
|
else:
|
308
324
|
self.__ack(msg)
|
309
325
|
|
310
|
-
|
326
|
+
with self.xmpp.store.session() as orm:
|
327
|
+
multi = self.xmpp.store.id_map.get_xmpp(
|
328
|
+
orm, recipient.stored.id, legacy_id, recipient.is_group
|
329
|
+
)
|
311
330
|
if not multi:
|
312
331
|
return
|
313
332
|
multi = [m for m in multi if react_to != m]
|
314
333
|
|
315
|
-
if isinstance(
|
334
|
+
if isinstance(recipient, LegacyMUC):
|
316
335
|
for xmpp_id in multi:
|
317
336
|
mc = copy(msg)
|
318
337
|
mc["reactions"]["id"] = xmpp_id
|
319
|
-
await
|
320
|
-
elif isinstance(
|
338
|
+
await recipient.echo(mc)
|
339
|
+
elif isinstance(recipient, LegacyContact):
|
321
340
|
for xmpp_id in multi:
|
322
|
-
|
341
|
+
recipient.react(legacy_id, emojis, xmpp_id=xmpp_id, carbon=True)
|
323
342
|
|
324
|
-
def __ack(self, msg: Message):
|
343
|
+
def __ack(self, msg: Message) -> None:
|
325
344
|
if not self.xmpp.PROPER_RECEIPTS:
|
326
345
|
self.xmpp.delivery_receipt.ack(msg)
|
327
346
|
|
328
347
|
async def __get_reply(
|
329
|
-
self, msg: Message, session: BaseSession,
|
348
|
+
self, msg: Message, session: BaseSession, recipient: Recipient
|
330
349
|
) -> tuple[
|
331
350
|
str, str | int | None, LegacyContact | LegacyParticipant | None, str | None
|
332
351
|
]:
|
333
352
|
try:
|
334
|
-
reply_to_msg_id = self._xmpp_msg_id_to_legacy(
|
353
|
+
reply_to_msg_id = self._xmpp_msg_id_to_legacy(
|
354
|
+
session, msg["reply"]["id"], recipient
|
355
|
+
)
|
335
356
|
except XMPPError:
|
336
357
|
session.log.debug(
|
337
358
|
"Could not determine reply-to legacy msg ID, sending quote instead."
|
@@ -359,7 +380,7 @@ class MessageContentMixin(DispatcherMixin):
|
|
359
380
|
)
|
360
381
|
|
361
382
|
if msg.get_plugin("fallback", check=True) and (
|
362
|
-
isinstance(
|
383
|
+
isinstance(recipient, LegacyMUC) or recipient.REPLIES
|
363
384
|
):
|
364
385
|
text = msg["fallback"].get_stripped_body(self.xmpp["xep_0461"].namespace)
|
365
386
|
try:
|
@@ -373,7 +394,7 @@ class MessageContentMixin(DispatcherMixin):
|
|
373
394
|
return text, reply_to_msg_id, reply_to, reply_fallback
|
374
395
|
|
375
396
|
async def __send_url(
|
376
|
-
self, url: str, session: BaseSession,
|
397
|
+
self, url: str, session: BaseSession, recipient: Recipient, **kwargs
|
377
398
|
) -> int | str | None:
|
378
399
|
async with self.xmpp.http.get(url) as response:
|
379
400
|
if response.status >= 400:
|
@@ -382,19 +403,23 @@ class MessageContentMixin(DispatcherMixin):
|
|
382
403
|
" instead.",
|
383
404
|
response,
|
384
405
|
)
|
385
|
-
return await session.on_text(
|
406
|
+
return await session.on_text(recipient, url, **kwargs)
|
386
407
|
|
387
|
-
return await session.on_file(
|
408
|
+
return await session.on_file(
|
409
|
+
recipient, url, http_response=response, **kwargs
|
410
|
+
)
|
388
411
|
|
389
412
|
async def __send_bob(
|
390
|
-
self, from_: JID, cid: str, session: BaseSession,
|
413
|
+
self, from_: JID, cid: str, session: BaseSession, recipient: Recipient, **kwargs
|
391
414
|
) -> int | str | None:
|
392
|
-
|
415
|
+
with self.xmpp.store.session() as orm:
|
416
|
+
sticker = self.xmpp.store.bob.get_sticker(orm, cid)
|
393
417
|
if sticker is None:
|
394
418
|
await self.xmpp.plugin["xep_0231"].get_bob(from_, cid)
|
395
|
-
|
419
|
+
with self.xmpp.store.session() as orm:
|
420
|
+
sticker = self.xmpp.store.bob.get_sticker(orm, cid)
|
396
421
|
assert sticker is not None
|
397
|
-
return await session.on_sticker(
|
422
|
+
return await session.on_sticker(recipient, sticker, **kwargs)
|
398
423
|
|
399
424
|
|
400
425
|
log = logging.getLogger(__name__)
|
@@ -6,6 +6,8 @@ from ..util import DispatcherMixin, exceptions_to_xmpp_errors
|
|
6
6
|
|
7
7
|
|
8
8
|
class MucAdminMixin(DispatcherMixin):
|
9
|
+
__slots__: list[str] = []
|
10
|
+
|
9
11
|
def __init__(self, xmpp) -> None:
|
10
12
|
super().__init__(xmpp)
|
11
13
|
self.xmpp.register_handler(
|
@@ -46,7 +48,7 @@ class MucAdminMixin(DispatcherMixin):
|
|
46
48
|
"Slidge only implements moderation/retraction",
|
47
49
|
)
|
48
50
|
|
49
|
-
legacy_id = self._xmpp_msg_id_to_legacy(muc.session, xmpp_id)
|
51
|
+
legacy_id = self._xmpp_msg_id_to_legacy(muc.session, xmpp_id, muc)
|
50
52
|
await muc.session.on_moderate(muc, legacy_id, moderate["reason"] or None)
|
51
53
|
iq.reply(clear=True).send()
|
52
54
|
|
@@ -90,8 +92,6 @@ class MucAdminMixin(DispatcherMixin):
|
|
90
92
|
|
91
93
|
reply = iq.reply()
|
92
94
|
reply.enable("mucadmin_query")
|
93
|
-
async for participant in muc.get_participants():
|
94
|
-
if not participant.affiliation == affiliation:
|
95
|
-
continue
|
95
|
+
async for participant in muc.get_participants(affiliation):
|
96
96
|
reply["mucadmin_query"].append(participant.mucadmin_item())
|
97
97
|
reply.send()
|
@@ -13,9 +13,11 @@ if TYPE_CHECKING:
|
|
13
13
|
|
14
14
|
|
15
15
|
class MamMixin(DispatcherMixin):
|
16
|
-
|
16
|
+
__slots__: list[str] = []
|
17
|
+
|
18
|
+
def __init__(self, xmpp: "BaseGateway") -> None:
|
17
19
|
super().__init__(xmpp)
|
18
|
-
self.__mam_cleanup_task = xmpp.loop.create_task(self.__mam_cleanup())
|
20
|
+
self.__mam_cleanup_task = xmpp.loop.create_task(self.__mam_cleanup()) # type:ignore[misc]
|
19
21
|
xmpp.register_handler(
|
20
22
|
CoroutineCallback(
|
21
23
|
"MAM_query",
|
@@ -38,15 +40,17 @@ class MamMixin(DispatcherMixin):
|
|
38
40
|
)
|
39
41
|
)
|
40
42
|
|
41
|
-
async def __mam_cleanup(self):
|
43
|
+
async def __mam_cleanup(self) -> None:
|
42
44
|
if not config.MAM_MAX_DAYS:
|
43
45
|
return
|
44
46
|
while True:
|
45
47
|
await asyncio.sleep(3600 * 6)
|
46
|
-
self.xmpp.store.
|
48
|
+
with self.xmpp.store.session() as orm:
|
49
|
+
self.xmpp.store.mam.nuke_older_than(orm, config.MAM_MAX_DAYS)
|
50
|
+
orm.commit()
|
47
51
|
|
48
52
|
@exceptions_to_xmpp_errors
|
49
|
-
async def __handle_mam(self, iq: Iq):
|
53
|
+
async def __handle_mam(self, iq: Iq) -> None:
|
50
54
|
muc = await self.get_muc_from_stanza(iq)
|
51
55
|
await muc.send_mam(iq)
|
52
56
|
|
@@ -78,6 +82,6 @@ class MamMixin(DispatcherMixin):
|
|
78
82
|
reply.send()
|
79
83
|
|
80
84
|
@exceptions_to_xmpp_errors
|
81
|
-
async def __handle_mam_metadata(self, iq: Iq):
|
85
|
+
async def __handle_mam_metadata(self, iq: Iq) -> None:
|
82
86
|
muc = await self.get_muc_from_stanza(iq)
|
83
87
|
await muc.send_mam_metadata(iq)
|
@@ -7,7 +7,9 @@ from ..util import DispatcherMixin, exceptions_to_xmpp_errors
|
|
7
7
|
|
8
8
|
|
9
9
|
class MucMiscMixin(DispatcherMixin):
|
10
|
-
|
10
|
+
__slots__: list[str] = []
|
11
|
+
|
12
|
+
def __init__(self, xmpp) -> None:
|
11
13
|
super().__init__(xmpp)
|
12
14
|
xmpp.register_handler(
|
13
15
|
CoroutineCallback(
|
@@ -22,7 +24,7 @@ class MucMiscMixin(DispatcherMixin):
|
|
22
24
|
xmpp.add_event_handler("groupchat_subject", self.on_groupchat_subject)
|
23
25
|
xmpp.add_event_handler("groupchat_message_error", self.__on_group_chat_error)
|
24
26
|
|
25
|
-
async def __on_group_chat_error(self, msg: Message):
|
27
|
+
async def __on_group_chat_error(self, msg: Message) -> None:
|
26
28
|
condition = msg["error"].get_condition()
|
27
29
|
if condition not in KICKABLE_ERRORS:
|
28
30
|
return
|
@@ -7,7 +7,9 @@ from ..util import DispatcherMixin, exceptions_to_xmpp_errors
|
|
7
7
|
|
8
8
|
|
9
9
|
class MucOwnerMixin(DispatcherMixin):
|
10
|
-
|
10
|
+
__slots__: list[str] = []
|
11
|
+
|
12
|
+
def __init__(self, xmpp) -> None:
|
11
13
|
super().__init__(xmpp)
|
12
14
|
xmpp.register_handler(
|
13
15
|
CoroutineCallback(
|
@@ -81,8 +83,8 @@ class MucOwnerMixin(DispatcherMixin):
|
|
81
83
|
reason = destroy["reason"] or None
|
82
84
|
await muc.on_destroy_request(reason)
|
83
85
|
user_participant = await muc.get_user_participant()
|
84
|
-
user_participant.
|
85
|
-
user_participant.
|
86
|
+
user_participant.stored.affiliation = "none"
|
87
|
+
user_participant.stored.role = "none"
|
86
88
|
presence = user_participant._make_presence(ptype="unavailable", force=True)
|
87
89
|
presence["muc"].enable("destroy")
|
88
90
|
if reason is not None:
|
@@ -9,12 +9,14 @@ from .util import DispatcherMixin, exceptions_to_xmpp_errors
|
|
9
9
|
|
10
10
|
|
11
11
|
class _IsDirectedAtComponent(Exception):
|
12
|
-
def __init__(self, session: BaseSession):
|
12
|
+
def __init__(self, session: BaseSession) -> None:
|
13
13
|
self.session = session
|
14
14
|
|
15
15
|
|
16
16
|
class PresenceHandlerMixin(DispatcherMixin):
|
17
|
-
|
17
|
+
__slots__: list[str] = []
|
18
|
+
|
19
|
+
def __init__(self, xmpp) -> None:
|
18
20
|
super().__init__(xmpp)
|
19
21
|
|
20
22
|
xmpp.add_event_handler("presence_subscribe", self._handle_subscribe)
|
@@ -33,7 +35,7 @@ class PresenceHandlerMixin(DispatcherMixin):
|
|
33
35
|
return await sess.contacts.by_jid(pto)
|
34
36
|
|
35
37
|
@exceptions_to_xmpp_errors
|
36
|
-
async def _handle_subscribe(self, pres: Presence):
|
38
|
+
async def _handle_subscribe(self, pres: Presence) -> None:
|
37
39
|
try:
|
38
40
|
contact = await self.__get_contact(pres)
|
39
41
|
except _IsDirectedAtComponent:
|
@@ -46,7 +48,7 @@ class PresenceHandlerMixin(DispatcherMixin):
|
|
46
48
|
await contact.on_friend_request(pres["status"])
|
47
49
|
|
48
50
|
@exceptions_to_xmpp_errors
|
49
|
-
async def _handle_unsubscribe(self, pres: Presence):
|
51
|
+
async def _handle_unsubscribe(self, pres: Presence) -> None:
|
50
52
|
pres.reply().send()
|
51
53
|
|
52
54
|
try:
|
@@ -60,7 +62,7 @@ class PresenceHandlerMixin(DispatcherMixin):
|
|
60
62
|
await contact.on_friend_delete(pres["status"])
|
61
63
|
|
62
64
|
@exceptions_to_xmpp_errors
|
63
|
-
async def _handle_subscribed(self, pres: Presence):
|
65
|
+
async def _handle_subscribed(self, pres: Presence) -> None:
|
64
66
|
try:
|
65
67
|
contact = await self.__get_contact(pres)
|
66
68
|
except _IsDirectedAtComponent:
|
@@ -69,7 +71,7 @@ class PresenceHandlerMixin(DispatcherMixin):
|
|
69
71
|
await contact.on_friend_accept()
|
70
72
|
|
71
73
|
@exceptions_to_xmpp_errors
|
72
|
-
async def _handle_unsubscribed(self, pres: Presence):
|
74
|
+
async def _handle_unsubscribed(self, pres: Presence) -> None:
|
73
75
|
try:
|
74
76
|
contact = await self.__get_contact(pres)
|
75
77
|
except _IsDirectedAtComponent:
|
@@ -80,7 +82,7 @@ class PresenceHandlerMixin(DispatcherMixin):
|
|
80
82
|
await contact.on_friend_delete(pres["status"])
|
81
83
|
|
82
84
|
@exceptions_to_xmpp_errors
|
83
|
-
async def _handle_probe(self, pres: Presence):
|
85
|
+
async def _handle_probe(self, pres: Presence) -> None:
|
84
86
|
try:
|
85
87
|
contact = await self.__get_contact(pres)
|
86
88
|
except _IsDirectedAtComponent:
|
@@ -120,16 +122,20 @@ class PresenceHandlerMixin(DispatcherMixin):
|
|
120
122
|
resources = self.xmpp.roster[self.xmpp.boundjid.bare][
|
121
123
|
p.get_from()
|
122
124
|
].resources
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
125
|
+
try:
|
126
|
+
await session.on_presence(
|
127
|
+
p.get_from().resource,
|
128
|
+
ptype, # type: ignore
|
129
|
+
p["status"],
|
130
|
+
resources,
|
131
|
+
merge_resources(resources),
|
132
|
+
)
|
133
|
+
except NotImplementedError:
|
134
|
+
pass
|
130
135
|
if p.get_type() == "available":
|
131
136
|
await self.xmpp.pubsub.on_presence_available(p, None)
|
132
|
-
|
137
|
+
for contact in session.contacts:
|
138
|
+
await self.xmpp.pubsub.on_presence_available(p, contact)
|
133
139
|
|
134
140
|
if p.get_type() == "available":
|
135
141
|
try:
|