v14: /reply and /r command to quick-reply to last DM peer
- /reply <msg> or /r <msg> sends encrypted DM to last person - lastDmPeer set when sending a DM or receiving one - Shows error if no prior DM conversation exists Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
17
chat.py
17
chat.py
@@ -223,7 +223,7 @@ CHAT_HTML = r"""<!DOCTYPE html>
|
||||
<div id="header">
|
||||
<input id="name" placeholder="Name" value="" autocomplete="off">
|
||||
<span id="group-tag"></span>
|
||||
<span id="header-info"><code>/dm @user msg</code> <code>/users</code> <code>/setpass</code> <code>/color</code></span>
|
||||
<span id="header-info"><code>/dm @user msg</code> <code>/r reply</code> <code>/users</code> <code>/setpass</code> <code>/color</code></span>
|
||||
</div>
|
||||
<div id="messages"></div>
|
||||
<div id="bottom">
|
||||
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user