diff --git a/bots/api/TYPES.md b/bots/api/TYPES.md index 4546a6aaa7..9708bf94a2 100644 --- a/bots/api/TYPES.md +++ b/bots/api/TYPES.md @@ -1144,6 +1144,11 @@ SimplexDomainNotReady: - simplexDomain: [SimplexDomain](#simplexdomain) - simplexDomainError: [SimplexDomainError](#simplexdomainerror) +NameRegistrationFailed: +- type: "nameRegistrationFailed" +- nameRegCode: string +- nameRegMessage: string? + NotResolvedLocally: - type: "notResolvedLocally" diff --git a/packages/simplex-chat-client/types/typescript/src/types.ts b/packages/simplex-chat-client/types/typescript/src/types.ts index 5faf084dce..354cf9ddfa 100644 --- a/packages/simplex-chat-client/types/typescript/src/types.ts +++ b/packages/simplex-chat-client/types/typescript/src/types.ts @@ -1080,6 +1080,7 @@ export type ChatErrorType = | ChatErrorType.ChatStoreChanged | ChatErrorType.InvalidConnReq | ChatErrorType.SimplexDomainNotReady + | ChatErrorType.NameRegistrationFailed | ChatErrorType.NotResolvedLocally | ChatErrorType.UnsupportedConnReq | ChatErrorType.ConnReqMessageProhibited @@ -1159,6 +1160,7 @@ export namespace ChatErrorType { | "chatStoreChanged" | "invalidConnReq" | "simplexDomainNotReady" + | "nameRegistrationFailed" | "notResolvedLocally" | "unsupportedConnReq" | "connReqMessageProhibited" @@ -1320,6 +1322,12 @@ export namespace ChatErrorType { simplexDomainError: SimplexDomainError } + export interface NameRegistrationFailed extends Interface { + type: "nameRegistrationFailed" + nameRegCode: string + nameRegMessage?: string + } + export interface NotResolvedLocally extends Interface { type: "notResolvedLocally" } diff --git a/packages/simplex-chat-python/src/simplex_chat/types/_types.py b/packages/simplex-chat-python/src/simplex_chat/types/_types.py index b00a559f92..dd813edf31 100644 --- a/packages/simplex-chat-python/src/simplex_chat/types/_types.py +++ b/packages/simplex-chat-python/src/simplex_chat/types/_types.py @@ -820,6 +820,11 @@ class ChatErrorType_simplexDomainNotReady(TypedDict): simplexDomain: "SimplexDomain" simplexDomainError: "SimplexDomainError" +class ChatErrorType_nameRegistrationFailed(TypedDict): + type: Literal["nameRegistrationFailed"] + nameRegCode: str + nameRegMessage: NotRequired[str] + class ChatErrorType_notResolvedLocally(TypedDict): type: Literal["notResolvedLocally"] @@ -1054,6 +1059,7 @@ ChatErrorType = ( | ChatErrorType_chatStoreChanged | ChatErrorType_invalidConnReq | ChatErrorType_simplexDomainNotReady + | ChatErrorType_nameRegistrationFailed | ChatErrorType_notResolvedLocally | ChatErrorType_unsupportedConnReq | ChatErrorType_connReqMessageProhibited @@ -1111,7 +1117,7 @@ ChatErrorType = ( | ChatErrorType_exception ) -ChatErrorType_Tag = Literal["noActiveUser", "noConnectionUser", "noSndFileUser", "noRcvFileUser", "userUnknown", "userExists", "chatRelayExists", "differentActiveUser", "cantDeleteActiveUser", "cantDeleteLastUser", "cantHideLastUser", "hiddenUserAlwaysMuted", "emptyUserPassword", "userAlreadyHidden", "userNotHidden", "invalidDisplayName", "chatNotStarted", "chatNotStopped", "chatStoreChanged", "invalidConnReq", "simplexDomainNotReady", "notResolvedLocally", "unsupportedConnReq", "connReqMessageProhibited", "contactNotReady", "contactNotActive", "contactDisabled", "connectionDisabled", "groupUserRole", "groupMemberInitialRole", "contactIncognitoCantInvite", "groupIncognitoCantInvite", "groupContactRole", "groupDuplicateMember", "groupDuplicateMemberId", "groupNotJoined", "groupMemberNotActive", "cantBlockMemberForSelf", "groupMemberUserRemoved", "groupMemberNotFound", "groupCantResendInvitation", "groupInternal", "fileNotFound", "fileSize", "fileAlreadyReceiving", "fileCancelled", "fileCancel", "fileAlreadyExists", "fileWrite", "fileSend", "fileRcvChunk", "fileInternal", "fileImageType", "fileImageSize", "fileNotReceived", "fileNotApproved", "fallbackToSMPProhibited", "inlineFileProhibited", "invalidForward", "invalidChatItemUpdate", "invalidChatItemDelete", "hasCurrentCall", "noCurrentCall", "callContact", "directMessagesProhibited", "agentVersion", "agentNoSubResult", "commandError", "agentCommandError", "invalidFileDescription", "connectionIncognitoChangeProhibited", "connectionUserChangeProhibited", "peerChatVRangeIncompatible", "relayTestError", "internalError", "exception"] +ChatErrorType_Tag = Literal["noActiveUser", "noConnectionUser", "noSndFileUser", "noRcvFileUser", "userUnknown", "userExists", "chatRelayExists", "differentActiveUser", "cantDeleteActiveUser", "cantDeleteLastUser", "cantHideLastUser", "hiddenUserAlwaysMuted", "emptyUserPassword", "userAlreadyHidden", "userNotHidden", "invalidDisplayName", "chatNotStarted", "chatNotStopped", "chatStoreChanged", "invalidConnReq", "simplexDomainNotReady", "nameRegistrationFailed", "notResolvedLocally", "unsupportedConnReq", "connReqMessageProhibited", "contactNotReady", "contactNotActive", "contactDisabled", "connectionDisabled", "groupUserRole", "groupMemberInitialRole", "contactIncognitoCantInvite", "groupIncognitoCantInvite", "groupContactRole", "groupDuplicateMember", "groupDuplicateMemberId", "groupNotJoined", "groupMemberNotActive", "cantBlockMemberForSelf", "groupMemberUserRemoved", "groupMemberNotFound", "groupCantResendInvitation", "groupInternal", "fileNotFound", "fileSize", "fileAlreadyReceiving", "fileCancelled", "fileCancel", "fileAlreadyExists", "fileWrite", "fileSend", "fileRcvChunk", "fileInternal", "fileImageType", "fileImageSize", "fileNotReceived", "fileNotApproved", "fallbackToSMPProhibited", "inlineFileProhibited", "invalidForward", "invalidChatItemUpdate", "invalidChatItemDelete", "hasCurrentCall", "noCurrentCall", "callContact", "directMessagesProhibited", "agentVersion", "agentNoSubResult", "commandError", "agentCommandError", "invalidFileDescription", "connectionIncognitoChangeProhibited", "connectionUserChangeProhibited", "peerChatVRangeIncompatible", "relayTestError", "internalError", "exception"] ChatFeature = Literal["timedMessages", "fullDelete", "reactions", "voice", "files", "calls", "sessions"] diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs index 6c35d408d4..9ab0238960 100644 --- a/src/Simplex/Chat/Controller.hs +++ b/src/Simplex/Chat/Controller.hs @@ -1471,6 +1471,9 @@ data ChatErrorType | CEChatStoreChanged | CEInvalidConnReq | CESimplexDomainNotReady {simplexDomain :: SimplexDomain, simplexDomainError :: SimplexDomainError} + -- | the names service refused the registration; @nameRegCode@ is the protocol + -- error code as sent on the wire, e.g. @name_taken@ + | CENameRegistrationFailed {nameRegCode :: Text, nameRegMessage :: Maybe Text} | CENotResolvedLocally -- a name or link is not a known chat in the local store and online resolution is off (PRMNever) | CEUnsupportedConnReq | CEInvalidChatMessage {connection :: Connection, msgMeta :: Maybe MsgMetaJSON, messageData :: Text, message :: String} diff --git a/src/Simplex/Chat/Library/Commands.hs b/src/Simplex/Chat/Library/Commands.hs index 0ca9b0a38b..d090a98883 100644 --- a/src/Simplex/Chat/Library/Commands.hs +++ b/src/Simplex/Chat/Library/Commands.hs @@ -1479,7 +1479,7 @@ processChatCommand cxt nm = \case progress NRPhaseCommitting Nothing sendNames (NRCommit commitment) >>= \case NRPCommitted {} -> pure () - NRPError {nrCode, nrMessage} -> throwCmdError $ nameRegError nrCode nrMessage + NRPError {nrCode, nrMessage} -> throwChatError $ CENameRegistrationFailed (textEncode nrCode) nrMessage _ -> throwCmdError "unexpected commit response" progress NRPhaseCommitted (Just commitWaitMs) liftIO $ threadDelay $ fromIntegral commitWaitMs * 1000 @@ -1487,7 +1487,7 @@ processChatCommand cxt nm = \case (expiry', txHash') <- sendNames (NRReveal nm' owner secret ttl sLink) >>= \case NRPRegistered {nrExpiry, nrTxHash} -> pure (nrExpiry, nrTxHash) - NRPError {nrCode, nrMessage} -> throwCmdError $ nameRegError nrCode nrMessage + NRPError {nrCode, nrMessage} -> throwChatError $ CENameRegistrationFailed (textEncode nrCode) nrMessage _ -> throwCmdError "unexpected reveal response" progress NRPhaseRegistered Nothing pure $ CRNameRegistered user nm' (tshow owner) expiry' txHash' @@ -1499,8 +1499,6 @@ processChatCommand cxt nm = \case (seed, AccountRef {arIndex}) <- withFastStore' $ \db -> getOrCreateAccountRef db user (atomically $ newSeed MS256 g) either (throwCmdError . ("wallet: " <>)) (pure . accountAddress) $ deriveAccount seed arIndex - nameRegError code message = - "name registration failed: " <> T.unpack (textEncode code) <> maybe "" ((": " <>) . T.unpack) message APISendServiceResponse userId requestId responseData -> withUserId userId $ \user -> do let AgentInvId invId = requestId connId <- withAgent $ \a -> sendServiceReplyAsync a "" (aUserId user) invId (LB.toStrict $ J.encode responseData) diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs index b3274ae201..884c4ffde1 100644 --- a/src/Simplex/Chat/View.hs +++ b/src/Simplex/Chat/View.hs @@ -2806,6 +2806,7 @@ viewChatError isCmd logLevel testView = \case CEAgentNoSubResult connId -> ["no subscription result for connection: " <> sShow connId] CEServerProtocol p -> [plain $ "Servers for protocol " <> strEncode p <> " cannot be configured by the users"] CECommandError e -> ["bad chat command: " <> plain e] + CENameRegistrationFailed code msg -> ["name registration failed: " <> plain code <> maybe "" ((": " <>) . plain) msg] CEAgentCommandError e -> ["agent command error: " <> plain e] CEInvalidFileDescription e -> ["invalid file description: " <> plain e] CEConnectionIncognitoChangeProhibited -> ["incognito mode change prohibited"] diff --git a/tests/Bots/NamesServiceTests.hs b/tests/Bots/NamesServiceTests.hs index 5bebc9270f..3398d5595b 100644 --- a/tests/Bots/NamesServiceTests.hs +++ b/tests/Bots/NamesServiceTests.hs @@ -80,11 +80,11 @@ testNamesRegister ps = -- the owner is the same within a session, so this is the duplicate a user hits. client ##> ("/name register " <> bsLink <> " alice.simplex simplex:/contact#/first") commitPhases client - client <## "bad chat command: name registration failed: name_taken" + client <## "name registration failed: name_taken" -- and the same name pointed at a different link is equally rejected client ##> ("/name register " <> bsLink <> " alice.simplex simplex:/contact#/second") commitPhases client - client <## "bad chat command: name registration failed: name_taken" + client <## "name registration failed: name_taken" where commitPhases client = do client <## "name alice.simplex: committing"