Merge branch 'master' of https://github.com/simplex-chat/simplex-chat into ab/names-lookup-api

This commit is contained in:
Alain Brenzikofer
2026-09-28 08:34:34 +02:00
244 changed files with 35454 additions and 494 deletions
+1 -1
View File
@@ -446,7 +446,7 @@ data ChatCommand
| APIGetCallInvitations
| APICallStatus ContactId WebRTCCallStatus
| APIUpdateProfile {userId :: UserId, profile :: Profile}
| APISetUserDomain {userId :: UserId, simplexDomain :: Maybe SimplexDomain}
| APISetUserDomain {userId :: UserId, simplexDomain :: Maybe (StrJSON "SimplexDomain" SimplexDomain)}
| APISetContactPrefs {contactId :: ContactId, preferences :: Preferences}
| APISetContactAlias {contactId :: ContactId, localAlias :: LocalAlias}
| APISetGroupAlias {groupId :: GroupId, localAlias :: LocalAlias}
+3 -2
View File
@@ -1595,7 +1595,8 @@ processChatCommand cxt nm = \case
withCurrentCall contactId $ \user ct call ->
updateCallItemStatus user ct call receivedStatus Nothing $> Just call
APIUpdateProfile userId profile -> withUserId userId (`updateProfile` profile)
APISetUserDomain userId domain_ -> withUserId userId $ \user@User {profile = p@LocalProfile {contactLink, contactDomain}} ->
APISetUserDomain userId strDomain_ -> withUserId userId $ \user@User {profile = p@LocalProfile {contactLink, contactDomain}} -> do
let domain_ = unStrJSON <$> strDomain_
if (claimDomain <$> contactDomain) == domain_
then pure $ CRUserProfileNoChange user
else do
@@ -6211,7 +6212,7 @@ chatCommandP =
"/_call status @" *> (APICallStatus <$> A.decimal <* A.space <*> strP),
"/_call get" $> APIGetCallInvitations,
"/_profile " *> (APIUpdateProfile <$> A.decimal <* A.space <*> jsonP),
"/_set domain " *> (APISetUserDomain <$> A.decimal <*> optional (A.space *> strP)),
"/_set domain " *> (APISetUserDomain <$> A.decimal <*> optional (A.space *> (StrJSON <$> strP))),
"/_set alias @" *> (APISetContactAlias <$> A.decimal <*> (A.space *> textP <|> pure "")),
"/_set alias #" *> (APISetGroupAlias <$> A.decimal <*> (A.space *> textP <|> pure "")),
"/_set alias :" *> (APISetConnectionAlias <$> A.decimal <*> (A.space *> textP <|> pure "")),
+10 -6
View File
@@ -443,10 +443,11 @@ xftpSndFileTransfer_ user file@(CryptoFile filePath cfArgs) fileSize n contactOr
fInv = (xftpFileInvitation fileName fileSize dummyFileDescr :: FileInvitation) {fileBadge}
fsFilePath <- lift $ toFSFilePath filePath
let srcFile = CryptoFile fsFilePath cfArgs
aFileId <- withAgent $ \a -> xftpSendFile a (aUserId user) srcFile (roundedFDCount n) Nothing
aFileId <- withAgent $ \a -> xftpPrepareSendFile a (aUserId user) srcFile (roundedFDCount n) Nothing
-- TODO CRSndFileStart event for XFTP
chSize <- asks $ fileChunkSize . config
ft@FileTransferMeta {fileId} <- withStore' $ \db -> createSndFileTransferXFTP db user contactOrGroup_ file fInv (AgentSndFileId aFileId) Nothing chSize
withAgent (`xftpStartSendFile` aFileId)
let fileSource = Just $ CryptoFile filePath cfArgs
ciFile = CIFile {fileId, fileName, fileSize, fileSource, fileStatus = CIFSSndStored, fileProtocol = FPXFTP, fileExpires = Nothing, fileProhibited = Nothing}
pure (fInv, ciFile, ft)
@@ -485,9 +486,10 @@ xftpSndFileRedirect user ftId vfd = do
let fileName = "redirect.yaml"
file = CryptoFile fileName Nothing
fInv = xftpFileInvitation fileName (fromIntegral $ B.length $ strEncode vfd) dummyFileDescr
aFileId <- withAgent $ \a -> xftpSendDescription a (aUserId user) vfd (roundedFDCount 1)
aFileId <- withAgent $ \a -> xftpPrepareSendDescription a (aUserId user) vfd (roundedFDCount 1)
chSize <- asks $ fileChunkSize . config
withStore' $ \db -> createSndFileTransferXFTP db user Nothing file fInv (AgentSndFileId aFileId) (Just ftId) chSize
ft <- withStore' $ \db -> createSndFileTransferXFTP db user Nothing file fInv (AgentSndFileId aFileId) (Just ftId) chSize
ft <$ withAgent (`xftpStartSendFile` aFileId)
dummyFileDescr :: FileDescr
dummyFileDescr = FileDescr {fileDescrText = "", fileDescrPartNo = 0, fileDescrComplete = False}
@@ -852,9 +854,10 @@ receiveViaCompleteFD user fileId RcvFileDescr {fileDescrText, fileDescrComplete}
where
receive' :: ValidFileDescription 'FRecipient -> Bool -> CM ()
receive' rd approved = do
aFileId <- withAgent $ \a -> xftpReceiveFile a (aUserId user) rd cfArgs approved
aFileId <- withAgent $ \a -> xftpPrepareReceiveFile a (aUserId user) rd cfArgs approved
startReceivingFile user fileId
withStore' $ \db -> updateRcvFileAgentId db fileId (Just $ AgentRcvFileId aFileId)
withAgent (`xftpStartReceiveFile` aFileId)
getUnknownSrvs :: [XFTPServer] -> CM [XFTPServer]
getUnknownSrvs srvs = do
knownSrvs <- L.map protoServer' <$> getKnownAgentServers SPXFTP user
@@ -905,13 +908,14 @@ receiveViaURI :: User -> FileDescriptionURI -> CryptoFile -> CM RcvFileTransfer
receiveViaURI user@User {userId} FileDescriptionURI {description} cf@CryptoFile {cryptoArgs} = do
fileId <- withStore $ \db -> createRcvStandaloneFileTransfer db userId cf fileSize chunkSize
-- currently the only use case is user migrating via their configured servers, so we pass approvedRelays = True
aFileId <- withAgent $ \a -> xftpReceiveFile a (aUserId user) description cryptoArgs True
withStore $ \db -> do
aFileId <- withAgent $ \a -> xftpPrepareReceiveFile a (aUserId user) description cryptoArgs True
ft <- withStore $ \db -> do
liftIO $ do
updateRcvFileStatus db fileId FSConnected
updateCIFileStatus db user fileId $ CIFSRcvTransfer 0 1
updateRcvFileAgentId db fileId (Just $ AgentRcvFileId aFileId)
getRcvFileTransfer db user fileId
ft <$ withAgent (`xftpStartReceiveFile` aFileId)
where
FD.ValidFileDescription FD.FileDescription {size = FD.FileSize fileSize, chunkSize = FD.FileSize chunkSize} = description
+5 -5
View File
@@ -518,11 +518,11 @@ displayNameTextP_ = (,"") <$> quoted '\'' <|> splitPunctuation <$> takeNameTill
refChar c = c > ' ' && c /= '#' && c /= '@' && c /= '\''
commandTextP :: Parser (Text, Text)
commandTextP = do
(cmd, punct) <- displayNameTextP_
case T.words cmd of
(keyword : _) | T.all (\c -> isAlpha c || isDigit c || c == '_') keyword -> pure (cmd, punct)
_ -> fail "invalid command keyword"
commandTextP = commandText <$> displayNameTextP_
where
commandText (cmd, punct)
| T.null cmd = (punct, "")
| otherwise = (cmd, punct)
splitPunctuation :: Text -> (Text, Text)
splitPunctuation s = (T.dropWhileEnd isPunctuation s, T.takeWhileEnd isPunctuation s)
+1 -1
View File
@@ -66,7 +66,7 @@ data ServicePaymentDestination
address :: Text,
cryptoAmount :: Text
}
deriving (Show)
deriving (Eq, Show)
-- confirmed
data InvoiceStatus = ISOpen | ISPaid | ISExpired
+4 -1
View File
@@ -92,7 +92,7 @@ import Simplex.Messaging.Version hiding (version)
-- This indirection is needed for backward/forward compatibility testing.
-- Testing with real app versions is still needed, as tests use the current code with different version ranges, not the old code.
currentChatVersion :: VersionChat
currentChatVersion = VersionChat 20
currentChatVersion = VersionChat 21
-- This should not be used directly in code, instead use `chatVRange` from ChatConfig (see comment above)
supportedChatVRange :: VersionRangeChat
@@ -140,6 +140,9 @@ groupRosterVersion = VersionChat 19
groupMemberKeyVersion :: VersionChat
groupMemberKeyVersion = VersionChat 20
anyTextCommandsVersion :: VersionChat
anyTextCommandsVersion = VersionChat 21
data ConnectionEntity
= RcvDirectMsgConnection {entityConnection :: Connection, contact :: Maybe Contact}
| RcvGroupMsgConnection {entityConnection :: Connection, groupInfo :: GroupInfo, groupMember :: GroupMember}
@@ -144,7 +144,7 @@ SEARCH r USING INDEX idx_rcv_file_chunk_replicas_rcv_file_chunk_id (rcv_file_chu
SEARCH s USING INTEGER PRIMARY KEY (rowid=?)
Query:
SELECT c.corr_id, cs.user_id, c.command
SELECT c.corr_id, cs.user_id, c.command, c.created_at
FROM commands c
JOIN connections cs USING (conn_id)
WHERE c.command_id = ?
@@ -249,6 +249,26 @@ Plan:
SEARCH snd_files USING INDEX idx_snd_files_status_created_at (status=? AND created_at>?)
USE TEMP B-TREE FOR ORDER BY
Query:
SELECT DISTINCT
s.xftp_host, s.xftp_port, s.xftp_key_hash
FROM rcv_file_chunk_replicas r
JOIN xftp_servers s ON s.xftp_server_id = r.xftp_server_id
JOIN rcv_file_chunks c ON c.rcv_file_chunk_id = r.rcv_file_chunk_id
JOIN rcv_files f ON f.rcv_file_id = c.rcv_file_id
WHERE (f.rcv_file_id = ? OR f.redirect_id = ?) AND r.replica_number = 1
Plan:
MULTI-INDEX OR
INDEX 1
SEARCH f USING INTEGER PRIMARY KEY (rowid=?)
INDEX 2
SEARCH f USING COVERING INDEX idx_rcv_files_redirect_id (redirect_id=?)
SEARCH c USING COVERING INDEX idx_rcv_file_chunks_rcv_file_id (rcv_file_id=?)
SEARCH r USING INDEX idx_rcv_file_chunk_replicas_rcv_file_chunk_id (rcv_file_chunk_id=?)
SEARCH s USING INTEGER PRIMARY KEY (rowid=?)
USE TEMP B-TREE FOR DISTINCT
Query:
SELECT MAX(internal_id)
FROM messages
@@ -1001,7 +1021,7 @@ SEARCH s USING PRIMARY KEY (host=? AND port=?)
SEARCH c USING PRIMARY KEY (conn_id=?)
Query:
SELECT c.user_id, q.conn_id, q.host, q.port, COALESCE(q.server_key_hash, s.key_hash), q.rcv_id, q.rcv_private_key, q.status, c.enable_ntfs, q.client_notice_id,
SELECT c.user_id, q.conn_id, q.rcv_id, q.rcv_private_key, q.status, c.enable_ntfs, q.client_notice_id,
q.rcv_queue_id, q.rcv_primary, q.replace_rcv_queue_id
FROM rcv_queues q
JOIN servers s ON q.host = s.host AND q.port = s.port
@@ -1013,7 +1033,7 @@ SEARCH q USING PRIMARY KEY (host=? AND port=?)
SEARCH c USING PRIMARY KEY (conn_id=?)
Query:
SELECT c.user_id, q.conn_id, q.host, q.port, COALESCE(q.server_key_hash, s.key_hash), q.rcv_id, q.rcv_private_key, q.status, c.enable_ntfs, q.client_notice_id,
SELECT c.user_id, q.conn_id, q.rcv_id, q.rcv_private_key, q.status, c.enable_ntfs, q.client_notice_id,
q.rcv_queue_id, q.rcv_primary, q.replace_rcv_queue_id
FROM rcv_queues q
JOIN servers s ON q.host = s.host AND q.port = s.port
@@ -1025,7 +1045,7 @@ SEARCH q USING PRIMARY KEY (host=? AND port=?)
SEARCH c USING PRIMARY KEY (conn_id=?)
Query:
SELECT c.user_id, q.conn_id, q.host, q.port, COALESCE(q.server_key_hash, s.key_hash), q.rcv_id, q.rcv_private_key, q.status, c.enable_ntfs, q.client_notice_id,
SELECT c.user_id, q.conn_id, q.rcv_id, q.rcv_private_key, q.status, c.enable_ntfs, q.client_notice_id,
q.rcv_queue_id, q.rcv_primary, q.replace_rcv_queue_id
FROM rcv_queues q
JOIN servers s ON q.host = s.host AND q.port = s.port
@@ -1374,6 +1394,10 @@ Query: UPDATE rcv_files SET key = ?, nonce = ?, chunk_size = ?, updated_at = ? W
Plan:
SEARCH rcv_files USING INTEGER PRIMARY KEY (rowid=?)
Query: UPDATE rcv_files SET status = ?, updated_at = ? WHERE (rcv_file_id = ? OR redirect_id = ?) AND status = ?
Plan:
SEARCH rcv_files USING INDEX idx_rcv_files_status_created_at (status=?)
Query: UPDATE rcv_files SET status = ?, updated_at = ? WHERE rcv_file_id = ?
Plan:
SEARCH rcv_files USING INTEGER PRIMARY KEY (rowid=?)
@@ -1430,6 +1454,10 @@ Query: UPDATE snd_files SET status = ?, updated_at = ? WHERE snd_file_id = ?
Plan:
SEARCH snd_files USING INTEGER PRIMARY KEY (rowid=?)
Query: UPDATE snd_files SET status = ?, updated_at = ? WHERE snd_file_id = ? AND status = ?
Plan:
SEARCH snd_files USING INTEGER PRIMARY KEY (rowid=?)
Query: UPDATE snd_messages SET rcpt_internal_id = ?, rcpt_status = ? WHERE conn_id = ? AND internal_snd_id = ?
Plan:
SEARCH snd_messages USING PRIMARY KEY (conn_id=? AND internal_snd_id=?)