simplex-chat 7.1.0b6.post2__tar.gz → 7.1.3__tar.gz
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.
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/PKG-INFO +1 -1
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/src/simplex_chat/_native.py +23 -10
- simplex_chat-7.1.3/src/simplex_chat/_version.py +16 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/src/simplex_chat/bot.py +4 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/src/simplex_chat/core.py +78 -6
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/src/simplex_chat/types/_commands.py +190 -1
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/src/simplex_chat/types/_responses.py +62 -1
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/src/simplex_chat/types/_types.py +244 -2
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/tests/test_client_and_waiters.py +52 -2
- simplex_chat-7.1.3/tests/test_codegen.py +146 -0
- simplex_chat-7.1.3/tests/test_core_resize_image.py +121 -0
- simplex_chat-7.1.0b6.post2/src/simplex_chat/_version.py +0 -16
- simplex_chat-7.1.0b6.post2/tests/test_codegen.py +0 -47
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/.gitignore +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/LICENSE +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/README.md +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/examples/squaring_bot.py +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/pyproject.toml +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/src/simplex_chat/__init__.py +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/src/simplex_chat/__main__.py +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/src/simplex_chat/api.py +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/src/simplex_chat/client.py +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/src/simplex_chat/filters.py +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/src/simplex_chat/py.typed +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/src/simplex_chat/types/__init__.py +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/src/simplex_chat/types/_events.py +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/src/simplex_chat/util.py +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/tests/test_api.py +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/tests/test_bot_registration.py +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/tests/test_core_migrate_init.py +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/tests/test_filters.py +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/tests/test_native_cache.py +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/tests/test_native_url.py +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/tests/test_recv_executor.py +0 -0
- {simplex_chat-7.1.0b6.post2 → simplex_chat-7.1.3}/tests/test_util.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: simplex-chat
|
|
3
|
-
Version: 7.1.
|
|
3
|
+
Version: 7.1.3
|
|
4
4
|
Summary: SimpleX Chat Python library for chat bots
|
|
5
5
|
Project-URL: Homepage, https://github.com/simplex-chat/simplex-chat/tree/stable/packages/simplex-chat-python
|
|
6
6
|
Project-URL: Issues, https://github.com/simplex-chat/simplex-chat/issues
|
|
@@ -277,17 +277,30 @@ def lib() -> ctypes.CDLL:
|
|
|
277
277
|
return _lib
|
|
278
278
|
|
|
279
279
|
|
|
280
|
-
|
|
281
|
-
"loaded libsimplex does not export chat_migrate_init_queue; queue size needs a newer libsimplex"
|
|
282
|
-
)
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
def migrate_init_queue() -> Any:
|
|
286
|
-
"""`chat_migrate_init_queue`, which older libsimplex releases do not export."""
|
|
280
|
+
def _optional_export(name: str, feature: str, argtypes: list[Any]) -> Any:
|
|
287
281
|
try:
|
|
288
|
-
fn = lib()
|
|
282
|
+
fn = getattr(lib(), name)
|
|
289
283
|
except AttributeError as e:
|
|
290
|
-
raise RuntimeError(
|
|
291
|
-
|
|
284
|
+
raise RuntimeError(
|
|
285
|
+
f"loaded libsimplex does not export {name}; {feature} needs a newer libsimplex"
|
|
286
|
+
) from e
|
|
287
|
+
fn.argtypes = argtypes
|
|
292
288
|
fn.restype = c_void_p
|
|
293
289
|
return fn
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def migrate_init_queue() -> Any:
|
|
293
|
+
"""`chat_migrate_init_queue`, which older libsimplex releases do not export."""
|
|
294
|
+
return _optional_export(
|
|
295
|
+
"chat_migrate_init_queue",
|
|
296
|
+
"queue size",
|
|
297
|
+
[c_char_p, c_char_p, c_char_p, c_int, POINTER(c_void_p)],
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def resize_image() -> Any:
|
|
302
|
+
return _optional_export("chat_resize_image", "image resizing", [c_char_p, c_int, c_int, c_int])
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def resize_image_uri() -> Any:
|
|
306
|
+
return _optional_export("chat_resize_image_uri", "image resizing", [c_char_p, c_int, c_int])
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Package version and the simplex-chat-libs release it loads.
|
|
2
|
+
|
|
3
|
+
Written by scripts/ci/packages_release.py prepare: it bumps the version
|
|
4
|
+
and pins new library releases with the SHA-256 of their assets.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
__version__ = "7.1.3" # PEP 440 — read by hatchling for wheel metadata
|
|
8
|
+
LIBS_RELEASE = "core-7.1.3.0" # simplex-chat-libs release tag
|
|
9
|
+
LIBS_SHA256 = {
|
|
10
|
+
"simplex-chat-libs-linux-aarch64.zip": "46e296417de8cddc0d6f800d7c634dec410a1af20ea38ff31f224ef388aaeb00",
|
|
11
|
+
"simplex-chat-libs-linux-x86_64-postgres.zip": "ea89b4e95836c79c887cc13a2dc9fc66e319b21ee4148ca38817539657601050",
|
|
12
|
+
"simplex-chat-libs-linux-x86_64.zip": "12b6ea97c64a5ea53a66f47e827dc8c0d6bc767fd44b22aab47786ac90e91d01",
|
|
13
|
+
"simplex-chat-libs-macos-aarch64.zip": "b7612b05cd17267f4e24efacfd16fa4a9f9b0c39b34c2f52465e34395492a452",
|
|
14
|
+
"simplex-chat-libs-macos-x86_64.zip": "ce7a9a2be0cd0e6782902d8ce4420e8660e4e2360d7fc0248584a0163f1a236d",
|
|
15
|
+
"simplex-chat-libs-windows-x86_64.zip": "a9ed55c82753d57cfddaddee78cc989b0edf3fe5fe08d7214e6f84ab43609999",
|
|
16
|
+
}
|
|
@@ -96,6 +96,7 @@ class Bot(Client):
|
|
|
96
96
|
update_profile: bool = True,
|
|
97
97
|
auto_accept: bool = True,
|
|
98
98
|
business_address: bool = False,
|
|
99
|
+
chat_layout: T.ChatLayout | None = None,
|
|
99
100
|
allow_files: bool = False,
|
|
100
101
|
log_contacts: bool = True,
|
|
101
102
|
log_network: bool = False,
|
|
@@ -115,6 +116,7 @@ class Bot(Client):
|
|
|
115
116
|
self._update_address = update_address
|
|
116
117
|
self._auto_accept = auto_accept
|
|
117
118
|
self._business_address = business_address
|
|
119
|
+
self._chat_layout = chat_layout
|
|
118
120
|
self._allow_files = allow_files
|
|
119
121
|
|
|
120
122
|
# ------------------------------------------------------------------ #
|
|
@@ -153,6 +155,8 @@ class Bot(Client):
|
|
|
153
155
|
desired: T.AddressSettings = {"businessAddress": self._business_address}
|
|
154
156
|
if self._auto_accept:
|
|
155
157
|
desired["autoAccept"] = {"acceptIncognito": False}
|
|
158
|
+
if self._chat_layout is not None:
|
|
159
|
+
desired["chatLayout"] = self._chat_layout
|
|
156
160
|
if self._welcome is not None:
|
|
157
161
|
desired["autoReply"] = (
|
|
158
162
|
{"type": "text", "text": self._welcome}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Typed async wrapper around libsimplex's C ABI functions.
|
|
2
2
|
|
|
3
3
|
Users interact with `Bot` / `ChatApi`. This module is exposed as
|
|
4
|
-
`simplex_chat.core` for tests
|
|
4
|
+
`simplex_chat.core` for tests, the api.ChatApi class and image resizing
|
|
5
|
+
(`resize_image`, `chat_resize_image`, `chat_resize_image_uri`).
|
|
5
6
|
"""
|
|
6
7
|
|
|
7
8
|
from __future__ import annotations
|
|
8
9
|
|
|
9
10
|
import asyncio
|
|
11
|
+
import base64
|
|
10
12
|
import ctypes
|
|
11
13
|
import json
|
|
12
14
|
from concurrent.futures import Executor
|
|
13
15
|
from enum import StrEnum
|
|
14
|
-
from typing import Any, TypedDict
|
|
16
|
+
from typing import Any, Literal, TypedDict, overload
|
|
15
17
|
|
|
16
18
|
from . import _native
|
|
17
19
|
from .types import CR, CEvt, T
|
|
@@ -70,6 +72,12 @@ class MigrationConfirmation(StrEnum):
|
|
|
70
72
|
ERROR = "error"
|
|
71
73
|
|
|
72
74
|
|
|
75
|
+
class ImageSize(StrEnum):
|
|
76
|
+
IMAGE = "image"
|
|
77
|
+
PROFILE_PREVIEW = "profilePreview"
|
|
78
|
+
MESSAGE_PREVIEW = "messagePreview"
|
|
79
|
+
|
|
80
|
+
|
|
73
81
|
class CryptoArgs(TypedDict): # wire-format JSON; camelCase fields
|
|
74
82
|
fileKey: str
|
|
75
83
|
fileNonce: str
|
|
@@ -88,6 +96,12 @@ def _read_and_free(ptr: int | None) -> str:
|
|
|
88
96
|
_native.libc().free(ctypes.c_void_p(ptr))
|
|
89
97
|
|
|
90
98
|
|
|
99
|
+
def _check_c_int(name: str, value: int) -> None:
|
|
100
|
+
# ctypes silently wraps ints that do not fit C int.
|
|
101
|
+
if ctypes.c_int(value).value != value:
|
|
102
|
+
raise ValueError(f"{name} {value} does not fit C int")
|
|
103
|
+
|
|
104
|
+
|
|
91
105
|
async def chat_send_cmd(ctrl: int, cmd: str) -> CR.ChatResponse:
|
|
92
106
|
def _call() -> str:
|
|
93
107
|
ptr = _native.lib().chat_send_cmd(ctrl, cmd.encode("utf-8"))
|
|
@@ -138,9 +152,8 @@ async def chat_migrate_init(
|
|
|
138
152
|
|
|
139
153
|
`queue_size` is the size of internal queues; the core default is used when None.
|
|
140
154
|
"""
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
raise ValueError(f"queue_size {queue_size} does not fit C int")
|
|
155
|
+
if queue_size is not None:
|
|
156
|
+
_check_c_int("queue_size", queue_size)
|
|
144
157
|
|
|
145
158
|
init_queue = _native.migrate_init_queue() if queue_size is not None else None
|
|
146
159
|
|
|
@@ -246,3 +259,62 @@ def _crypto_args_result(raw: str) -> CryptoArgs:
|
|
|
246
259
|
if parsed.get("type") == "error":
|
|
247
260
|
raise RuntimeError(parsed.get("writeError", "unknown write error"))
|
|
248
261
|
raise RuntimeError(f"unexpected result: {raw[:200]}")
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
async def chat_resize_image_uri(data: bytes, max_size: int) -> str:
|
|
265
|
+
_check_c_int("len(data)", len(data))
|
|
266
|
+
_check_c_int("max_size", max_size)
|
|
267
|
+
resize = _native.resize_image_uri()
|
|
268
|
+
|
|
269
|
+
def _call() -> str:
|
|
270
|
+
return _read_and_free(resize(data, len(data), max_size))
|
|
271
|
+
|
|
272
|
+
return _resized_image(await asyncio.to_thread(_call))
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
async def chat_resize_image(
|
|
276
|
+
data: bytes, max_size: int, image_format: Literal["jpeg", "png"]
|
|
277
|
+
) -> bytes:
|
|
278
|
+
return await _resize_image_data(data, max_size, 1 if image_format == "png" else 0)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
@overload
|
|
282
|
+
async def resize_image(data: bytes, size: Literal[ImageSize.IMAGE]) -> bytes: ...
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
@overload
|
|
286
|
+
async def resize_image(
|
|
287
|
+
data: bytes, size: Literal[ImageSize.PROFILE_PREVIEW, ImageSize.MESSAGE_PREVIEW]
|
|
288
|
+
) -> str: ...
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
@overload
|
|
292
|
+
async def resize_image(data: bytes, size: ImageSize) -> bytes | str: ...
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
async def resize_image(data: bytes, size: ImageSize) -> bytes | str:
|
|
296
|
+
"""Resize image to the app size limit: JPEG or PNG for an image, a data URI for a preview."""
|
|
297
|
+
match size:
|
|
298
|
+
case ImageSize.IMAGE:
|
|
299
|
+
return await _resize_image_data(data, 261120, -1)
|
|
300
|
+
case ImageSize.PROFILE_PREVIEW:
|
|
301
|
+
return await chat_resize_image_uri(data, 12500)
|
|
302
|
+
case ImageSize.MESSAGE_PREVIEW:
|
|
303
|
+
return await chat_resize_image_uri(data, 14000)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
async def _resize_image_data(data: bytes, max_size: int, png: int) -> bytes:
|
|
307
|
+
_check_c_int("len(data)", len(data))
|
|
308
|
+
_check_c_int("max_size", max_size)
|
|
309
|
+
resize = _native.resize_image()
|
|
310
|
+
|
|
311
|
+
def _call() -> str:
|
|
312
|
+
return _read_and_free(resize(data, len(data), max_size, png))
|
|
313
|
+
|
|
314
|
+
return base64.b64decode(_resized_image(await asyncio.to_thread(_call)))
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def _resized_image(res: str) -> str:
|
|
318
|
+
if not res:
|
|
319
|
+
raise RuntimeError("image cannot be decoded or does not fit max_size")
|
|
320
|
+
return res
|
|
@@ -342,6 +342,32 @@ def APIListMembers_cmd_string(self: APIListMembers) -> str:
|
|
|
342
342
|
APIListMembers_Response = CR.GroupMembers | CR.ChatCmdError
|
|
343
343
|
|
|
344
344
|
|
|
345
|
+
# Create a direct message contact with a group member.
|
|
346
|
+
# Network usage: interactive.
|
|
347
|
+
class APICreateMemberContact(TypedDict):
|
|
348
|
+
groupId: int # int64
|
|
349
|
+
groupMemberId: int # int64
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def APICreateMemberContact_cmd_string(self: APICreateMemberContact) -> str:
|
|
353
|
+
return '/_create member contact #' + str(self['groupId']) + ' ' + str(self['groupMemberId'])
|
|
354
|
+
|
|
355
|
+
APICreateMemberContact_Response = CR.NewMemberContact | CR.ChatCmdError
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
# Send a direct message invitation to a group member contact.
|
|
359
|
+
# Network usage: background.
|
|
360
|
+
class APISendMemberContactInvitation(TypedDict):
|
|
361
|
+
contactId: int # int64
|
|
362
|
+
msgContent_: NotRequired["T.MsgContent"]
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def APISendMemberContactInvitation_cmd_string(self: APISendMemberContactInvitation) -> str:
|
|
366
|
+
return '/_invite member contact @' + str(self['contactId']) + ((' json ' + json.dumps(self.get('msgContent_'))) if self.get('msgContent_') is not None else '')
|
|
367
|
+
|
|
368
|
+
APISendMemberContactInvitation_Response = CR.NewMemberContactSentInv | CR.ChatCmdError
|
|
369
|
+
|
|
370
|
+
|
|
345
371
|
# Create group.
|
|
346
372
|
# Network usage: no.
|
|
347
373
|
class APINewGroup(TypedDict):
|
|
@@ -512,7 +538,7 @@ class APIConnectPlan(TypedDict):
|
|
|
512
538
|
|
|
513
539
|
|
|
514
540
|
def APIConnectPlan_cmd_string(self: APIConnectPlan) -> str:
|
|
515
|
-
return '/_connect plan ' + str(self['userId']) + ' ' + self.get('connectTarget')
|
|
541
|
+
return '/_connect plan ' + str(self['userId']) + ' ' + self.get('connectTarget') + T.PlanResolveMode_cmd_string(self['resolveMode']) + ((' sig=' + json.dumps(self.get('linkOwnerSig'))) if self.get('linkOwnerSig') is not None else '')
|
|
516
542
|
|
|
517
543
|
APIConnectPlan_Response = CR.ConnectionPlan | CR.ChatCmdError
|
|
518
544
|
|
|
@@ -553,6 +579,80 @@ Connect_Response = (
|
|
|
553
579
|
)
|
|
554
580
|
|
|
555
581
|
|
|
582
|
+
# Prepare contact chat from link data before connecting.
|
|
583
|
+
# Network usage: no.
|
|
584
|
+
class APIPrepareContact(TypedDict):
|
|
585
|
+
userId: int # int64
|
|
586
|
+
connLink: "T.CreatedConnLink"
|
|
587
|
+
verifiedDomain: NotRequired[str]
|
|
588
|
+
contactSLinkData: "T.ContactShortLinkData"
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
def APIPrepareContact_cmd_string(self: APIPrepareContact) -> str:
|
|
592
|
+
return '/_prepare contact ' + str(self['userId']) + ' ' + T.CreatedConnLink_cmd_string(self['connLink']) + ((' domain=' + self.get('verifiedDomain')) if self.get('verifiedDomain') is not None else '') + ' ' + json.dumps(self['contactSLinkData'])
|
|
593
|
+
|
|
594
|
+
APIPrepareContact_Response = CR.NewPreparedChat | CR.ChatCmdError
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
# Prepare group chat from link data before connecting.
|
|
598
|
+
# Network usage: no.
|
|
599
|
+
class APIPrepareGroup(TypedDict):
|
|
600
|
+
userId: int # int64
|
|
601
|
+
connLinkContact: "T.CreatedConnLink"
|
|
602
|
+
direct: bool
|
|
603
|
+
verifiedDomain: NotRequired[str]
|
|
604
|
+
groupSLinkData: "T.GroupShortLinkData"
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
def APIPrepareGroup_cmd_string(self: APIPrepareGroup) -> str:
|
|
608
|
+
return '/_prepare group ' + str(self['userId']) + ' ' + T.CreatedConnLink_cmd_string(self['connLinkContact']) + (' direct=off' if not self['direct'] else '') + ((' domain=' + self.get('verifiedDomain')) if self.get('verifiedDomain') is not None else '') + ' ' + json.dumps(self['groupSLinkData'])
|
|
609
|
+
|
|
610
|
+
APIPrepareGroup_Response = CR.NewPreparedChat | CR.ChatCmdError
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
# Connect to prepared contact.
|
|
614
|
+
# Network usage: interactive.
|
|
615
|
+
class APIConnectPreparedContact(TypedDict):
|
|
616
|
+
contactId: int # int64
|
|
617
|
+
incognito: bool
|
|
618
|
+
msgContent_: NotRequired["T.MsgContent"]
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
def APIConnectPreparedContact_cmd_string(self: APIConnectPreparedContact) -> str:
|
|
622
|
+
return '/_connect contact @' + str(self['contactId']) + (' incognito=on' if self['incognito'] else '') + ((' json ' + json.dumps(self.get('msgContent_'))) if self.get('msgContent_') is not None else '')
|
|
623
|
+
|
|
624
|
+
APIConnectPreparedContact_Response = CR.StartedConnectionToContact | CR.ContactAlreadyExists | CR.ChatCmdError
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
# Connect to prepared group.
|
|
628
|
+
# Network usage: interactive.
|
|
629
|
+
class APIConnectPreparedGroup(TypedDict):
|
|
630
|
+
groupId: int # int64
|
|
631
|
+
incognito: bool
|
|
632
|
+
ownerContact: NotRequired["T.GroupOwnerContact"]
|
|
633
|
+
msgContent_: NotRequired["T.MsgContent"]
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
def APIConnectPreparedGroup_cmd_string(self: APIConnectPreparedGroup) -> str:
|
|
637
|
+
return '/_connect group #' + str(self['groupId']) + (' incognito=on' if self['incognito'] else '') + ((' ' + T.GroupOwnerContact_cmd_string(self.get('ownerContact'))) if self.get('ownerContact') is not None else '') + ((' json ' + json.dumps(self.get('msgContent_'))) if self.get('msgContent_') is not None else '')
|
|
638
|
+
|
|
639
|
+
APIConnectPreparedGroup_Response = CR.StartedConnectionToGroup | CR.ChatCmdError
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
# Connect to existing contact via address in its profile.
|
|
643
|
+
# Network usage: interactive.
|
|
644
|
+
class APIConnectContactViaAddress(TypedDict):
|
|
645
|
+
userId: int # int64
|
|
646
|
+
incognito: bool
|
|
647
|
+
contactId: int # int64
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
def APIConnectContactViaAddress_cmd_string(self: APIConnectContactViaAddress) -> str:
|
|
651
|
+
return '/_connect contact ' + str(self['userId']) + (' incognito=on' if self['incognito'] else '') + ' ' + str(self['contactId'])
|
|
652
|
+
|
|
653
|
+
APIConnectContactViaAddress_Response = CR.SentInvitationToContact | CR.ChatCmdError
|
|
654
|
+
|
|
655
|
+
|
|
556
656
|
# Accept contact request.
|
|
557
657
|
# Network usage: interactive.
|
|
558
658
|
class APIAcceptContact(TypedDict):
|
|
@@ -622,6 +722,59 @@ def APIGetChats_cmd_string(self: APIGetChats) -> str:
|
|
|
622
722
|
APIGetChats_Response = CR.ApiChats | CR.ChatCmdError
|
|
623
723
|
|
|
624
724
|
|
|
725
|
+
# Get chat messages.
|
|
726
|
+
# Network usage: no.
|
|
727
|
+
class APIGetChat(TypedDict):
|
|
728
|
+
chatRef: "T.ChatRef"
|
|
729
|
+
contentTag: NotRequired["T.MsgContentTag"]
|
|
730
|
+
chatPagination: "T.ChatPagination"
|
|
731
|
+
search: NotRequired[str]
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
def APIGetChat_cmd_string(self: APIGetChat) -> str:
|
|
735
|
+
return '/_get chat ' + T.ChatRef_cmd_string(self['chatRef']) + ((' content=' + str(self.get('contentTag'))) if self.get('contentTag') is not None else '') + ' ' + T.ChatPagination_cmd_string(self['chatPagination']) + ((' search=' + self.get('search')) if self.get('search') is not None else '')
|
|
736
|
+
|
|
737
|
+
APIGetChat_Response = CR.ApiChat | CR.ChatCmdError
|
|
738
|
+
|
|
739
|
+
|
|
740
|
+
# Mark messages as read.
|
|
741
|
+
# Network usage: no.
|
|
742
|
+
class APIChatItemsRead(TypedDict):
|
|
743
|
+
chatRef: "T.ChatRef"
|
|
744
|
+
chatItemIds: list[int] # int64, non-empty
|
|
745
|
+
|
|
746
|
+
|
|
747
|
+
def APIChatItemsRead_cmd_string(self: APIChatItemsRead) -> str:
|
|
748
|
+
return '/_read chat items ' + T.ChatRef_cmd_string(self['chatRef']) + ' ' + ','.join(map(str, self['chatItemIds']))
|
|
749
|
+
|
|
750
|
+
APIChatItemsRead_Response = CR.ItemsReadForChat | CR.ChatCmdError
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
# Get contact information.
|
|
754
|
+
# Network usage: no.
|
|
755
|
+
class APIContactInfo(TypedDict):
|
|
756
|
+
contactId: int # int64
|
|
757
|
+
|
|
758
|
+
|
|
759
|
+
def APIContactInfo_cmd_string(self: APIContactInfo) -> str:
|
|
760
|
+
return '/_info @' + str(self['contactId'])
|
|
761
|
+
|
|
762
|
+
APIContactInfo_Response = CR.ContactInfo | CR.ChatCmdError
|
|
763
|
+
|
|
764
|
+
|
|
765
|
+
# Get message information.
|
|
766
|
+
# Network usage: no.
|
|
767
|
+
class APIGetChatItemInfo(TypedDict):
|
|
768
|
+
chatRef: "T.ChatRef"
|
|
769
|
+
chatItemId: int # int64
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
def APIGetChatItemInfo_cmd_string(self: APIGetChatItemInfo) -> str:
|
|
773
|
+
return '/_get item info ' + T.ChatRef_cmd_string(self['chatRef']) + ' ' + str(self['chatItemId'])
|
|
774
|
+
|
|
775
|
+
APIGetChatItemInfo_Response = CR.ChatItemInfo | CR.ChatCmdError
|
|
776
|
+
|
|
777
|
+
|
|
625
778
|
# Delete chat.
|
|
626
779
|
# Network usage: background.
|
|
627
780
|
class APIDeleteChat(TypedDict):
|
|
@@ -825,6 +978,42 @@ def APIStopChat_cmd_string(self: APIStopChat) -> str:
|
|
|
825
978
|
APIStopChat_Response = CR.ChatStopped
|
|
826
979
|
|
|
827
980
|
|
|
981
|
+
# Get network configuration.
|
|
982
|
+
# Network usage: no.
|
|
983
|
+
class APIGetNetworkConfig(TypedDict):
|
|
984
|
+
pass
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
def APIGetNetworkConfig_cmd_string(self: APIGetNetworkConfig) -> str:
|
|
988
|
+
return '/network'
|
|
989
|
+
|
|
990
|
+
APIGetNetworkConfig_Response = CR.NetworkConfig | CR.ChatCmdError
|
|
991
|
+
|
|
992
|
+
|
|
993
|
+
# Set network configuration.
|
|
994
|
+
# Network usage: background.
|
|
995
|
+
class APISetNetworkConfig(TypedDict):
|
|
996
|
+
networkConfig: "T.NetworkConfig"
|
|
997
|
+
|
|
998
|
+
|
|
999
|
+
def APISetNetworkConfig_cmd_string(self: APISetNetworkConfig) -> str:
|
|
1000
|
+
return '/_network ' + json.dumps(self['networkConfig'])
|
|
1001
|
+
|
|
1002
|
+
APISetNetworkConfig_Response = CR.CmdOk | CR.ChatCmdError
|
|
1003
|
+
|
|
1004
|
+
|
|
1005
|
+
# Get user servers and chat relays, grouped by operator.
|
|
1006
|
+
# Network usage: no.
|
|
1007
|
+
class APIGetUserServers(TypedDict):
|
|
1008
|
+
userId: int # int64
|
|
1009
|
+
|
|
1010
|
+
|
|
1011
|
+
def APIGetUserServers_cmd_string(self: APIGetUserServers) -> str:
|
|
1012
|
+
return '/_servers ' + str(self['userId'])
|
|
1013
|
+
|
|
1014
|
+
APIGetUserServers_Response = CR.UserServers | CR.ChatCmdError
|
|
1015
|
+
|
|
1016
|
+
|
|
828
1017
|
# Remote control commands
|
|
829
1018
|
# Allows a bot to accept an incoming remote control session from a SimpleX Desktop client, giving the desktop live access to the bot's SimpleX instance.
|
|
830
1019
|
|
|
@@ -13,6 +13,18 @@ class ActiveUser(TypedDict):
|
|
|
13
13
|
type: Literal["activeUser"]
|
|
14
14
|
user: "T.User"
|
|
15
15
|
|
|
16
|
+
class ApiChat(TypedDict):
|
|
17
|
+
type: Literal["apiChat"]
|
|
18
|
+
user: "T.User"
|
|
19
|
+
chat: "T.AChat"
|
|
20
|
+
navInfo: NotRequired["T.NavigationInfo"]
|
|
21
|
+
|
|
22
|
+
class ChatItemInfo(TypedDict):
|
|
23
|
+
type: Literal["chatItemInfo"]
|
|
24
|
+
user: "T.User"
|
|
25
|
+
chatItem: "T.AChatItem"
|
|
26
|
+
chatItemInfo: "T.ChatItemInfo"
|
|
27
|
+
|
|
16
28
|
class ChatItemNotChanged(TypedDict):
|
|
17
29
|
type: Literal["chatItemNotChanged"]
|
|
18
30
|
user: "T.User"
|
|
@@ -81,6 +93,13 @@ class ContactDeleted(TypedDict):
|
|
|
81
93
|
user: "T.User"
|
|
82
94
|
contact: "T.Contact"
|
|
83
95
|
|
|
96
|
+
class ContactInfo(TypedDict):
|
|
97
|
+
type: Literal["contactInfo"]
|
|
98
|
+
user: "T.User"
|
|
99
|
+
contact: "T.Contact"
|
|
100
|
+
connectionStats_: NotRequired["T.ConnectionStats"]
|
|
101
|
+
customUserProfile: NotRequired["T.Profile"]
|
|
102
|
+
|
|
84
103
|
class ContactPrefsUpdated(TypedDict):
|
|
85
104
|
type: Literal["contactPrefsUpdated"]
|
|
86
105
|
user: "T.User"
|
|
@@ -192,6 +211,11 @@ class Invitation(TypedDict):
|
|
|
192
211
|
connLinkInvitation: "T.CreatedConnLink"
|
|
193
212
|
connection: "T.PendingContactConnection"
|
|
194
213
|
|
|
214
|
+
class ItemsReadForChat(TypedDict):
|
|
215
|
+
type: Literal["itemsReadForChat"]
|
|
216
|
+
user: "T.User"
|
|
217
|
+
chatInfo: "T.ChatInfo"
|
|
218
|
+
|
|
195
219
|
class LeftMemberUser(TypedDict):
|
|
196
220
|
type: Literal["leftMemberUser"]
|
|
197
221
|
user: "T.User"
|
|
@@ -219,11 +243,34 @@ class MembersRoleUser(TypedDict):
|
|
|
219
243
|
toRole: "T.GroupMemberRole"
|
|
220
244
|
msgSigned: bool
|
|
221
245
|
|
|
246
|
+
class NetworkConfig(TypedDict):
|
|
247
|
+
type: Literal["networkConfig"]
|
|
248
|
+
networkConfig: "T.NetworkConfig"
|
|
249
|
+
|
|
222
250
|
class NewChatItems(TypedDict):
|
|
223
251
|
type: Literal["newChatItems"]
|
|
224
252
|
user: "T.User"
|
|
225
253
|
chatItems: list["T.AChatItem"]
|
|
226
254
|
|
|
255
|
+
class NewMemberContact(TypedDict):
|
|
256
|
+
type: Literal["newMemberContact"]
|
|
257
|
+
user: "T.User"
|
|
258
|
+
contact: "T.Contact"
|
|
259
|
+
groupInfo: "T.GroupInfo"
|
|
260
|
+
member: "T.GroupMember"
|
|
261
|
+
|
|
262
|
+
class NewMemberContactSentInv(TypedDict):
|
|
263
|
+
type: Literal["newMemberContactSentInv"]
|
|
264
|
+
user: "T.User"
|
|
265
|
+
contact: "T.Contact"
|
|
266
|
+
groupInfo: "T.GroupInfo"
|
|
267
|
+
member: "T.GroupMember"
|
|
268
|
+
|
|
269
|
+
class NewPreparedChat(TypedDict):
|
|
270
|
+
type: Literal["newPreparedChat"]
|
|
271
|
+
user: "T.User"
|
|
272
|
+
chat: "T.AChat"
|
|
273
|
+
|
|
227
274
|
class RcvFileAccepted(TypedDict):
|
|
228
275
|
type: Literal["rcvFileAccepted"]
|
|
229
276
|
user: "T.User"
|
|
@@ -353,6 +400,11 @@ class UserProfileNoChange(TypedDict):
|
|
|
353
400
|
type: Literal["userProfileNoChange"]
|
|
354
401
|
user: "T.User"
|
|
355
402
|
|
|
403
|
+
class UserServers(TypedDict):
|
|
404
|
+
type: Literal["userServers"]
|
|
405
|
+
user: "T.User"
|
|
406
|
+
userServers: list["T.UserOperatorServers"]
|
|
407
|
+
|
|
356
408
|
class UsersList(TypedDict):
|
|
357
409
|
type: Literal["usersList"]
|
|
358
410
|
users: list["T.UserInfo"]
|
|
@@ -365,6 +417,8 @@ class ApiChats(TypedDict):
|
|
|
365
417
|
ChatResponse = (
|
|
366
418
|
AcceptingContactRequest
|
|
367
419
|
| ActiveUser
|
|
420
|
+
| ApiChat
|
|
421
|
+
| ChatItemInfo
|
|
368
422
|
| ChatItemNotChanged
|
|
369
423
|
| ChatItemReaction
|
|
370
424
|
| ChatItemUpdated
|
|
@@ -379,6 +433,7 @@ ChatResponse = (
|
|
|
379
433
|
| ContactAlreadyExists
|
|
380
434
|
| ContactConnectionDeleted
|
|
381
435
|
| ContactDeleted
|
|
436
|
+
| ContactInfo
|
|
382
437
|
| ContactPrefsUpdated
|
|
383
438
|
| ContactRequestRejected
|
|
384
439
|
| ContactsList
|
|
@@ -398,11 +453,16 @@ ChatResponse = (
|
|
|
398
453
|
| GroupsList
|
|
399
454
|
| GroupDomainVerified
|
|
400
455
|
| Invitation
|
|
456
|
+
| ItemsReadForChat
|
|
401
457
|
| LeftMemberUser
|
|
402
458
|
| MemberAccepted
|
|
403
459
|
| MembersBlockedForAllUser
|
|
404
460
|
| MembersRoleUser
|
|
461
|
+
| NetworkConfig
|
|
405
462
|
| NewChatItems
|
|
463
|
+
| NewMemberContact
|
|
464
|
+
| NewMemberContactSentInv
|
|
465
|
+
| NewPreparedChat
|
|
406
466
|
| RcvFileAccepted
|
|
407
467
|
| RcvFileAcceptedSndCancelled
|
|
408
468
|
| RcvFileCancelled
|
|
@@ -425,8 +485,9 @@ ChatResponse = (
|
|
|
425
485
|
| UserDeletedMembers
|
|
426
486
|
| UserProfileUpdated
|
|
427
487
|
| UserProfileNoChange
|
|
488
|
+
| UserServers
|
|
428
489
|
| UsersList
|
|
429
490
|
| ApiChats
|
|
430
491
|
)
|
|
431
492
|
|
|
432
|
-
ChatResponse_Tag = Literal["acceptingContactRequest", "activeUser", "chatItemNotChanged", "chatItemReaction", "chatItemUpdated", "chatItemsDeleted", "chatMsgContent", "chatRunning", "chatStarted", "chatStopped", "cmdOk", "chatCmdError", "connectionPlan", "contactAlreadyExists", "contactConnectionDeleted", "contactDeleted", "contactPrefsUpdated", "contactRequestRejected", "contactsList", "groupDeletedUser", "groupLink", "groupLinkCreated", "groupLinkDeleted", "groupCreated", "publicGroupCreated", "publicGroupCreationFailed", "groupRelays", "groupRelaysAdded", "groupRelaysAddFailed", "relayGroupAllowed", "groupMembers", "groupUpdated", "groupsList", "groupDomainVerified", "invitation", "leftMemberUser", "memberAccepted", "membersBlockedForAllUser", "membersRoleUser", "newChatItems", "rcvFileAccepted", "rcvFileAcceptedSndCancelled", "rcvFileCancelled", "remoteCtrlConnected", "remoteCtrlConnecting", "sentConfirmation", "sentGroupInvitation", "sentGroupInvitationViaGroup", "sentInvitation", "sentInvitationToContact", "serviceReplyAccepted", "sndFileCancelled", "startedConnectionToContact", "startedConnectionToGroup", "userAcceptedGroupSent", "userContactLink", "userContactLinkCreated", "userContactLinkDeleted", "userContactLinkUpdated", "userDeletedMembers", "userProfileUpdated", "userProfileNoChange", "usersList", "apiChats"]
|
|
493
|
+
ChatResponse_Tag = Literal["acceptingContactRequest", "activeUser", "apiChat", "chatItemInfo", "chatItemNotChanged", "chatItemReaction", "chatItemUpdated", "chatItemsDeleted", "chatMsgContent", "chatRunning", "chatStarted", "chatStopped", "cmdOk", "chatCmdError", "connectionPlan", "contactAlreadyExists", "contactConnectionDeleted", "contactDeleted", "contactInfo", "contactPrefsUpdated", "contactRequestRejected", "contactsList", "groupDeletedUser", "groupLink", "groupLinkCreated", "groupLinkDeleted", "groupCreated", "publicGroupCreated", "publicGroupCreationFailed", "groupRelays", "groupRelaysAdded", "groupRelaysAddFailed", "relayGroupAllowed", "groupMembers", "groupUpdated", "groupsList", "groupDomainVerified", "invitation", "itemsReadForChat", "leftMemberUser", "memberAccepted", "membersBlockedForAllUser", "membersRoleUser", "networkConfig", "newChatItems", "newMemberContact", "newMemberContactSentInv", "newPreparedChat", "rcvFileAccepted", "rcvFileAcceptedSndCancelled", "rcvFileCancelled", "remoteCtrlConnected", "remoteCtrlConnecting", "sentConfirmation", "sentGroupInvitation", "sentGroupInvitationViaGroup", "sentInvitation", "sentInvitationToContact", "serviceReplyAccepted", "sndFileCancelled", "startedConnectionToContact", "startedConnectionToGroup", "userAcceptedGroupSent", "userContactLink", "userContactLinkCreated", "userContactLinkDeleted", "userContactLinkUpdated", "userDeletedMembers", "userProfileUpdated", "userProfileNoChange", "userServers", "usersList", "apiChats"]
|