This commit is contained in:
spaced4ndy
2026-07-06 16:01:46 +04:00
parent bc39692958
commit e58aa1625e
10 changed files with 16 additions and 14 deletions
+3 -3
View File
@@ -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**:
+1 -1
View File
@@ -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)
+2 -1
View File
@@ -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
+2 -2
View File
@@ -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?)
+3
View File
@@ -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
+1 -4
View File
@@ -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