From a2de9a384650a3b70e8810939326cbe3a61e46ef Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Thu, 11 May 2023 17:33:23 +0200 Subject: [PATCH] update typescript client (#2427) * update typescript client * update bot * fix bot --- .../typescript/examples/squaring-bot.js | 9 +- .../typescript/package.json | 6 +- .../typescript/src/client.ts | 32 +- .../typescript/src/command.ts | 346 ++++++++++++++++-- .../typescript/src/response.ts | 135 +++++-- 5 files changed, 465 insertions(+), 63 deletions(-) diff --git a/packages/simplex-chat-client/typescript/examples/squaring-bot.js b/packages/simplex-chat-client/typescript/examples/squaring-bot.js index 8f874b2f4..5a96dfb20 100644 --- a/packages/simplex-chat-client/typescript/examples/squaring-bot.js +++ b/packages/simplex-chat-client/typescript/examples/squaring-bot.js @@ -17,7 +17,7 @@ async function run() { const address = (await chat.apiGetUserAddress()) || (await chat.apiCreateUserAddress()) console.log(`Bot address: ${address}`) // enables automatic acceptance of contact connections - await chat.addressAutoAccept(true) + await chat.enableAddressAutoAccept() await processMessages(chat) async function processMessages(chat) { @@ -40,14 +40,11 @@ async function run() { const {chatInfo} = resp.chatItem if (chatInfo.type !== ChatInfoType.Direct) continue const msg = ciContentText(resp.chatItem.chatItem.content) - let reply if (msg) { const n = +msg - reply = typeof n === "number" ? `${n} * ${n} = ${n * n}` : `${n} is not a number` - } else { - reply = "no message text" + const reply = typeof n === "number" && !isNaN(n) ? `${n} * ${n} = ${n * n}` : `this is not a number` + await chat.apiSendTextMessage(ChatType.Direct, chatInfo.contact.contactId, reply) } - await chat.apiSendTextMessage(ChatType.Direct, chatInfo.contact.contactId, reply) } } } diff --git a/packages/simplex-chat-client/typescript/package.json b/packages/simplex-chat-client/typescript/package.json index e780d2f28..c8aa6b4f1 100644 --- a/packages/simplex-chat-client/typescript/package.json +++ b/packages/simplex-chat-client/typescript/package.json @@ -1,6 +1,6 @@ { "name": "simplex-chat", - "version": "0.1.1", + "version": "0.2.0", "description": "SimpleX Chat client", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -36,7 +36,7 @@ }, "devDependencies": { "@types/jest": "^27.5.1", - "@types/node": "^17.0.24", + "@types/node": "^18.11.18", "@typescript-eslint/eslint-plugin": "^5.23.0", "@typescript-eslint/parser": "^5.23.0", "eslint": "^8.15.0", @@ -48,7 +48,7 @@ "rollup": "^2.72.1", "ts-jest": "^28.0.2", "ts-node": "^10.7.0", - "typescript": "^4.6.3" + "typescript": "^4.9.3" }, "husky": { "hooks": { diff --git a/packages/simplex-chat-client/typescript/src/client.ts b/packages/simplex-chat-client/typescript/src/client.ts index 3efbbd07d..eb3e39f00 100644 --- a/packages/simplex-chat-client/typescript/src/client.ts +++ b/packages/simplex-chat-client/typescript/src/client.ts @@ -105,8 +105,8 @@ export class ChatClient { } } - async apiCreateActiveUser(profile: CC.Profile): Promise { - const r = await this.sendChatCommand({type: "createActiveUser", profile}) + async apiCreateActiveUser(profile?: Profile, sameServers = true, pastTimestamp = false): Promise { + const r = await this.sendChatCommand({type: "createActiveUser", profile, sameServers, pastTimestamp}) if (r.type === "activeUser") return r.user throw new ChatCommandError("unexpected response", r) } @@ -129,15 +129,22 @@ export class ChatClient { return this.okChatCommand({type: "setIncognito", incognito}) } - async addressAutoAccept(autoAccept: boolean, autoReply: CC.MsgContent): Promise { - const r = await this.sendChatCommand({type: "addressAutoAccept", autoAccept, autoReply}) + async enableAddressAutoAccept(acceptIncognito = false, autoReply?: CC.MsgContent): Promise { + const r = await this.sendChatCommand({type: "addressAutoAccept", autoAccept: {acceptIncognito, autoReply}}) if (r.type !== "userContactLinkUpdated") { throw new ChatCommandError("error changing user contact address mode", r) } } - async apiGetChats(): Promise { - const r = await this.sendChatCommand({type: "apiGetChats"}) + async disableAddressAutoAccept(): Promise { + const r = await this.sendChatCommand({type: "addressAutoAccept"}) + if (r.type !== "userContactLinkUpdated") { + throw new ChatCommandError("error changing user contact address mode", r) + } + } + + async apiGetChats(userId: number): Promise { + const r = await this.sendChatCommand({type: "apiGetChats", userId}) if (r.type === "apiChats") return r.chats throw new ChatCommandError("error loading chats", r) } @@ -169,9 +176,14 @@ export class ChatClient { throw new ChatCommandError("error updating chat item", r) } - async apiDeleteChatItem(chatType: ChatType, chatId: number, chatItemId: number, deleteMode: CC.DeleteMode): Promise { + async apiDeleteChatItem( + chatType: ChatType, + chatId: number, + chatItemId: number, + deleteMode: CC.DeleteMode + ): Promise { const r = await this.sendChatCommand({type: "apiDeleteChatItem", chatType, chatId, chatItemId, deleteMode}) - if (r.type === "chatItemDeleted") return r.toChatItem.chatItem + if (r.type === "chatItemDeleted") return r.toChatItem?.chatItem throw new ChatCommandError("error deleting chat item", r) } @@ -215,8 +227,8 @@ export class ChatClient { throw new ChatCommandError("error clearing chat", r) } - async apiUpdateProfile(profile: CC.Profile): Promise { - const r = await this.sendChatCommand({type: "apiUpdateProfile", profile}) + async apiUpdateProfile(userId: number, profile: CC.Profile): Promise { + const r = await this.sendChatCommand({type: "apiUpdateProfile", userId, profile}) switch (r.type) { case "userProfileNoChange": return undefined diff --git a/packages/simplex-chat-client/typescript/src/command.ts b/packages/simplex-chat-client/typescript/src/command.ts index 2694e4d25..b49a3605b 100644 --- a/packages/simplex-chat-client/typescript/src/command.ts +++ b/packages/simplex-chat-client/typescript/src/command.ts @@ -1,9 +1,18 @@ export type ChatCommand = | ShowActiveUser | CreateActiveUser + | ListUsers + | APISetActiveUser + | APIHideUser + | APIUnhideUser + | APIMuteUser + | APIUnmuteUser + | APIDeleteUser | StartChat | APIStopChat + | SetTempFolder | SetFilesFolder + | APISetXFTPConfig | SetIncognito | APIExportArchive | APIImportArchive @@ -13,6 +22,7 @@ export type ChatCommand = | APISendMessage | APIUpdateChatItem | APIDeleteChatItem + | APIDeleteMemberChatItem | APIChatRead | APIDeleteChat | APIClearChat @@ -28,17 +38,31 @@ export type ChatCommand = | APILeaveGroup | APIListMembers | APIUpdateGroupProfile - | GetUserSMPServers - | SetUserSMPServers + | APICreateGroupLink + | APIGroupLinkMemberRole + | APIDeleteGroupLink + | APIGetGroupLink + | APIGetUserProtoServers + | APISetUserProtoServers | APIContactInfo | APIGroupMemberInfo + | APIGetContactCode + | APIGetGroupMemberCode + | APIVerifyContact + | APIVerifyGroupMember | AddContact | Connect | ConnectSimplex | CreateMyAddress | DeleteMyAddress | ShowMyAddress + | SetProfileAddress | AddressAutoAccept + | APICreateMyAddress + | APIDeleteMyAddress + | APIShowMyAddress + | APISetProfileAddress + | APIAddressAutoAccept | ReceiveFile | CancelFile | FileStatus @@ -64,6 +88,8 @@ export type ChatCommand = // APIMemberRole -- not implemented // ListContacts // ListGroups +// APISetChatItemTTL +// APIGetChatItemTTL // APISetNetworkConfig // APIGetNetworkConfig // APISetChatSettings @@ -74,9 +100,19 @@ export type ChatCommand = type ChatCommandTag = | "showActiveUser" | "createActiveUser" + | "listUsers" + | "apiSetActiveUser" + | "setActiveUser" + | "apiHideUser" + | "apiUnhideUser" + | "apiMuteUser" + | "apiUnmuteUser" + | "apiDeleteUser" | "startChat" | "apiStopChat" + | "setTempFolder" | "setFilesFolder" + | "apiSetXFTPConfig" | "setIncognito" | "apiExportArchive" | "apiImportArchive" @@ -86,6 +122,7 @@ type ChatCommandTag = | "apiSendMessage" | "apiUpdateChatItem" | "apiDeleteChatItem" + | "apiDeleteMemberChatItem" | "apiChatRead" | "apiDeleteChat" | "apiClearChat" @@ -101,17 +138,31 @@ type ChatCommandTag = | "apiLeaveGroup" | "apiListMembers" | "apiUpdateGroupProfile" - | "getUserSMPServers" - | "setUserSMPServers" + | "apiCreateGroupLink" + | "apiGroupLinkMemberRole" + | "apiDeleteGroupLink" + | "apiGetGroupLink" + | "apiGetUserProtoServers" + | "apiSetUserProtoServers" | "apiContactInfo" | "apiGroupMemberInfo" + | "apiGetContactCode" + | "apiGetGroupMemberCode" + | "apiVerifyContact" + | "apiVerifyGroupMember" | "addContact" | "connect" | "connectSimplex" | "createMyAddress" | "deleteMyAddress" | "showMyAddress" + | "setProfileAddress" | "addressAutoAccept" + | "apiCreateMyAddress" + | "apiDeleteMyAddress" + | "apiShowMyAddress" + | "apiSetProfileAddress" + | "apiAddressAutoAccept" | "receiveFile" | "cancelFile" | "fileStatus" @@ -126,24 +177,80 @@ export interface ShowActiveUser extends IChatCommand { export interface CreateActiveUser extends IChatCommand { type: "createActiveUser" - profile: Profile + profile?: Profile + sameServers: boolean + pastTimestamp: boolean +} + +export interface ListUsers extends IChatCommand { + type: "listUsers" +} + +export interface APISetActiveUser extends IChatCommand { + type: "apiSetActiveUser" + userId: number + viewPwd?: string +} + +export interface APIHideUser extends IChatCommand { + type: "apiHideUser" + userId: number + viewPwd: string +} + +export interface APIUnhideUser extends IChatCommand { + type: "apiUnhideUser" + userId: number + viewPwd: string +} + +export interface APIMuteUser extends IChatCommand { + type: "apiMuteUser" + userId: number +} + +export interface APIUnmuteUser extends IChatCommand { + type: "apiUnmuteUser" + userId: number +} + +export interface APIDeleteUser extends IChatCommand { + type: "apiDeleteUser" + userId: number + delSMPQueues: boolean + viewPwd?: string } export interface StartChat extends IChatCommand { type: "startChat" subscribeConnections?: boolean - expireChatItems?: boolean + enableExpireChatItems?: boolean + startXFTPWorkers?: boolean } export interface APIStopChat extends IChatCommand { type: "apiStopChat" } +export interface SetTempFolder extends IChatCommand { + type: "setTempFolder" + tempFolder: string +} + export interface SetFilesFolder extends IChatCommand { type: "setFilesFolder" filePath: string } +export interface APISetXFTPConfig extends IChatCommand { + type: "apiSetXFTPConfig" + config?: XFTPFileConfig +} + +export interface XFTPFileConfig { + minFileSize: number +} + export interface SetIncognito extends IChatCommand { type: "setIncognito" incognito: boolean @@ -165,6 +272,7 @@ export interface APIDeleteStorage extends IChatCommand { export interface APIGetChats extends IChatCommand { type: "apiGetChats" + userId: number pendingConnections?: boolean } @@ -205,6 +313,13 @@ export interface APIDeleteChatItem extends IChatCommand { deleteMode: DeleteMode } +export interface APIDeleteMemberChatItem extends IChatCommand { + type: "apiDeleteMemberChatItem" + groupId: number + groupMemberId: number + itemId: number +} + export interface APIChatRead extends IChatCommand { type: "apiChatRead" chatType: ChatType @@ -241,6 +356,7 @@ export interface APIRejectContact extends IChatCommand { export interface APIUpdateProfile extends IChatCommand { type: "apiUpdateProfile" + userId: number profile: Profile } @@ -294,13 +410,51 @@ export interface APIUpdateGroupProfile extends IChatCommand { groupProfile: GroupProfile } -export interface GetUserSMPServers extends IChatCommand { - type: "getUserSMPServers" +export interface APICreateGroupLink extends IChatCommand { + type: "apiCreateGroupLink" + groupId: number + memberRole: GroupMemberRole } -export interface SetUserSMPServers extends IChatCommand { - type: "setUserSMPServers" - servers: [string] +export interface APIGroupLinkMemberRole extends IChatCommand { + type: "apiGroupLinkMemberRole" + groupId: number + memberRole: GroupMemberRole +} + +export interface APIDeleteGroupLink extends IChatCommand { + type: "apiDeleteGroupLink" + groupId: number +} + +export interface APIGetGroupLink extends IChatCommand { + type: "apiGetGroupLink" + groupId: number +} + +export interface APIGetUserProtoServers extends IChatCommand { + type: "apiGetUserProtoServers" + userId: number + serverProtocol: ServerProtocol +} + +export interface APISetUserProtoServers extends IChatCommand { + type: "apiSetUserProtoServers" + userId: number + serverProtocol: ServerProtocol + servers: ServerCfg[] +} + +export interface ServerCfg { + server: string + preset: boolean + tested?: boolean + enabled: boolean +} + +export enum ServerProtocol { + SMP = "smp", + XFTP = "xftp", } export interface APIContactInfo extends IChatCommand { @@ -314,6 +468,30 @@ export interface APIGroupMemberInfo extends IChatCommand { memberId: number } +export interface APIGetContactCode extends IChatCommand { + type: "apiGetContactCode" + contactId: number +} + +export interface APIGetGroupMemberCode extends IChatCommand { + type: "apiGetGroupMemberCode" + groupId: number + groupMemberId: number +} + +export interface APIVerifyContact extends IChatCommand { + type: "apiVerifyContact" + contactId: number + connectionCode: string +} + +export interface APIVerifyGroupMember extends IChatCommand { + type: "apiVerifyGroupMember" + groupId: number + groupMemberId: number + connectionCode: string +} + export interface AddContact extends IChatCommand { type: "addContact" } @@ -339,9 +517,45 @@ export interface ShowMyAddress extends IChatCommand { type: "showMyAddress" } +export interface SetProfileAddress extends IChatCommand { + type: "setProfileAddress" + includeInProfile: boolean +} + export interface AddressAutoAccept extends IChatCommand { type: "addressAutoAccept" - autoAccept: boolean + autoAccept?: AutoAccept +} + +export interface APICreateMyAddress extends IChatCommand { + type: "apiCreateMyAddress" + userId: number +} + +export interface APIDeleteMyAddress extends IChatCommand { + type: "apiDeleteMyAddress" + userId: number +} + +export interface APIShowMyAddress extends IChatCommand { + type: "apiShowMyAddress" + userId: number +} + +export interface APISetProfileAddress extends IChatCommand { + type: "apiSetProfileAddress" + userId: number + includeInProfile: boolean +} + +export interface APIAddressAutoAccept extends IChatCommand { + type: "apiAddressAutoAccept" + userId: number + autoAccept?: AutoAccept +} + +export interface AutoAccept { + acceptIncognito: boolean autoReply?: MsgContent } @@ -361,10 +575,28 @@ export interface FileStatus extends IChatCommand { fileId: number } +interface NewUser { + profile?: Profile + sameServers: boolean + pastTimestamp: boolean +} + export interface Profile { displayName: string fullName: string // can be empty string image?: string + contactLink?: string + // preferences?: Preferences +} + +export interface LocalProfile { + profileId: number + displayName: string + fullName: string + image?: string + contactLink?: string + // preferences?: Preferences + localAlias: string } export enum ChatType { @@ -449,16 +681,36 @@ export function cmdString(cmd: ChatCommand): string { switch (cmd.type) { case "showActiveUser": return "/u" - case "createActiveUser": - return `/create user ${JSON.stringify(cmd.profile)}` + case "createActiveUser": { + const user: NewUser = {profile: cmd.profile, sameServers: cmd.sameServers, pastTimestamp: cmd.pastTimestamp} + return `/_create user ${JSON.stringify(user)}` + } + case "listUsers": + return `/users` + case "apiSetActiveUser": + return `/_user ${cmd.userId}${maybeJSON(cmd.viewPwd)}` + case "apiHideUser": + return `/_hide user ${cmd.userId} ${JSON.stringify(cmd.viewPwd)}` + case "apiUnhideUser": + return `/_unhide user ${cmd.userId} ${JSON.stringify(cmd.viewPwd)}` + case "apiMuteUser": + return `/_mute user ${cmd.userId}` + case "apiUnmuteUser": + return `/_unmute user ${cmd.userId}` + case "apiDeleteUser": + return `/_delete user ${cmd.userId} del_smp=${onOff(cmd.delSMPQueues)}${maybeJSON(cmd.viewPwd)}` case "startChat": - return `/_start subscribe=${cmd.subscribeConnections ? "on" : "off"} expire=${cmd.expireChatItems ? "on" : "off"}` + return `/_start subscribe=${cmd.subscribeConnections ? "on" : "off"} expire=${cmd.enableExpireChatItems ? "on" : "off"}` case "apiStopChat": return "/_stop" + case "setTempFolder": + return `/_temp_folder ${cmd.tempFolder}` case "setFilesFolder": return `/_files_folder ${cmd.filePath}` + case "apiSetXFTPConfig": + return `/_xftp ${onOff(cmd.config)}${maybeJSON(cmd.config)}` case "setIncognito": - return `/incognito ${cmd.incognito ? "on" : "off"}` + return `/incognito ${onOff(cmd.incognito)}` case "apiExportArchive": return `/_db export ${JSON.stringify(cmd.config)}` case "apiImportArchive": @@ -466,7 +718,7 @@ export function cmdString(cmd: ChatCommand): string { case "apiDeleteStorage": return "/_db delete" case "apiGetChats": - return `/_get chats pcc=${cmd.pendingConnections ? "on" : "off"}` + return `/_get chats pcc=${onOff(cmd.pendingConnections)}` case "apiGetChat": return `/_get chat ${cmd.chatType}${cmd.chatId}${paginationStr(cmd.pagination)}` case "apiSendMessage": @@ -475,6 +727,8 @@ export function cmdString(cmd: ChatCommand): string { return `/_update item ${cmd.chatType}${cmd.chatId} ${cmd.chatItemId} json ${JSON.stringify(cmd.msgContent)}` case "apiDeleteChatItem": return `/_delete item ${cmd.chatType}${cmd.chatId} ${cmd.chatItemId} ${cmd.deleteMode}` + case "apiDeleteMemberChatItem": + return `/_delete member item #${cmd.groupId} ${cmd.groupMemberId} ${cmd.itemId}` case "apiChatRead": { const itemRange = cmd.itemRange ? ` from=${cmd.itemRange.fromItem} to=${cmd.itemRange.toItem}` : "" return `/_read chat ${cmd.chatType}${cmd.chatId}${itemRange}` @@ -488,7 +742,7 @@ export function cmdString(cmd: ChatCommand): string { case "apiRejectContact": return `/_reject ${cmd.contactReqId}` case "apiUpdateProfile": - return `/_profile ${JSON.stringify(cmd.profile)}` + return `/_profile ${cmd.userId} ${JSON.stringify(cmd.profile)}` case "apiSetContactAlias": return `/_set alias @${cmd.contactId} ${cmd.localAlias.trim()}` case "apiParseMarkdown": @@ -507,14 +761,30 @@ export function cmdString(cmd: ChatCommand): string { return `/_members #${cmd.groupId}` case "apiUpdateGroupProfile": return `/_group_profile #${cmd.groupId} ${JSON.stringify(cmd.groupProfile)}` - case "getUserSMPServers": - return "/smp_servers" - case "setUserSMPServers": - return `/smp_servers ${cmd.servers.join(",") || "default"}` + case "apiCreateGroupLink": + return `/_create link #${cmd.groupId} ${cmd.memberRole}` + case "apiGroupLinkMemberRole": + return `/_set link role #${cmd.groupId} ${cmd.memberRole}` + case "apiDeleteGroupLink": + return `/_delete link #${cmd.groupId}` + case "apiGetGroupLink": + return `/_get link #${cmd.groupId}` + case "apiGetUserProtoServers": + return `/_servers ${cmd.userId} ${cmd.serverProtocol}` + case "apiSetUserProtoServers": + return `/_servers ${cmd.userId} ${cmd.serverProtocol} ${JSON.stringify({servers: cmd.servers})}` case "apiContactInfo": return `/_info @${cmd.contactId}` case "apiGroupMemberInfo": return `/_info #${cmd.groupId} ${cmd.memberId}` + case "apiGetContactCode": + return `/_get code @${cmd.contactId}` + case "apiGetGroupMemberCode": + return `/_get code #${cmd.groupId} ${cmd.groupMemberId}` + case "apiVerifyContact": + return `/_verify code @${cmd.contactId}${maybe(cmd.connectionCode)}` + case "apiVerifyGroupMember": + return `/_verify code #${cmd.groupId} ${cmd.groupMemberId}${maybe(cmd.connectionCode)}` case "addContact": return "/connect" case "connect": @@ -527,8 +797,20 @@ export function cmdString(cmd: ChatCommand): string { return "/delete_address" case "showMyAddress": return "/show_address" + case "setProfileAddress": + return `/profile_address ${onOff(cmd.includeInProfile)}` case "addressAutoAccept": - return `/auto_accept ${cmd.autoAccept ? "on" : "off"}${cmd.autoReply ? " " + JSON.stringify(cmd.autoReply) : ""}` + return `/auto_accept ${autoAcceptStr(cmd.autoAccept)}` + case "apiCreateMyAddress": + return `/_address ${cmd.userId}` + case "apiDeleteMyAddress": + return `/_delete_address ${cmd.userId}` + case "apiShowMyAddress": + return `/_show_address ${cmd.userId}` + case "apiSetProfileAddress": + return `/_profile_address ${cmd.userId} ${onOff(cmd.includeInProfile)}` + case "apiAddressAutoAccept": + return `/_auto_accept ${cmd.userId} ${autoAcceptStr(cmd.autoAccept)}` case "receiveFile": return `/freceive ${cmd.fileId}${cmd.filePath ? " " + cmd.filePath : ""}` case "cancelFile": @@ -542,3 +824,21 @@ function paginationStr(cp: ChatPagination): string { const base = "after" in cp ? ` after=${cp.after}` : "before" in cp ? ` before=${cp.before}` : "" return base + ` count=${cp.count}` } + +function maybe(value: T | undefined): string { + return value ? ` ${value}` : "" +} + +function maybeJSON(value: T | undefined): string { + return value ? ` json ${JSON.stringify(value)}` : "" +} + +function onOff(value: T | undefined): string { + return value ? "on" : "off" +} + +function autoAcceptStr(autoAccept: AutoAccept | undefined): string { + if (!autoAccept) return "off" + const msg = autoAccept.autoReply + return "on" + (autoAccept.acceptIncognito ? " incognito=on" : "") + (msg ? " json " + JSON.stringify(msg) : "") +} diff --git a/packages/simplex-chat-client/typescript/src/response.ts b/packages/simplex-chat-client/typescript/src/response.ts index 3de336c05..0e1b2799b 100644 --- a/packages/simplex-chat-client/typescript/src/response.ts +++ b/packages/simplex-chat-client/typescript/src/response.ts @@ -1,14 +1,15 @@ -import {ChatItemId, MsgContent, DeleteMode, Profile, GroupMemberRole} from "./command" +import {ChatItemId, MsgContent, DeleteMode, Profile, GroupMemberRole, LocalProfile, ServerProtocol, ServerCfg} from "./command" export type ChatResponse = | CRActiveUser + | CRUsersList | CRChatStarted | CRChatRunning | CRChatStopped | CRApiChats | CRApiChat | CRApiParsedMarkdown - | CRUserSMPServers + | CRUserProtoServers | CRContactInfo | CRGroupMemberInfo | CRNewChatItem @@ -40,8 +41,6 @@ export type ChatResponse = | CRContactConnecting | CRContactConnected | CRContactAnotherClient - | CRContactDisconnected - | CRContactSubscribed | CRContactSubError | CRContactSubSummary | CRContactsDisconnected @@ -101,13 +100,14 @@ export type ChatResponse = type ChatResponseTag = | "activeUser" + | "usersList" | "chatStarted" | "chatRunning" | "chatStopped" | "apiChats" | "apiChat" | "apiParsedMarkdown" - | "userSMPServers" + | "userProtoServers" | "contactInfo" | "groupMemberInfo" | "newChatItem" @@ -139,8 +139,6 @@ type ChatResponseTag = | "contactConnecting" | "contactConnected" | "contactAnotherClient" - | "contactDisconnected" - | "contactSubscribed" | "contactSubError" | "contactSubSummary" | "contactsDisconnected" @@ -202,6 +200,11 @@ export interface CRActiveUser extends CR { user: User } +export interface CRUsersList extends CR { + type: "usersList" + users: UserInfo[] +} + export interface CRChatStarted extends CR { type: "chatStarted" } @@ -216,11 +219,13 @@ export interface CRChatStopped extends CR { export interface CRApiChats extends CR { type: "apiChats" + user: User chats: Chat[] } export interface CRApiChat extends CR { type: "apiChat" + user: User chat: Chat } @@ -229,13 +234,15 @@ export interface CRApiParsedMarkdown extends CR { formattedText?: FormattedText[] } -export interface CRUserSMPServers extends CR { - type: "userSMPServers" - smpServers: string[] +export interface CRUserProtoServers extends CR { + type: "userProtoServers" + user: User + servers: UserProtoServers } export interface CRContactInfo extends CR { type: "contactInfo" + user: User contact: Contact connectionStats: ConnectionStats customUserProfile?: Profile @@ -243,6 +250,7 @@ export interface CRContactInfo extends CR { export interface CRGroupMemberInfo extends CR { type: "groupMemberInfo" + user: User groupInfo: GroupInfo member: GroupMember connectionStats_?: ConnectionStats @@ -250,21 +258,25 @@ export interface CRGroupMemberInfo extends CR { export interface CRNewChatItem extends CR { type: "newChatItem" + user: User chatItem: AChatItem } export interface CRChatItemStatusUpdated extends CR { type: "chatItemStatusUpdated" + user: User chatItem: AChatItem } export interface CRChatItemUpdated extends CR { type: "chatItemUpdated" + user: User chatItem: AChatItem } export interface CRChatItemDeleted extends CR { type: "chatItemDeleted" + user: User deletedChatItem: AChatItem toChatItem?: AChatItem byUser: boolean @@ -272,20 +284,24 @@ export interface CRChatItemDeleted extends CR { export interface CRMsgIntegrityError extends CR { type: "msgIntegrityError" + user: User msgError: MsgErrorType } export interface CRCmdOk extends CR { type: "cmdOk" + user_?: User } export interface CRUserContactLink extends CR { type: "userContactLink" + user: User contactLink: UserContactLink } export interface CRUserContactLinkUpdated extends CR { type: "userContactLinkUpdated" + user: User connReqContact: string autoAccept: boolean autoReply?: MsgContent @@ -293,138 +309,153 @@ export interface CRUserContactLinkUpdated extends CR { export interface CRContactRequestRejected extends CR { type: "contactRequestRejected" + user: User contactRequest: UserContactRequest } export interface CRUserProfile extends CR { type: "userProfile" + user: User profile: Profile } export interface CRUserProfileNoChange extends CR { type: "userProfileNoChange" + user: User } export interface CRUserProfileUpdated extends CR { type: "userProfileUpdated" + user: User fromProfile: Profile toProfile: Profile } export interface CRContactAliasUpdated extends CR { type: "contactAliasUpdated" + user: User toContact: Contact } export interface CRInvitation extends CR { type: "invitation" + user: User connReqInvitation: string } export interface CRSentConfirmation extends CR { type: "sentConfirmation" + user: User } export interface CRSentInvitation extends CR { type: "sentInvitation" + user: User } export interface CRContactUpdated extends CR { type: "contactUpdated" + user: User fromContact: Contact toContact: Contact } export interface CRContactsMerged extends CR { type: "contactsMerged" + user: User intoContact: Contact mergedContact: Contact } export interface CRContactDeleted extends CR { type: "contactDeleted" + user: User contact: Contact } export interface CRChatCleared extends CR { type: "chatCleared" + user: User chatInfo: ChatInfo } export interface CRUserContactLinkCreated extends CR { type: "userContactLinkCreated" + user: User connReqContact: string } export interface CRUserContactLinkDeleted extends CR { type: "userContactLinkDeleted" + user: User } export interface CRReceivedContactRequest extends CR { type: "receivedContactRequest" + user: User contactRequest: UserContactRequest } export interface CRAcceptingContactRequest extends CR { type: "acceptingContactRequest" + user: User contact: Contact } export interface CRContactAlreadyExists extends CR { type: "contactAlreadyExists" + user: User contact: Contact } export interface CRContactRequestAlreadyAccepted extends CR { type: "contactRequestAlreadyAccepted" + user: User contact: Contact } export interface CRContactConnecting extends CR { type: "contactConnecting" + user: User contact: Contact } export interface CRContactConnected extends CR { type: "contactConnected" contact: Contact + user: User userCustomProfile?: Profile } export interface CRContactAnotherClient extends CR { type: "contactAnotherClient" - contact: Contact -} - -export interface CRContactDisconnected extends CR { - type: "contactDisconnected" - contact: Contact -} - -export interface CRContactSubscribed extends CR { - type: "contactSubscribed" + user: User contact: Contact } export interface CRContactSubError extends CR { type: "contactSubError" + user: User contact: Contact chatError: ChatError } export interface CRContactSubSummary extends CR { type: "contactSubSummary" + user: User contactSubscriptions: ContactSubStatus[] } export interface CRContactsDisconnected extends CR { type: "contactsDisconnected" + user: User server: string contactRefs: ContactRef[] } export interface CRContactsSubscribed extends CR { type: "contactsSubscribed" + user: User server: string contactRefs: ContactRef[] } @@ -443,11 +474,13 @@ export interface CRHostDisconnected extends CR { export interface CRGroupEmpty extends CR { type: "groupEmpty" + user: User groupInfo: GroupInfo } export interface CRMemberSubError extends CR { type: "memberSubError" + user: User groupInfo: GroupInfo member: GroupMember chatError: ChatError @@ -455,70 +488,83 @@ export interface CRMemberSubError extends CR { export interface CRMemberSubSummary extends CR { type: "memberSubSummary" + user: User memberSubscriptions: MemberSubStatus[] } export interface CRGroupSubscribed extends CR { type: "groupSubscribed" + user: User groupInfo: GroupInfo } export interface CRRcvFileAccepted extends CR { type: "rcvFileAccepted" + user: User chatItem: AChatItem } export interface CRRcvFileAcceptedSndCancelled extends CR { type: "rcvFileAcceptedSndCancelled" + user: User rcvFileTransfer: RcvFileTransfer } export interface CRRcvFileStart extends CR { type: "rcvFileStart" + user: User chatItem: AChatItem } export interface CRRcvFileComplete extends CR { type: "rcvFileComplete" + user: User chatItem: AChatItem } export interface CRRcvFileCancelled extends CR { type: "rcvFileCancelled" + user: User rcvFileTransfer: RcvFileTransfer } export interface CRRcvFileSndCancelled extends CR { type: "rcvFileSndCancelled" + user: User rcvFileTransfer: RcvFileTransfer } export interface CRSndFileStart extends CR { type: "sndFileStart" + user: User chatItem: AChatItem sndFileTransfer: SndFileTransfer } export interface CRSndFileComplete extends CR { type: "sndFileComplete" + user: User chatItem: AChatItem sndFileTransfer: SndFileTransfer } export interface CRSndFileCancelled extends CR { type: "sndFileCancelled" + user: User chatItem: AChatItem sndFileTransfer: SndFileTransfer } export interface CRSndFileRcvCancelled extends CR { type: "sndFileRcvCancelled" + user: User chatItem: AChatItem sndFileTransfer: SndFileTransfer } export interface CRSndGroupFileCancelled extends CR { type: "sndGroupFileCancelled" + user: User chatItem: AChatItem fileTransferMeta: FileTransferMeta sndFileTransfers: SndFileTransfer[] @@ -526,45 +572,53 @@ export interface CRSndGroupFileCancelled extends CR { export interface CRSndFileSubError extends CR { type: "sndFileSubError" + user: User sndFileTransfer: SndFileTransfer chatError: ChatError } export interface CRRcvFileSubError extends CR { type: "rcvFileSubError" + user: User rcvFileTransfer: RcvFileTransfer chatError: ChatError } export interface CRPendingSubSummary extends CR { type: "pendingSubSummary" + user: User pendingSubStatus: PendingSubStatus[] } export interface CRGroupCreated extends CR { type: "groupCreated" + user: User groupInfo: GroupInfo } export interface CRGroupMembers extends CR { type: "groupMembers" + user: User group: Group } export interface CRUserAcceptedGroupSent extends CR { type: "userAcceptedGroupSent" + user: User groupInfo: GroupInfo hostContact?: Contact // included when joining group via group link } export interface CRUserDeletedMember extends CR { type: "userDeletedMember" + user: User groupInfo: GroupInfo member: GroupMember } export interface CRSentGroupInvitation extends CR { type: "sentGroupInvitation" + user: User groupInfo: GroupInfo contact: Contact member: GroupMember @@ -572,21 +626,25 @@ export interface CRSentGroupInvitation extends CR { export interface CRLeftMemberUser extends CR { type: "leftMemberUser" + user: User groupInfo: GroupInfo } export interface CRGroupDeletedUser extends CR { type: "groupDeletedUser" + user: User groupInfo: GroupInfo } export interface CRGroupInvitation extends CR { type: "groupInvitation" + user: User groupInfo: GroupInfo } export interface CRReceivedGroupInvitation extends CR { type: "receivedGroupInvitation" + user: User groupInfo: GroupInfo contact: Contact memberRole: GroupMemberRole @@ -594,18 +652,21 @@ export interface CRReceivedGroupInvitation extends CR { export interface CRUserJoinedGroup extends CR { type: "userJoinedGroup" + user: User groupInfo: GroupInfo hostMember: GroupMember } export interface CRJoinedGroupMember extends CR { type: "joinedGroupMember" + user: User groupInfo: GroupInfo member: GroupMember } export interface CRJoinedGroupMemberConnecting extends CR { type: "joinedGroupMemberConnecting" + user: User groupInfo: GroupInfo hostMember: GroupMember member: GroupMember @@ -613,12 +674,14 @@ export interface CRJoinedGroupMemberConnecting extends CR { export interface CRConnectedToGroupMember extends CR { type: "connectedToGroupMember" + user: User groupInfo: GroupInfo member: GroupMember } export interface CRDeletedMember extends CR { type: "deletedMember" + user: User groupInfo: GroupInfo byMember: GroupMember deletedMember: GroupMember @@ -626,29 +689,34 @@ export interface CRDeletedMember extends CR { export interface CRDeletedMemberUser extends CR { type: "deletedMemberUser" + user: User groupInfo: GroupInfo member: GroupMember } export interface CRLeftMember extends CR { type: "leftMember" + user: User groupInfo: GroupInfo member: GroupMember } export interface CRGroupRemoved extends CR { type: "groupRemoved" + user: User groupInfo: GroupInfo } export interface CRGroupDeleted extends CR { type: "groupDeleted" + user: User groupInfo: GroupInfo member: GroupMember } export interface CRGroupUpdated extends CR { type: "groupUpdated" + user: User fromGroup: GroupInfo toGroup: GroupInfo member_?: GroupMember @@ -665,36 +733,51 @@ export interface CRUserContactLinkSubError extends CR { export interface CRNewContactConnection extends CR { type: "newContactConnection" + user: User connection: PendingContactConnection } export interface CRContactConnectionDeleted extends CR { type: "contactConnectionDeleted" + user: User connection: PendingContactConnection } export interface CRMessageError extends CR { type: "messageError" + user: User severity: string errorMessage: string } export interface CRChatCmdError extends CR { type: "chatCmdError" + user_?: User chatError: ChatError } export interface CRChatError extends CR { type: "chatError" + user_?: User chatError: ChatError } export interface User { userId: number + agentUserId: string userContactId: number localDisplayName: string - profile: Profile + profile: LocalProfile + // fullPreferences :: FullPreferences activeUser: boolean + viewPwdHash: string + showNtfs: boolean +} + +export interface UserProtoServers { + serverProtocol: ServerProtocol + protoServers: ServerCfg[] + presetServers: string } export interface Chat { @@ -730,6 +813,16 @@ interface CInfoContactRequest extends IChatInfo { contactRequest: UserContactRequest } +export interface UserPwdHash { + hash: string + salt: string +} + +interface UserInfo { + user: User + unreadCount: number +} + export interface Contact { contactId: number localDisplayName: string