Rewrite kind 3063 fetch to use #i tag filtering via direct WebSocket, bypassing NDK grouping/cache issues
This commit is contained in:
@@ -11,6 +11,7 @@ Usage:
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
import struct
|
import struct
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
@@ -33,7 +34,6 @@ KZAPSTORE_COMMUNITY_PUBKEY = "acfeaea6e51420e8068fac446ca9d17d7a9ef6a5d20d93894e
|
|||||||
# Load real app developer pubkeys (kind 32267 events) so stack `a` tags
|
# Load real app developer pubkeys (kind 32267 events) so stack `a` tags
|
||||||
# reference events that actually exist on the relay.
|
# reference events that actually exist on the relay.
|
||||||
# Generated by fetching kind 32267 events from wss://relay.zapstore.dev.
|
# Generated by fetching kind 32267 events from wss://relay.zapstore.dev.
|
||||||
import os
|
|
||||||
_PUBKEYS_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "app_pubkeys.json")
|
_PUBKEYS_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "app_pubkeys.json")
|
||||||
try:
|
try:
|
||||||
with open(_PUBKEYS_PATH) as f:
|
with open(_PUBKEYS_PATH) as f:
|
||||||
|
|||||||
+82
-21
@@ -206,6 +206,8 @@
|
|||||||
let appVersions = {}; // identifier -> { version, size, url, created_at }
|
let appVersions = {}; // identifier -> { version, size, url, created_at }
|
||||||
let assetSub = null;
|
let assetSub = null;
|
||||||
let assetsLoaded = false;
|
let assetsLoaded = false;
|
||||||
|
let assetEventCount = 0; // total kind 3063 events received
|
||||||
|
let assetOldestTimestamp = Infinity; // oldest raw event timestamp seen (for pagination)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
AUTH STATE MODEL (Template reference)
|
AUTH STATE MODEL (Template reference)
|
||||||
@@ -788,7 +790,8 @@
|
|||||||
console.log('[app-stacks] Added app def:', apps[apps.length - 1].name);
|
console.log('[app-stacks] Added app def:', apps[apps.length - 1].name);
|
||||||
if (appDefsLoaded) renderApps();
|
if (appDefsLoaded) renderApps();
|
||||||
});
|
});
|
||||||
window.addEventListener('ndkEose', () => {
|
window.addEventListener('ndkEose', (event) => {
|
||||||
|
if (appDefSub && event.detail && event.detail.subId !== appDefSub.subId) return;
|
||||||
if (!appDefsLoaded) { appDefsLoaded = true; renderApps(); }
|
if (!appDefsLoaded) { appDefsLoaded = true; renderApps(); }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -823,7 +826,8 @@
|
|||||||
console.log('[app-stacks] Added stack:', stacks[stacks.length - 1].name);
|
console.log('[app-stacks] Added stack:', stacks[stacks.length - 1].name);
|
||||||
if (stacksLoaded) renderApps();
|
if (stacksLoaded) renderApps();
|
||||||
});
|
});
|
||||||
window.addEventListener('ndkEose', function() {
|
window.addEventListener('ndkEose', function(event) {
|
||||||
|
if (stackSub && event.detail && event.detail.subId !== stackSub.subId) return;
|
||||||
if (!stacksLoaded) { stacksLoaded = true; renderApps(); }
|
if (!stacksLoaded) { stacksLoaded = true; renderApps(); }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -841,27 +845,84 @@
|
|||||||
return { identifier, version, size, url: urls[0] || '', created_at: evt.created_at || 0 };
|
return { identifier, version, size, url: urls[0] || '', created_at: evt.created_at || 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Direct WebSocket fetch of kind 3063 events from relay.zapstore.dev.
|
||||||
|
// Uses #i tag filtering to request only events for our specific apps.
|
||||||
|
// Bypasses NDK to avoid grouping/cache issues.
|
||||||
|
var ZAPSTORE_RELAY = 'wss://relay.zapstore.dev';
|
||||||
|
|
||||||
function subscribeAppAssets() {
|
function subscribeAppAssets() {
|
||||||
console.log('[app-stacks] Subscribing to app assets (kind 3063)...');
|
// Wait for app definitions to load so we know the identifiers
|
||||||
assetSub = subscribe({ kinds: [3063], limit: 500 }, { closeOnEose: false, cacheUsage: 'CACHE_FIRST' });
|
if (!appDefsLoaded || apps.length === 0) {
|
||||||
|
setTimeout(subscribeAppAssets, 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('[app-stacks] Fetching kind 3063 events for ' + apps.length + ' apps from ' + ZAPSTORE_RELAY);
|
||||||
|
fetchAppAssetsByIdentifier();
|
||||||
}
|
}
|
||||||
|
|
||||||
function initAppAssetListener() {
|
function fetchAppAssetsByIdentifier() {
|
||||||
window.addEventListener('ndkEvent', function(event) {
|
var identifiers = apps.map(function(a) { return a.identifier; });
|
||||||
var evt = event.detail;
|
var batchSize = 50;
|
||||||
if (evt.kind !== 3063) return;
|
var batches = [];
|
||||||
var parsed = parseAppAsset(evt);
|
for (var i = 0; i < identifiers.length; i += batchSize) {
|
||||||
if (!parsed.identifier) return;
|
batches.push(identifiers.slice(i, i + batchSize));
|
||||||
// Keep the latest version (highest created_at)
|
}
|
||||||
var existing = appVersions[parsed.identifier];
|
console.log('[app-stacks] Fetching in ' + batches.length + ' batches of up to ' + batchSize + ' apps each');
|
||||||
if (!existing || parsed.created_at > existing.created_at) {
|
|
||||||
appVersions[parsed.identifier] = parsed;
|
var batchIndex = 0;
|
||||||
if (assetsLoaded) renderApps();
|
function fetchNextBatch() {
|
||||||
|
if (batchIndex >= batches.length) {
|
||||||
|
if (!assetsLoaded) {
|
||||||
|
assetsLoaded = true;
|
||||||
|
renderApps();
|
||||||
|
}
|
||||||
|
console.log('[app-stacks] Kind 3063 fetch complete. Total events: ' + assetEventCount + ', unique apps with versions: ' + Object.keys(appVersions).length);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
window.addEventListener('ndkEose', function() {
|
var batch = batches[batchIndex];
|
||||||
if (!assetsLoaded) { assetsLoaded = true; renderApps(); }
|
batchIndex++;
|
||||||
});
|
var reqId = 'assets-' + batchIndex + '-' + Date.now();
|
||||||
|
console.log('[app-stacks] Fetching batch ' + batchIndex + '/' + batches.length + ' (' + batch.length + ' apps)...');
|
||||||
|
|
||||||
|
var ws = new WebSocket(ZAPSTORE_RELAY);
|
||||||
|
ws.onopen = function() {
|
||||||
|
ws.send(JSON.stringify(['REQ', reqId, { kinds: [3063], '#i': batch, limit: 500 }]));
|
||||||
|
};
|
||||||
|
ws.onmessage = function(ev) {
|
||||||
|
var msg = JSON.parse(ev.data);
|
||||||
|
if (msg[0] === 'EVENT' && msg[1] === reqId) {
|
||||||
|
var evt = msg[2];
|
||||||
|
assetEventCount++;
|
||||||
|
var parsed = parseAppAsset(evt);
|
||||||
|
if (parsed.identifier) {
|
||||||
|
var existing = appVersions[parsed.identifier];
|
||||||
|
if (!existing || parsed.created_at > existing.created_at) {
|
||||||
|
appVersions[parsed.identifier] = parsed;
|
||||||
|
if (assetsLoaded) renderApps();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (msg[0] === 'EOSE' && msg[1] === reqId) {
|
||||||
|
ws.send(JSON.stringify(['CLOSE', reqId]));
|
||||||
|
ws.close();
|
||||||
|
console.log('[app-stacks] Batch ' + batchIndex + ' complete (total events: ' + assetEventCount + ', unique apps: ' + Object.keys(appVersions).length + ')');
|
||||||
|
if (!assetsLoaded) {
|
||||||
|
assetsLoaded = true;
|
||||||
|
renderApps();
|
||||||
|
}
|
||||||
|
setTimeout(fetchNextBatch, 100);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ws.onerror = function(err) {
|
||||||
|
console.error('[app-stacks] WebSocket error in batch ' + batchIndex + ':', err);
|
||||||
|
if (!assetsLoaded) {
|
||||||
|
assetsLoaded = true;
|
||||||
|
renderApps();
|
||||||
|
}
|
||||||
|
setTimeout(fetchNextBatch, 100);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
fetchNextBatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function publishAppStack(name, description) {
|
async function publishAppStack(name, description) {
|
||||||
@@ -970,8 +1031,8 @@
|
|||||||
initAppStackListener();
|
initAppStackListener();
|
||||||
subscribeAppStacks();
|
subscribeAppStacks();
|
||||||
|
|
||||||
// Set up app-asset (kind 3063) listener and subscription for version info
|
// Fetch kind 3063 (Software Asset) events directly from relay.zapstore.dev
|
||||||
initAppAssetListener();
|
// for version info. Bypasses NDK to avoid grouping/cache issues.
|
||||||
subscribeAppAssets();
|
subscribeAppAssets();
|
||||||
|
|
||||||
// Optional UX note for public mode pages.
|
// Optional UX note for public mode pages.
|
||||||
|
|||||||
+3
-3
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"VERSION": "v0.7.97",
|
"VERSION": "v0.7.98",
|
||||||
"VERSION_NUMBER": "0.7.97",
|
"VERSION_NUMBER": "0.7.98",
|
||||||
"BUILD_DATE": "2026-08-04T13:32:52.287Z"
|
"BUILD_DATE": "2026-08-04T15:37:02.089Z"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user