import { fetchMessageApi, createMessageApi, updateMessageApi, removeMessageApi, } from "../../api/message"; import { deleteChannelMessage, setChannelMessage } from "../../store/channel"; import { deleteAttachment } from "../../store/file"; import { deleteMessage, setMessage } from "../../store/message"; import { state } from "../../store/state"; import { base64ToBuffer, bufferToBase64, decryptData, encryptData, generateIv, } from "../crypto"; import { fetchMedia } from "../file"; const fetchMessage = async (id: string, communityId: string) => { const data = await fetchMessageApi({ id: id, }); if (typeof data.error === "string") { return; } try { const decrypted = await decryptMessage(communityId, data.text, data.iv); if (!decrypted) { return; } setMessage({ ...data, text: decrypted, }); } catch {} data.attachments.forEach((attachmentId) => { fetchMedia(communityId, attachmentId); }); }; const createMessage = async ( communityId: string, channelId: string, ownerId: string, text: string, attachments: string[], replyToId?: string, ) => { const encrypted = await encryptMessage(communityId, text); if (!encrypted) { return; } const [encryptedMessage, iv] = encrypted; const tempUUID = crypto.randomUUID(); setMessage({ id: tempUUID, iv: iv, text: text, attachments: attachments, edited: false, reactions: [], creationDate: new Date().getTime(), editHistory: [], replyToId: replyToId, channelId: channelId, ownerId: ownerId, decryptionStatus: true, notSentYet: true, }); const data = await createMessageApi({ text: encryptedMessage, iv: iv, channelId: channelId, replyToId: replyToId, attachments: attachments, }); if (typeof data.error === "string") { return; } deleteChannelMessage(channelId, tempUUID); setMessage({ ...data, text: text, decryptionStatus: true, }); }; const updateMessage = async (id: string, text: string, communityId: string) => { const encrypted = await encryptMessage(communityId, text); if (!encrypted) { return; } const [encryptedMessage, iv] = encrypted; const data = await updateMessageApi({ id: id, iv: iv, text: encryptedMessage, }); if (typeof data.error === "string") { return; } setMessage({ ...data, text: text, decryptionStatus: true, }); }; const removeMessage = async (id: string, channelId?: string) => { const data = await removeMessageApi({ id: id, }); if (typeof data.error === "string") { return; } deleteMessage(); if (channelId) { deleteChannelMessage(channelId, id); } }; const encryptMessage = async ( communityId: string, text: string, ): Promise<[string, string] | undefined> => { const key = state.community.communities[communityId]?.derivedKey; if (!key) { return; } const iv = generateIv(); if (text.length === 0) { return ["", bufferToBase64(iv.buffer)]; } const encrypted = await encryptData({ key: key, iv: iv, data: text, }); return [bufferToBase64(encrypted), bufferToBase64(iv.buffer)]; }; const decryptMessage = async ( communityId: string, text: string, iv: string, ): Promise => { const key = state.community.communities[communityId]?.derivedKey; if (!key) { return; } const ivBytes = base64ToBuffer(iv); const textBytes = base64ToBuffer(text); if (!ivBytes || !textBytes) { return; } return await decryptData({ key: key, iv: new Uint8Array(ivBytes), encryptedData: textBytes, }); }; export { fetchMessage, createMessage, updateMessage, removeMessage, encryptMessage, decryptMessage, };