aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-10-18 09:01:17 -0700
committerAdam Soltys <[email protected]>2026-10-18 09:01:17 -0700
commit56cad7ef0da868e7c7c2b3c902143acd611b4c48 (patch)
tree64d7b789b2194304381606d8e4d7e65af8379631
parent2e897103836a6814a39dbb905d6a7ed1417344d7 (diff)
downloadcoinosv3-server-56cad7ef0da868e7c7c2b3c902143acd611b4c48.tar.gz
coinosv3-server-56cad7ef0da868e7c7c2b3c902143acd611b4c48.zip
nwcpush: calls push only to an app that says it rings for them (reasons.call), not to an older one whose worker would show a call as chat.
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_013ZDf1cyCQLkfjftYhymZAg
-rw-r--r--nwcpush/server.js4
-rw-r--r--tools/nwcpush-call-test.js6
2 files changed, 7 insertions, 3 deletions
diff --git a/nwcpush/server.js b/nwcpush/server.js
index 198757c..947b52e 100644
--- a/nwcpush/server.js
+++ b/nwcpush/server.js
@@ -213,8 +213,10 @@ function onNotifyEvent(ev) {
if (ev.kind === CALL_WRAP) {
if (!p || String(ev.content || '').length < CALL_OFFER_MIN) return;
keepCallWrap(ev);
+ // only to an app that says it rings for calls (reasons.call): an older
+ // one's worker has no words for a call and would call it chat
for (const [id, r] of Object.entries(notifyRegs)) {
- if ((r.ptags || []).includes(p)) pushNotify(id, r, 'call', { wrapId: ev.id }).catch(() => {});
+ if (r.reasons?.call === true && (r.ptags || []).includes(p)) pushNotify(id, r, 'call', { wrapId: ev.id }).catch(() => {});
}
return;
}
diff --git a/tools/nwcpush-call-test.js b/tools/nwcpush-call-test.js
index 9145744..99b366b 100644
--- a/tools/nwcpush-call-test.js
+++ b/tools/nwcpush-call-test.js
@@ -33,7 +33,7 @@ const relay = Bun.serve({ port: 0, hostname: '127.0.0.1',
close(ws) { for (const s of ws.data.values()) subs.delete(s); },
} });
// the devices: what each was pushed
-const got = { on: [], off: [] };
+const got = { on: [], off: [], old: [] };
const devices = Bun.serve({ port: 0, hostname: '127.0.0.1', fetch: async (req) => { got[new URL(req.url).pathname.slice(1)].push(await req.json()); return new Response('ok'); } });
const dir = mkdtempSync(tmpdir() + '/nwcpush-call-');
@@ -54,7 +54,8 @@ try {
for (let i = 0; i < 40; i++) { try { if ((await fetch(N + '/health')).ok) break; } catch {} await sleep(150); }
const reg = (path, reasons) => fetch(N + '/register', { method: 'POST', headers: { 'content-type': 'application/json' },
body: JSON.stringify({ subscription: { endpoint: `http://127.0.0.1:${devices.port}/${path}`, unifiedpush: true }, notify: { ptags: [ME], reasons } }) });
- check('a device registers for its pubkey', (await reg('on', {})).ok);
+ check('a device registers for its pubkey', (await reg('on', { call: true })).ok);
+ check('...an older app, saying nothing of calls', (await reg('old', {})).ok);
check('...another with calls turned off', (await reg('off', { call: false })).ok);
await sleep(1000); // the notifier resubscribes
@@ -65,6 +66,7 @@ try {
const push = got.on.find((p) => p.reason === 'call');
check('the device is woken: a call, naming the wrap', !!push && push.type === 'notify' && push.wrapId === offer.id, JSON.stringify(got.on));
check('...not the one that turned calls off', !got.off.some((p) => p.reason === 'call'));
+ check('...nor an older app (its worker would call it chat)', !got.old.some((p) => p.reason === 'call'));
const fetched = await (await fetch(N + '/wrap/' + offer.id)).json();
check('the wrap can be fetched from the notifier, as sent', fetched.id === offer.id && fetched.content === offer.content);
check('...from any page (CORS)', (await fetch(N + '/wrap/' + offer.id)).headers.get('access-control-allow-origin') === '*');