slidge 0.1.0b2__py3-none-any.whl → 0.1.1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. slidge/__init__.py +55 -31
  2. slidge/__main__.py +118 -116
  3. slidge/command/__init__.py +28 -0
  4. slidge/command/adhoc.py +258 -0
  5. slidge/command/admin.py +193 -0
  6. slidge/command/base.py +441 -0
  7. slidge/command/categories.py +3 -0
  8. slidge/command/chat_command.py +288 -0
  9. slidge/command/register.py +179 -0
  10. slidge/command/user.py +250 -0
  11. slidge/contact/__init__.py +8 -0
  12. slidge/contact/contact.py +452 -0
  13. slidge/contact/roster.py +192 -0
  14. slidge/core/__init__.py +2 -0
  15. slidge/core/cache.py +183 -0
  16. slidge/core/config.py +216 -0
  17. slidge/core/gateway/__init__.py +3 -0
  18. slidge/core/gateway/base.py +895 -0
  19. slidge/core/gateway/caps.py +63 -0
  20. slidge/core/gateway/delivery_receipt.py +52 -0
  21. slidge/core/gateway/disco.py +80 -0
  22. slidge/core/gateway/mam.py +75 -0
  23. slidge/core/gateway/muc_admin.py +35 -0
  24. slidge/core/gateway/ping.py +66 -0
  25. slidge/core/gateway/presence.py +95 -0
  26. slidge/core/gateway/registration.py +53 -0
  27. slidge/core/gateway/search.py +102 -0
  28. slidge/core/gateway/session_dispatcher.py +789 -0
  29. slidge/core/gateway/vcard_temp.py +130 -0
  30. slidge/core/mixins/__init__.py +19 -0
  31. slidge/core/mixins/attachment.py +506 -0
  32. slidge/core/mixins/avatar.py +167 -0
  33. slidge/core/mixins/base.py +31 -0
  34. slidge/core/mixins/disco.py +130 -0
  35. slidge/core/mixins/lock.py +31 -0
  36. slidge/core/mixins/message.py +398 -0
  37. slidge/core/mixins/message_maker.py +154 -0
  38. slidge/core/mixins/presence.py +217 -0
  39. slidge/core/mixins/recipient.py +43 -0
  40. slidge/core/pubsub.py +282 -116
  41. slidge/core/session.py +595 -372
  42. slidge/group/__init__.py +10 -0
  43. slidge/group/archive.py +125 -0
  44. slidge/group/bookmarks.py +163 -0
  45. slidge/group/participant.py +458 -0
  46. slidge/group/room.py +1103 -0
  47. slidge/migration.py +18 -0
  48. slidge/slixfix/__init__.py +68 -0
  49. slidge/{util/xep_0084 → slixfix/link_preview}/__init__.py +3 -5
  50. slidge/slixfix/link_preview/link_preview.py +17 -0
  51. slidge/slixfix/link_preview/stanza.py +99 -0
  52. slidge/slixfix/roster.py +60 -0
  53. slidge/{util → slixfix}/xep_0077/register.py +14 -2
  54. slidge/slixfix/xep_0077/stanza.py +104 -0
  55. slidge/{util → slixfix}/xep_0100/gateway.py +25 -15
  56. slidge/slixfix/xep_0100/stanza.py +9 -0
  57. slidge/slixfix/xep_0153/__init__.py +10 -0
  58. slidge/slixfix/xep_0153/stanza.py +25 -0
  59. slidge/slixfix/xep_0153/vcard_avatar.py +23 -0
  60. slidge/slixfix/xep_0264/__init__.py +5 -0
  61. slidge/slixfix/xep_0264/stanza.py +36 -0
  62. slidge/slixfix/xep_0264/thumbnail.py +23 -0
  63. slidge/slixfix/xep_0292/__init__.py +5 -0
  64. slidge/slixfix/xep_0292/vcard4.py +100 -0
  65. slidge/slixfix/xep_0313/__init__.py +12 -0
  66. slidge/slixfix/xep_0313/mam.py +262 -0
  67. slidge/slixfix/xep_0313/stanza.py +359 -0
  68. slidge/slixfix/xep_0317/__init__.py +5 -0
  69. slidge/slixfix/xep_0317/hats.py +17 -0
  70. slidge/slixfix/xep_0317/stanza.py +28 -0
  71. slidge/{util → slixfix}/xep_0356_old/privilege.py +9 -7
  72. slidge/slixfix/xep_0424/__init__.py +9 -0
  73. slidge/slixfix/xep_0424/retraction.py +77 -0
  74. slidge/slixfix/xep_0424/stanza.py +28 -0
  75. slidge/slixfix/xep_0490/__init__.py +8 -0
  76. slidge/slixfix/xep_0490/mds.py +47 -0
  77. slidge/slixfix/xep_0490/stanza.py +17 -0
  78. slidge/util/__init__.py +4 -6
  79. slidge/util/archive_msg.py +61 -0
  80. slidge/util/conf.py +206 -0
  81. slidge/util/db.py +57 -76
  82. slidge/util/schema.sql +126 -0
  83. slidge/util/sql.py +508 -0
  84. slidge/util/test.py +215 -25
  85. slidge/util/types.py +177 -4
  86. slidge/util/util.py +225 -59
  87. slidge-0.1.1.dist-info/METADATA +110 -0
  88. slidge-0.1.1.dist-info/RECORD +96 -0
  89. {slidge-0.1.0b2.dist-info → slidge-0.1.1.dist-info}/WHEEL +1 -1
  90. slidge/core/contact.py +0 -891
  91. slidge/core/gateway.py +0 -916
  92. slidge/plugins/discord/__init__.py +0 -90
  93. slidge/plugins/discord/client.py +0 -108
  94. slidge/plugins/discord/session.py +0 -162
  95. slidge/plugins/dummy.py +0 -203
  96. slidge/plugins/facebook.py +0 -493
  97. slidge/plugins/hackernews.py +0 -213
  98. slidge/plugins/mattermost/__init__.py +0 -1
  99. slidge/plugins/mattermost/api.py +0 -280
  100. slidge/plugins/mattermost/gateway.py +0 -365
  101. slidge/plugins/mattermost/websocket.py +0 -252
  102. slidge/plugins/signal/__init__.py +0 -3
  103. slidge/plugins/signal/contact.py +0 -106
  104. slidge/plugins/signal/gateway.py +0 -282
  105. slidge/plugins/signal/session.py +0 -448
  106. slidge/plugins/signal/txt.py +0 -53
  107. slidge/plugins/skype.py +0 -325
  108. slidge/plugins/steam.py +0 -310
  109. slidge/plugins/telegram/__init__.py +0 -5
  110. slidge/plugins/telegram/client.py +0 -228
  111. slidge/plugins/telegram/config.py +0 -12
  112. slidge/plugins/telegram/contact.py +0 -176
  113. slidge/plugins/telegram/gateway.py +0 -150
  114. slidge/plugins/telegram/session.py +0 -256
  115. slidge/util/xep_0030/__init__.py +0 -13
  116. slidge/util/xep_0030/disco.py +0 -811
  117. slidge/util/xep_0030/stanza/__init__.py +0 -7
  118. slidge/util/xep_0030/stanza/info.py +0 -270
  119. slidge/util/xep_0030/stanza/items.py +0 -147
  120. slidge/util/xep_0030/static.py +0 -467
  121. slidge/util/xep_0055/__init__.py +0 -5
  122. slidge/util/xep_0055/search.py +0 -75
  123. slidge/util/xep_0055/stanza.py +0 -10
  124. slidge/util/xep_0077/stanza.py +0 -71
  125. slidge/util/xep_0084/avatar.py +0 -137
  126. slidge/util/xep_0084/stanza.py +0 -104
  127. slidge/util/xep_0115/__init__.py +0 -12
  128. slidge/util/xep_0115/caps.py +0 -379
  129. slidge/util/xep_0115/stanza.py +0 -16
  130. slidge/util/xep_0115/static.py +0 -137
  131. slidge/util/xep_0292/__init__.py +0 -1
  132. slidge/util/xep_0292/stanza.py +0 -167
  133. slidge/util/xep_0292/vcard4.py +0 -75
  134. slidge/util/xep_0333/__init__.py +0 -10
  135. slidge/util/xep_0333/markers.py +0 -96
  136. slidge/util/xep_0333/stanza.py +0 -34
  137. slidge/util/xep_0356/__init__.py +0 -7
  138. slidge/util/xep_0356/permissions.py +0 -35
  139. slidge/util/xep_0356/privilege.py +0 -160
  140. slidge/util/xep_0356/stanza.py +0 -44
  141. slidge/util/xep_0363/__init__.py +0 -16
  142. slidge/util/xep_0363/http_upload.py +0 -215
  143. slidge/util/xep_0363/stanza.py +0 -46
  144. slidge/util/xep_0461/__init__.py +0 -6
  145. slidge/util/xep_0461/reply.py +0 -48
  146. slidge/util/xep_0461/stanza.py +0 -47
  147. slidge-0.1.0b2.dist-info/METADATA +0 -171
  148. slidge-0.1.0b2.dist-info/RECORD +0 -81
  149. /slidge/{plugins/__init__.py → py.typed} +0 -0
  150. /slidge/{util → slixfix}/xep_0077/__init__.py +0 -0
  151. /slidge/{util → slixfix}/xep_0100/__init__.py +0 -0
  152. /slidge/{util → slixfix}/xep_0356_old/__init__.py +0 -0
  153. /slidge/{util → slixfix}/xep_0356_old/stanza.py +0 -0
  154. {slidge-0.1.0b2.dist-info → slidge-0.1.1.dist-info}/LICENSE +0 -0
  155. {slidge-0.1.0b2.dist-info → slidge-0.1.1.dist-info}/entry_points.txt +0 -0
