mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-11-07 12:28:05 +00:00
Merge branch 'master' into ep/link-notices
This commit is contained in:
commit
2a86c24a57
1320 files changed
+121675
-7495
No files matched your search
@@ -7,6 +7,7 @@ from __future__ import annotations
|
||||
|
||||
import ctypes
|
||||
import errno
|
||||
import hashlib
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
@@ -18,7 +19,7 @@ from ctypes import POINTER, c_char_p, c_int, c_uint8, c_void_p
|
||||
from pathlib import Path
|
||||
from typing import Any, Literal
|
||||
|
||||
from ._version import LIBS_VERSION
|
||||
from ._version import LIBS_RELEASE, LIBS_SHA256
|
||||
|
||||
Backend = Literal["sqlite", "postgres"]
|
||||
|
||||
@@ -59,11 +60,14 @@ def _libname() -> str:
|
||||
return _LIBNAME[sys.platform]
|
||||
|
||||
|
||||
def _libs_url(backend: Backend) -> str:
|
||||
def _libs_asset(backend: Backend) -> str:
|
||||
suffix = "-postgres" if backend == "postgres" else ""
|
||||
return f"simplex-chat-libs-{_platform_tag()}{suffix}.zip"
|
||||
|
||||
|
||||
def _libs_url(backend: Backend) -> str:
|
||||
return (
|
||||
f"https://github.com/{_GITHUB_REPO}/releases/download/"
|
||||
f"v{LIBS_VERSION}/simplex-chat-libs-{_platform_tag()}{suffix}.zip"
|
||||
f"https://github.com/{_GITHUB_REPO}/releases/download/{LIBS_RELEASE}/{_libs_asset(backend)}"
|
||||
)
|
||||
|
||||
|
||||
@@ -84,7 +88,7 @@ def _resolve_libs_dir(backend: Backend) -> Path:
|
||||
"postgres backend is only supported on linux-x86_64; "
|
||||
f"current platform is {_platform_tag()}"
|
||||
)
|
||||
target = _cache_root() / f"v{LIBS_VERSION}" / backend
|
||||
target = _cache_root() / LIBS_RELEASE / backend
|
||||
if not (target / _libname()).exists():
|
||||
_download(target, backend)
|
||||
return target
|
||||
@@ -125,16 +129,21 @@ def _download(target: Path, backend: Backend) -> None:
|
||||
what we need and proceed. NEVER rmtree the target: that creates a TOCTOU
|
||||
window where another process is reading/loading the file we're deleting.
|
||||
"""
|
||||
asset = _libs_asset(backend)
|
||||
sha256 = LIBS_SHA256.get(asset)
|
||||
if sha256 is None:
|
||||
raise RuntimeError(f"no SHA-256 is pinned for {asset}")
|
||||
target.parent.mkdir(parents=True, exist_ok=True)
|
||||
url = _libs_url(backend)
|
||||
print(
|
||||
f"Downloading libsimplex ({_platform_tag()}, {backend}) v{LIBS_VERSION} from {url} ...",
|
||||
f"Downloading libsimplex ({_platform_tag()}, {backend}) {LIBS_RELEASE} from {url} ...",
|
||||
file=sys.stderr,
|
||||
flush=True,
|
||||
)
|
||||
with tempfile.TemporaryDirectory(dir=target.parent) as tmp:
|
||||
zip_path = Path(tmp) / "libs.zip"
|
||||
_stream_to_file(url, zip_path, timeout=60.0)
|
||||
_verify_sha256(zip_path, sha256, url)
|
||||
with zipfile.ZipFile(zip_path) as zf:
|
||||
zf.extractall(tmp)
|
||||
# zip layout: <tmp>/libs/libsimplex.* + libHS*.*
|
||||
@@ -158,6 +167,16 @@ def _download(target: Path, backend: Backend) -> None:
|
||||
) from e
|
||||
|
||||
|
||||
def _verify_sha256(file: Path, expected: str, url: str) -> None:
|
||||
digest = hashlib.sha256()
|
||||
with file.open("rb") as f:
|
||||
while chunk := f.read(_DOWNLOAD_CHUNK):
|
||||
digest.update(chunk)
|
||||
actual = digest.hexdigest()
|
||||
if actual != expected:
|
||||
raise RuntimeError(f"SHA-256 of {url} is {actual}, expected {expected}")
|
||||
|
||||
|
||||
_lock = threading.Lock()
|
||||
_lib: ctypes.CDLL | None = None
|
||||
_libc: ctypes.CDLL | None = None
|
||||
@@ -230,8 +249,8 @@ def lib_for(backend: Backend) -> ctypes.CDLL:
|
||||
if _lib is not None:
|
||||
if _backend != backend:
|
||||
raise RuntimeError(
|
||||
f"libsimplex already loaded with backend={_backend!r}; "
|
||||
f"cannot switch to {backend!r} in the same process"
|
||||
f"libsimplex already loaded with backend={_backend}; "
|
||||
f"cannot switch to {backend} in the same process"
|
||||
)
|
||||
return _lib
|
||||
libs_dir = _resolve_libs_dir(backend)
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
"""Single source of truth for both the Python package version and the
|
||||
simplex-chat-libs release tag we depend on.
|
||||
"""Package version and the simplex-chat-libs release it loads.
|
||||
|
||||
Bump both together for normal releases. For wrapper-only fixes use a PEP 440
|
||||
post-release: __version__ = "6.5.2.post1", LIBS_VERSION unchanged.
|
||||
Written by scripts/ci/packages_release.py prepare: it bumps the version
|
||||
and pins new library releases with the SHA-256 of their assets.
|
||||
"""
|
||||
|
||||
__version__ = "7.1.0b4" # PEP 440 — read by hatchling for wheel metadata
|
||||
LIBS_VERSION = "7.1.0-beta.4" # simplex-chat-libs release tag (no 'v' prefix)
|
||||
__version__ = "7.1.0b6.post2" # PEP 440 — read by hatchling for wheel metadata
|
||||
LIBS_RELEASE = "core-7.1.0.14" # simplex-chat-libs release tag
|
||||
LIBS_SHA256 = {
|
||||
"simplex-chat-libs-linux-aarch64.zip": "375a6021f0c2e5d79b2cd192e17c6c22c8eae73f46e3758fba24ee5c26a671aa",
|
||||
"simplex-chat-libs-linux-x86_64-postgres.zip": "c3e8a54d37801e685c6361c4e7e53e1f5163d3aa9195dcfe686b6cf90e668ef3",
|
||||
"simplex-chat-libs-linux-x86_64.zip": "cc41ab9049d61be3b386d799fa9394f2870e8ae3b2b9b8745dd3f53ba99f211e",
|
||||
"simplex-chat-libs-macos-aarch64.zip": "ac3a46004f25976f71b3ead8a20b9a01c170fe12f125a0a6799ae97ea990f234",
|
||||
"simplex-chat-libs-macos-x86_64.zip": "0d85ffcccc3a6dfe3e0da18d0b7be9ef36ad27381f047ef66cfde67ee4a7e882",
|
||||
"simplex-chat-libs-windows-x86_64.zip": "f1d1c7efc333a5ec5328a5843c9d3c9ef038fb2886c0b60ac12e87a5c1e85bbd",
|
||||
}
|
||||
@@ -351,6 +351,23 @@ class ChatApi:
|
||||
return r["member"]
|
||||
raise ChatCommandError("error adding member", r)
|
||||
|
||||
async def api_add_member_via_group(
|
||||
self, group_id: int, via_group_id: int, group_member_id: int, member_role: T.GroupMemberRole
|
||||
) -> T.GroupMember:
|
||||
r = await self.send_chat_cmd(
|
||||
CC.APIAddMemberViaGroup_cmd_string(
|
||||
{
|
||||
"groupId": group_id,
|
||||
"viaGroupId": via_group_id,
|
||||
"groupMemberId": group_member_id,
|
||||
"memberRole": member_role,
|
||||
}
|
||||
)
|
||||
)
|
||||
if r["type"] == "sentGroupInvitationViaGroup":
|
||||
return r["member"]
|
||||
raise ChatCommandError("error adding member", r)
|
||||
|
||||
async def api_join_group(self, group_id: int) -> T.GroupInfo:
|
||||
r = await self.send_chat_cmd(CC.APIJoinGroup_cmd_string({"groupId": group_id}))
|
||||
if r["type"] == "userAcceptedGroupSent":
|
||||
|
||||
@@ -235,6 +235,21 @@ def APIAddMember_cmd_string(self: APIAddMember) -> str:
|
||||
APIAddMember_Response = CR.SentGroupInvitation | CR.ChatCmdError
|
||||
|
||||
|
||||
# Add member of another group to group. Requires bot to have Admin role in the group, and direct messages allowed for its role in another group.
|
||||
# Network usage: interactive.
|
||||
class APIAddMemberViaGroup(TypedDict):
|
||||
groupId: int # int64
|
||||
viaGroupId: int # int64
|
||||
groupMemberId: int # int64
|
||||
memberRole: "T.GroupMemberRole"
|
||||
|
||||
|
||||
def APIAddMemberViaGroup_cmd_string(self: APIAddMemberViaGroup) -> str:
|
||||
return '/_add #' + str(self['groupId']) + ' #' + str(self['viaGroupId']) + ' ' + str(self['groupMemberId']) + ' ' + str(self['memberRole'])
|
||||
|
||||
APIAddMemberViaGroup_Response = CR.SentGroupInvitationViaGroup | CR.ChatCmdError
|
||||
|
||||
|
||||
# Join group.
|
||||
# Network usage: interactive.
|
||||
class APIJoinGroup(TypedDict):
|
||||
|
||||
@@ -84,6 +84,15 @@ class ReceivedGroupInvitation(TypedDict):
|
||||
fromMemberRole: "T.GroupMemberRole"
|
||||
memberRole: "T.GroupMemberRole"
|
||||
|
||||
class ReceivedGroupInvitationViaGroup(TypedDict):
|
||||
type: Literal["receivedGroupInvitationViaGroup"]
|
||||
user: "T.User"
|
||||
groupInfo: "T.GroupInfo"
|
||||
viaGroupInfo: "T.GroupInfo"
|
||||
viaMember: "T.GroupMember"
|
||||
fromMemberRole: "T.GroupMemberRole"
|
||||
memberRole: "T.GroupMemberRole"
|
||||
|
||||
class UserJoinedGroup(TypedDict):
|
||||
type: Literal["userJoinedGroup"]
|
||||
user: "T.User"
|
||||
@@ -352,6 +361,7 @@ ChatEvent = (
|
||||
| GroupChatItemsDeleted
|
||||
| ChatItemsStatusesUpdated
|
||||
| ReceivedGroupInvitation
|
||||
| ReceivedGroupInvitationViaGroup
|
||||
| UserJoinedGroup
|
||||
| GroupUpdated
|
||||
| JoinedGroupMember
|
||||
@@ -394,7 +404,7 @@ ChatEvent = (
|
||||
| ChatErrors
|
||||
)
|
||||
|
||||
ChatEvent_Tag = Literal["contactConnected", "contactUpdated", "contactDeletedByContact", "receivedContactRequest", "newMemberContactReceivedInv", "contactSndReady", "newChatItems", "chatItemReaction", "chatItemsDeleted", "chatItemUpdated", "groupChatItemsDeleted", "chatItemsStatusesUpdated", "receivedGroupInvitation", "userJoinedGroup", "groupUpdated", "joinedGroupMember", "memberRole", "deletedMember", "leftMember", "deletedMemberUser", "groupDeleted", "connectedToGroupMember", "memberAcceptedByOther", "memberBlockedForAll", "groupMemberUpdated", "groupLinkDataUpdated", "groupRelayUpdated", "rcvFileDescrReady", "rcvFileComplete", "sndFileCompleteXFTP", "rcvFileStart", "rcvFileSndCancelled", "rcvFileAccepted", "rcvFileError", "rcvFileWarning", "sndFileError", "sndFileWarning", "acceptingContactRequest", "acceptingBusinessRequest", "contactConnecting", "businessLinkConnecting", "joinedGroupMemberConnecting", "groupLinkConnecting", "hostConnected", "hostDisconnected", "subscriptionStatus", "serviceRequest", "serviceReplySent", "remoteCtrlSessionCode", "remoteCtrlStopped", "messageError", "chatError", "chatErrors"]
|
||||
ChatEvent_Tag = Literal["contactConnected", "contactUpdated", "contactDeletedByContact", "receivedContactRequest", "newMemberContactReceivedInv", "contactSndReady", "newChatItems", "chatItemReaction", "chatItemsDeleted", "chatItemUpdated", "groupChatItemsDeleted", "chatItemsStatusesUpdated", "receivedGroupInvitation", "receivedGroupInvitationViaGroup", "userJoinedGroup", "groupUpdated", "joinedGroupMember", "memberRole", "deletedMember", "leftMember", "deletedMemberUser", "groupDeleted", "connectedToGroupMember", "memberAcceptedByOther", "memberBlockedForAll", "groupMemberUpdated", "groupLinkDataUpdated", "groupRelayUpdated", "rcvFileDescrReady", "rcvFileComplete", "sndFileCompleteXFTP", "rcvFileStart", "rcvFileSndCancelled", "rcvFileAccepted", "rcvFileError", "rcvFileWarning", "sndFileError", "sndFileWarning", "acceptingContactRequest", "acceptingBusinessRequest", "contactConnecting", "businessLinkConnecting", "joinedGroupMemberConnecting", "groupLinkConnecting", "hostConnected", "hostDisconnected", "subscriptionStatus", "serviceRequest", "serviceReplySent", "remoteCtrlSessionCode", "remoteCtrlStopped", "messageError", "chatError", "chatErrors"]
|
||||
|
||||
|
||||
class OnEventDecorator(Protocol):
|
||||
@@ -483,6 +493,12 @@ class OnEventDecorator(Protocol):
|
||||
Callable[["ReceivedGroupInvitation"], Awaitable[None]],
|
||||
]: ...
|
||||
|
||||
@overload
|
||||
def __call__(self, event: Literal["receivedGroupInvitationViaGroup"], /) -> Callable[
|
||||
[Callable[["ReceivedGroupInvitationViaGroup"], Awaitable[None]]],
|
||||
Callable[["ReceivedGroupInvitationViaGroup"], Awaitable[None]],
|
||||
]: ...
|
||||
|
||||
@overload
|
||||
def __call__(self, event: Literal["userJoinedGroup"], /) -> Callable[
|
||||
[Callable[["UserJoinedGroup"], Awaitable[None]]],
|
||||
|
||||
@@ -264,6 +264,14 @@ class SentGroupInvitation(TypedDict):
|
||||
contact: "T.Contact"
|
||||
member: "T.GroupMember"
|
||||
|
||||
class SentGroupInvitationViaGroup(TypedDict):
|
||||
type: Literal["sentGroupInvitationViaGroup"]
|
||||
user: "T.User"
|
||||
groupInfo: "T.GroupInfo"
|
||||
member: "T.GroupMember"
|
||||
viaGroupInfo: "T.GroupInfo"
|
||||
viaMember: "T.GroupMember"
|
||||
|
||||
class SentInvitation(TypedDict):
|
||||
type: Literal["sentInvitation"]
|
||||
user: "T.User"
|
||||
@@ -402,6 +410,7 @@ ChatResponse = (
|
||||
| RemoteCtrlConnecting
|
||||
| SentConfirmation
|
||||
| SentGroupInvitation
|
||||
| SentGroupInvitationViaGroup
|
||||
| SentInvitation
|
||||
| SentInvitationToContact
|
||||
| ServiceReplyAccepted
|
||||
@@ -420,4 +429,4 @@ ChatResponse = (
|
||||
| ApiChats
|
||||
)
|
||||
|
||||
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", "sentInvitation", "sentInvitationToContact", "serviceReplyAccepted", "sndFileCancelled", "startedConnectionToContact", "startedConnectionToGroup", "userAcceptedGroupSent", "userContactLink", "userContactLinkCreated", "userContactLinkDeleted", "userContactLinkUpdated", "userDeletedMembers", "userProfileUpdated", "userProfileNoChange", "usersList", "apiChats"]
|
||||
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"]
|
||||
@@ -188,6 +188,9 @@ class BadgeProof(TypedDict):
|
||||
class BadgeRedeemError_invalidCode(TypedDict):
|
||||
type: Literal["invalidCode"]
|
||||
|
||||
class BadgeRedeemError_invalidReceipt(TypedDict):
|
||||
type: Literal["invalidReceipt"]
|
||||
|
||||
class BadgeRedeemError_serviceNotConfigured(TypedDict):
|
||||
type: Literal["serviceNotConfigured"]
|
||||
|
||||
@@ -210,6 +213,7 @@ class BadgeRedeemError_credentialNotVerified(TypedDict):
|
||||
|
||||
BadgeRedeemError = (
|
||||
BadgeRedeemError_invalidCode
|
||||
| BadgeRedeemError_invalidReceipt
|
||||
| BadgeRedeemError_serviceNotConfigured
|
||||
| BadgeRedeemError_badgeActive
|
||||
| BadgeRedeemError_serviceError
|
||||
@@ -218,14 +222,85 @@ BadgeRedeemError = (
|
||||
| BadgeRedeemError_credentialNotVerified
|
||||
)
|
||||
|
||||
BadgeRedeemError_Tag = Literal["invalidCode", "serviceNotConfigured", "badgeActive", "serviceError", "invalidResponse", "unknownKeyIndex", "credentialNotVerified"]
|
||||
BadgeRedeemError_Tag = Literal["invalidCode", "invalidReceipt", "serviceNotConfigured", "badgeActive", "serviceError", "invalidResponse", "unknownKeyIndex", "credentialNotVerified"]
|
||||
|
||||
BadgeServiceErrorCode = Literal["bad_request", "unsupported_version", "unknown_purchase_key", "unknown_offer_id", "offer_disabled", "offer_mismatch", "product_unavailable", "payment_not_entitled", "payment_pending", "provider_unavailable", "rate_limited", "code_invalid", "code_used", "code_expired", "receipt_invalid", "receipt_used", "internal"]
|
||||
BadgeServiceErrorCode = Literal["bad_request", "unsupported_version", "unknown_purchase_key", "unknown_offer_id", "offer_disabled", "offer_mismatch", "product_unavailable", "payment_not_entitled", "payment_pending", "provider_unavailable", "provider_not_configured", "rate_limited", "code_invalid", "code_used", "code_expired", "receipt_invalid", "receipt_used", "test_purchase", "internal"]
|
||||
|
||||
BadgeStatus = Literal["active", "expired", "expiredOld", "failed", "unknownKey"]
|
||||
|
||||
BadgeType = Literal["supporter", "legend", "investor"]
|
||||
|
||||
class BlockToken_lineBreak(TypedDict):
|
||||
type: Literal["lineBreak"]
|
||||
|
||||
class BlockToken_softBreak(TypedDict):
|
||||
type: Literal["softBreak"]
|
||||
|
||||
class BlockToken_hardBreak(TypedDict):
|
||||
type: Literal["hardBreak"]
|
||||
|
||||
class BlockToken_paragraphBreak(TypedDict):
|
||||
type: Literal["paragraphBreak"]
|
||||
lineBreaks: int # int
|
||||
|
||||
class BlockToken_indent(TypedDict):
|
||||
type: Literal["indent"]
|
||||
|
||||
class BlockToken_headingMark(TypedDict):
|
||||
type: Literal["headingMark"]
|
||||
level: int # int
|
||||
|
||||
class BlockToken_headingClose(TypedDict):
|
||||
type: Literal["headingClose"]
|
||||
|
||||
class BlockToken_headingUnderline(TypedDict):
|
||||
type: Literal["headingUnderline"]
|
||||
level: int # int
|
||||
|
||||
class BlockToken_listMark(TypedDict):
|
||||
type: Literal["listMark"]
|
||||
number: NotRequired[str]
|
||||
|
||||
class BlockToken_quoteMark(TypedDict):
|
||||
type: Literal["quoteMark"]
|
||||
|
||||
class BlockToken_fenceMark(TypedDict):
|
||||
type: Literal["fenceMark"]
|
||||
language: NotRequired[str]
|
||||
|
||||
class BlockToken_rowMark(TypedDict):
|
||||
type: Literal["rowMark"]
|
||||
|
||||
class BlockToken_cellMark(TypedDict):
|
||||
type: Literal["cellMark"]
|
||||
|
||||
class BlockToken_delimiterRow(TypedDict):
|
||||
type: Literal["delimiterRow"]
|
||||
columns: list["TableAlign"]
|
||||
|
||||
class BlockToken_ruleMark(TypedDict):
|
||||
type: Literal["ruleMark"]
|
||||
|
||||
BlockToken = (
|
||||
BlockToken_lineBreak
|
||||
| BlockToken_softBreak
|
||||
| BlockToken_hardBreak
|
||||
| BlockToken_paragraphBreak
|
||||
| BlockToken_indent
|
||||
| BlockToken_headingMark
|
||||
| BlockToken_headingClose
|
||||
| BlockToken_headingUnderline
|
||||
| BlockToken_listMark
|
||||
| BlockToken_quoteMark
|
||||
| BlockToken_fenceMark
|
||||
| BlockToken_rowMark
|
||||
| BlockToken_cellMark
|
||||
| BlockToken_delimiterRow
|
||||
| BlockToken_ruleMark
|
||||
)
|
||||
|
||||
BlockToken_Tag = Literal["lineBreak", "softBreak", "hardBreak", "paragraphBreak", "indent", "headingMark", "headingClose", "headingUnderline", "listMark", "quoteMark", "fenceMark", "rowMark", "cellMark", "delimiterRow", "ruleMark"]
|
||||
|
||||
class BlockingInfo(TypedDict):
|
||||
reason: "BlockingReason"
|
||||
notice: NotRequired["ClientNotice"]
|
||||
@@ -688,6 +763,7 @@ class CIQuote(TypedDict):
|
||||
sentAt: str # ISO-8601 timestamp
|
||||
content: "MsgContent"
|
||||
formattedText: NotRequired[list["FormattedText"]]
|
||||
markdownBlocks: NotRequired[list["MarkdownBlock"]] # non-empty
|
||||
|
||||
class CIReaction(TypedDict):
|
||||
chatDir: "CIDirection"
|
||||
@@ -1226,6 +1302,7 @@ class ChatItem(TypedDict):
|
||||
content: "CIContent"
|
||||
mentions: dict[str, "CIMention"]
|
||||
formattedText: NotRequired[list["FormattedText"]]
|
||||
markdownBlocks: NotRequired[list["MarkdownBlock"]] # non-empty
|
||||
quotedItem: NotRequired["CIQuote"]
|
||||
reactions: list["CIReactionCount"]
|
||||
file: NotRequired["CIFile"]
|
||||
@@ -1249,7 +1326,7 @@ ChatListQuery = ChatListQuery_filters | ChatListQuery_search
|
||||
|
||||
ChatListQuery_Tag = Literal["filters", "search"]
|
||||
|
||||
ChatPeerType = Literal["human", "bot", "business"]
|
||||
ChatPeerType = Literal["human", "bot", "business", "agent"]
|
||||
|
||||
# Used in API commands. Chat scope can only be passed with groups.
|
||||
|
||||
@@ -1803,8 +1880,11 @@ class FileTransferMeta(TypedDict):
|
||||
|
||||
FileType = Literal["normal", "roster"]
|
||||
|
||||
# The format markup is a token of block Markdown syntax; its text is the syntax. The format escape is the backslash of a backslash escape. Bold singleStar: written with single stars.
|
||||
|
||||
class Format_bold(TypedDict):
|
||||
type: Literal["bold"]
|
||||
singleStar: bool
|
||||
|
||||
class Format_italic(TypedDict):
|
||||
type: Literal["italic"]
|
||||
@@ -1858,6 +1938,13 @@ class Format_email(TypedDict):
|
||||
class Format_phone(TypedDict):
|
||||
type: Literal["phone"]
|
||||
|
||||
class Format_escape(TypedDict):
|
||||
type: Literal["escape"]
|
||||
|
||||
class Format_markup(TypedDict):
|
||||
type: Literal["markup"]
|
||||
token: "BlockToken"
|
||||
|
||||
Format = (
|
||||
Format_bold
|
||||
| Format_italic
|
||||
@@ -1874,9 +1961,11 @@ Format = (
|
||||
| Format_mention
|
||||
| Format_email
|
||||
| Format_phone
|
||||
| Format_escape
|
||||
| Format_markup
|
||||
)
|
||||
|
||||
Format_Tag = Literal["bold", "italic", "strikeThrough", "snippet", "secret", "small", "colored", "uri", "hyperLink", "simplexLink", "simplexName", "command", "mention", "email", "phone"]
|
||||
Format_Tag = Literal["bold", "italic", "strikeThrough", "snippet", "secret", "small", "colored", "uri", "hyperLink", "simplexLink", "simplexName", "command", "mention", "email", "phone", "escape", "markup"]
|
||||
|
||||
class FormattedText(TypedDict):
|
||||
format: NotRequired["Format"]
|
||||
@@ -2209,6 +2298,11 @@ class LinkPreview(TypedDict):
|
||||
image: str
|
||||
content: NotRequired["LinkContent"]
|
||||
|
||||
class ListEntry(TypedDict):
|
||||
number: NotRequired[str]
|
||||
content: "SegmentRange"
|
||||
items: list["ListEntry"]
|
||||
|
||||
class LocalBadge(TypedDict):
|
||||
badge: "BadgeInfo"
|
||||
status: "BadgeStatus"
|
||||
@@ -2228,6 +2322,50 @@ class LocalProfile(TypedDict):
|
||||
contactDomain: NotRequired["SimplexDomainClaim"]
|
||||
contactDomainVerified: NotRequired[bool]
|
||||
|
||||
class MarkdownBlock_paragraph(TypedDict):
|
||||
type: Literal["paragraph"]
|
||||
content: "SegmentRange"
|
||||
|
||||
class MarkdownBlock_heading(TypedDict):
|
||||
type: Literal["heading"]
|
||||
level: int # int
|
||||
content: "SegmentRange"
|
||||
|
||||
class MarkdownBlock_codeBlock(TypedDict):
|
||||
type: Literal["codeBlock"]
|
||||
language: NotRequired[str]
|
||||
content: "SegmentRange"
|
||||
|
||||
class MarkdownBlock_quote(TypedDict):
|
||||
type: Literal["quote"]
|
||||
content: "SegmentRange"
|
||||
|
||||
class MarkdownBlock_list(TypedDict):
|
||||
type: Literal["list"]
|
||||
items: list["ListEntry"] # non-empty
|
||||
|
||||
class MarkdownBlock_table(TypedDict):
|
||||
type: Literal["table"]
|
||||
columns: list["TableAlign"] # non-empty
|
||||
header: list["SegmentRange"]
|
||||
rows: list[list["SegmentRange"]]
|
||||
|
||||
class MarkdownBlock_rule(TypedDict):
|
||||
type: Literal["rule"]
|
||||
mark: "SegmentRange"
|
||||
|
||||
MarkdownBlock = (
|
||||
MarkdownBlock_paragraph
|
||||
| MarkdownBlock_heading
|
||||
| MarkdownBlock_codeBlock
|
||||
| MarkdownBlock_quote
|
||||
| MarkdownBlock_list
|
||||
| MarkdownBlock_table
|
||||
| MarkdownBlock_rule
|
||||
)
|
||||
|
||||
MarkdownBlock_Tag = Literal["paragraph", "heading", "codeBlock", "quote", "list", "table", "rule"]
|
||||
|
||||
MemberCriteria = Literal["all"]
|
||||
|
||||
# Connection link sent in a message - only short links are allowed.
|
||||
@@ -2955,6 +3093,11 @@ class SecurityCode(TypedDict):
|
||||
securityCode: str
|
||||
verifiedAt: str # ISO-8601 timestamp
|
||||
|
||||
SegmentRange = TypedDict("SegmentRange", {
|
||||
"from": int, # int
|
||||
"to": int, # int
|
||||
})
|
||||
|
||||
class SimplePreference(TypedDict):
|
||||
allow: "FeatureAllowed"
|
||||
|
||||
@@ -3591,6 +3734,8 @@ class SupportGroupPreference(TypedDict):
|
||||
|
||||
SwitchPhase = Literal["started", "confirmed", "secured", "completed"]
|
||||
|
||||
TableAlign = Literal["none", "left", "center", "right"]
|
||||
|
||||
class TimedMessagesGroupPreference(TypedDict):
|
||||
enable: "GroupFeatureEnabled"
|
||||
ttl: NotRequired[int] # int
|
||||
|
||||
Reference in new issue
Block a user