const b4a = window.require('b4a'); export async function handleData(network, peerKey, data, conn) { try { const parsed = JSON.parse(b4a.toString(data)); switch (parsed.type) { case 'identity': await handleIdentity(network, peerKey, parsed); break; case 'whois': handleWhois(network, parsed, conn); break; case 'whois_reply': handleWhoisReply(network, parsed); break; case 'ephemeral': handleEphemeral(network, peerKey, parsed); break; default: // Could be a standard message core, which is handled by replication, not this handler. } } catch (err) { // Likely binary data from core replication, ignore. } } async function handleIdentity(network, peerKey, parsed) { const peerInfo = network.peers.get(peerKey); if (!peerInfo) return; peerInfo.displayName = parsed.displayName; peerInfo.username = parsed.username; peerInfo.avatar = parsed.avatar; peerInfo.coreKey = parsed.coreKey; const profileObj = { displayName: parsed.displayName, username: parsed.username, avatar: parsed.avatar }; network.knownProfiles.set(peerKey, profileObj); if (network.profilesDb) await network.profilesDb.put(peerKey, profileObj); if (network.coresDb && parsed.coreKey) await network.coresDb.put(peerKey, parsed.coreKey); network._emitKnownProfiles(); if (parsed.username) { const uname = parsed.username.toLowerCase(); network.userDirectory.set(uname, { pubKey: peerKey, profile: parsed }); network.dirDb.put(uname, { pubKey: peerKey, profile: parsed }); network._checkPendingRequests(uname, peerKey, parsed); } if (network.dms[peerKey]) { network.dms[peerKey].profile = profileObj; await network.db.put('dm:' + peerKey, network.dms[peerKey]); if (network.onDMsUpdate) network.onDMsUpdate({ ...network.dms }); } if (network.onPeerUpdate) network.onPeerUpdate(network.getPeerList()); network._emitMessages(); await network.trackPeerCore(parsed.coreKey); } function handleWhois(network, parsed, conn) { const uname = parsed.username; if (network.userDirectory.has(uname)) { const cached = network.userDirectory.get(uname); const reply = b4a.from(JSON.stringify({ type: 'whois_reply', queryId: parsed.queryId, username: uname, pubKey: cached.pubKey, profile: cached.profile })); conn.write(reply); } } function handleWhoisReply(network, parsed) { const cb = network.pendingWhois.get(parsed.queryId); if (cb) cb({ pubKey: parsed.pubKey, profile: parsed.profile }); network.userDirectory.set(parsed.username, { pubKey: parsed.pubKey, profile: parsed.profile }); network.dirDb.put(parsed.username, { pubKey: parsed.pubKey, profile: parsed.profile }); network._checkPendingRequests(parsed.username, parsed.pubKey, parsed.profile); } function handleEphemeral(network, peerKey, parsed) { const { payload } = parsed; if (!payload) return; if (payload.type === 'offline') { const peerInfo = network.peers.get(peerKey); if (peerInfo) { network.peers.delete(peerKey); try { peerInfo.conn.destroy(); } catch (e) {} if (network.onPeerUpdate) network.onPeerUpdate(network.getPeerList()); } } if (payload.type.startsWith('webrtc-') || payload.type === 'voice_activity' || payload.type.startsWith('vc-')) { for (const fn of network.webrtcListeners) fn(peerKey, payload); } if (payload.type === 'transfer_progress') { const current = network.transfers[payload.id] || { progress: 0, speed: 0 }; if (payload.progress >= current.progress || payload.progress === 1) { network.transfers[payload.id] = { ...current, progress: payload.progress, speed: payload.speed, state: payload.progress >= 1 ? 'completed' : 'uploading' }; if (network.onTransfersUpdate) network.onTransfersUpdate(network.transfers); } } if (network.onEphemeral) network.onEphemeral(peerKey, payload); }