@@ -1,448 +0,0 @@
1
- import asyncio
2
- import functools
3
- import logging
4
- import os
5
- import tempfile
6
- from datetime import datetime
7
- from pathlib import Path
8
- from typing import TYPE_CHECKING, Any
9
-
10
- import aiohttp
11
- import aiosignald.exc as sigexc
12
- import aiosignald.generated as sigapi
13
- from slixmpp.exceptions import XMPPError
14
-
15
- from slidge import *
16
-
17
- if TYPE_CHECKING:
18
- from .contact import Contact, Roster
19
- from .gateway import Gateway
20
-
21
- from . import txt
22
-
23
-
24
- def handle_unregistered_recipient(func):
25
- @functools.wraps(func)
26
- async def wrapped(*a, **kw):
27
- try:
28
- return await func(*a, **kw)
29
- except (
30
- sigexc.UnregisteredUserError,
31
- sigexc.IllegalArgumentException,
32
- sigexc.InternalError,
33
- ) as e:
34
- raise XMPPError(
35
- "item-not-found",
36
- text=e.message,
37
- )
38
-
39
- return wrapped
40
-
41
-
42
- class Session(BaseSession["Contact", "Roster", "Gateway"]):
43
- """
44
- Represents a signal account
45
- """
46
-
47
- def __init__(self, user: GatewayUser):
48
- """
49
-
50
- :param user:
51
- """
52
- super().__init__(user)
53
- self.phone = self.user.registration_form["phone"]
54
- if self.phone is None:
55
- raise RuntimeError
56
- self.signal = self.xmpp.signal
57
- self.xmpp.sessions_by_phone[self.phone] = self
58
- self.reaction_ack_futures: dict[tuple[int, str], asyncio.Future[None]] = {}
59
- self.connected = self.xmpp.loop.create_future()
60
-
61
- @staticmethod
62
- def xmpp_msg_id_to_legacy_msg_id(i: str) -> int:
63
- try:
64
- return int(i)
65
- except ValueError:
66
- raise NotImplementedError
67
-
68
- @handle_unregistered_recipient
69
- async def paused(self, c: "Contact"):
70
- await (await self.signal).typing(
71
- account=self.phone, typing=False, address=c.signal_address
72
- )
73
-
74
- async def correct(self, text: str, legacy_msg_id: Any, c: "Contact"):
75
- return await self.send_text("Correction: " + text, c)
76
-
77
- async def search(self, form_values: dict[str, str]):
78
- phone = form_values.get("phone")
79
- if phone is None:
80
- raise ValueError("Empty phone")
81
-
82
- try:
83
- address = await (await self.signal).resolve_address(
84
- account=self.phone,
85
- partial=sigapi.JsonAddressv1(number=form_values.get("phone")),
86
- )
87
- except sigexc.UnregisteredUserError:
88
- return
89
-
90
- contact = self.contacts.by_json_address(address)
91
-
92
- return SearchResult(
93
- fields=[FormField("phone"), FormField("jid", type="jid-single")],
94
- items=[{"phone": phone, "jid": contact.jid.bare}],
95
- )
96
-
97
- async def login(self):
98
- """
99
- Attempt to listen to incoming events for this account,
100
- or pursue the registration process if needed.
101
- """
102
- try:
103
- await (await self.signal).subscribe(account=self.phone)
104
- except sigexc.NoSuchAccountError:
105
- device = self.user.registration_form["device"]
106
- try:
107
- if device == "primary":
108
- await self.register()
109
- elif device == "secondary":
110
- await self.link()
111
- else:
112
- # This should never happen
113
- self.send_gateway_status("Disconnected", show="dnd")
114
- raise TypeError("Unknown device type", device)
115
- except sigexc.SignaldException as e:
116
- self.xmpp.send_message(
117
- mto=self.user.jid,
118
- mbody=f"Something went wrong: {e}",
119
- mfrom=self.xmpp.boundjid,
120
- )
121
- raise
122
- await (await self.signal).subscribe(account=self.phone)
123
- await self.connected
124
- await self.add_contacts_to_roster()
125
- return f"Connected as {self.phone}"
126
-
127
- async def on_websocket_connection_state(
128
- self, state: sigapi.WebSocketConnectionStatev1
129
- ):
130
- if (
131
- state.state == "CONNECTED"
132
- and state.socket == "IDENTIFIED"
133
- and not self.connected.done()
134
- ):
135
- self.connected.set_result(True)
136
-
137
- async def register(self):
138
- self.send_gateway_status("Registering…", show="dnd")
139
- try:
140
- await (await self.signal).register(self.phone)
141
- except sigexc.CaptchaRequiredError:
142
- self.send_gateway_status("Captcha required", show="dnd")
143
- captcha = await self.input(txt.CAPTCHA_REQUIRED)
144
- await (await self.signal).register(self.phone, captcha=captcha)
145
- sms_code = await self.input(
146
- f"Reply to this message with the code you have received by SMS at {self.phone}.",
147
- )
148
- await (await self.signal).verify(account=self.phone, code=sms_code)
149
- await (await self.signal).set_profile(
150
- account=self.phone, name=self.user.registration_form["name"]
151
- )
152
- self.send_gateway_message(txt.REGISTER_SUCCESS)
153
-
154
- async def send_linking_qrcode(self):
155
- self.send_gateway_status("QR scan needed", show="dnd")
156
- resp = await (await self.signal).generate_linking_uri()
157
- await self.send_qr(resp.uri)
158
- self.xmpp.send_message(
159
- mto=self.user.jid,
160
- mbody=f"Use this URI or QR code on another signal device to "
161
- f"finish linking your XMPP account\n{resp.uri}",
162
- mfrom=self.xmpp.boundjid,
163
- )
164
- return resp
165
-
166
- async def link(self):
167
- resp = await self.send_linking_qrcode()
168
- try:
169
- await (await self.signal).finish_link(
170
- device_name=self.user.registration_form["device_name"],
171
- session_id=resp.session_id,
172
- )
173
- except sigexc.ScanTimeoutError:
174
- while True:
175
- r = await self.input(txt.LINK_TIMEOUT)
176
- if r in ("cancel", "link"):
177
- break
178
- else:
179
- self.send_gateway_message("Please reply either 'link' or 'cancel'")
180
- if r == "cancel":
181
- raise
182
- elif r == "link":
183
- await self.link() # TODO: set a max number of attempts
184
- except sigexc.SignaldException as e:
185
- self.xmpp.send_message(
186
- mto=self.user.jid,
187
- mbody=f"Something went wrong during the linking process: {e}.",
188
- mfrom=self.xmpp.boundjid,
189
- )
190
- raise
191
- else:
192
- self.send_gateway_message(txt.LINK_SUCCESS)
193
-
194
- async def logout(self):
195
- await (await self.signal).unsubscribe(account=self.phone)
196
-
197
- async def add_contacts_to_roster(self):
198
- """
199
- Populate a user's roster
200
- """
201
- profiles = await (await self.signal).list_contacts(account=self.phone)
202
- for profile in profiles.profiles:
203
- contact = self.contacts.by_json_address(profile.address)
204
- await contact.update_info()
205
- await contact.add_to_roster()
206
- contact.online()
207
-
208
- async def on_signal_message(self, msg: sigapi.IncomingMessagev1):
209
- """
210
- User has received 'something' from signal
211
-
212
- :param msg:
213
- """
214
- if (sync_msg := msg.sync_message) is not None:
215
- if sync_msg.contacts is not None and msg.sync_message.contactsComplete:
216
- log.debug("Received a sync contact updates")
217
- await self.add_contacts_to_roster()
218
-
219
- if (sent := sync_msg.sent) is None:
220
- # Probably a 'message read' marker
221
- log.debug("No sent message in this sync message")
222
- return
223
- sent_msg = sent.message
224
- if sent_msg.group or sent_msg.groupV2:
225
- return
226
-
227
- contact = self.contacts.by_json_address(sent.destination)
228
-
229
- if (body := sent_msg.body) is not None:
230
- contact.carbon(
231
- body=body,
232
- when=datetime.fromtimestamp(sent_msg.timestamp / 1000),
233
- )
234
- if (reaction := sent_msg.reaction) is not None:
235
- try:
236
- fut = self.reaction_ack_futures.pop(
237
- (reaction.targetSentTimestamp, reaction.emoji)
238
- )
239
- except KeyError:
240
- contact.carbon_react(
241
- reaction.targetSentTimestamp,
242
- () if reaction.remove else reaction.emoji,
243
- )
244
- else:
245
- fut.set_result(None)
246
- if (delete := sent_msg.remoteDelete) is not None:
247
- contact.carbon_retract(delete.target_sent_timestamp)
248
-
249
- contact = self.contacts.by_json_address(msg.source)
250
-
251
- if (data := msg.data_message) is not None:
252
- if data.group or data.groupV2:
253
- return
254
- if (quote := data.quote) is None:
255
- reply_to_msg_id = None
256
- else:
257
- reply_to_msg_id = quote.id
258
- await contact.send_attachments(
259
- data.attachments,
260
- legacy_msg_id=msg.data_message.timestamp,
261
- reply_to_msg_id=reply_to_msg_id,
262
- )
263
- if (body := data.body) is not None:
264
- contact.send_text(
265
- body=body,
266
- legacy_msg_id=msg.data_message.timestamp,
267
- reply_to_msg_id=reply_to_msg_id,
268
- when=datetime.fromtimestamp(msg.data_message.timestamp / 1000),
269
- )
270
- if (reaction := data.reaction) is not None:
271
- self.log.debug("Reaction: %s", reaction)
272
- if reaction.remove:
273
- contact.react(reaction.targetSentTimestamp)
274
- else:
275
- contact.react(reaction.targetSentTimestamp, reaction.emoji)
276
- if (delete := data.remoteDelete) is not None:
277
- contact.retract(delete.target_sent_timestamp)
278
-
279
- if (typing_message := msg.typing_message) is not None:
280
- if typing_message.group_id:
281
- return
282
- action = typing_message.action
283
- if action == "STARTED":
284
- contact.active()
285
- contact.composing()
286
- elif action == "STOPPED":
287
- contact.paused()
288
-
289
- if (receipt_message := msg.receipt_message) is not None:
290
- type_ = receipt_message.type
291
- if type_ == "DELIVERY":
292
- for t in msg.receipt_message.timestamps:
293
- contact.received(t)
294
- elif type_ == "READ":
295
- for t in msg.receipt_message.timestamps:
296
- contact.displayed(t)
297
-
298
- @handle_unregistered_recipient
299
- async def send_text(self, t: str, c: "Contact", *, reply_to_msg_id=None) -> int:
300
- if reply_to_msg_id is None:
301
- quote = None
302
- else:
303
- quote = sigapi.JsonQuotev1(
304
- id=reply_to_msg_id,
305
- author=c.signal_address,
306
- text="" # not sure what this accomplishes? does not seem to have any effect,
307
- # but must not be None or NullPointerException
308
- )
309
- response = await (await self.signal).send(
310
- account=self.phone,
311
- recipientAddress=c.signal_address,
312
- messageBody=t,
313
- quote=quote,
314
- )
315
- result = response.results[0]
316
- log.debug("Result: %s", result)
317
- if result.networkFailure or result.proof_required_failure:
318
- raise XMPPError(str(result))
319
- elif result.identityFailure:
320
- s = await self.signal
321
- identities = (
322
- await s.get_identities(
323
- account=self.phone,
324
- address=c.signal_address,
325
- )
326
- ).identities
327
- ans = await self.input(
328
- f"The identity of {c.legacy_id} has changed. "
329
- f"Do you want to trust all their identities and resend the message?"
330
- )
331
- if ans.lower().startswith("y"):
332
- for i in identities:
333
- await (await self.signal).trust(
334
- account=self.phone,
335
- address=c.signal_address,
336
- safety_number=i.safety_number,
337
- )
338
- await self.send_text(t, c, reply_to_msg_id=reply_to_msg_id)
339
- else:
340
- raise XMPPError(str(result))
341
- return response.timestamp
342
-
343
- @handle_unregistered_recipient
344
- async def send_file(self, u: str, c: "Contact", *, reply_to_msg_id=None):
345
- s = await self.signal
346
- async with aiohttp.ClientSession() as client:
347
- async with client.get(url=u) as r:
348
- with tempfile.TemporaryDirectory(
349
- dir=Path(self.xmpp.signal_socket).parent,
350
- ) as d:
351
- os.chmod(d, 0o777)
352
- with open(Path(d) / r.url.name, "wb") as f:
353
- f.write(await r.content.read())
354
- os.chmod(
355
- f.name, 0o666
356
- ) # temp file is 0600 https://stackoverflow.com/a/10541972/5902284
357
- signal_r = await s.send(
358
- account=self.phone,
359
- recipientAddress=c.signal_address,
360
- attachments=[sigapi.JsonAttachmentv1(filename=f.name)],
361
- )
362
- return signal_r.timestamp
363
-
364
- async def active(self, c: "Contact"):
365
- pass
366
-
367
- async def inactive(self, c: "Contact"):
368
- pass
369
-
370
- @handle_unregistered_recipient
371
- async def composing(self, c: "Contact"):
372
- self.log.debug("COMPOSING %s", c)
373
- await (await self.signal).typing(
374
- account=self.phone,
375
- address=c.signal_address,
376
- typing=True,
377
- )
378
-
379
- @handle_unregistered_recipient
380
- async def displayed(self, legacy_msg_id: int, c: "Contact"):
381
- await (await self.signal).mark_read(
382
- account=self.phone,
383
- to=c.signal_address,
384
- timestamps=[legacy_msg_id],
385
- )
386
-
387
- @handle_unregistered_recipient
388
- async def react(self, legacy_msg_id: int, emojis: list[str], c: "Contact"):
389
- remove = len(emojis) == 0
390
- if remove:
391
- try:
392
- emoji = c.user_reactions.pop(legacy_msg_id)
393
- except KeyError:
394
- self.send_gateway_message(
395
- f"Slidge failed to remove your reactions on message '{legacy_msg_id}'"
396
- )
397
- self.log.warning("Could not find the emoji to remove reaction")
398
- return
399
- else:
400
- emoji = emojis[-1]
401
- if len(emojis) > 1:
402
- self.send_gateway_message("Only one reaction per message on signal")
403
- c.carbon_react(legacy_msg_id, emoji)
404
- c.user_reactions[legacy_msg_id] = emoji
405
-
406
- response = await (await self.signal).react(
407
- username=self.phone,
408
- recipientAddress=c.signal_address,
409
- reaction=sigapi.JsonReactionv1(
410
- emoji=emoji,
411
- remove=remove,
412
- targetAuthor=sigapi.JsonAddressv1(number=self.phone)
413
- if legacy_msg_id in self.sent
414
- else c.signal_address,
415
- targetSentTimestamp=legacy_msg_id,
416
- ),
417
- )
418
- result = response.results[0]
419
- if (
420
- result.networkFailure
421
- or result.identityFailure
422
- or result.proof_required_failure
423
- ):
424
- raise XMPPError(str(result))
425
- f = self.reaction_ack_futures[
426
- (legacy_msg_id, emoji)
427
- ] = self.xmpp.loop.create_future()
428
- await f
429
-
430
- @handle_unregistered_recipient
431
- async def retract(self, legacy_msg_id: int, c: "Contact"):
432
- try:
433
- await (await self.signal).remote_delete(
434
- account=self.phone, address=c.signal_address, timestamp=legacy_msg_id
435
- )
436
- except sigexc.SignaldException as e:
437
- raise XMPPError(text=f"Something went wrong during remote delete: {e}")
438
-
439
- async def add_device(self, uri: str):
440
- try:
441
- await (await self.signal).add_device(account=self.phone, uri=uri)
442
- except sigexc.SignaldException as e:
443
- self.send_gateway_message(f"Problem: {e}")
444
- else:
445
- self.send_gateway_message("Linking OK")
446
-
447
-
448
- log = logging.getLogger(__name__)
@@ -1,53 +0,0 @@
1
- from slidge import *
2
-
3
- REGISTRATION_INSTRUCTIONS = (
4
- "Fill the form to use your XMPP account as a signal client. "
5
- "More information at https://slidge.readthedocs.io/en/latest/user/plugins/signal.html"
6
- )
7
- REGISTRATION_FIELDS = [
8
- FormField(var="phone", label="Phone number (ex: +123456789)", required=True),
9
- FormField(
10
- var="device",
11
- type="list-single",
12
- label="What do you want to do?",
13
- options=[
14
- {"label": "Create a new signal account", "value": "primary"},
15
- {"label": "Link to an existing signal account", "value": "secondary"},
16
- ],
17
- required=True,
18
- ),
19
- FormField(
20
- var="name",
21
- label="Your name (only used if you chose to create a new signal account; "
22
- "doesn't have to be your real name)",
23
- ),
24
- FormField(
25
- var="device_name",
26
- label="Device name (only used if you chose to link to an existing signal account)",
27
- value="slidge",
28
- ),
29
- ]
30
-
31
- CAPTCHA_REQUIRED = (
32
- "Signal requires you to complete a captcha to register a new account. "
33
- "Please follow the instructions at https://signald.org/articles/captcha/#getting-a-token and "
34
- "reply to this message with the token (signalcaptcha://XXXXXXXXX)."
35
- )
36
-
37
- NAME_REQUIRED = (
38
- "If you want to register a new signal account, you must enter a name. "
39
- "Nothing forces you to use your real name."
40
- )
41
-
42
- LINK_TIMEOUT = (
43
- "You took too much time… "
44
- "Reply to this message with 'link' once you're ready or 'cancel' "
45
- "to remove your gateway registration"
46
- )
47
-
48
- LINK_SUCCESS = (
49
- "It looks like everything's all set up. You should now send and "
50
- "receive signal messages via XMPP."
51
- )
52
-
53
- REGISTER_SUCCESS = "This XMPP bridge is now your 'primary' signal device. Congrats!"