diff --git a/chat.py b/chat.py index ff32e03..c0c9777 100644 --- a/chat.py +++ b/chat.py @@ -223,7 +223,7 @@ CHAT_HTML = r"""
@@ -336,11 +336,23 @@ function send() { // Local commands const dmMatch = text.match(/^\/dm\s+@?(\S+)\s+([\s\S]+)/); if (dmMatch) { + lastDmPeer = dmMatch[1]; encryptAndSendDM(dmMatch[1], dmMatch[2]); $input.value = ''; $input.style.height = 'auto'; return; } + const replyMatch = text.match(/^\/(?:reply|r)\s+([\s\S]+)/); + if (replyMatch) { + if (!lastDmPeer) { + addMsg({ts:Date.now()/1000, user:'***', text:'No one to reply to. Use /dm @user first.'}); + } else { + encryptAndSendDM(lastDmPeer, replyMatch[1]); + } + $input.value = ''; + $input.style.height = 'auto'; + return; + } if (text === '/users' || text === '/online') { fetch('/keys').then(r => r.json()).then(users => { addMsg({ts:Date.now()/1000, user:'***', text:'Users with keys: ' + users.join(', ')}); @@ -494,6 +506,7 @@ document.getElementById('pw-input').onkeydown = function(e) { // ── E2E Encrypted DMs (ECDH + AES-256-GCM via Web Crypto) ── let myKeyPair = null; +let lastDmPeer = null; // for /reply let myPubJwk = null; const derivedKeys = {}; // cache: username -> CryptoKey (AES) @@ -595,6 +608,8 @@ async function handleEncryptedDM(data) { // Only decrypt if we are sender or recipient if (data.to !== myName && data.user !== myName) return; const otherUser = data.user === myName ? data.to : data.user; + // Update reply target when someone DMs us + if (data.user !== myName) lastDmPeer = data.user; try { const aesKey = await getAESKey(otherUser); if (!aesKey) throw new Error('no key');