Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4dfd31263 |
@@ -11,6 +11,7 @@ Usage:
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
@@ -33,7 +34,6 @@ KZAPSTORE_COMMUNITY_PUBKEY = "acfeaea6e51420e8068fac446ca9d17d7a9ef6a5d20d93894e
|
||||
# Load real app developer pubkeys (kind 32267 events) so stack `a` tags
|
||||
# reference events that actually exist on the relay.
|
||||
# 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")
|
||||
try:
|
||||
with open(_PUBKEYS_PATH) as f:
|
||||
|
||||
+82
-21
@@ -206,6 +206,8 @@
|
||||
let appVersions = {}; // identifier -> { version, size, url, created_at }
|
||||
let assetSub = null;
|
||||
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)
|
||||
@@ -788,7 +790,8 @@
|
||||
console.log('[app-stacks] Added app def:', apps[apps.length - 1].name);
|
||||
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(); }
|
||||
});
|
||||
}
|
||||
@@ -823,7 +826,8 @@
|
||||
console.log('[app-stacks] Added stack:', stacks[stacks.length - 1].name);
|
||||
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(); }
|
||||
});
|
||||
}
|
||||
@@ -841,27 +845,84 @@
|
||||
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() {
|
||||
console.log('[app-stacks] Subscribing to app assets (kind 3063)...');
|
||||
assetSub = subscribe({ kinds: [3063], limit: 500 }, { closeOnEose: false, cacheUsage: 'CACHE_FIRST' });
|
||||
// Wait for app definitions to load so we know the identifiers
|
||||
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() {
|
||||
window.addEventListener('ndkEvent', function(event) {
|
||||
var evt = event.detail;
|
||||
if (evt.kind !== 3063) return;
|
||||
var parsed = parseAppAsset(evt);
|
||||
if (!parsed.identifier) return;
|
||||
// Keep the latest version (highest created_at)
|
||||
var existing = appVersions[parsed.identifier];
|
||||
if (!existing || parsed.created_at > existing.created_at) {
|
||||
appVersions[parsed.identifier] = parsed;
|
||||
if (assetsLoaded) renderApps();
|
||||
function fetchAppAssetsByIdentifier() {
|
||||
var identifiers = apps.map(function(a) { return a.identifier; });
|
||||
var batchSize = 50;
|
||||
var batches = [];
|
||||
for (var i = 0; i < identifiers.length; i += batchSize) {
|
||||
batches.push(identifiers.slice(i, i + batchSize));
|
||||
}
|
||||
console.log('[app-stacks] Fetching in ' + batches.length + ' batches of up to ' + batchSize + ' apps each');
|
||||
|
||||
var batchIndex = 0;
|
||||
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() {
|
||||
if (!assetsLoaded) { assetsLoaded = true; renderApps(); }
|
||||
});
|
||||
|
||||
var batch = batches[batchIndex];
|
||||
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) {
|
||||
@@ -970,8 +1031,8 @@
|
||||
initAppStackListener();
|
||||
subscribeAppStacks();
|
||||
|
||||
// Set up app-asset (kind 3063) listener and subscription for version info
|
||||
initAppAssetListener();
|
||||
// Fetch kind 3063 (Software Asset) events directly from relay.zapstore.dev
|
||||
// for version info. Bypasses NDK to avoid grouping/cache issues.
|
||||
subscribeAppAssets();
|
||||
|
||||
// Optional UX note for public mode pages.
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"VERSION": "v0.7.97",
|
||||
"VERSION_NUMBER": "0.7.97",
|
||||
"BUILD_DATE": "2026-08-04T13:32:52.287Z"
|
||||
"VERSION": "v0.7.98",
|
||||
"VERSION_NUMBER": "0.7.98",
|
||||
"BUILD_DATE": "2026-08-04T15:37:02.089Z"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user