/* eslint-disable */ // [TSM.ID].[11031972] -- All Rights Reserved. Proprietary & Confidential. import CryptoJS from 'crypto-js'; export interface EncryptedMessage { id: string; sender: string; ciphertext: string; timestamp: number; } export interface DecryptedMessage { id: string; sender: string; content: string; timestamp: number; status: string; } /** * XCUTelepathyMatrix FASE 2: * Telah berevolusi meninggalkan NodeJS, Yjs, dan WebSockets usang. * Menggunakan arsitektur WebTransport Datagrams yang menembak langsung ke Rust Engine (Port 8443). */ export class XCUTelepathyMatrix { private roomName: string; private secretKey: string; private transport: any = null; // WebTransport instance private isActive: boolean = false; private participantId: number; private username: string = ""; public onMessagesUpdate: ((messages: DecryptedMessage[]) => void) | null = null; public onTypingUpdate: ((typingUsers: Record) => void) | null = null; public onQuantumResonance: ((senderId: number, type: string) => void) | null = null; public onSovereignSignal: ((command: string, targetId?: number) => void) | null = null; // Local state untuk dirender private messages: DecryptedMessage[] = []; private typingState: Record = {}; constructor(roomName: string, secretKey: string = 'QUANTUM-X-SECRET-256') { this.roomName = roomName; this.secretKey = secretKey; this.participantId = Math.floor(Math.random() * 65534) + 1; } public async ignite(serverUrl: string, username: string) { this.username = username; this.isActive = true; try { // 1. Ekstrak host dari serverUrl let host = window.location.hostname; if (serverUrl && serverUrl !== "/") { const urlObj = new URL(serverUrl); host = urlObj.hostname; } const secureProto = window.location.protocol; const wtUrl = `${secureProto}//${host}:8443/neural-link/${this.roomName}`; console.log("[XTM] Menginisialisasi WebTransport ke:", wtUrl); // 2. Setup WebTransport // Gunakan any cast karena WebTransport mungkin belum diakui di semua tsconfig const WT = (window as any).WebTransport; if (!WT) { throw new Error("WebTransport tidak didukung di browser ini!"); } this.transport = new WT(wtUrl); await this.transport.ready; console.log("[XTM] Pipa WebTransport Kuantum TERHUBUNG!"); // 3. Mulai Membaca Datagrams this.readDatagrams(); } catch (e) { console.error("[XTM] Ignition Failed:", e); // Fallback: Jika WebTransport diblokir firewall, XTM akan mengaktifkan SSE Relay (TBD) } } private async readDatagrams() { if (!this.transport || !this.transport.datagrams) return; try { const reader = this.transport.datagrams.readable.getReader(); while (this.isActive) { const { value, done } = await reader.read(); if (done) break; if (value && value.length >= 8) { const type = value[0]; // byte 2-3 = participantId pengirim const senderId = new DataView(value.buffer).getUint16(2, true); if (senderId === this.participantId) continue; const payload = value.slice(8); if (type === 7) { // 7 = Chat Text this.decryptAndPush(payload); } else if (type === 8) { // 8 = Telepathic Resonance (Typing) // Mendekripsi siapa yang mengetik this.handleTypingResonance(payload); } else if (type === 9) { // 9 = PKEPX Resonance (Emoji) this.handleQuantumResonance(payload, senderId); } else if (type === 10) { // 10 = PKEPX Sovereign Command this.handleSovereignCommand(payload); } } } } catch (e) { if (this.isActive) console.error("[XTM] Datagram Reader terputus:", e); } } private async decryptAndPush(payload: Uint8Array) { try { // Convert Uint8Array to WordArray const wordArr = CryptoJS.lib.WordArray.create(payload as any); const ciphertext = CryptoJS.enc.Base64.stringify(wordArr); const bytes = CryptoJS.AES.decrypt(ciphertext, this.secretKey); const originalText = bytes.toString(CryptoJS.enc.Utf8); if (originalText) { const parsed = JSON.parse(originalText); this.messages.push({ id: Math.random().toString(), sender: parsed.sender, content: parsed.text, timestamp: parsed.timestamp, status: 'delivered' }); if (this.onMessagesUpdate) { this.onMessagesUpdate([...this.messages]); } } } catch (e) { console.error("Gagal dekripsi pesan XTM", e); } } private async handleTypingResonance(payload: Uint8Array) { try { const wordArr = CryptoJS.lib.WordArray.create(payload as any); const ciphertext = CryptoJS.enc.Base64.stringify(wordArr); const bytes = CryptoJS.AES.decrypt(ciphertext, this.secretKey); const name = bytes.toString(CryptoJS.enc.Utf8); if (name) { this.typingState[name] = Date.now(); if (this.onTypingUpdate) this.onTypingUpdate({...this.typingState}); setTimeout(() => { delete this.typingState[name]; if (this.onTypingUpdate) this.onTypingUpdate({...this.typingState}); }, 3000); } } catch(e) {} } // ===================================== // PKEPX ZOOM-KILLER: JUMPA CHAT PORT // ===================================== private async handleQuantumResonance(payload: Uint8Array, senderId: number) { try { const wordArr = CryptoJS.lib.WordArray.create(payload as any); const ciphertext = CryptoJS.enc.Base64.stringify(wordArr); const bytes = CryptoJS.AES.decrypt(ciphertext, this.secretKey); const reactionType = bytes.toString(CryptoJS.enc.Utf8); if (reactionType && this.onQuantumResonance) { this.onQuantumResonance(senderId, reactionType); } } catch(e) {} } private async handleSovereignCommand(payload: Uint8Array) { try { const wordArr = CryptoJS.lib.WordArray.create(payload as any); const ciphertext = CryptoJS.enc.Base64.stringify(wordArr); const bytes = CryptoJS.AES.decrypt(ciphertext, this.secretKey); const cmdStr = bytes.toString(CryptoJS.enc.Utf8); if (cmdStr && this.onSovereignSignal) { const cmd = JSON.parse(cmdStr); this.onSovereignSignal(cmd.command, cmd.targetId); } } catch(e) {} } public async emitResonance(reactionType: string) { if (!this.transport || !this.transport.datagrams) return; const ciphertext = CryptoJS.AES.encrypt(reactionType, this.secretKey).toString(); const encWordArr = CryptoJS.enc.Base64.parse(ciphertext); const encPayload = new Uint8Array(encWordArr.sigBytes); for (let i = 0; i < encWordArr.sigBytes; i++) { encPayload[i] = (encWordArr.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; } const header = new Uint8Array(8); header[0] = 9; // Tipe 9 = Resonance new DataView(header.buffer).setUint16(2, this.participantId, true); const fullPacket = new Uint8Array(8 + encPayload.length); fullPacket.set(header, 0); fullPacket.set(encPayload, 8); let writer: any = null; try { writer = this.transport.datagrams.writable.getWriter(); await writer.write(fullPacket); if (this.onQuantumResonance) this.onQuantumResonance(this.participantId, reactionType); } catch (e) {} finally { if (writer) writer.releaseLock(); } } public async broadcastSovereignSignal(command: string, targetId?: number) { if (!this.transport || !this.transport.datagrams) return; const payloadStr = JSON.stringify({ command, targetId }); const ciphertext = CryptoJS.AES.encrypt(payloadStr, this.secretKey).toString(); const encWordArr = CryptoJS.enc.Base64.parse(ciphertext); const encPayload = new Uint8Array(encWordArr.sigBytes); for (let i = 0; i < encWordArr.sigBytes; i++) { encPayload[i] = (encWordArr.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; } const header = new Uint8Array(8); header[0] = 10; // Tipe 10 = Sovereign new DataView(header.buffer).setUint16(2, this.participantId, true); const fullPacket = new Uint8Array(8 + encPayload.length); fullPacket.set(header, 0); fullPacket.set(encPayload, 8); let writer: any = null; try { writer = this.transport.datagrams.writable.getWriter(); await writer.write(fullPacket); } catch (e) {} finally { if (writer) writer.releaseLock(); } } // Encrypt and send public async sendMessage(sender: string, content: string) { if (!this.transport || !this.transport.datagrams) { // Fallback simpan ke local buffer jika belum konek this.messages.push({ id: Math.random().toString(), sender, content, timestamp: Date.now(), status: 'failed_offline' }); if (this.onMessagesUpdate) this.onMessagesUpdate([...this.messages]); return; } const payloadStr = JSON.stringify({ sender, text: content, timestamp: Date.now() }); // E2EE: AES Encryption const ciphertext = CryptoJS.AES.encrypt(payloadStr, this.secretKey).toString(); const encWordArr = CryptoJS.enc.Base64.parse(ciphertext); // Convert WordArray to Uint8Array const encPayload = new Uint8Array(encWordArr.sigBytes); for (let i = 0; i < encWordArr.sigBytes; i++) { encPayload[i] = (encWordArr.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; } // Header const header = new Uint8Array(8); header[0] = 7; // Tipe 7 = Text Message header[1] = 0; new DataView(header.buffer).setUint16(2, this.participantId, true); const fullPacket = new Uint8Array(8 + encPayload.length); fullPacket.set(header, 0); fullPacket.set(encPayload, 8); let writer: any = null; try { writer = this.transport.datagrams.writable.getWriter(); await writer.write(fullPacket); // Optimistic UI Update this.messages.push({ id: Math.random().toString(), sender, content, timestamp: Date.now(), status: 'delivered' }); if (this.onMessagesUpdate) this.onMessagesUpdate([...this.messages]); } catch (e) { console.error("Gagal mengirim pesan Kuantum:", e); } finally { if (writer) writer.releaseLock(); } } public async setTyping(username: string, charCount: number) { if (!this.transport || !this.transport.datagrams) return; const ciphertext = CryptoJS.AES.encrypt(username, this.secretKey).toString(); const encWordArr = CryptoJS.enc.Base64.parse(ciphertext); const encPayload = new Uint8Array(encWordArr.sigBytes); for (let i = 0; i < encWordArr.sigBytes; i++) { encPayload[i] = (encWordArr.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; } const header = new Uint8Array(8); header[0] = 8; // Tipe 8 = Typing new DataView(header.buffer).setUint16(2, this.participantId, true); const fullPacket = new Uint8Array(8 + encPayload.length); fullPacket.set(header, 0); fullPacket.set(encPayload, 8); let writer: any = null; try { writer = this.transport.datagrams.writable.getWriter(); await writer.write(fullPacket); } catch (e) {} finally { if (writer) writer.releaseLock(); } } public shutdown() { this.isActive = false; if (this.transport) { try { this.transport.close(); } catch(e){} } } }