From 9ef5c1a809f39c5a4384006867dbb23ad7bbfcb3 Mon Sep 17 00:00:00 2001 From: you Date: Fri, 20 Mar 2026 09:30:41 +0000 Subject: [PATCH] fix: My Nodes filter uses server-side findPacketsForNode for all packet types Client was matching field names that only exist on ADVERTs. Now sends pubkeys to server, which uses findPacketsForNode() (byNode index + text search) to find ALL packet types referencing those nodes. --- public/index.html | 2 +- public/packets.js | 24 ++++++++++-------------- server.js | 21 ++++++++++++++++++++- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/public/index.html b/public/index.html index 6354d74c..652c5d30 100644 --- a/public/index.html +++ b/public/index.html @@ -81,7 +81,7 @@ - + diff --git a/public/packets.js b/public/packets.js index 72ca31ed..47158137 100644 --- a/public/packets.js +++ b/public/packets.js @@ -587,25 +587,21 @@ const groupBtn = document.getElementById('fGroup'); if (groupBtn) groupBtn.classList.toggle('active', groupByHash); - // Filter to claimed/favorited nodes if toggle is on + // Filter to claimed/favorited nodes if toggle is on — use server-side multi-node lookup let displayPackets = packets; if (filters.myNodes) { const myNodes = JSON.parse(localStorage.getItem('meshcore-my-nodes') || '[]'); - const myKeys = new Set(myNodes.map(n => n.pubkey)); + const myKeys = myNodes.map(n => n.pubkey).filter(Boolean); const favs = getFavorites(); - const allKeys = new Set([...myKeys, ...favs]); - displayPackets = packets.filter(p => { + const allKeys = [...new Set([...myKeys, ...favs])]; + if (allKeys.length > 0) { try { - const d = JSON.parse(p.decoded_json || '{}'); - const pathHops = JSON.parse(p.path_json || '[]'); - return (d.pubKey && allKeys.has(d.pubKey)) || - (d.srcPubKey && allKeys.has(d.srcPubKey)) || - (d.destPubKey && allKeys.has(d.destPubKey)) || - (d.srcHash && allKeys.has(d.srcHash)) || - (d.destHash && allKeys.has(d.destHash)) || - pathHops.some(h => allKeys.has(h)); - } catch { return false; } - }); + const myData = await api('/packets?nodes=' + allKeys.join(',') + '&limit=500'); + displayPackets = myData.packets || []; + } catch { displayPackets = []; } + } else { + displayPackets = []; + } } if (!displayPackets.length) { diff --git a/server.js b/server.js index b2fc89f0..af46701d 100644 --- a/server.js +++ b/server.js @@ -671,9 +671,28 @@ app.get('/api/stats', (req, res) => { }); app.get('/api/packets', (req, res) => { - const { limit = 50, offset = 0, type, route, region, observer, hash, since, until, groupByHash, node } = req.query; + const { limit = 50, offset = 0, type, route, region, observer, hash, since, until, groupByHash, node, nodes } = req.query; const order = req.query.order === 'asc' ? 'ASC' : 'DESC'; + // Multi-node filter: comma-separated pubkeys + if (nodes) { + const pubkeys = nodes.split(',').map(s => s.trim()).filter(Boolean); + const allPackets = new Map(); + for (const pk of pubkeys) { + const { packets: found } = pktStore.findPacketsForNode(pk); + for (const p of found) allPackets.set(p.id, p); + } + let results = [...allPackets.values()].sort((a, b) => order === 'DESC' ? b.timestamp.localeCompare(a.timestamp) : a.timestamp.localeCompare(b.timestamp)); + // Apply additional filters + if (type !== undefined) results = results.filter(p => String(p.payload_type) === String(type)); + if (region) results = results.filter(p => (p.observer_id || '').includes(region) || (p.decoded_json || '').includes(region)); + if (since) results = results.filter(p => p.timestamp >= since); + if (until) results = results.filter(p => p.timestamp <= until); + const total = results.length; + const paged = results.slice(Number(offset), Number(offset) + Number(limit)); + return res.json({ packets: paged, total, limit: Number(limit), offset: Number(offset) }); + } + if (groupByHash === 'true') { return res.json(pktStore.queryGrouped({ limit, offset, type, route, region, observer, hash, since, until, node })); }