Secret ChatsUSER-ONLY
Secret chats are one-to-one, end-to-end encrypted conversations available to user clients. MTKruto handles the key exchange, encryption, and key rotation.
A secret chat has its own identifier. Use the other user’s ordinary chat identifier only to request one; methods that operate on it use the returned secret chat identifier.
Persisting Secret Chats
MTKruto stores secret chat keys and sequencing state in the client cache. To keep secret chats usable after a restart, use persistent storage and set persistCache to true.
const client = new Client({
storage,
persistCache: true,
// ...
});
The storage contains secret chat key material and must be protected.
Requesting a Secret Chat
Use requestSecretChat with the identifier of a private chat.
const secretChat = await client.requestSecretChat(chatId);
console.log(secretChat.id);
console.log(secretChat.type); // "pending"
Keep secretChat.id. It is the identifier used by every method that operates on the secret chat.
Handling Secret Chat States
The secretChat update contains a SecretChat whenever a secret chat changes state. Access it through ctx.secretChat.
pendingmeans the request was sent and is waiting for the other user.requestedmeans the other user requested a secret chat.activemeans messages can be sent.discardedmeans the secret chat has ended.
Accept incoming requests with acceptSecretChat. Check userId before accepting one.
client.on("secretChat", async (ctx) => {
const secretChat = ctx.secretChat;
if (
secretChat.type === "requested" &&
secretChat.userId === expectedUserId
) {
await ctx.acceptSecretChat();
}
});
Wait for an active secret chat before sending messages.
Sending Messages
Use sendSecretMessage with the secret chat identifier.
await client.sendSecretMessage(secretChatId, "This message is encrypted.");
Set ttl to request a self-destruct timer in seconds. A value of 0 disables the timer.
await client.sendSecretMessage(secretChatId, "This message expires.", {
ttl: 30,
});
Text and captions support parseMode and SecretMessageEntity objects. Secret message identifiers are strings. Pass one as replyToMessageId to quote a message.
await client.sendSecretMessage(secretChatId, "**Understood.**", {
parseMode: "Markdown",
replyToMessageId: message.id,
});
Secret sending methods return void, not the outgoing message.
Sending Media and Other Content
Secret chats have separate methods for each supported content type:
- sendSecretPhoto, sendSecretVideo, and sendSecretAnimation
- sendSecretDocument, sendSecretAudio, and sendSecretVoice
- sendSecretVideoNote and sendSecretSticker
- sendSecretLocation, sendSecretVenue, and sendSecretContact
File methods accept a FileSource. MTKruto encrypts the file before uploading it.
await client.sendSecretPhoto(secretChatId, "./photo.jpg", {
caption: "Encrypted photo",
ttl: 30,
});
Handling Secret Messages
Incoming messages arrive in the secretMessage update as a SecretMessage. Access them through ctx.secretMessage, not ctx.msg.
client.on("secretMessage", (ctx) => {
const message = ctx.secretMessage;
console.log(message.chatId, message.id, message.type, message.ttl);
});
Secret messages do not contain an ordinary chat or user. Keep the corresponding secret chat’s userId if the participant’s identity is needed.
Filter secret messages by content type when needed.
client.on("secretMessage:text", async (ctx) => {
console.log(ctx.secretMessage.text);
await ctx.replySecret("Received.", { isQuoted: true });
});
If an application stores or displays secret messages, it must respect each message’s ttl.
Downloading Secret Media
Encrypted media includes fileInformation. Pass it to download with the file identifier so MTKruto can decrypt the file.
client.on("secretMessage:document", async (ctx) => {
const message = ctx.secretMessage;
for await (
const chunk of client.download(message.document.fileId, {
fileInformation: message.fileInformation,
})
) {
// Process the decrypted chunk.
}
});
Typing and Screenshots
Use sendSecretTypingAction and sendSecretCancelTypingAction to update the typing state. The secretTyping update contains the identifier of a secret chat in which the other user is typing.
await client.sendSecretTypingAction(secretChatId);
await client.sendSecretCancelTypingAction(secretChatId);
client.on("secretTyping", (ctx) => {
console.log(ctx.update.chatId);
});
If the application detects a screenshot, use sendSecretScreenshotNotification to notify the other participant. MTKruto does not detect screenshots.
await client.sendSecretScreenshotNotification(secretChatId, [message.id]);
Ending a Secret Chat
Use endSecretChat to discard a secret chat. Set isHistoryDeleted to request deletion of its history.
await client.endSecretChat(secretChatId, {
isHistoryDeleted: true,
});