Merge branch 'master' into ep/smp-server-pages

This commit is contained in:
Evgeny Poberezkin
2026-03-23 08:32:26 +00:00
504 changed files with 38814 additions and 2453 deletions
+17 -10
View File
@@ -72,7 +72,7 @@ instance IsString ErrorTypeDoc where fromString s = TD s ""
-- category name, category description, commands
-- inner: constructor, description, responses, errors (ChatErrorType constructors), network usage, syntax
-- inner: constructor, hidden params, description, responses, errors (ChatErrorType constructors), network usage, syntax
chatCommandsDocsData :: [(String, String, [(ConsName, [String], Text, [ConsName], [ErrorTypeDoc], Maybe UsesNetwork, Expr)])]
chatCommandsDocsData =
[ ( "Address commands",
@@ -132,7 +132,7 @@ chatCommandsDocsData =
"These commands may be used to create connections. Most bots do not need to use them - bot users will connect via bot address with auto-accept enabled.",
[ ("APIAddContact", [], "Create 1-time invitation link.", ["CRInvitation", "CRChatCmdError"], [], Just UNInteractive, "/_connect " <> Param "userId" <> OnOffParam "incognito" "incognito" (Just False)),
("APIConnectPlan", [], "Determine SimpleX link type and if the bot is already connected via this link.", ["CRConnectionPlan", "CRChatCmdError"], [], Just UNInteractive, "/_connect plan " <> Param "userId" <> " " <> Param "connectionLink"),
("APIConnect", [], "Connect via prepared SimpleX link. The link can be 1-time invitation link, contact address or group link", ["CRSentConfirmation", "CRContactAlreadyExists", "CRSentInvitation", "CRChatCmdError"], [], Just UNInteractive, "/_connect " <> Param "userId" <> Optional "" (" " <> Param "$0") "preparedLink_"),
("APIConnect", [], "Connect via prepared SimpleX link. The link can be 1-time invitation link, contact address or group link.", ["CRSentConfirmation", "CRContactAlreadyExists", "CRSentInvitation", "CRChatCmdError"], [], Just UNInteractive, "/_connect " <> Param "userId" <> Optional "" (" " <> Param "$0") "preparedLink_"),
("Connect", [], "Connect via SimpleX link as string in the active user profile.", ["CRSentConfirmation", "CRContactAlreadyExists", "CRSentInvitation", "CRChatCmdError"], [], Just UNInteractive, "/connect" <> Optional "" (" " <> Param "$0") "connLink_"),
("APIAcceptContact", ["incognito"], "Accept contact request.", ["CRAcceptingContactRequest", "CRChatCmdError"], [], Just UNInteractive, "/_accept " <> Param "contactReqId"),
("APIRejectContact", [], "Reject contact request. The user who sent the request is **not notified**.", ["CRContactRequestRejected", "CRChatCmdError"], [], Nothing, "/_reject " <> Param "contactReqId")
@@ -142,7 +142,10 @@ chatCommandsDocsData =
"Commands to list and delete conversations.",
[ ("APIListContacts", [], "Get contacts.", ["CRContactsList", "CRChatCmdError"], [], Nothing, "/_contacts " <> Param "userId"),
("APIListGroups", [], "Get groups.", ["CRGroupsList", "CRChatCmdError"], [], Nothing, "/_groups " <> Param "userId" <> Optional "" (" @" <> Param "$0") "contactId_" <> Optional "" (" " <> Param "$0") "search"),
("APIDeleteChat", [], "Delete chat.", ["CRContactDeleted", "CRContactConnectionDeleted", "CRGroupDeletedUser", "CRChatCmdError"], [], Just UNBackground, "/_delete " <> Param "chatRef" <> " " <> Param "chatDeleteMode")
("APIDeleteChat", [], "Delete chat.", ["CRContactDeleted", "CRContactConnectionDeleted", "CRGroupDeletedUser", "CRChatCmdError"], [], Just UNBackground, "/_delete " <> Param "chatRef" <> " " <> Param "chatDeleteMode"),
("APISetGroupCustomData", [], "Set group custom data.", ["CRCmdOk", "CRChatCmdError"], [], Nothing, "/_set custom #" <> Param "groupId" <> Optional "" (" " <> Json "$0") "customData"),
("APISetContactCustomData", [], "Set contact custom data.", ["CRCmdOk", "CRChatCmdError"], [], Nothing, "/_set custom @" <> Param "contactId" <> Optional "" (" " <> Json "$0") "customData"),
("APISetUserAutoAcceptMemberContacts", [], "Set auto-accept member contacts.", ["CRCmdOk", "CRChatCmdError"], [], Nothing, "/_set accept member contacts " <> Param "userId" <> " " <> OnOff "onOff")
-- ("APIChatItemsRead", [], "Mark items as read.", ["CRItemsReadForChat"], [], Nothing, ""),
-- ("APIChatRead", [], "Mark chat as read.", ["CRCmdOk"], [], Nothing, ""),
-- ("APIChatUnread", [], "Mark chat as unread.", ["CRCmdOk"], [], Nothing, ""),
@@ -163,21 +166,27 @@ chatCommandsDocsData =
),
( "User profile commands",
"Most bots don't need to use these commands, as bot profile can be configured manually via CLI or desktop client. These commands can be used by bots that need to manage multiple user profiles (e.g., the profiles of support agents).",
[ ("ShowActiveUser", [], "Get active user profile", ["CRActiveUser", "CRChatCmdError"], [], Nothing, "/user"),
[ ("ShowActiveUser", [], "Get active user profile.", ["CRActiveUser", "CRChatCmdError"], [], Nothing, "/user"),
( "CreateActiveUser",
[],
"Create new user profile",
"Create new user profile.",
["CRActiveUser", "CRChatCmdError"],
[TD "CEUserExists" "User or contact with this name already exists", TD "CEInvalidDisplayName" "Invalid user display name"],
Nothing,
"/_create user " <> Json "newUser"
),
("ListUsers", [], "Get all user profiles", ["CRUsersList", "CRChatCmdError"], [], Nothing, "/users"),
("APISetActiveUser", [], "Set active user profile", ["CRActiveUser", "CRChatCmdError"], ["CEChatNotStarted"], Nothing, "/_user " <> Param "userId" <> Optional "" (" " <> Json "$0") "viewPwd"),
("ListUsers", [], "Get all user profiles.", ["CRUsersList", "CRChatCmdError"], [], Nothing, "/users"),
("APISetActiveUser", [], "Set active user profile.", ["CRActiveUser", "CRChatCmdError"], ["CEChatNotStarted"], Nothing, "/_user " <> Param "userId" <> Optional "" (" " <> Json "$0") "viewPwd"),
("APIDeleteUser", [], "Delete user profile.", ["CRCmdOk", "CRChatCmdError"], [], Just UNBackground, "/_delete user " <> Param "userId" <> OnOffParam "del_smp" "delSMPQueues" Nothing <> Optional "" (" " <> Json "$0") "viewPwd"),
("APIUpdateProfile", [], "Update user profile.", ["CRUserProfileUpdated", "CRUserProfileNoChange", "CRChatCmdError"], [], Just UNBackground, "/_profile " <> Param "userId" <> " " <> Json "profile"),
("APISetContactPrefs", [], "Configure chat preference overrides for the contact.", ["CRContactPrefsUpdated", "CRChatCmdError"], [], Just UNBackground, "/_set prefs @" <> Param "contactId" <> " " <> Json "preferences")
]
),
( "Chat management",
"These commands should not be used with CLI-based bots",
[ ("StartChat", [], "Start chat controller.", ["CRChatStarted", "CRChatRunning"], [], Nothing, "/_start"),
("APIStopChat", [], "Stop chat controller.", ["CRChatStopped"], [], Nothing, "/_stop")
]
)
]
@@ -341,6 +350,7 @@ undocumentedCommands =
"APIGetAppSettings",
"APIGetCallInvitations",
"APIGetChat",
"APIGetChatContentTypes",
"APIGetChatItemInfo",
"APIGetChatItems",
"APIGetChatItemTTL",
@@ -392,11 +402,9 @@ undocumentedCommands =
"APISetServerOperators",
"APISetUserContactReceipts",
"APISetUserGroupReceipts",
"APISetUserAutoAcceptMemberContacts",
"APISetUserServers",
"APISetUserUIThemes",
"APIStandaloneFileInfo",
"APIStopChat",
"APIStorageEncryption",
"APISuspendChat",
"APISwitchContact",
@@ -453,7 +461,6 @@ undocumentedCommands =
"SetTempFolder",
"SetUserProtoServers",
"SlowSQLQueries",
"StartChat",
"StartRemoteHost",
"StopRemoteCtrl",
"StopRemoteHost",
+9 -4
View File
@@ -136,6 +136,14 @@ chatEventsDocsData =
],
[]
),
( "Network connection events",
"",
[ ("CEvtHostConnected", "Messaging or file server connected"),
("CEvtHostDisconnected", "Messaging or file server disconnected"),
("CEvtSubscriptionStatus", "Messaging subscription status changed")
],
[]
),
( "Error events",
"Bots may log these events for debugging. \
\There will be many error events - this does NOT indicate a malfunction - \
@@ -143,7 +151,7 @@ chatEventsDocsData =
\or because messages may be delivered to deleted chats for a short period of time \
\(they will be ignored).",
[ ("CEvtMessageError", ""),
("CEvtChatError", ""), -- only used in WebSockets API, Haskell code uses Either, with error in Left
("CEvtChatError", "Chat error (only used in WebSockets API)."), -- Haskell code uses Either, with error in Left
("CEvtChatErrors", "")
],
[]
@@ -178,10 +186,7 @@ undocumentedEvents =
"CEvtCustomChatEvent",
"CEvtGroupMemberRatchetSync",
"CEvtGroupMemberSwitch",
"CEvtHostConnected",
"CEvtHostDisconnected",
"CEvtServiceSubStatus",
"CEvtSubscriptionStatus",
"CEvtNewRemoteHost",
"CEvtNoMemberContactCreating",
"CEvtNtfMessage",
+1 -1
View File
@@ -73,7 +73,7 @@ syntaxText :: TypeAndFields -> Expr -> Text
syntaxText r syntax =
"\n**Syntax**:\n"
<> "\n```\n" <> docSyntaxText r syntax <> "\n```\n"
<> (if isConst syntax then "" else "\n```javascript\n" <> jsSyntaxText False r syntax <> " // JavaScript\n```\n")
<> (if isConst syntax then "" else "\n```javascript\n" <> jsSyntaxText False "" r syntax <> " // JavaScript\n```\n")
<> (if isConst syntax then "" else "\n```python\n" <> pySyntaxText r syntax <> " # Python\n```\n")
camelToSpace :: String -> String
+6 -6
View File
@@ -49,7 +49,7 @@ commandsCodeText =
<> "}\n\n"
<> ("export namespace " <> T.pack constrName <> " {\n")
<> (" export type Response = " <> constrsCode " " "CR" (("CR." <> ) . T.pack . fstToUpper . memberTag) (map responseType responses))
<> (if syntax == "" then "" else funcCode APITypeDef {typeName' = constrName, typeDef = ATDRecord params} syntax)
<> (if syntax == "" then "" else funcCode APITypeDef {typeName' = constrName, typeDef = ATDRecord params} "T." syntax)
<> "}\n"
where
constrName = fstToUpper tag
@@ -86,7 +86,7 @@ typesCodeText = ("// API Types\n// " <> autoGenerated <> "\n") <> foldMap typeCo
"ConnectionMode" -> T.pack $ map toUpper tag
"FileProtocol" -> T.pack $ map toUpper tag
_ -> T.replace "-" "_" $ T.pack $ fstToUpper tag
namespaceFuncCode = "\nexport namespace " <> name' <> " {" <> funcCode td typeSyntax <> "}\n"
namespaceFuncCode = "\nexport namespace " <> name' <> " {" <> funcCode td "" typeSyntax <> "}\n"
typeDefCode = case typeDef of
ATDRecord fields ->
("\nexport interface " <> name' <> " {\n")
@@ -107,7 +107,7 @@ unionTypeCode unionNamespace typesNamespace td@APITypeDef {typeName' = name} cs
<> (" export type Tag = " <> constrsCode " " name' constrTag (L.toList cs) <> "\n")
<> (" interface Interface {\n type: Tag\n }\n")
<> foldMap constrType cs
<> (if cmdSyntax == "" then "" else funcCode td cmdSyntax)
<> (if cmdSyntax == "" then "" else funcCode td typesNamespace cmdSyntax)
<> "}\n"
where
name' = T.pack name
@@ -128,9 +128,9 @@ constrsCode indent name' constr cs
line = T.intercalate " | " cs'
cs' = map constr cs
funcCode :: APITypeDef -> Expr -> Text
funcCode td@APITypeDef {typeName' = name, typeDef} cmdSyntax =
"\n export function cmdString(" <> param <> ": " <> T.pack name <> "): string {\n return " <> jsSyntaxText True (name, self : typeFields) cmdSyntax <> "\n }\n"
funcCode :: APITypeDef -> String -> Expr -> Text
funcCode td@APITypeDef {typeName' = name, typeDef} typeNamespace cmdSyntax =
"\n export function cmdString(" <> param <> ": " <> T.pack name <> "): string {\n return " <> jsSyntaxText True typeNamespace (name, self : typeFields) cmdSyntax <> "\n }\n"
where
param = if hasParams cmdSyntax then "self" else "_self"
self = APIRecordField "self" (ATDef td)
+5 -4
View File
@@ -51,8 +51,11 @@ chatResponsesDocsData =
("CRChatItemReaction", "Message reaction"),
("CRChatItemUpdated", "Message updated"),
("CRChatItemsDeleted", "Messages deleted"),
("CRChatRunning", ""),
("CRChatStarted", ""),
("CRChatStopped", ""),
("CRCmdOk", "Ok"),
("CRChatCmdError", "Command error"), -- only used in WebSockets API, Haskell code uses Either, with error in Left
("CRChatCmdError", "Command error (only used in WebSockets API)"), -- Haskell code uses Either, with error in Left
("CRConnectionPlan", "Connection link information"),
("CRContactAlreadyExists", ""),
("CRContactConnectionDeleted", "Connection deleted"),
@@ -121,15 +124,13 @@ undocumentedResponses =
"CRBroadcastSent",
"CRCallInvitations",
"CRChatCleared",
"CRChatContentTypes",
"CRChatHelp",
"CRChatItemId",
"CRChatItemInfo",
"CRChatItems",
"CRChatItemTTL",
"CRChatRunning",
"CRChats",
"CRChatStarted",
"CRChatStopped",
"CRConnectionsDiff",
"CRChatTags",
"CRConnectionAliasUpdated",
+3 -3
View File
@@ -99,8 +99,8 @@ withOptBoolParam r param p f =
(ATOptional (ATPrim (PT TBool))) -> f True
_ -> paramError r param p "is not [optional] boolean"
jsSyntaxText :: Bool -> TypeAndFields -> Expr -> Text
jsSyntaxText useSelf r = T.replace "' + '" "" . T.pack . go Nothing True
jsSyntaxText :: Bool -> String -> TypeAndFields -> Expr -> Text
jsSyntaxText useSelf typeNamespace r = T.replace "' + '" "" . T.pack . go Nothing True
where
go param top = \case
Concat exs -> intercalate " + " $ map (go param False) $ L.toList exs
@@ -112,7 +112,7 @@ jsSyntaxText useSelf r = T.replace "' + '" "" . T.pack . go Nothing True
_ -> paramName' useSelf param p
where
toStringSyntax (APITypeDef typeName _)
| typeHasSyntax typeName = paramName' useSelf param p <> ".toString()"
| typeHasSyntax typeName = typeNamespace <> typeName <> ".cmdString(" <> paramName' useSelf param p <> ")"
| otherwise = paramName' useSelf param p
Optional exN exJ p -> open <> n <> " ? " <> go (Just p) False exJ <> " : " <> nothing <> close
where
+4 -1
View File
@@ -176,6 +176,7 @@ ciQuoteType =
updateRecord (RecordTypeInfo name fields) = RecordTypeInfo name $ map optChatDir fields
in st {recordTypes = map updateRecord records} -- need to map even though there is one constructor in this type
-- type info, JSON encoding, constructor prefix, removed constructors, string encoding for commands, description
chatTypesDocsData :: [(SumTypeInfo, SumTypeJsonEncoding, String, [ConsName], Expr, Text)]
chatTypesDocsData =
[ ((sti @(Chat 'CTDirect)) {typeName = "AChat"}, STRecord, "", [], "", ""),
@@ -239,7 +240,7 @@ chatTypesDocsData =
(sti @ConnectionErrorType, STUnion, "", [], "", ""),
(sti @ConnectionMode, (STEnum' $ take 3 . consLower "CM"), "", [], "", ""),
(sti @ConnectionPlan, STUnion, "CP", [], "", ""),
(sti @ConnStatus, (STEnum' $ consSep "Conn" '-'), "", [], "", ""),
(sti @ConnStatus, STUnion, "Conn", [], "", ""),
(sti @ConnType, (STEnum' $ consSep "Conn" '_'), "", [], "", ""),
(sti @Contact, STRecord, "", [], "", ""),
(sti @ContactAddressPlan, STUnion, "CAP", [], "", ""),
@@ -332,6 +333,7 @@ chatTypesDocsData =
(sti @SndGroupEvent, STUnion, "SGE", [], "", ""),
(sti @SrvError, STUnion, "SrvErr", [], "", ""),
(sti @StoreError, STUnion, "SE", [], "", ""),
(sti @SubscriptionStatus, STUnion, "SS", [], "", ""),
(sti @SwitchPhase, STEnum, "SP", [], "", ""),
(sti @TimedMessagesGroupPreference, STRecord, "", [], "", ""),
(sti @TimedMessagesPreference, STRecord, "", [], "", ""),
@@ -522,6 +524,7 @@ deriving instance Generic SndFileTransfer
deriving instance Generic SndGroupEvent
deriving instance Generic SrvError
deriving instance Generic StoreError
deriving instance Generic SubscriptionStatus
deriving instance Generic SwitchPhase
deriving instance Generic TimedMessagesGroupPreference
deriving instance Generic TimedMessagesPreference
+2
View File
@@ -194,6 +194,7 @@ toTypeInfo tr =
primitiveToLower st@(ST t ps) = let t' = fstToLower t in if t' `elem` primitiveTypes then ST t' ps else st
stringTypes =
[ "AConnectionLink",
"AProtocolType",
"AgentConnId",
"AgentInvId",
"AgentRcvFileId",
@@ -212,6 +213,7 @@ toTypeInfo tr =
"ProtocolServer",
"SbKey",
"SharedMsgId",
"TransportHost",
"UIColor",
"UserPwd",
"XContactId"