slidge 0.1.0rc1__py3-none-any.whl → 0.1.2__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- slidge/__init__.py +54 -31
- slidge/__main__.py +51 -5
- slidge/command/__init__.py +28 -0
- slidge/command/adhoc.py +258 -0
- slidge/command/admin.py +193 -0
- slidge/command/base.py +441 -0
- slidge/command/categories.py +3 -0
- slidge/command/chat_command.py +288 -0
- slidge/command/register.py +179 -0
- slidge/command/user.py +250 -0
- slidge/contact/__init__.py +8 -0
- slidge/contact/contact.py +452 -0
- slidge/contact/roster.py +192 -0
- slidge/core/__init__.py +2 -0
- slidge/core/cache.py +121 -39
- slidge/core/config.py +116 -11
- slidge/core/gateway/__init__.py +3 -0
- slidge/core/gateway/base.py +895 -0
- slidge/core/gateway/caps.py +63 -0
- slidge/core/gateway/delivery_receipt.py +52 -0
- slidge/core/gateway/disco.py +80 -0
- slidge/core/gateway/mam.py +75 -0
- slidge/core/gateway/muc_admin.py +35 -0
- slidge/core/gateway/ping.py +66 -0
- slidge/core/gateway/presence.py +95 -0
- slidge/core/gateway/registration.py +53 -0
- slidge/core/gateway/search.py +102 -0
- slidge/core/gateway/session_dispatcher.py +795 -0
- slidge/core/gateway/vcard_temp.py +130 -0
- slidge/core/mixins/__init__.py +9 -1
- slidge/core/mixins/attachment.py +506 -0
- slidge/core/mixins/avatar.py +167 -0
- slidge/core/mixins/base.py +6 -19
- slidge/core/mixins/disco.py +66 -15
- slidge/core/mixins/lock.py +31 -0
- slidge/core/mixins/message.py +254 -252
- slidge/core/mixins/message_maker.py +154 -0
- slidge/core/mixins/presence.py +128 -31
- slidge/core/mixins/recipient.py +43 -0
- slidge/core/pubsub.py +275 -116
- slidge/core/session.py +586 -518
- slidge/group/__init__.py +10 -0
- slidge/group/archive.py +125 -0
- slidge/group/bookmarks.py +163 -0
- slidge/group/participant.py +458 -0
- slidge/group/room.py +1103 -0
- slidge/migration.py +18 -0
- slidge/slixfix/__init__.py +68 -0
- slidge/{util/xep_0050 → slixfix/link_preview}/__init__.py +4 -5
- slidge/slixfix/link_preview/link_preview.py +17 -0
- slidge/slixfix/link_preview/stanza.py +99 -0
- slidge/slixfix/roster.py +60 -0
- slidge/{util → slixfix}/xep_0077/register.py +1 -2
- slidge/slixfix/xep_0077/stanza.py +104 -0
- slidge/{util → slixfix}/xep_0100/gateway.py +17 -12
- slidge/slixfix/xep_0153/__init__.py +10 -0
- slidge/slixfix/xep_0153/stanza.py +25 -0
- slidge/slixfix/xep_0153/vcard_avatar.py +23 -0
- slidge/slixfix/xep_0264/__init__.py +5 -0
- slidge/slixfix/xep_0264/stanza.py +36 -0
- slidge/slixfix/xep_0264/thumbnail.py +23 -0
- slidge/slixfix/xep_0292/__init__.py +5 -0
- slidge/slixfix/xep_0292/vcard4.py +100 -0
- slidge/slixfix/xep_0313/__init__.py +12 -0
- slidge/slixfix/xep_0313/mam.py +262 -0
- slidge/slixfix/xep_0313/stanza.py +359 -0
- slidge/slixfix/xep_0317/__init__.py +5 -0
- slidge/slixfix/xep_0317/hats.py +17 -0
- slidge/slixfix/xep_0317/stanza.py +28 -0
- slidge/{util → slixfix}/xep_0356_old/privilege.py +9 -7
- slidge/slixfix/xep_0424/__init__.py +9 -0
- slidge/slixfix/xep_0424/retraction.py +77 -0
- slidge/slixfix/xep_0424/stanza.py +28 -0
- slidge/slixfix/xep_0490/__init__.py +8 -0
- slidge/slixfix/xep_0490/mds.py +47 -0
- slidge/slixfix/xep_0490/stanza.py +17 -0
- slidge/util/__init__.py +4 -6
- slidge/util/archive_msg.py +61 -0
- slidge/util/conf.py +25 -4
- slidge/util/db.py +23 -69
- slidge/util/schema.sql +126 -0
- slidge/util/sql.py +508 -0
- slidge/util/test.py +136 -86
- slidge/util/types.py +155 -14
- slidge/util/util.py +225 -51
- slidge-0.1.2.dist-info/METADATA +111 -0
- slidge-0.1.2.dist-info/RECORD +96 -0
- {slidge-0.1.0rc1.dist-info → slidge-0.1.2.dist-info}/WHEEL +1 -1
- slidge/core/adhoc.py +0 -492
- slidge/core/chat_command.py +0 -197
- slidge/core/contact.py +0 -441
- slidge/core/disco.py +0 -59
- slidge/core/gateway.py +0 -899
- slidge/core/muc/__init__.py +0 -3
- slidge/core/muc/bookmarks.py +0 -74
- slidge/core/muc/participant.py +0 -152
- slidge/core/muc/room.py +0 -348
- slidge/plugins/discord/__init__.py +0 -121
- slidge/plugins/discord/client.py +0 -121
- slidge/plugins/discord/session.py +0 -172
- slidge/plugins/dummy.py +0 -334
- slidge/plugins/facebook.py +0 -591
- slidge/plugins/hackernews.py +0 -209
- slidge/plugins/mattermost/__init__.py +0 -1
- slidge/plugins/mattermost/api.py +0 -288
- slidge/plugins/mattermost/gateway.py +0 -417
- slidge/plugins/mattermost/websocket.py +0 -248
- slidge/plugins/signal/__init__.py +0 -4
- slidge/plugins/signal/config.py +0 -4
- slidge/plugins/signal/contact.py +0 -104
- slidge/plugins/signal/gateway.py +0 -379
- slidge/plugins/signal/group.py +0 -76
- slidge/plugins/signal/session.py +0 -515
- slidge/plugins/signal/txt.py +0 -13
- slidge/plugins/signal/util.py +0 -32
- slidge/plugins/skype.py +0 -310
- slidge/plugins/steam.py +0 -400
- slidge/plugins/telegram/__init__.py +0 -6
- slidge/plugins/telegram/client.py +0 -325
- slidge/plugins/telegram/config.py +0 -21
- slidge/plugins/telegram/contact.py +0 -154
- slidge/plugins/telegram/gateway.py +0 -182
- slidge/plugins/telegram/group.py +0 -184
- slidge/plugins/telegram/session.py +0 -275
- slidge/plugins/telegram/util.py +0 -153
- slidge/plugins/whatsapp/__init__.py +0 -6
- slidge/plugins/whatsapp/config.py +0 -17
- slidge/plugins/whatsapp/contact.py +0 -33
- slidge/plugins/whatsapp/event.go +0 -455
- slidge/plugins/whatsapp/gateway.go +0 -156
- slidge/plugins/whatsapp/gateway.py +0 -69
- slidge/plugins/whatsapp/go.mod +0 -17
- slidge/plugins/whatsapp/go.sum +0 -22
- slidge/plugins/whatsapp/session.go +0 -371
- slidge/plugins/whatsapp/session.py +0 -370
- slidge/util/xep_0030/__init__.py +0 -13
- slidge/util/xep_0030/disco.py +0 -811
- slidge/util/xep_0030/stanza/__init__.py +0 -7
- slidge/util/xep_0030/stanza/info.py +0 -270
- slidge/util/xep_0030/stanza/items.py +0 -147
- slidge/util/xep_0030/static.py +0 -467
- slidge/util/xep_0050/adhoc.py +0 -631
- slidge/util/xep_0050/stanza.py +0 -180
- slidge/util/xep_0077/stanza.py +0 -71
- slidge/util/xep_0292/__init__.py +0 -1
- slidge/util/xep_0292/stanza.py +0 -167
- slidge/util/xep_0292/vcard4.py +0 -74
- slidge/util/xep_0356/__init__.py +0 -7
- slidge/util/xep_0356/permissions.py +0 -35
- slidge/util/xep_0356/privilege.py +0 -160
- slidge/util/xep_0356/stanza.py +0 -44
- slidge/util/xep_0461/__init__.py +0 -6
- slidge/util/xep_0461/reply.py +0 -48
- slidge/util/xep_0461/stanza.py +0 -80
- slidge-0.1.0rc1.dist-info/METADATA +0 -171
- slidge-0.1.0rc1.dist-info/RECORD +0 -99
- /slidge/{plugins/__init__.py → py.typed} +0 -0
- /slidge/{util → slixfix}/xep_0077/__init__.py +0 -0
- /slidge/{util → slixfix}/xep_0100/__init__.py +0 -0
- /slidge/{util → slixfix}/xep_0100/stanza.py +0 -0
- /slidge/{util → slixfix}/xep_0356_old/__init__.py +0 -0
- /slidge/{util → slixfix}/xep_0356_old/stanza.py +0 -0
- {slidge-0.1.0rc1.dist-info → slidge-0.1.2.dist-info}/LICENSE +0 -0
- {slidge-0.1.0rc1.dist-info → slidge-0.1.2.dist-info}/entry_points.txt +0 -0
slidge/core/mixins/message.py
CHANGED
@@ -1,141 +1,75 @@
|
|
1
1
|
import logging
|
2
|
-
|
3
|
-
|
4
|
-
from
|
5
|
-
from typing import
|
6
|
-
|
7
|
-
import
|
8
|
-
|
9
|
-
from
|
10
|
-
from
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
def _make_message(
|
26
|
-
self,
|
27
|
-
state: Optional[ChatState] = None,
|
28
|
-
hints: Iterable[ProcessingHint] = (),
|
29
|
-
legacy_msg_id: Optional[LegacyMessageType] = None,
|
30
|
-
when: Optional[datetime] = None,
|
31
|
-
reply_to_msg_id: Optional[LegacyMessageType] = None,
|
32
|
-
reply_to_fallback_text: Optional[str] = None,
|
33
|
-
reply_to_jid: Optional[JID] = None,
|
34
|
-
carbon=False,
|
35
|
-
**kwargs,
|
36
|
-
):
|
37
|
-
body = kwargs.pop("mbody", None)
|
38
|
-
mfrom = kwargs.pop("mfrom", self.jid)
|
39
|
-
mto = kwargs.pop("mto", None)
|
40
|
-
if carbon:
|
41
|
-
# the msg needs to have jabber:client as xmlns, so
|
42
|
-
# we don't want to associate with the XML stream
|
43
|
-
msg_cls = Message # type:ignore
|
44
|
-
else:
|
45
|
-
msg_cls = self.xmpp.Message # type:ignore
|
46
|
-
msg = msg_cls(sfrom=mfrom, stype=self.mtype, sto=mto, **kwargs)
|
47
|
-
if body:
|
48
|
-
if self._is_composing:
|
49
|
-
state = "active"
|
50
|
-
self._is_composing = False
|
51
|
-
msg["body"] = body
|
52
|
-
if state:
|
53
|
-
self._is_composing = state == "composing"
|
54
|
-
msg["chat_state"] = state
|
55
|
-
for hint in hints:
|
56
|
-
msg.enable(hint)
|
57
|
-
self._set_msg_id(msg, legacy_msg_id)
|
58
|
-
self._add_delay(msg, when)
|
59
|
-
self._add_reply_to(msg, reply_to_msg_id, reply_to_fallback_text, reply_to_jid)
|
60
|
-
return msg
|
61
|
-
|
62
|
-
def _set_msg_id(
|
63
|
-
self, msg: Message, legacy_msg_id: Optional[LegacyMessageType] = None
|
64
|
-
):
|
65
|
-
if legacy_msg_id is not None:
|
66
|
-
i = self._legacy_to_xmpp(legacy_msg_id)
|
67
|
-
msg.set_id(i)
|
68
|
-
if self.USE_STANZA_ID:
|
69
|
-
msg["stanza_id"]["id"] = i
|
70
|
-
msg["stanza_id"]["by"] = self.muc.jid # type: ignore
|
71
|
-
|
72
|
-
def _legacy_to_xmpp(self, legacy_id: LegacyMessageType):
|
73
|
-
return self.session.sent.get(
|
74
|
-
legacy_id
|
75
|
-
) or self.session.legacy_msg_id_to_xmpp_msg_id(legacy_id)
|
76
|
-
|
77
|
-
def _add_delay(self, msg: Message, when: Optional[datetime]):
|
78
|
-
if when:
|
79
|
-
if when.tzinfo is None:
|
80
|
-
when = when.astimezone(timezone.utc)
|
81
|
-
if self.STRIP_SHORT_DELAY:
|
82
|
-
delay = datetime.now().astimezone(timezone.utc) - when
|
83
|
-
if delay < config.IGNORE_DELAY_THRESHOLD:
|
84
|
-
return
|
85
|
-
msg["delay"].set_stamp(when)
|
86
|
-
msg["delay"].set_from(self.xmpp.boundjid.bare)
|
87
|
-
|
88
|
-
def _add_reply_to(
|
89
|
-
self,
|
90
|
-
msg: Message,
|
91
|
-
reply_to_msg_id: Optional[LegacyMessageType] = None,
|
92
|
-
reply_to_fallback_text: Optional[str] = None,
|
93
|
-
reply_to_author: Optional[JID] = None,
|
94
|
-
):
|
95
|
-
if reply_to_msg_id is not None:
|
96
|
-
xmpp_id = self._legacy_to_xmpp(reply_to_msg_id)
|
97
|
-
msg["reply"]["id"] = xmpp_id
|
98
|
-
# FIXME: https://xmpp.org/extensions/xep-0461.html#usecases mentions that a full JID must be used here
|
99
|
-
if reply_to_author:
|
100
|
-
msg["reply"]["to"] = reply_to_author
|
101
|
-
if reply_to_fallback_text:
|
102
|
-
msg["feature_fallback"].add_quoted_fallback(reply_to_fallback_text)
|
2
|
+
import uuid
|
3
|
+
import warnings
|
4
|
+
from datetime import datetime
|
5
|
+
from typing import TYPE_CHECKING, Iterable, Optional
|
6
|
+
|
7
|
+
from slixmpp import Iq, Message
|
8
|
+
|
9
|
+
from ...slixfix.xep_0490.mds import PUBLISH_OPTIONS
|
10
|
+
from ...util.types import (
|
11
|
+
ChatState,
|
12
|
+
LegacyMessageType,
|
13
|
+
LegacyThreadType,
|
14
|
+
LinkPreview,
|
15
|
+
Marker,
|
16
|
+
MessageReference,
|
17
|
+
ProcessingHint,
|
18
|
+
)
|
19
|
+
from .attachment import AttachmentMixin
|
20
|
+
from .message_maker import MessageMaker
|
21
|
+
|
22
|
+
if TYPE_CHECKING:
|
23
|
+
from ...group import LegacyMUC
|
103
24
|
|
104
25
|
|
105
26
|
class ChatStateMixin(MessageMaker):
|
106
|
-
def
|
107
|
-
|
108
|
-
|
109
|
-
|
27
|
+
def __init__(self):
|
28
|
+
super().__init__()
|
29
|
+
self.__last_chat_state: Optional[ChatState] = None
|
30
|
+
|
31
|
+
def _chat_state(self, state: ChatState, forced=False, **kwargs):
|
32
|
+
carbon = kwargs.get("carbon", False)
|
33
|
+
if carbon or (state == self.__last_chat_state and not forced):
|
34
|
+
return
|
35
|
+
self.__last_chat_state = state
|
36
|
+
msg = self._make_message(state=state, hints={"no-store"})
|
110
37
|
self._send(msg, **kwargs)
|
111
38
|
|
112
39
|
def active(self, **kwargs):
|
113
40
|
"""
|
114
|
-
Send an "active" chat state (:xep:`0085`) from this
|
41
|
+
Send an "active" chat state (:xep:`0085`) from this
|
42
|
+
:term:`XMPP Entity`.
|
115
43
|
"""
|
116
44
|
self._chat_state("active", **kwargs)
|
117
45
|
|
118
46
|
def composing(self, **kwargs):
|
119
47
|
"""
|
120
|
-
Send a "composing" (ie "typing notification") chat state (:xep:`0085`)
|
48
|
+
Send a "composing" (ie "typing notification") chat state (:xep:`0085`)
|
49
|
+
from this :term:`XMPP Entity`.
|
121
50
|
"""
|
122
|
-
self._chat_state("composing", **kwargs)
|
51
|
+
self._chat_state("composing", forced=True, **kwargs)
|
123
52
|
|
124
53
|
def paused(self, **kwargs):
|
125
54
|
"""
|
126
|
-
Send a "paused" (ie "typing paused notification") chat state
|
55
|
+
Send a "paused" (ie "typing paused notification") chat state
|
56
|
+
(:xep:`0085`) from this :term:`XMPP Entity`.
|
127
57
|
"""
|
128
58
|
self._chat_state("paused", **kwargs)
|
129
59
|
|
130
60
|
def inactive(self, **kwargs):
|
131
61
|
"""
|
132
|
-
Send an "inactive" (ie "
|
62
|
+
Send an "inactive" (ie "contact has not interacted with the chat session
|
63
|
+
interface for an intermediate period of time") chat state (:xep:`0085`)
|
64
|
+
from this :term:`XMPP Entity`.
|
133
65
|
"""
|
134
66
|
self._chat_state("inactive", **kwargs)
|
135
67
|
|
136
68
|
def gone(self, **kwargs):
|
137
69
|
"""
|
138
|
-
Send
|
70
|
+
Send a "gone" (ie "contact has not interacted with the chat session interface,
|
71
|
+
system, or device for a relatively long period of time") chat state
|
72
|
+
(:xep:`0085`) from this :term:`XMPP Entity`.
|
139
73
|
"""
|
140
74
|
self._chat_state("gone", **kwargs)
|
141
75
|
|
@@ -150,14 +84,9 @@ class MarkerMixin(MessageMaker):
|
|
150
84
|
msg[marker]["id"] = self._legacy_to_xmpp(legacy_msg_id)
|
151
85
|
return msg
|
152
86
|
|
153
|
-
def _make_receipt(self, legacy_msg_id: LegacyMessageType, carbon=False):
|
154
|
-
msg = self._make_message(carbon=carbon)
|
155
|
-
msg["receipt"] = self._legacy_to_xmpp(legacy_msg_id)
|
156
|
-
return msg
|
157
|
-
|
158
87
|
def ack(self, legacy_msg_id: LegacyMessageType, **kwargs):
|
159
88
|
"""
|
160
|
-
Send an "acknowledged" message marker (:xep:`0333`) from this
|
89
|
+
Send an "acknowledged" message marker (:xep:`0333`) from this :term:`XMPP Entity`.
|
161
90
|
|
162
91
|
:param legacy_msg_id: The message this marker refers to
|
163
92
|
"""
|
@@ -170,23 +99,28 @@ class MarkerMixin(MessageMaker):
|
|
170
99
|
|
171
100
|
def received(self, legacy_msg_id: LegacyMessageType, **kwargs):
|
172
101
|
"""
|
173
|
-
Send a "received" message marker (:xep:`0333`)
|
174
|
-
|
175
|
-
|
102
|
+
Send a "received" message marker (:xep:`0333`) from this :term:`XMPP Entity`.
|
103
|
+
If called on a :class:`LegacyContact`, also send a delivery receipt
|
104
|
+
marker (:xep:`0184`).
|
176
105
|
|
177
106
|
:param legacy_msg_id: The message this marker refers to
|
178
107
|
"""
|
179
108
|
carbon = kwargs.get("carbon")
|
180
|
-
if
|
181
|
-
|
182
|
-
|
109
|
+
if self.mtype == "chat":
|
110
|
+
self._send(
|
111
|
+
self.xmpp.delivery_receipt.make_ack(
|
112
|
+
self._legacy_to_xmpp(legacy_msg_id),
|
113
|
+
mfrom=self.jid,
|
114
|
+
mto=self.user.jid,
|
115
|
+
)
|
116
|
+
)
|
183
117
|
self._send(
|
184
118
|
self._make_marker(legacy_msg_id, "received", carbon=carbon), **kwargs
|
185
119
|
)
|
186
120
|
|
187
121
|
def displayed(self, legacy_msg_id: LegacyMessageType, **kwargs):
|
188
122
|
"""
|
189
|
-
Send a "displayed" message marker (:xep:`0333`) from this
|
123
|
+
Send a "displayed" message marker (:xep:`0333`) from this :term:`XMPP Entity`.
|
190
124
|
|
191
125
|
:param legacy_msg_id: The message this marker refers to
|
192
126
|
"""
|
@@ -194,34 +128,52 @@ class MarkerMixin(MessageMaker):
|
|
194
128
|
self._make_marker(legacy_msg_id, "displayed", carbon=kwargs.get("carbon")),
|
195
129
|
**kwargs,
|
196
130
|
)
|
131
|
+
if getattr(self, "is_user", False):
|
132
|
+
self.session.create_task(self.__send_mds(legacy_msg_id))
|
197
133
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
if
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
134
|
+
async def __send_mds(self, legacy_msg_id: LegacyMessageType):
|
135
|
+
# Send a MDS displayed marker on behalf of the user for a group chat
|
136
|
+
if muc := getattr(self, "muc", None):
|
137
|
+
muc_jid = muc.jid.bare
|
138
|
+
else:
|
139
|
+
# This is not implemented for 1:1 chat because it would rely on
|
140
|
+
# storing the XMPP-server injected stanza-id, which we don't track
|
141
|
+
# ATM.
|
142
|
+
# In practice, MDS should mostly be useful for public group chats,
|
143
|
+
# so it should not be an issue.
|
144
|
+
# We'll see if we need to implement that later
|
145
|
+
return
|
146
|
+
xmpp_msg_id = self._legacy_to_xmpp(legacy_msg_id)
|
147
|
+
iq = Iq(sto=self.user.bare_jid, sfrom=self.user.bare_jid, stype="set")
|
148
|
+
iq["pubsub"]["publish"]["node"] = self.xmpp["xep_0490"].stanza.NS
|
149
|
+
iq["pubsub"]["publish"]["item"]["id"] = muc_jid
|
150
|
+
displayed = self.xmpp["xep_0490"].stanza.Displayed()
|
151
|
+
displayed["stanza_id"]["id"] = xmpp_msg_id
|
152
|
+
displayed["stanza_id"]["by"] = muc_jid
|
153
|
+
iq["pubsub"]["publish"]["item"]["payload"] = displayed
|
154
|
+
iq["pubsub"]["publish_options"] = PUBLISH_OPTIONS
|
213
155
|
try:
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
156
|
+
await self.xmpp["xep_0356"].send_privileged_iq(iq)
|
157
|
+
except Exception as e:
|
158
|
+
self.session.log.debug("Could not MDS mark", exc_info=e)
|
159
|
+
|
160
|
+
|
161
|
+
class ContentMessageMixin(AttachmentMixin):
|
162
|
+
def __default_hints(self, hints: Optional[Iterable[ProcessingHint]] = None):
|
163
|
+
if hints is not None:
|
164
|
+
return hints
|
165
|
+
elif self.mtype == "chat":
|
166
|
+
return {"markable", "store"}
|
167
|
+
elif self.mtype == "groupchat":
|
168
|
+
return {"markable"}
|
169
|
+
|
170
|
+
def __replace_id(self, legacy_msg_id: LegacyMessageType):
|
171
|
+
if self.mtype == "groupchat":
|
172
|
+
return self.session.muc_sent_msg_ids.get(
|
173
|
+
legacy_msg_id
|
174
|
+
) or self._legacy_to_xmpp(legacy_msg_id)
|
175
|
+
else:
|
176
|
+
return self._legacy_to_xmpp(legacy_msg_id)
|
225
177
|
|
226
178
|
def send_text(
|
227
179
|
self,
|
@@ -229,167 +181,217 @@ class ContentMessageMixin(MessageMaker):
|
|
229
181
|
legacy_msg_id: Optional[LegacyMessageType] = None,
|
230
182
|
*,
|
231
183
|
when: Optional[datetime] = None,
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
184
|
+
reply_to: Optional[MessageReference] = None,
|
185
|
+
thread: Optional[LegacyThreadType] = None,
|
186
|
+
hints: Optional[Iterable[ProcessingHint]] = None,
|
187
|
+
carbon=False,
|
188
|
+
archive_only=False,
|
189
|
+
correction=False,
|
190
|
+
correction_event_id: Optional[LegacyMessageType] = None,
|
191
|
+
link_previews: Optional[list[LinkPreview]] = None,
|
192
|
+
**send_kwargs,
|
236
193
|
):
|
237
194
|
"""
|
238
|
-
|
195
|
+
Send a text message from this :term:`XMPP Entity`.
|
239
196
|
|
240
|
-
:param body:
|
197
|
+
:param body: Content of the message
|
241
198
|
:param legacy_msg_id: If you want to be able to transport read markers from the gateway
|
242
199
|
user to the legacy network, specify this
|
243
200
|
:param when: when the message was sent, for a "delay" tag (:xep:`0203`)
|
244
|
-
:param
|
245
|
-
:param
|
246
|
-
:param
|
201
|
+
:param reply_to: Quote another message (:xep:`0461`)
|
202
|
+
:param hints:
|
203
|
+
:param thread:
|
204
|
+
:param carbon: (only used if called on a :class:`LegacyContact`)
|
205
|
+
Set this to ``True`` if this is actually a message sent **to** the
|
206
|
+
:class:`LegacyContact` by the :term:`User`.
|
207
|
+
Use this to synchronize outgoing history for legacy official apps.
|
208
|
+
:param correction: whether this message is a correction or not
|
209
|
+
:param correction_event_id: in the case where an ID is associated with the legacy
|
210
|
+
'correction event', specify it here to use it on the XMPP side. If not specified,
|
211
|
+
a random ID will be used.
|
212
|
+
:param link_previews: A little of sender (or server, or gateway)-generated
|
213
|
+
previews of URLs linked in the body.
|
214
|
+
:param archive_only: (only in groups) Do not send this message to user,
|
215
|
+
but store it in the archive. Meant to be used during ``MUC.backfill()``
|
247
216
|
"""
|
217
|
+
if carbon:
|
218
|
+
if not correction and legacy_msg_id in self.session.sent:
|
219
|
+
log.warning(
|
220
|
+
"Carbon message for a message an XMPP has sent? This is a bug! %s",
|
221
|
+
legacy_msg_id,
|
222
|
+
)
|
223
|
+
return
|
224
|
+
self.session.sent[legacy_msg_id] = self.session.legacy_to_xmpp_msg_id(
|
225
|
+
legacy_msg_id
|
226
|
+
)
|
227
|
+
hints = self.__default_hints(hints)
|
248
228
|
msg = self._make_message(
|
249
229
|
mbody=body,
|
250
|
-
legacy_msg_id=legacy_msg_id,
|
230
|
+
legacy_msg_id=correction_event_id if correction else legacy_msg_id,
|
251
231
|
when=when,
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
232
|
+
reply_to=reply_to,
|
233
|
+
hints=hints or (),
|
234
|
+
carbon=carbon,
|
235
|
+
thread=thread,
|
236
|
+
link_previews=link_previews,
|
257
237
|
)
|
258
|
-
|
238
|
+
if correction:
|
239
|
+
msg["replace"]["id"] = self.__replace_id(legacy_msg_id)
|
240
|
+
return self._send(msg, archive_only=archive_only, carbon=carbon, **send_kwargs)
|
259
241
|
|
260
|
-
|
242
|
+
def correct(
|
261
243
|
self,
|
262
|
-
|
263
|
-
|
244
|
+
legacy_msg_id: LegacyMessageType,
|
245
|
+
new_text: str,
|
264
246
|
*,
|
265
|
-
content_type: Optional[str] = None,
|
266
|
-
input_file: Optional[IO[bytes]] = None,
|
267
|
-
url: Optional[str] = None,
|
268
|
-
reply_to_msg_id: Optional[LegacyMessageType] = None,
|
269
|
-
reply_to_fallback_text: Optional[str] = None,
|
270
|
-
reply_to_jid: Optional[JID] = None,
|
271
247
|
when: Optional[datetime] = None,
|
272
|
-
|
273
|
-
|
248
|
+
reply_to: Optional[MessageReference] = None,
|
249
|
+
thread: Optional[LegacyThreadType] = None,
|
250
|
+
hints: Optional[Iterable[ProcessingHint]] = None,
|
251
|
+
carbon=False,
|
252
|
+
archive_only=False,
|
253
|
+
correction_event_id: Optional[LegacyMessageType] = None,
|
254
|
+
link_previews: Optional[list[LinkPreview]] = None,
|
255
|
+
**send_kwargs,
|
274
256
|
):
|
275
257
|
"""
|
276
|
-
|
258
|
+
Modify a message that was previously sent by this :term:`XMPP Entity`.
|
277
259
|
|
278
|
-
|
279
|
-
|
280
|
-
:param
|
281
|
-
|
282
|
-
:param
|
283
|
-
|
284
|
-
:param
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
:param
|
289
|
-
|
290
|
-
:param
|
291
|
-
|
260
|
+
Uses last message correction (:xep:`0308`)
|
261
|
+
|
262
|
+
:param new_text: New content of the message
|
263
|
+
:param legacy_msg_id: The legacy message ID of the message to correct
|
264
|
+
:param when: when the message was sent, for a "delay" tag (:xep:`0203`)
|
265
|
+
:param reply_to: Quote another message (:xep:`0461`)
|
266
|
+
:param hints:
|
267
|
+
:param thread:
|
268
|
+
:param carbon: (only in 1:1) Reflect a message sent to this ``Contact`` by the user.
|
269
|
+
Use this to synchronize outgoing history for legacy official apps.
|
270
|
+
:param archive_only: (only in groups) Do not send this message to user,
|
271
|
+
but store it in the archive. Meant to be used during ``MUC.backfill()``
|
272
|
+
:param correction_event_id: in the case where an ID is associated with the legacy
|
273
|
+
'correction event', specify it here to use it on the XMPP side. If not specified,
|
274
|
+
a random ID will be used.
|
275
|
+
:param link_previews: A little of sender (or server, or gateway)-generated
|
276
|
+
previews of URLs linked in the body.
|
292
277
|
"""
|
293
|
-
|
294
|
-
|
278
|
+
self.send_text(
|
279
|
+
new_text,
|
280
|
+
legacy_msg_id,
|
295
281
|
when=when,
|
296
|
-
|
297
|
-
|
298
|
-
reply_to_jid=reply_to_jid,
|
282
|
+
reply_to=reply_to,
|
283
|
+
hints=hints,
|
299
284
|
carbon=carbon,
|
285
|
+
thread=thread,
|
286
|
+
correction=True,
|
287
|
+
archive_only=archive_only,
|
288
|
+
correction_event_id=correction_event_id,
|
289
|
+
link_previews=link_previews,
|
290
|
+
**send_kwargs,
|
300
291
|
)
|
301
|
-
uploaded_url = await self._upload(filename, content_type, input_file, url)
|
302
|
-
if uploaded_url is None:
|
303
|
-
if url is not None:
|
304
|
-
uploaded_url = url
|
305
|
-
else:
|
306
|
-
msg["body"] = (
|
307
|
-
"I tried to send a file, but something went wrong. "
|
308
|
-
"Tell your XMPP admin to check slidge logs."
|
309
|
-
)
|
310
|
-
self._set_msg_id(msg, legacy_msg_id)
|
311
|
-
self._send(msg, **kwargs)
|
312
|
-
return
|
313
|
-
|
314
|
-
msg["oob"]["url"] = uploaded_url
|
315
|
-
msg["body"] = uploaded_url
|
316
|
-
if caption:
|
317
|
-
self._send(msg, carbon=carbon, **kwargs)
|
318
|
-
self.send_text(
|
319
|
-
caption, legacy_msg_id=legacy_msg_id, when=when, carbon=carbon, **kwargs
|
320
|
-
)
|
321
|
-
else:
|
322
|
-
self._set_msg_id(msg, legacy_msg_id)
|
323
|
-
self._send(msg, **kwargs)
|
324
|
-
|
325
|
-
def correct(self, legacy_msg_id: LegacyMessageType, new_text: str, **kwargs):
|
326
|
-
"""
|
327
|
-
Call this when a legacy contact has modified his last message content.
|
328
|
-
|
329
|
-
Uses last message correction (:xep:`0308`)
|
330
|
-
|
331
|
-
:param legacy_msg_id: Legacy message ID this correction refers to
|
332
|
-
:param new_text: The new text
|
333
|
-
"""
|
334
|
-
msg = self._make_message(mbody=new_text, carbon=kwargs.get("carbon"))
|
335
|
-
msg["replace"]["id"] = self._legacy_to_xmpp(legacy_msg_id)
|
336
|
-
self._send(msg, **kwargs)
|
337
292
|
|
338
293
|
def react(
|
339
|
-
self,
|
294
|
+
self,
|
295
|
+
legacy_msg_id: LegacyMessageType,
|
296
|
+
emojis: Iterable[str] = (),
|
297
|
+
thread: Optional[LegacyThreadType] = None,
|
298
|
+
**kwargs,
|
340
299
|
):
|
341
300
|
"""
|
342
|
-
|
301
|
+
Send a reaction (:xep:`0444`) from this :term:`XMPP Entity`.
|
343
302
|
|
344
303
|
:param legacy_msg_id: The message which the reaction refers to.
|
345
|
-
:param emojis:
|
346
|
-
:
|
304
|
+
:param emojis: An iterable of emojis used as reactions
|
305
|
+
:param thread:
|
347
306
|
"""
|
348
|
-
msg = self._make_message(
|
349
|
-
|
307
|
+
msg = self._make_message(
|
308
|
+
hints={"store"}, carbon=kwargs.get("carbon"), thread=thread
|
309
|
+
)
|
310
|
+
xmpp_id = kwargs.pop("xmpp_id", None)
|
311
|
+
if not xmpp_id:
|
312
|
+
xmpp_id = self._legacy_to_xmpp(legacy_msg_id)
|
350
313
|
self.xmpp["xep_0444"].set_reactions(msg, to_id=xmpp_id, reactions=emojis)
|
351
314
|
self._send(msg, **kwargs)
|
352
315
|
|
353
|
-
def retract(
|
316
|
+
def retract(
|
317
|
+
self,
|
318
|
+
legacy_msg_id: LegacyMessageType,
|
319
|
+
thread: Optional[LegacyThreadType] = None,
|
320
|
+
**kwargs,
|
321
|
+
):
|
354
322
|
"""
|
355
|
-
|
323
|
+
Send a message retraction (:XEP:`0424`) from this :term:`XMPP Entity`.
|
356
324
|
|
357
325
|
:param legacy_msg_id: Legacy ID of the message to delete
|
326
|
+
:param thread:
|
358
327
|
"""
|
359
328
|
msg = self._make_message(
|
360
329
|
state=None,
|
361
330
|
hints={"store"},
|
362
|
-
mbody=f"
|
363
|
-
"but your XMPP client does not support that",
|
331
|
+
mbody=f"/me retracted the message {legacy_msg_id}",
|
364
332
|
carbon=kwargs.get("carbon"),
|
333
|
+
thread=thread,
|
365
334
|
)
|
366
335
|
msg.enable("fallback")
|
367
|
-
|
368
|
-
msg["
|
336
|
+
# namespace version mismatch between slidge and slixmpp, update me later
|
337
|
+
msg["fallback"]["for"] = self.xmpp["xep_0424"].namespace[:-1] + "1"
|
338
|
+
msg["retract"]["id"] = msg["replace"]["id"] = self.__replace_id(legacy_msg_id)
|
369
339
|
self._send(msg, **kwargs)
|
370
340
|
|
371
341
|
|
372
342
|
class CarbonMessageMixin(ContentMessageMixin, MarkerMixin):
|
373
343
|
def _privileged_send(self, msg: Message):
|
374
|
-
|
344
|
+
i = msg.get_id()
|
345
|
+
if not i:
|
346
|
+
i = str(uuid.uuid4())
|
347
|
+
msg.set_id(i)
|
348
|
+
msg.del_origin_id()
|
349
|
+
self.session.ignore_messages.add(i)
|
375
350
|
try:
|
376
351
|
self.xmpp["xep_0356"].send_privileged_message(msg)
|
377
352
|
except PermissionError:
|
378
353
|
try:
|
379
354
|
self.xmpp["xep_0356_old"].send_privileged_message(msg)
|
380
355
|
except PermissionError:
|
381
|
-
|
382
|
-
"Slidge does not have privileges to send message on behalf of
|
383
|
-
"Refer to
|
384
|
-
"
|
356
|
+
warnings.warn(
|
357
|
+
"Slidge does not have privileges to send message on behalf of"
|
358
|
+
" user.Refer to"
|
359
|
+
" https://slidge.readthedocs.io/en/latest/admin/xmpp_server.html"
|
360
|
+
" for more info."
|
385
361
|
)
|
386
362
|
|
387
363
|
|
388
|
-
class
|
364
|
+
class InviteMixin(MessageMaker):
|
365
|
+
def invite_to(
|
366
|
+
self,
|
367
|
+
muc: "LegacyMUC",
|
368
|
+
reason: Optional[str] = None,
|
369
|
+
password: Optional[str] = None,
|
370
|
+
**send_kwargs,
|
371
|
+
):
|
372
|
+
"""
|
373
|
+
Send an invitation to join a group (:xep:`0249`) from this :term:`XMPP Entity`.
|
374
|
+
|
375
|
+
:param muc: the muc the user is invited to
|
376
|
+
:param reason: a text explaining why the user should join this muc
|
377
|
+
:param password: maybe this will make sense later? not sure
|
378
|
+
:param send_kwargs: additional kwargs to be passed to _send()
|
379
|
+
(internal use by slidge)
|
380
|
+
"""
|
381
|
+
msg = self._make_message(mtype="normal")
|
382
|
+
msg["groupchat_invite"]["jid"] = muc.jid
|
383
|
+
if reason:
|
384
|
+
msg["groupchat_invite"]["reason"] = reason
|
385
|
+
if password:
|
386
|
+
msg["groupchat_invite"]["password"] = password
|
387
|
+
self._send(msg, **send_kwargs)
|
388
|
+
|
389
|
+
|
390
|
+
class MessageMixin(InviteMixin, ChatStateMixin, MarkerMixin, ContentMessageMixin):
|
389
391
|
pass
|
390
392
|
|
391
393
|
|
392
|
-
class MessageCarbonMixin(ChatStateMixin, CarbonMessageMixin):
|
394
|
+
class MessageCarbonMixin(InviteMixin, ChatStateMixin, CarbonMessageMixin):
|
393
395
|
pass
|
394
396
|
|
395
397
|
|