mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-11-04 17:17:39 +00:00
bots, nodejs: document chat, connection, member contact and network commands, typed commands in library (#7808)
* bots, nodejs: document chat, connection, member contact and network commands, typed commands in library * bots, nodejs: restore apiConnect, wrap domain once, test all connect responses * nodejs: JSDoc for new methods * docs: plan for bot API commands and typed Node library methods * tests: channel prepared with a domain has a verified SimpleX name * docs: apply review fixes to the plan for bot API commands * docs: apply second review pass to the plan for bot API commands * docs: refer the bot API plan to the rewritten test commit * docs: record decisions in the plan for bot API commands * docs: plan tests of the generated Python command strings * python: test the generated strings of the documented commands * docs: plan the message information command for bots * bots, nodejs: message information with the file servers for bots * docs: plan the relay approval option of receiving files in Node * nodejs: receive files without approving unknown relays * docs: plan the user servers command for bots * bots, nodejs: user servers and relays by operator for bots * nodejs: document the message information method * docs: plan the file upload progress event for bots * bots: file upload progress event for bots * bots: drop the file upload progress event * docs: drop the upload progress event plan * nodejs: document user servers and relay approval of received files
This commit is contained in:
1 parent
d1b3da8410
commit
99b91696f7
34 files changed
+3716
-204
No files matched your search
@@ -342,6 +342,32 @@ def APIListMembers_cmd_string(self: APIListMembers) -> str:
|
||||
APIListMembers_Response = CR.GroupMembers | CR.ChatCmdError
|
||||
|
||||
|
||||
# Create a direct message contact with a group member.
|
||||
# Network usage: interactive.
|
||||
class APICreateMemberContact(TypedDict):
|
||||
groupId: int # int64
|
||||
groupMemberId: int # int64
|
||||
|
||||
|
||||
def APICreateMemberContact_cmd_string(self: APICreateMemberContact) -> str:
|
||||
return '/_create member contact #' + str(self['groupId']) + ' ' + str(self['groupMemberId'])
|
||||
|
||||
APICreateMemberContact_Response = CR.NewMemberContact | CR.ChatCmdError
|
||||
|
||||
|
||||
# Send a direct message invitation to a group member contact.
|
||||
# Network usage: background.
|
||||
class APISendMemberContactInvitation(TypedDict):
|
||||
contactId: int # int64
|
||||
msgContent_: NotRequired["T.MsgContent"]
|
||||
|
||||
|
||||
def APISendMemberContactInvitation_cmd_string(self: APISendMemberContactInvitation) -> str:
|
||||
return '/_invite member contact @' + str(self['contactId']) + ((' json ' + json.dumps(self.get('msgContent_'))) if self.get('msgContent_') is not None else '')
|
||||
|
||||
APISendMemberContactInvitation_Response = CR.NewMemberContactSentInv | CR.ChatCmdError
|
||||
|
||||
|
||||
# Create group.
|
||||
# Network usage: no.
|
||||
class APINewGroup(TypedDict):
|
||||
@@ -512,7 +538,7 @@ class APIConnectPlan(TypedDict):
|
||||
|
||||
|
||||
def APIConnectPlan_cmd_string(self: APIConnectPlan) -> str:
|
||||
return '/_connect plan ' + str(self['userId']) + ' ' + self.get('connectTarget')
|
||||
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 '')
|
||||
|
||||
APIConnectPlan_Response = CR.ConnectionPlan | CR.ChatCmdError
|
||||
|
||||
@@ -553,6 +579,80 @@ Connect_Response = (
|
||||
)
|
||||
|
||||
|
||||
# Prepare contact chat from link data before connecting.
|
||||
# Network usage: no.
|
||||
class APIPrepareContact(TypedDict):
|
||||
userId: int # int64
|
||||
connLink: "T.CreatedConnLink"
|
||||
verifiedDomain: NotRequired[str]
|
||||
contactSLinkData: "T.ContactShortLinkData"
|
||||
|
||||
|
||||
def APIPrepareContact_cmd_string(self: APIPrepareContact) -> str:
|
||||
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'])
|
||||
|
||||
APIPrepareContact_Response = CR.NewPreparedChat | CR.ChatCmdError
|
||||
|
||||
|
||||
# Prepare group chat from link data before connecting.
|
||||
# Network usage: no.
|
||||
class APIPrepareGroup(TypedDict):
|
||||
userId: int # int64
|
||||
connLinkContact: "T.CreatedConnLink"
|
||||
direct: bool
|
||||
verifiedDomain: NotRequired[str]
|
||||
groupSLinkData: "T.GroupShortLinkData"
|
||||
|
||||
|
||||
def APIPrepareGroup_cmd_string(self: APIPrepareGroup) -> str:
|
||||
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'])
|
||||
|
||||
APIPrepareGroup_Response = CR.NewPreparedChat | CR.ChatCmdError
|
||||
|
||||
|
||||
# Connect to prepared contact.
|
||||
# Network usage: interactive.
|
||||
class APIConnectPreparedContact(TypedDict):
|
||||
contactId: int # int64
|
||||
incognito: bool
|
||||
msgContent_: NotRequired["T.MsgContent"]
|
||||
|
||||
|
||||
def APIConnectPreparedContact_cmd_string(self: APIConnectPreparedContact) -> str:
|
||||
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 '')
|
||||
|
||||
APIConnectPreparedContact_Response = CR.StartedConnectionToContact | CR.ContactAlreadyExists | CR.ChatCmdError
|
||||
|
||||
|
||||
# Connect to prepared group.
|
||||
# Network usage: interactive.
|
||||
class APIConnectPreparedGroup(TypedDict):
|
||||
groupId: int # int64
|
||||
incognito: bool
|
||||
ownerContact: NotRequired["T.GroupOwnerContact"]
|
||||
msgContent_: NotRequired["T.MsgContent"]
|
||||
|
||||
|
||||
def APIConnectPreparedGroup_cmd_string(self: APIConnectPreparedGroup) -> str:
|
||||
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 '')
|
||||
|
||||
APIConnectPreparedGroup_Response = CR.StartedConnectionToGroup | CR.ChatCmdError
|
||||
|
||||
|
||||
# Connect to existing contact via address in its profile.
|
||||
# Network usage: interactive.
|
||||
class APIConnectContactViaAddress(TypedDict):
|
||||
userId: int # int64
|
||||
incognito: bool
|
||||
contactId: int # int64
|
||||
|
||||
|
||||
def APIConnectContactViaAddress_cmd_string(self: APIConnectContactViaAddress) -> str:
|
||||
return '/_connect contact ' + str(self['userId']) + (' incognito=on' if self['incognito'] else '') + ' ' + str(self['contactId'])
|
||||
|
||||
APIConnectContactViaAddress_Response = CR.SentInvitationToContact | CR.ChatCmdError
|
||||
|
||||
|
||||
# Accept contact request.
|
||||
# Network usage: interactive.
|
||||
class APIAcceptContact(TypedDict):
|
||||
@@ -622,6 +722,59 @@ def APIGetChats_cmd_string(self: APIGetChats) -> str:
|
||||
APIGetChats_Response = CR.ApiChats | CR.ChatCmdError
|
||||
|
||||
|
||||
# Get chat messages.
|
||||
# Network usage: no.
|
||||
class APIGetChat(TypedDict):
|
||||
chatRef: "T.ChatRef"
|
||||
contentTag: NotRequired["T.MsgContentTag"]
|
||||
chatPagination: "T.ChatPagination"
|
||||
search: NotRequired[str]
|
||||
|
||||
|
||||
def APIGetChat_cmd_string(self: APIGetChat) -> str:
|
||||
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 '')
|
||||
|
||||
APIGetChat_Response = CR.ApiChat | CR.ChatCmdError
|
||||
|
||||
|
||||
# Mark messages as read.
|
||||
# Network usage: no.
|
||||
class APIChatItemsRead(TypedDict):
|
||||
chatRef: "T.ChatRef"
|
||||
chatItemIds: list[int] # int64, non-empty
|
||||
|
||||
|
||||
def APIChatItemsRead_cmd_string(self: APIChatItemsRead) -> str:
|
||||
return '/_read chat items ' + T.ChatRef_cmd_string(self['chatRef']) + ' ' + ','.join(map(str, self['chatItemIds']))
|
||||
|
||||
APIChatItemsRead_Response = CR.ItemsReadForChat | CR.ChatCmdError
|
||||
|
||||
|
||||
# Get contact information.
|
||||
# Network usage: no.
|
||||
class APIContactInfo(TypedDict):
|
||||
contactId: int # int64
|
||||
|
||||
|
||||
def APIContactInfo_cmd_string(self: APIContactInfo) -> str:
|
||||
return '/_info @' + str(self['contactId'])
|
||||
|
||||
APIContactInfo_Response = CR.ContactInfo | CR.ChatCmdError
|
||||
|
||||
|
||||
# Get message information.
|
||||
# Network usage: no.
|
||||
class APIGetChatItemInfo(TypedDict):
|
||||
chatRef: "T.ChatRef"
|
||||
chatItemId: int # int64
|
||||
|
||||
|
||||
def APIGetChatItemInfo_cmd_string(self: APIGetChatItemInfo) -> str:
|
||||
return '/_get item info ' + T.ChatRef_cmd_string(self['chatRef']) + ' ' + str(self['chatItemId'])
|
||||
|
||||
APIGetChatItemInfo_Response = CR.ChatItemInfo | CR.ChatCmdError
|
||||
|
||||
|
||||
# Delete chat.
|
||||
# Network usage: background.
|
||||
class APIDeleteChat(TypedDict):
|
||||
@@ -825,6 +978,42 @@ def APIStopChat_cmd_string(self: APIStopChat) -> str:
|
||||
APIStopChat_Response = CR.ChatStopped
|
||||
|
||||
|
||||
# Get network configuration.
|
||||
# Network usage: no.
|
||||
class APIGetNetworkConfig(TypedDict):
|
||||
pass
|
||||
|
||||
|
||||
def APIGetNetworkConfig_cmd_string(self: APIGetNetworkConfig) -> str:
|
||||
return '/network'
|
||||
|
||||
APIGetNetworkConfig_Response = CR.NetworkConfig | CR.ChatCmdError
|
||||
|
||||
|
||||
# Set network configuration.
|
||||
# Network usage: background.
|
||||
class APISetNetworkConfig(TypedDict):
|
||||
networkConfig: "T.NetworkConfig"
|
||||
|
||||
|
||||
def APISetNetworkConfig_cmd_string(self: APISetNetworkConfig) -> str:
|
||||
return '/_network ' + json.dumps(self['networkConfig'])
|
||||
|
||||
APISetNetworkConfig_Response = CR.CmdOk | CR.ChatCmdError
|
||||
|
||||
|
||||
# Get user servers and chat relays, grouped by operator.
|
||||
# Network usage: no.
|
||||
class APIGetUserServers(TypedDict):
|
||||
userId: int # int64
|
||||
|
||||
|
||||
def APIGetUserServers_cmd_string(self: APIGetUserServers) -> str:
|
||||
return '/_servers ' + str(self['userId'])
|
||||
|
||||
APIGetUserServers_Response = CR.UserServers | CR.ChatCmdError
|
||||
|
||||
|
||||
# Remote control commands
|
||||
# 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.
|
||||
|
||||
|
||||
@@ -13,6 +13,18 @@ class ActiveUser(TypedDict):
|
||||
type: Literal["activeUser"]
|
||||
user: "T.User"
|
||||
|
||||
class ApiChat(TypedDict):
|
||||
type: Literal["apiChat"]
|
||||
user: "T.User"
|
||||
chat: "T.AChat"
|
||||
navInfo: NotRequired["T.NavigationInfo"]
|
||||
|
||||
class ChatItemInfo(TypedDict):
|
||||
type: Literal["chatItemInfo"]
|
||||
user: "T.User"
|
||||
chatItem: "T.AChatItem"
|
||||
chatItemInfo: "T.ChatItemInfo"
|
||||
|
||||
class ChatItemNotChanged(TypedDict):
|
||||
type: Literal["chatItemNotChanged"]
|
||||
user: "T.User"
|
||||
@@ -81,6 +93,13 @@ class ContactDeleted(TypedDict):
|
||||
user: "T.User"
|
||||
contact: "T.Contact"
|
||||
|
||||
class ContactInfo(TypedDict):
|
||||
type: Literal["contactInfo"]
|
||||
user: "T.User"
|
||||
contact: "T.Contact"
|
||||
connectionStats_: NotRequired["T.ConnectionStats"]
|
||||
customUserProfile: NotRequired["T.Profile"]
|
||||
|
||||
class ContactPrefsUpdated(TypedDict):
|
||||
type: Literal["contactPrefsUpdated"]
|
||||
user: "T.User"
|
||||
@@ -192,6 +211,11 @@ class Invitation(TypedDict):
|
||||
connLinkInvitation: "T.CreatedConnLink"
|
||||
connection: "T.PendingContactConnection"
|
||||
|
||||
class ItemsReadForChat(TypedDict):
|
||||
type: Literal["itemsReadForChat"]
|
||||
user: "T.User"
|
||||
chatInfo: "T.ChatInfo"
|
||||
|
||||
class LeftMemberUser(TypedDict):
|
||||
type: Literal["leftMemberUser"]
|
||||
user: "T.User"
|
||||
@@ -219,11 +243,34 @@ class MembersRoleUser(TypedDict):
|
||||
toRole: "T.GroupMemberRole"
|
||||
msgSigned: bool
|
||||
|
||||
class NetworkConfig(TypedDict):
|
||||
type: Literal["networkConfig"]
|
||||
networkConfig: "T.NetworkConfig"
|
||||
|
||||
class NewChatItems(TypedDict):
|
||||
type: Literal["newChatItems"]
|
||||
user: "T.User"
|
||||
chatItems: list["T.AChatItem"]
|
||||
|
||||
class NewMemberContact(TypedDict):
|
||||
type: Literal["newMemberContact"]
|
||||
user: "T.User"
|
||||
contact: "T.Contact"
|
||||
groupInfo: "T.GroupInfo"
|
||||
member: "T.GroupMember"
|
||||
|
||||
class NewMemberContactSentInv(TypedDict):
|
||||
type: Literal["newMemberContactSentInv"]
|
||||
user: "T.User"
|
||||
contact: "T.Contact"
|
||||
groupInfo: "T.GroupInfo"
|
||||
member: "T.GroupMember"
|
||||
|
||||
class NewPreparedChat(TypedDict):
|
||||
type: Literal["newPreparedChat"]
|
||||
user: "T.User"
|
||||
chat: "T.AChat"
|
||||
|
||||
class RcvFileAccepted(TypedDict):
|
||||
type: Literal["rcvFileAccepted"]
|
||||
user: "T.User"
|
||||
@@ -353,6 +400,11 @@ class UserProfileNoChange(TypedDict):
|
||||
type: Literal["userProfileNoChange"]
|
||||
user: "T.User"
|
||||
|
||||
class UserServers(TypedDict):
|
||||
type: Literal["userServers"]
|
||||
user: "T.User"
|
||||
userServers: list["T.UserOperatorServers"]
|
||||
|
||||
class UsersList(TypedDict):
|
||||
type: Literal["usersList"]
|
||||
users: list["T.UserInfo"]
|
||||
@@ -365,6 +417,8 @@ class ApiChats(TypedDict):
|
||||
ChatResponse = (
|
||||
AcceptingContactRequest
|
||||
| ActiveUser
|
||||
| ApiChat
|
||||
| ChatItemInfo
|
||||
| ChatItemNotChanged
|
||||
| ChatItemReaction
|
||||
| ChatItemUpdated
|
||||
@@ -379,6 +433,7 @@ ChatResponse = (
|
||||
| ContactAlreadyExists
|
||||
| ContactConnectionDeleted
|
||||
| ContactDeleted
|
||||
| ContactInfo
|
||||
| ContactPrefsUpdated
|
||||
| ContactRequestRejected
|
||||
| ContactsList
|
||||
@@ -398,11 +453,16 @@ ChatResponse = (
|
||||
| GroupsList
|
||||
| GroupDomainVerified
|
||||
| Invitation
|
||||
| ItemsReadForChat
|
||||
| LeftMemberUser
|
||||
| MemberAccepted
|
||||
| MembersBlockedForAllUser
|
||||
| MembersRoleUser
|
||||
| NetworkConfig
|
||||
| NewChatItems
|
||||
| NewMemberContact
|
||||
| NewMemberContactSentInv
|
||||
| NewPreparedChat
|
||||
| RcvFileAccepted
|
||||
| RcvFileAcceptedSndCancelled
|
||||
| RcvFileCancelled
|
||||
@@ -425,8 +485,9 @@ ChatResponse = (
|
||||
| UserDeletedMembers
|
||||
| UserProfileUpdated
|
||||
| UserProfileNoChange
|
||||
| UserServers
|
||||
| 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"]
|
||||
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"]
|
||||
@@ -1312,6 +1312,20 @@ class ChatItemDeletion(TypedDict):
|
||||
deletedChatItem: "AChatItem"
|
||||
toChatItem: NotRequired["AChatItem"]
|
||||
|
||||
class ChatItemInfo(TypedDict):
|
||||
itemVersions: list["ChatItemVersion"]
|
||||
memberDeliveryStatuses: NotRequired[list["MemberDeliveryStatus"]] # non-empty
|
||||
forwardedFromChatItem: NotRequired["AChatItem"]
|
||||
fileXftpServers: list[str]
|
||||
|
||||
class ChatItemVersion(TypedDict):
|
||||
chatItemVersionId: int # int64
|
||||
msgContent: "MsgContent"
|
||||
formattedText: NotRequired[list["FormattedText"]]
|
||||
markdownBlocks: NotRequired[list["MarkdownBlock"]] # non-empty
|
||||
itemVersionTs: str # ISO-8601 timestamp
|
||||
createdAt: str # ISO-8601 timestamp
|
||||
|
||||
ChatLayout = Literal["classic", "terminal"]
|
||||
|
||||
class ChatListQuery_filters(TypedDict):
|
||||
@@ -1327,6 +1341,43 @@ ChatListQuery = ChatListQuery_filters | ChatListQuery_search
|
||||
|
||||
ChatListQuery_Tag = Literal["filters", "search"]
|
||||
|
||||
class ChatPagination_last(TypedDict):
|
||||
type: Literal["last"]
|
||||
count: int # int
|
||||
|
||||
class ChatPagination_after(TypedDict):
|
||||
type: Literal["after"]
|
||||
chatItemId: int # int64
|
||||
count: int # int
|
||||
|
||||
class ChatPagination_before(TypedDict):
|
||||
type: Literal["before"]
|
||||
chatItemId: int # int64
|
||||
count: int # int
|
||||
|
||||
class ChatPagination_around(TypedDict):
|
||||
type: Literal["around"]
|
||||
chatItemId: int # int64
|
||||
count: int # int
|
||||
|
||||
class ChatPagination_initial(TypedDict):
|
||||
type: Literal["initial"]
|
||||
count: int # int
|
||||
|
||||
ChatPagination = (
|
||||
ChatPagination_last
|
||||
| ChatPagination_after
|
||||
| ChatPagination_before
|
||||
| ChatPagination_around
|
||||
| ChatPagination_initial
|
||||
)
|
||||
|
||||
ChatPagination_Tag = Literal["last", "after", "before", "around", "initial"]
|
||||
|
||||
|
||||
def ChatPagination_cmd_string(self: ChatPagination) -> str:
|
||||
return 'count=' + str(self['count']) if str(self['type']) == 'last' else 'after=' + str(self['chatItemId']) + ' count=' + str(self['count']) if str(self['type']) == 'after' else 'before=' + str(self['chatItemId']) + ' count=' + str(self['count']) if str(self['type']) == 'before' else 'around=' + str(self['chatItemId']) + ' count=' + str(self['count']) if str(self['type']) == 'around' else 'initial=' + str(self['count']) # type: ignore[typeddict-item]
|
||||
|
||||
ChatPeerType = Literal["human", "bot", "business", "agent"]
|
||||
|
||||
# Used in API commands. Chat scope can only be passed with groups.
|
||||
@@ -1437,6 +1488,19 @@ class ComposedMessage(TypedDict):
|
||||
msgContent: "MsgContent"
|
||||
mentions: dict[str, int] # str : int64
|
||||
|
||||
class ConditionsAcceptance_accepted(TypedDict):
|
||||
type: Literal["accepted"]
|
||||
acceptedAt: NotRequired[str] # ISO-8601 timestamp
|
||||
autoAccepted: bool
|
||||
|
||||
class ConditionsAcceptance_required(TypedDict):
|
||||
type: Literal["required"]
|
||||
deadline: NotRequired[str] # ISO-8601 timestamp
|
||||
|
||||
ConditionsAcceptance = ConditionsAcceptance_accepted | ConditionsAcceptance_required
|
||||
|
||||
ConditionsAcceptance_Tag = Literal["accepted", "required"]
|
||||
|
||||
class ConnStatus_new(TypedDict):
|
||||
type: Literal["new"]
|
||||
|
||||
@@ -1583,6 +1647,14 @@ ConnectionPlan = (
|
||||
|
||||
ConnectionPlan_Tag = Literal["invitationLink", "contactAddress", "groupLink", "error"]
|
||||
|
||||
class ConnectionStats(TypedDict):
|
||||
connAgentVersion: int # int
|
||||
rcvQueuesInfo: list["RcvQueueInfo"]
|
||||
sndQueuesInfo: list["SndQueueInfo"]
|
||||
ratchetSyncState: "RatchetSyncState"
|
||||
ratchetSyncSupported: bool
|
||||
subStatus: NotRequired["SubscriptionStatus"]
|
||||
|
||||
class Contact(TypedDict):
|
||||
contactId: int # int64
|
||||
localDisplayName: str
|
||||
@@ -2152,6 +2224,14 @@ class GroupMemberSettings(TypedDict):
|
||||
|
||||
GroupMemberStatus = Literal["rejected", "removed", "left", "deleted", "unknown", "invited", "pending_approval", "pending_review", "introduced", "intro-inv", "accepted", "announced", "connected", "complete", "creator"]
|
||||
|
||||
class GroupOwnerContact(TypedDict):
|
||||
contactId: int # int64
|
||||
memberId: str
|
||||
|
||||
|
||||
def GroupOwnerContact_cmd_string(self: GroupOwnerContact) -> str:
|
||||
return 'contact=' + str(self['contactId']) + ' owner=' + self['memberId']
|
||||
|
||||
class GroupPreference(TypedDict):
|
||||
enable: "GroupFeatureEnabled"
|
||||
|
||||
@@ -2199,6 +2279,47 @@ class GroupShortLinkInfo(TypedDict):
|
||||
groupRelays: list[str]
|
||||
publicGroupId: NotRequired[str]
|
||||
|
||||
class GroupSndStatus_new(TypedDict):
|
||||
type: Literal["new"]
|
||||
|
||||
class GroupSndStatus_forwarded(TypedDict):
|
||||
type: Literal["forwarded"]
|
||||
|
||||
class GroupSndStatus_inactive(TypedDict):
|
||||
type: Literal["inactive"]
|
||||
|
||||
class GroupSndStatus_sent(TypedDict):
|
||||
type: Literal["sent"]
|
||||
|
||||
class GroupSndStatus_rcvd(TypedDict):
|
||||
type: Literal["rcvd"]
|
||||
msgRcptStatus: "MsgReceiptStatus"
|
||||
|
||||
class GroupSndStatus_error(TypedDict):
|
||||
type: Literal["error"]
|
||||
agentError: "SndError"
|
||||
|
||||
class GroupSndStatus_warning(TypedDict):
|
||||
type: Literal["warning"]
|
||||
agentError: "SndError"
|
||||
|
||||
class GroupSndStatus_invalid(TypedDict):
|
||||
type: Literal["invalid"]
|
||||
text: str
|
||||
|
||||
GroupSndStatus = (
|
||||
GroupSndStatus_new
|
||||
| GroupSndStatus_forwarded
|
||||
| GroupSndStatus_inactive
|
||||
| GroupSndStatus_sent
|
||||
| GroupSndStatus_rcvd
|
||||
| GroupSndStatus_error
|
||||
| GroupSndStatus_warning
|
||||
| GroupSndStatus_invalid
|
||||
)
|
||||
|
||||
GroupSndStatus_Tag = Literal["new", "forwarded", "inactive", "sent", "rcvd", "error", "warning", "invalid"]
|
||||
|
||||
class GroupSummary(TypedDict):
|
||||
currentMembers: int # int64
|
||||
publicMemberCount: NotRequired[int] # int64
|
||||
@@ -2214,6 +2335,8 @@ GroupType = Literal["channel", "group"]
|
||||
|
||||
HandshakeError = Literal["PARSE", "IDENTITY", "BAD_AUTH", "BAD_SERVICE"]
|
||||
|
||||
HostMode = Literal["onionViaSocks", "onion", "public"]
|
||||
|
||||
InlineFileMode = Literal["offer", "sent"]
|
||||
|
||||
class InvitationLinkPlan_ok(TypedDict):
|
||||
@@ -2255,6 +2378,11 @@ InvitedBy = InvitedBy_contact | InvitedBy_user | InvitedBy_unknown
|
||||
|
||||
InvitedBy_Tag = Literal["contact", "user", "unknown"]
|
||||
|
||||
class KeepAliveOpts(TypedDict):
|
||||
keepIdle: int # int
|
||||
keepIntvl: int # int
|
||||
keepCnt: int # int
|
||||
|
||||
class LinkContent_page(TypedDict):
|
||||
type: Literal["page"]
|
||||
|
||||
@@ -2356,6 +2484,11 @@ MarkdownBlock_Tag = Literal["paragraph", "heading", "codeBlock", "quote", "list"
|
||||
|
||||
MemberCriteria = Literal["all"]
|
||||
|
||||
class MemberDeliveryStatus(TypedDict):
|
||||
groupMemberId: int # int64
|
||||
memberDeliveryStatus: "GroupSndStatus"
|
||||
sentViaProxy: NotRequired[bool]
|
||||
|
||||
# Connection link sent in a message - only short links are allowed.
|
||||
|
||||
class MsgChatLink_contact(TypedDict):
|
||||
@@ -2438,6 +2571,8 @@ MsgContent = (
|
||||
|
||||
MsgContent_Tag = Literal["text", "link", "image", "video", "voice", "file", "report", "chat", "unknown"]
|
||||
|
||||
MsgContentTag = Literal["text", "link", "image", "video", "voice", "file", "report", "chat"]
|
||||
|
||||
MsgDecryptError = Literal["ratchetHeader", "tooManySkipped", "ratchetEarlier", "other", "ratchetSync"]
|
||||
|
||||
MsgDirection = Literal["rcv", "snd"]
|
||||
@@ -2510,6 +2645,28 @@ NameErrorType = NameErrorType_NO_RESOLVER | NameErrorType_NOT_FOUND | NameErrorT
|
||||
|
||||
NameErrorType_Tag = Literal["NO_RESOLVER", "NOT_FOUND", "RESOLVER"]
|
||||
|
||||
class NavigationInfo(TypedDict):
|
||||
afterUnread: int # int
|
||||
afterTotal: int # int
|
||||
|
||||
class NetworkConfig(TypedDict):
|
||||
socksProxy: NotRequired[str]
|
||||
socksMode: "SocksMode"
|
||||
hostMode: "HostMode"
|
||||
requiredHostMode: bool
|
||||
sessionMode: "TransportSessionMode"
|
||||
smpProxyMode: "SMPProxyMode"
|
||||
smpProxyFallback: "SMPProxyFallback"
|
||||
smpWebPortServers: "SMPWebPortServers"
|
||||
tcpConnectTimeout: "NetworkTimeout"
|
||||
tcpTimeout: "NetworkTimeout"
|
||||
tcpTimeoutPerKb: int # int64
|
||||
rcvConcurrency: int # int
|
||||
tcpKeepAlive: NotRequired["KeepAliveOpts"]
|
||||
smpPingInterval: int # int64
|
||||
smpPingCount: int # int
|
||||
logTLSErrors: bool
|
||||
|
||||
class NetworkError_connectError(TypedDict):
|
||||
type: Literal["connectError"]
|
||||
connectError: str
|
||||
@@ -2542,6 +2699,10 @@ NetworkError = (
|
||||
|
||||
NetworkError_Tag = Literal["connectError", "tLSError", "unknownCAError", "failedError", "timeoutError", "subscribeError"]
|
||||
|
||||
class NetworkTimeout(TypedDict):
|
||||
backgroundTimeout: int # int
|
||||
interactiveTimeout: int # int
|
||||
|
||||
class NewUser(TypedDict):
|
||||
profile: NotRequired["Profile"]
|
||||
pastTimestamp: bool
|
||||
@@ -2557,6 +2718,8 @@ class NoteFolder(TypedDict):
|
||||
favorite: bool
|
||||
unread: bool
|
||||
|
||||
OperatorTag = Literal["simplex", "flux"]
|
||||
|
||||
class OwnerVerification_verified(TypedDict):
|
||||
type: Literal["verified"]
|
||||
|
||||
@@ -2595,6 +2758,10 @@ class PendingContactConnection(TypedDict):
|
||||
|
||||
PlanResolveMode = Literal["allGroups", "unknown", "never"]
|
||||
|
||||
|
||||
def PlanResolveMode_cmd_string(self: PlanResolveMode) -> str:
|
||||
return ' resolve=allGroups' if str(self) == 'allGroups' else ' resolve=never' if str(self) == 'never' else ''
|
||||
|
||||
class PrefEnabled(TypedDict):
|
||||
forUser: bool
|
||||
forContact: bool
|
||||
@@ -2687,6 +2854,8 @@ class PublicGroupProfile(TypedDict):
|
||||
publicGroupId: str
|
||||
publicGroupAccess: NotRequired["PublicGroupAccess"]
|
||||
|
||||
QueueStatus = Literal["new", "confirmed", "secured", "active", "disabled"]
|
||||
|
||||
class RCErrorType_internal(TypedDict):
|
||||
type: Literal["internal"]
|
||||
internalErr: str
|
||||
@@ -2956,6 +3125,15 @@ RcvMsgError = RcvMsgError_dropped | RcvMsgError_parseError
|
||||
|
||||
RcvMsgError_Tag = Literal["dropped", "parseError"]
|
||||
|
||||
class RcvQueueInfo(TypedDict):
|
||||
rcvServer: str
|
||||
status: "QueueStatus"
|
||||
rcvSwitchStatus: NotRequired["RcvSwitchStatus"]
|
||||
canAbortSwitch: bool
|
||||
subStatus: "SubscriptionStatus"
|
||||
|
||||
RcvSwitchStatus = Literal["switch_started", "sending_qadd", "sending_quse", "received_message", "received_qend"]
|
||||
|
||||
class RelayCapabilities(TypedDict):
|
||||
webDomain: NotRequired[str]
|
||||
|
||||
@@ -3077,6 +3255,12 @@ SMPAgentError = (
|
||||
|
||||
SMPAgentError_Tag = Literal["A_MESSAGE", "A_PROHIBITED", "A_VERSION", "A_LINK", "A_CRYPTO", "A_DUPLICATE", "A_QUEUE", "A_SERVICE"]
|
||||
|
||||
SMPProxyFallback = Literal["allow", "allowProtected", "prohibit"]
|
||||
|
||||
SMPProxyMode = Literal["always", "unknown", "unprotected", "never"]
|
||||
|
||||
SMPWebPortServers = Literal["all", "preset", "off"]
|
||||
|
||||
class SecurityCode(TypedDict):
|
||||
securityCode: str
|
||||
verifiedAt: str # ISO-8601 timestamp
|
||||
@@ -3086,6 +3270,27 @@ SegmentRange = TypedDict("SegmentRange", {
|
||||
"to": int, # int
|
||||
})
|
||||
|
||||
class ServerOperator(TypedDict):
|
||||
operatorId: int # int64
|
||||
operatorTag: NotRequired["OperatorTag"]
|
||||
tradeName: str
|
||||
legalName: NotRequired[str]
|
||||
serverDomains: list[str]
|
||||
conditionsAcceptance: "ConditionsAcceptance"
|
||||
enabled: bool
|
||||
smpRoles: "ServerRoles"
|
||||
xftpRoles: "ServerRoles"
|
||||
|
||||
class ServerRoles(TypedDict):
|
||||
storage: bool
|
||||
proxy: bool
|
||||
names: bool
|
||||
|
||||
class ServerRolesOverride(TypedDict):
|
||||
storage: NotRequired[bool]
|
||||
proxy: NotRequired[bool]
|
||||
names: NotRequired[bool]
|
||||
|
||||
class SimplePreference(TypedDict):
|
||||
allow: "FeatureAllowed"
|
||||
|
||||
@@ -3245,6 +3450,15 @@ SndGroupEvent = (
|
||||
|
||||
SndGroupEvent_Tag = Literal["memberRole", "memberBlocked", "userRole", "memberDeleted", "userLeft", "groupUpdated", "memberAccepted", "userPendingReview"]
|
||||
|
||||
class SndQueueInfo(TypedDict):
|
||||
sndServer: str
|
||||
status: "QueueStatus"
|
||||
sndSwitchStatus: NotRequired["SndSwitchStatus"]
|
||||
|
||||
SndSwitchStatus = Literal["sending_qkey", "sending_qtest", "securing_queue", "sending_qend"]
|
||||
|
||||
SocksMode = Literal["always", "onion"]
|
||||
|
||||
class SrvError_host(TypedDict):
|
||||
type: Literal["host"]
|
||||
|
||||
@@ -3762,6 +3976,8 @@ TransportError = (
|
||||
|
||||
TransportError_Tag = Literal["badBlock", "version", "largeMsg", "badSession", "noServerAuth", "handshake"]
|
||||
|
||||
TransportSessionMode = Literal["user", "session", "server", "entity"]
|
||||
|
||||
UIColorMode = Literal["light", "dark"]
|
||||
|
||||
class UIColors(TypedDict):
|
||||
@@ -3860,6 +4076,12 @@ class UserInfo(TypedDict):
|
||||
user: "User"
|
||||
unreadCount: int # int
|
||||
|
||||
class UserOperatorServers(TypedDict):
|
||||
operator: NotRequired["ServerOperator"]
|
||||
smpServers: list["UserServer"]
|
||||
xftpServers: list["UserServer"]
|
||||
chatRelays: list["UserChatRelay"]
|
||||
|
||||
class UserProfileUpdateSummary(TypedDict):
|
||||
updateSuccesses: int # int
|
||||
updateFailures: int # int
|
||||
@@ -3869,6 +4091,15 @@ class UserPwdHash(TypedDict):
|
||||
hash: str
|
||||
salt: str
|
||||
|
||||
class UserServer(TypedDict):
|
||||
serverId: int # int64
|
||||
server: str
|
||||
preset: bool
|
||||
tested: NotRequired[bool]
|
||||
enabled: bool
|
||||
roles: "ServerRolesOverride"
|
||||
deleted: bool
|
||||
|
||||
class VersionRange(TypedDict):
|
||||
minVersion: int # int
|
||||
maxVersion: int # int
|
||||
|
||||
@@ -45,3 +45,102 @@ def test_api_connect_cmd_string_renders_incognito():
|
||||
link = {"connFullLink": "L"}
|
||||
assert CC.APIConnect_cmd_string({"userId": 1, "incognito": True, "preparedLink_": link}) == "/_connect 1 incognito=on L"
|
||||
assert CC.APIConnect_cmd_string({"userId": 1, "incognito": False, "preparedLink_": link}) == "/_connect 1 L"
|
||||
|
||||
|
||||
def test_chat_pagination_cmd_string():
|
||||
assert T.ChatPagination_cmd_string({"type": "last", "count": 0}) == "count=0"
|
||||
assert T.ChatPagination_cmd_string({"type": "initial", "count": 1}) == "initial=1"
|
||||
assert (
|
||||
T.ChatPagination_cmd_string({"type": "around", "chatItemId": 5, "count": 0})
|
||||
== "around=5 count=0"
|
||||
)
|
||||
assert (
|
||||
T.ChatPagination_cmd_string({"type": "after", "chatItemId": 5, "count": 100})
|
||||
== "after=5 count=100"
|
||||
)
|
||||
assert (
|
||||
T.ChatPagination_cmd_string({"type": "before", "chatItemId": 5, "count": 10})
|
||||
== "before=5 count=10"
|
||||
)
|
||||
|
||||
|
||||
def test_api_get_chat_cmd_string():
|
||||
ref = {"chatType": "direct", "chatId": 2}
|
||||
last = {"type": "last", "count": 10}
|
||||
assert (
|
||||
CC.APIGetChat_cmd_string(
|
||||
{"chatRef": ref, "contentTag": "image", "chatPagination": last, "search": "k"}
|
||||
)
|
||||
== "/_get chat @2 content=image count=10 search=k"
|
||||
)
|
||||
assert (
|
||||
CC.APIGetChat_cmd_string(
|
||||
{"chatRef": ref, "chatPagination": {"type": "initial", "count": 1}}
|
||||
)
|
||||
== "/_get chat @2 initial=1"
|
||||
)
|
||||
|
||||
|
||||
def test_api_chat_items_read_cmd_string():
|
||||
ref = {"chatType": "direct", "chatId": 2}
|
||||
assert (
|
||||
CC.APIChatItemsRead_cmd_string({"chatRef": ref, "chatItemIds": [3, 4]})
|
||||
== "/_read chat items @2 3,4"
|
||||
)
|
||||
|
||||
|
||||
def test_api_connect_plan_cmd_string_omits_default_resolve_mode():
|
||||
assert T.PlanResolveMode_cmd_string("unknown") == ""
|
||||
assert T.PlanResolveMode_cmd_string("allGroups") == " resolve=allGroups"
|
||||
assert T.PlanResolveMode_cmd_string("never") == " resolve=never"
|
||||
assert (
|
||||
CC.APIConnectPlan_cmd_string({"userId": 1, "connectTarget": "L", "resolveMode": "unknown"})
|
||||
== "/_connect plan 1 L"
|
||||
)
|
||||
assert (
|
||||
CC.APIConnectPlan_cmd_string({"userId": 1, "connectTarget": "L", "resolveMode": "never"})
|
||||
== "/_connect plan 1 L resolve=never"
|
||||
)
|
||||
|
||||
|
||||
def test_api_connect_prepared_group_cmd_string():
|
||||
owner = {"contactId": 1, "memberId": "abc"}
|
||||
msg = {"type": "text", "text": "hi"}
|
||||
assert T.GroupOwnerContact_cmd_string(owner) == "contact=1 owner=abc"
|
||||
assert (
|
||||
CC.APIConnectPreparedGroup_cmd_string(
|
||||
{"groupId": 3, "incognito": False, "ownerContact": owner}
|
||||
)
|
||||
== "/_connect group #3 contact=1 owner=abc"
|
||||
)
|
||||
assert (
|
||||
CC.APIConnectPreparedGroup_cmd_string({"groupId": 3, "incognito": True, "msgContent_": msg})
|
||||
== '/_connect group #3 incognito=on json {"type": "text", "text": "hi"}'
|
||||
)
|
||||
|
||||
|
||||
def test_member_contact_cmd_string():
|
||||
assert (
|
||||
CC.APICreateMemberContact_cmd_string({"groupId": 1, "groupMemberId": 2})
|
||||
== "/_create member contact #1 2"
|
||||
)
|
||||
assert (
|
||||
CC.APISendMemberContactInvitation_cmd_string({"contactId": 2})
|
||||
== "/_invite member contact @2"
|
||||
)
|
||||
|
||||
|
||||
def test_api_get_network_config_cmd_string():
|
||||
assert CC.APIGetNetworkConfig_cmd_string({}) == "/network"
|
||||
|
||||
|
||||
def test_api_get_chat_item_info_cmd_string():
|
||||
ref = {"chatType": "direct", "chatId": 2}
|
||||
assert (
|
||||
CC.APIGetChatItemInfo_cmd_string({"chatRef": ref, "chatItemId": 5})
|
||||
== "/_get item info @2 5"
|
||||
)
|
||||
|
||||
|
||||
def test_api_get_user_servers_cmd_string():
|
||||
assert CC.APIGetUserServers_cmd_string({"userId": 1}) == "/_servers 1"
|
||||
Reference in new issue
Block a user