From bf057c14f48c1f55af00ef0865928a465a7a4c63 Mon Sep 17 00:00:00 2001 From: RoyceDa Date: Tue, 24 Feb 2026 14:33:47 +0200 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D1=89=D0=B8=D1=89=D0=B5=D0=BD?= =?UTF-8?q?=D0=BD=D0=B0=D1=8F=20=D1=81=D0=B8=D0=BD=D1=85=D1=80=D0=BE=D0=BD?= =?UTF-8?q?=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D0=BA=D0=BB=D1=8E=D1=87?= =?UTF-8?q?=D0=B5=D0=B9=20=D0=B8=20=D0=BC=D0=B5=D1=82=D0=B0-=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B3=D1=80=D1=83=D0=BF=D0=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/providers/DialogProvider/useGroups.ts | 26 +++------ .../DialogProvider/useSynchronize.ts | 53 ++++++++++++++++++- .../protocol/packets/packet.group.join.ts | 18 +++++++ app/servers.ts | 4 +- 4 files changed, 77 insertions(+), 24 deletions(-) diff --git a/app/providers/DialogProvider/useGroups.ts b/app/providers/DialogProvider/useGroups.ts index 78499d6..1935cdc 100644 --- a/app/providers/DialogProvider/useGroups.ts +++ b/app/providers/DialogProvider/useGroups.ts @@ -162,26 +162,10 @@ export function useGroups() : { const groupId = packet.getGroupId(); info(`Creating group with id ${groupId}`); const encryptKey = generateRandomKey(64); - const secureKey = await encodeWithPassword(privatePlain, encryptKey); - let content = await encodeWithPassword(encryptKey, `$a=Group created`); - let plainMessage = await encodeWithPassword(privatePlain, `$a=Group created`); - await runQuery(` - INSERT INTO groups (account, group_id, title, description, key) VALUES (?, ?, ?, ?, ?) - `, [publicKey, groupId, title, description, secureKey]); - await runQuery(` - INSERT INTO messages - (from_public_key, to_public_key, content, timestamp, read, chacha_key, from_me, plain_message, account, message_id, delivered, attachments) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - `, [publicKey, "#group:" + groupId, content, Date.now(), 1, "", 1, plainMessage, publicKey, generateRandomKey(16), - DeliveredMessageState.DELIVERED - , '[]']); - updateDialog("#group:" + groupId); - updateGroupInformation({ - groupId: groupId, - title: title, - description: description - }); - setLoading(false); - navigate(`/main/chat/${prepareForRoute(groupId)}`); + /** + * После создания группы в нее необходимо зайти, в соотвествии с новым протоколом + */ + joinGroup(await constructGroupString(groupId, title, encryptKey, description)); }); } @@ -201,9 +185,11 @@ export function useGroups() : { const groupId = parsed.groupId; const title = parsed.title; const description = parsed.description; + const encodedGroupString = await encodeWithPassword(privatePlain, groupString); const packet = new PacketGroupJoin(); packet.setGroupId(parsed.groupId); + packet.setGroupString(encodedGroupString); send(packet); setLoading(true); diff --git a/app/providers/DialogProvider/useSynchronize.ts b/app/providers/DialogProvider/useSynchronize.ts index 0456a64..332ab79 100644 --- a/app/providers/DialogProvider/useSynchronize.ts +++ b/app/providers/DialogProvider/useSynchronize.ts @@ -8,6 +8,16 @@ import { useSender } from "../ProtocolProvider/useSender"; import { usePacket } from "../ProtocolProvider/usePacket"; import { whenFinish } from "./dialogQueue"; import { useProtocol } from "../ProtocolProvider/useProtocol"; +import { PacketGroupJoin } from "../ProtocolProvider/protocol/packets/packet.group.join"; +import { useGroups } from "./useGroups"; +import { decodeWithPassword, encodeWithPassword } from "@/app/workers/crypto/crypto"; +import { usePrivatePlain } from "../AccountProvider/usePrivatePlain"; +import { GroupStatus } from "../ProtocolProvider/protocol/packets/packet.group.invite.info"; +import { useConsoleLogger } from "@/app/hooks/useConsoleLogger"; +import { useNavigate } from "react-router-dom"; +import { useDialogsList } from "../DialogListProvider/useDialogsList"; +import { useUpdateGroupInformation } from "../InformationProvider/useUpdateGroupInformation"; +import { useGroupInviteStatus } from "./useGroupInviteStatus"; /** * Хук отвечает за синхронизацию сообщений, запрос синхронизации @@ -19,7 +29,14 @@ export function useSynchronize() { const publicKey = usePublicKey(); const send = useSender(); const {protocol} = useProtocol(); + const {parseGroupString} = useGroups(); + const privatePlain = usePrivatePlain(); + const {error, info} = useConsoleLogger('useSynchronize'); + const {setInviteStatusByGroupId} = useGroupInviteStatus(''); + const updateGroupInformation = useUpdateGroupInformation(); + const {updateDialog} = useDialogsList(); + useEffect(() => { if(protocol.handshakeExchangeComplete){ trySync(); @@ -38,15 +55,47 @@ export function useSynchronize() { send(packet); } + /** + * Пакет приходит либо при входе в группу (но там используется слушатель once), либо при + * синхронизации. В данном случае этот пакет прийдет только при синхронизации + */ + usePacket(20, async (packet: PacketGroupJoin) => { + const decryptedGroupString = await decodeWithPassword(privatePlain, packet.getGroupString()); + const parsed = await parseGroupString(decryptedGroupString); + if(!parsed){ + error("Received invalid group string, skipping"); + return; + } + const groupStatus = packet.getGroupStatus(); + if(groupStatus != GroupStatus.JOINED){ + error("Cannot sync group that is not joined, skipping"); + return; + } + const secureKey = await encodeWithPassword(privatePlain, parsed.encryptKey); + await runQuery(` + INSERT INTO groups (account, group_id, title, description, key) VALUES (?, ?, ?, ?, ?) + `, [publicKey, parsed.groupId, parsed.title, parsed.description, secureKey]); + updateDialog("#group:" + parsed.groupId); + setInviteStatusByGroupId(parsed.groupId, GroupStatus.JOINED); + updateGroupInformation({ + groupId: parsed.groupId, + title: parsed.title, + description: parsed.description + }); + info("Group synchronized " + parsed.groupId); + }, [publicKey]); + usePacket(25, async (packet: PacketSync) => { const status = packet.getStatus(); if(status == SyncStatus.BATCH_START){ setProtocolState(ProtocolState.SYNCHRONIZATION); } if(status == SyncStatus.BATCH_END){ - console.info("Batch start"); + /** + * Этот Promise ждет пока все сообщения синхронизируются и обработаются, только + * после этого + */ await whenFinish(); - console.info("Batch finished"); await runQuery( "INSERT INTO accounts_sync_times (account, last_sync) VALUES (?, ?) " + "ON CONFLICT(account) DO UPDATE SET last_sync = ? WHERE account = ?", diff --git a/app/providers/ProtocolProvider/protocol/packets/packet.group.join.ts b/app/providers/ProtocolProvider/protocol/packets/packet.group.join.ts index 89c271c..2f9f71c 100644 --- a/app/providers/ProtocolProvider/protocol/packets/packet.group.join.ts +++ b/app/providers/ProtocolProvider/protocol/packets/packet.group.join.ts @@ -12,6 +12,14 @@ export class PacketGroupJoin extends Packet { private groupId: string = ""; private groupStatus: GroupStatus = GroupStatus.NOT_JOINED; + /** + * Строка группы, которая содержит информацию о группе, такую как ее название, описание и ключ + * Строка зашифрована обратимым шифрованием, где ключом выступает - реальный приватный ключ + * входящего в группу клиента. Нужно это для будущей синхронзации, так как клиенту на его другом + * устройстве нужно получить ключ группы и ее информацию. Сервер расшифровать эту строку не может. Эту + * строку может расшифровать только клиент, так как она зашифрована его приватным ключом + */ + private groupString: string = ""; public getPacketId(): number { return 0x14; @@ -20,6 +28,7 @@ export class PacketGroupJoin extends Packet { public _receive(stream: Stream): void { this.groupId = stream.readString(); this.groupStatus = stream.readInt8(); + this.groupString = stream.readString(); } public _send(): Promise | Stream { @@ -27,6 +36,7 @@ export class PacketGroupJoin extends Packet { stream.writeInt16(this.getPacketId()); stream.writeString(this.groupId); stream.writeInt8(this.groupStatus); + stream.writeString(this.groupString); return stream; } @@ -45,5 +55,13 @@ export class PacketGroupJoin extends Packet { public getGroupStatus(): GroupStatus { return this.groupStatus; } + + public setGroupString(groupString: string) { + this.groupString = groupString; + } + + public getGroupString(): string { + return this.groupString; + } } \ No newline at end of file diff --git a/app/servers.ts b/app/servers.ts index aa52cbb..53d4fca 100644 --- a/app/servers.ts +++ b/app/servers.ts @@ -1,8 +1,8 @@ export const SERVERS = [ //'wss://cdn.rosetta-im.com', //'ws://10.211.55.2:3000', - //'ws://127.0.0.1:3000', - 'wss://wss.rosetta.im' + 'ws://127.0.0.1:3000', + //'wss://wss.rosetta.im' ]; export function selectServer(): string {