Merge pull request #736 from PR0M3TH3AN/codex/fix-import-and-migration-for-older-index

nostr: support legacy manifest id
This commit is contained in:
thePR0M3TH3AN
2025-08-03 14:38:01 -04:00
committed by GitHub
2 changed files with 85 additions and 22 deletions

View File

@@ -407,7 +407,9 @@ class NostrClient:
}
)
manifest_identifier = f"{MANIFEST_ID_PREFIX}{self.fingerprint}"
manifest_identifier = (
self.current_manifest_id or f"{MANIFEST_ID_PREFIX}{self.fingerprint}"
)
manifest_event = (
EventBuilder(Kind(KIND_MANIFEST), manifest_json)
.tags([Tag.identifier(manifest_identifier)])
@@ -516,35 +518,47 @@ class NostrClient:
self.last_error = None
pubkey = self.keys.public_key()
ident = f"{MANIFEST_ID_PREFIX}{self.fingerprint}"
f = Filter().author(pubkey).kind(Kind(KIND_MANIFEST)).identifier(ident).limit(1)
identifiers = [
f"{MANIFEST_ID_PREFIX}{self.fingerprint}",
MANIFEST_ID_PREFIX.rstrip("-"),
]
timeout = timedelta(seconds=10)
try:
events = (await self.client.fetch_events(f, timeout)).to_vec()
except Exception as e: # pragma: no cover - network errors
self.last_error = str(e)
logger.error(
"Failed to fetch manifest from relays %s: %s",
self.relays,
e,
for ident in identifiers:
f = (
Filter()
.author(pubkey)
.kind(Kind(KIND_MANIFEST))
.identifier(ident)
.limit(1)
)
return None
if not events:
return None
for manifest_event in events:
try:
result = await self._fetch_chunks_with_retry(manifest_event)
if result is not None:
return result
events = (await self.client.fetch_events(f, timeout)).to_vec()
except Exception as e: # pragma: no cover - network errors
self.last_error = str(e)
logger.error(
"Error retrieving snapshot from relays %s: %s",
"Failed to fetch manifest from relays %s: %s",
self.relays,
e,
)
return None
if not events:
continue
for manifest_event in events:
try:
result = await self._fetch_chunks_with_retry(manifest_event)
if result is not None:
return result
except Exception as e: # pragma: no cover - network errors
self.last_error = str(e)
logger.error(
"Error retrieving snapshot from relays %s: %s",
self.relays,
e,
)
# manifest was found but chunks missing; do not try other identifiers
return None
if self.last_error is None:
self.last_error = "Snapshot not found on relays"
@@ -557,7 +571,7 @@ class NostrClient:
return
await self._connect_async()
pubkey = self.keys.public_key()
ident = f"{MANIFEST_ID_PREFIX}{self.fingerprint}"
ident = self.current_manifest_id or f"{MANIFEST_ID_PREFIX}{self.fingerprint}"
f = Filter().author(pubkey).kind(Kind(KIND_MANIFEST)).identifier(ident).limit(1)
timeout = timedelta(seconds=10)
try:

View File

@@ -0,0 +1,49 @@
import asyncio
from helpers import TEST_SEED, dummy_nostr_client
from nostr.backup_models import KIND_MANIFEST
from nostr.client import MANIFEST_ID_PREFIX, NostrClient
def test_fetch_latest_snapshot_legacy_identifier(dummy_nostr_client, monkeypatch):
client, relay = dummy_nostr_client
data = b"legacy"
asyncio.run(client.publish_snapshot(data))
relay.manifests[-1].tags = [MANIFEST_ID_PREFIX.rstrip("-")]
relay.filters.clear()
orig_fetch = relay.fetch_events
async def fetch_events(self, f, timeout):
identifier = f.ids[0] if getattr(f, "ids", None) else None
kind = getattr(f, "kind_val", None)
if kind == KIND_MANIFEST:
events = [m for m in self.manifests if identifier in m.tags]
self.filters.append(f)
class Res:
def __init__(self, evs):
self._evs = evs
def to_vec(self):
return self._evs
return Res(events)
return await orig_fetch(f, timeout)
monkeypatch.setattr(
relay, "fetch_events", fetch_events.__get__(relay, relay.__class__)
)
enc_mgr = client.encryption_manager
monkeypatch.setattr(
enc_mgr, "decrypt_parent_seed", lambda: TEST_SEED, raising=False
)
monkeypatch.setattr("nostr.client.KeyManager", type(client.key_manager))
client2 = NostrClient(enc_mgr, "fp")
relay.filters.clear()
result = asyncio.run(client2.fetch_latest_snapshot())
assert result is not None
ids = [f.ids[0] for f in relay.filters]
assert ids[0] == f"{MANIFEST_ID_PREFIX}fp"
assert MANIFEST_ID_PREFIX.rstrip("-") in ids