mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-08-28 09:44:15 +00:00
wip
This commit is contained in:
@@ -289,15 +289,15 @@ Send messages.
|
||||
**Syntax**:
|
||||
|
||||
```
|
||||
/_send <str(sendRef)>[ live=on][ ttl=<ttl>] json <json(composedMessages)>
|
||||
/_send <str(sendRef)>[ live=on][ ttl=<ttl>][ sign=on] json <json(composedMessages)>
|
||||
```
|
||||
|
||||
```javascript
|
||||
'/_send ' + ChatRef.cmdString(sendRef) + (liveMessage ? ' live=on' : '') + (ttl ? ' ttl=' + ttl : '') + ' json ' + JSON.stringify(composedMessages) // JavaScript
|
||||
'/_send ' + ChatRef.cmdString(sendRef) + (liveMessage ? ' live=on' : '') + (ttl ? ' ttl=' + ttl : '') + (signMessages ? ' sign=on' : '') + ' json ' + JSON.stringify(composedMessages) // JavaScript
|
||||
```
|
||||
|
||||
```python
|
||||
'/_send ' + ChatRef_cmd_string(sendRef) + (' live=on' if liveMessage else '') + ((' ttl=' + str(ttl)) if ttl is not None else '') + ' json ' + json.dumps(composedMessages) # Python
|
||||
'/_send ' + ChatRef_cmd_string(sendRef) + (' live=on' if liveMessage else '') + ((' ttl=' + str(ttl)) if ttl is not None else '') + (' sign=on' if signMessages else '') + ' json ' + json.dumps(composedMessages) # Python
|
||||
```
|
||||
|
||||
**Responses**:
|
||||
|
||||
@@ -86,7 +86,7 @@ chatCommandsDocsData =
|
||||
),
|
||||
( "Message commands",
|
||||
"Commands to send, update, delete, moderate messages and set message reactions",
|
||||
[ ("APISendMessages", [], "Send messages.", ["CRNewChatItems", "CRChatCmdError"], [], Just UNBackground, "/_send " <> Param "sendRef" <> OnOffParam "live" "liveMessage" (Just False) <> Optional "" (" ttl=" <> Param "$0") "ttl" <> " json " <> Json "composedMessages"),
|
||||
[ ("APISendMessages", [], "Send messages.", ["CRNewChatItems", "CRChatCmdError"], [], Just UNBackground, "/_send " <> Param "sendRef" <> OnOffParam "live" "liveMessage" (Just False) <> Optional "" (" ttl=" <> Param "$0") "ttl" <> OnOffParam "sign" "signMessages" (Just False) <> " json " <> Json "composedMessages"),
|
||||
( "APIUpdateChatItem",
|
||||
[],
|
||||
"Update message.",
|
||||
|
||||
@@ -97,7 +97,7 @@ export namespace APISendMessages {
|
||||
export type Response = CR.NewChatItems | CR.ChatCmdError
|
||||
|
||||
export function cmdString(self: APISendMessages): string {
|
||||
return '/_send ' + T.ChatRef.cmdString(self.sendRef) + (self.liveMessage ? ' live=on' : '') + (self.ttl ? ' ttl=' + self.ttl : '') + ' json ' + JSON.stringify(self.composedMessages)
|
||||
return '/_send ' + T.ChatRef.cmdString(self.sendRef) + (self.liveMessage ? ' live=on' : '') + (self.ttl ? ' ttl=' + self.ttl : '') + (self.signMessages ? ' sign=on' : '') + ' json ' + JSON.stringify(self.composedMessages)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ export class ChatClient {
|
||||
|
||||
async apiSendMessages(chatType: T.ChatType, chatId: number, messages: T.ComposedMessage[]): Promise<T.AChatItem[]> {
|
||||
const r = await this.sendChatCmd(
|
||||
CC.APISendMessages.cmdString({sendRef: {chatType, chatId}, composedMessages: messages, liveMessage: false})
|
||||
CC.APISendMessages.cmdString({sendRef: {chatType, chatId}, composedMessages: messages, liveMessage: false, signMessages: false})
|
||||
)
|
||||
if (r.type === "newChatItems") return r.chatItems
|
||||
throw new ChatCommandError("unexpected response", r)
|
||||
|
||||
@@ -423,7 +423,8 @@ export class ChatApi {
|
||||
CC.APISendMessages.cmdString({
|
||||
sendRef,
|
||||
composedMessages: messages,
|
||||
liveMessage
|
||||
liveMessage,
|
||||
signMessages: false
|
||||
})
|
||||
)
|
||||
if (r.type === "newChatItems") return r.chatItems
|
||||
|
||||
@@ -193,6 +193,7 @@ class ChatApi:
|
||||
"sendRef": send_ref,
|
||||
"composedMessages": messages,
|
||||
"liveMessage": live_message,
|
||||
"signMessages": False,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -85,7 +85,7 @@ class APISendMessages(TypedDict):
|
||||
|
||||
|
||||
def APISendMessages_cmd_string(self: APISendMessages) -> str:
|
||||
return '/_send ' + T.ChatRef_cmd_string(self['sendRef']) + (' live=on' if self['liveMessage'] else '') + ((' ttl=' + str(self.get('ttl'))) if self.get('ttl') is not None else '') + ' json ' + json.dumps(self['composedMessages'])
|
||||
return '/_send ' + T.ChatRef_cmd_string(self['sendRef']) + (' live=on' if self['liveMessage'] else '') + ((' ttl=' + str(self.get('ttl'))) if self.get('ttl') is not None else '') + (' sign=on' if self['signMessages'] else '') + ' json ' + json.dumps(self['composedMessages'])
|
||||
|
||||
APISendMessages_Response = CR.NewChatItems | CR.ChatCmdError
|
||||
|
||||
|
||||
@@ -839,10 +839,10 @@ processChatCommand cxt nm = \case
|
||||
SMDRcv -> False
|
||||
itemsMsgIds :: [CChatItem c] -> [SharedMsgId]
|
||||
itemsMsgIds = mapMaybe (\(CChatItem _ ChatItem {meta = CIMeta {itemSharedMsgId}}) -> itemSharedMsgId)
|
||||
-- per-item self/history delete signer: sign iff the target item was held signed (preserves self-delete deniability)
|
||||
-- history delete always signs (attributable owner action); self-delete signs iff the target was held signed (deniability)
|
||||
delEventSigned :: GroupInfo -> Maybe GroupChatScopeInfo -> Bool -> CChatItem 'CTGroup -> Maybe (Maybe MsgSigning, ChatMsgEvent 'Json)
|
||||
delEventSigned gInfo chatScopeInfo onlyHistory (CChatItem _ ChatItem {meta = CIMeta {itemSharedMsgId, msgSigned}}) =
|
||||
(\msgId -> let evt = XMsgDel msgId Nothing (toMsgScope gInfo <$> chatScopeInfo) onlyHistory in (groupMsgSigning (isJust msgSigned) gInfo evt, evt)) <$> itemSharedMsgId
|
||||
(\msgId -> let evt = XMsgDel msgId Nothing (toMsgScope gInfo <$> chatScopeInfo) onlyHistory in (groupMsgSigning (onlyHistory || isJust msgSigned) gInfo evt, evt)) <$> itemSharedMsgId
|
||||
APIDeleteMemberChatItem gId itemIds -> withUser $ \user -> withGroupLock "deleteChatItem" gId $ do
|
||||
(gInfo, items) <- getCommandGroupChatItems user gId itemIds
|
||||
-- TODO [knocking] check scope is Nothing for all items? (prohibit moderation in support chats?)
|
||||
|
||||
@@ -2351,6 +2351,9 @@ processAgentMessageConn cxt user@User {userId} corrId agentConnId agentMessage =
|
||||
| senderRole < GRModerator -> do
|
||||
messageError $ "x.msg.del: message not found, message of another member with insufficient member permissions, " <> tshow e
|
||||
pure Nothing
|
||||
-- a forged unsigned moderation would pre-censor a not-yet-received post via CIModeration; require verified (relay moderation always signs)
|
||||
| useRelays' gInfo && msgSigned /= Just MSSVerified ->
|
||||
messageError ("x.msg.del: unverified moderation of message not yet received, " <> tshow e) $> Nothing
|
||||
| otherwise -> case scope_ of
|
||||
Just (MSMember scopeMemberId) ->
|
||||
withStore $ \db -> do
|
||||
|
||||
@@ -105,10 +105,7 @@ batchDeliveryTasks1 _vr maxLen = toResult . foldl' addToBatch ([], [], [], 0, 0)
|
||||
|
||||
-- | Encode a batch element for relay groups: ><GrpMsgForward>[/<sigs>]<body>.
|
||||
encodeFwdElement :: GrpMsgForward -> VerifiedMsg 'Json -> ByteString
|
||||
encodeFwdElement fwd@GrpMsgForward {fwdSender} verifiedMsg
|
||||
| FwdChannel <- fwdSender, isJust signedMsg_ =
|
||||
error "encodeFwdElement: signed message must forward as FwdMember, not FwdChannel"
|
||||
| otherwise = ">" <> smpEncode fwd <> encodeBatchElement signedMsg_ msgBody
|
||||
encodeFwdElement fwd verifiedMsg = ">" <> smpEncode fwd <> encodeBatchElement signedMsg_ msgBody
|
||||
where
|
||||
(_, signedMsg_, msgBody) = verifiedMsgParts verifiedMsg
|
||||
|
||||
|
||||
Reference in New Issue
Block a user