tangled
alpha
login
or
join now
nekomimi.pet
/
cutebook
28
fork
atom
web components for a integratabtle atproto based guestbook
28
fork
atom
overview
issues
pulls
pipelines
async fetch profiles
nekomimi.pet
3 months ago
7befa943
f4580322
verified
This commit was signed with the committer's
known signature
.
nekomimi.pet
SSH Key Fingerprint:
SHA256:knUvGhH8rbrdqbzO9WXAIaTK0LrdYw2UC0qWB43Ic0Q=
+75
-33
1 changed file
expand all
collapse all
unified
split
lib
guestbook-display.ts
+75
-33
lib/guestbook-display.ts
···
315
315
}
316
316
317
317
const data: ConstellationBacklinksResponse = await response.json();
318
318
-
318
318
+
319
319
console.log('Constellation response:', data);
320
320
321
321
// fetch actual records
···
323
323
console.warn('No records found in response');
324
324
this.signatures = [];
325
325
} else {
326
326
-
// fetch each record from the repository
327
327
-
const signatures: GuestbookSignature[] = [];
328
328
-
329
329
-
for (const record of data.records) {
326
326
+
// Fetch all records in parallel
327
327
+
const recordPromises = data.records.map(async (record) => {
330
328
try {
331
329
const recordUrl = new URL('/xrpc/com.atproto.repo.getRecord', 'https://slingshot.wisp.place');
332
330
recordUrl.searchParams.set('repo', record.did);
333
331
recordUrl.searchParams.set('collection', record.collection);
334
332
recordUrl.searchParams.set('rkey', record.rkey);
335
335
-
333
333
+
336
334
const recordResponse = await fetch(recordUrl.toString());
337
335
if (!recordResponse.ok) {
338
336
console.warn(`Failed to fetch record ${record.did}/${record.collection}/${record.rkey}`);
339
339
-
continue;
337
337
+
return null;
340
338
}
341
341
-
339
339
+
342
340
const recordData = await recordResponse.json();
343
343
-
341
341
+
344
342
// validate the record
345
343
if (
346
344
recordData.value &&
···
348
346
typeof recordData.value.message === 'string' &&
349
347
typeof recordData.value.createdAt === 'string'
350
348
) {
351
351
-
// Fetch the handle for this author
352
352
-
let authorHandle: string | undefined;
353
353
-
try {
354
354
-
const profileResponse = await fetch(
355
355
-
`https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=${record.did}`
356
356
-
);
357
357
-
if (profileResponse.ok) {
358
358
-
const profileData = await profileResponse.json();
359
359
-
authorHandle = profileData.handle;
360
360
-
}
361
361
-
} catch (err) {
362
362
-
console.warn(`Failed to fetch handle for ${record.did}:`, err);
363
363
-
}
364
364
-
365
365
-
signatures.push({
349
349
+
return {
366
350
uri: recordData.uri,
367
351
cid: recordData.cid,
368
352
value: recordData.value,
369
353
author: record.did,
370
370
-
authorHandle: authorHandle,
371
371
-
});
354
354
+
authorHandle: undefined,
355
355
+
} as GuestbookSignature;
372
356
}
373
357
} catch (err) {
374
358
console.warn(`Error fetching record ${record.did}/${record.collection}/${record.rkey}:`, err);
375
359
}
376
376
-
}
377
377
-
378
378
-
// sort by creation time, newest first
379
379
-
this.signatures = signatures.sort((a, b) => {
360
360
+
return null;
361
361
+
});
362
362
+
363
363
+
const results = await Promise.all(recordPromises);
364
364
+
const validSignatures = results.filter((sig): sig is GuestbookSignature => sig !== null);
365
365
+
366
366
+
// Sort once after collecting all signatures
367
367
+
validSignatures.sort((a, b) => {
380
368
return new Date(b.value.createdAt).getTime() - new Date(a.value.createdAt).getTime();
381
369
});
382
382
-
}
383
370
371
371
+
this.signatures = validSignatures;
384
372
this.loading = false;
385
373
this.updateContent();
386
374
375
375
+
// Batch fetch profiles asynchronously
376
376
+
if (validSignatures.length > 0) {
377
377
+
const uniqueDids = Array.from(new Set(validSignatures.map(sig => sig.author)));
378
378
+
379
379
+
// Batch fetch profiles up to 25 at a time (API limit)
380
380
+
const profilePromises = [];
381
381
+
for (let i = 0; i < uniqueDids.length; i += 25) {
382
382
+
const batch = uniqueDids.slice(i, i + 25);
383
383
+
384
384
+
const profileUrl = new URL('/xrpc/app.bsky.actor.getProfiles', 'https://public.api.bsky.app');
385
385
+
batch.forEach(d => profileUrl.searchParams.append('actors', d));
386
386
+
387
387
+
profilePromises.push(
388
388
+
fetch(profileUrl.toString())
389
389
+
.then(profileResponse => profileResponse.ok ? profileResponse.json() : null)
390
390
+
.then(profilesData => {
391
391
+
if (profilesData?.profiles && Array.isArray(profilesData.profiles)) {
392
392
+
const handles = new Map<string, string>();
393
393
+
profilesData.profiles.forEach((profile: any) => {
394
394
+
if (profile.handle) {
395
395
+
handles.set(profile.did, profile.handle);
396
396
+
}
397
397
+
});
398
398
+
return handles;
399
399
+
}
400
400
+
return new Map<string, string>();
401
401
+
})
402
402
+
.catch((err) => {
403
403
+
console.warn('Failed to fetch profile batch:', err);
404
404
+
return new Map<string, string>();
405
405
+
})
406
406
+
);
407
407
+
}
408
408
+
409
409
+
// Wait for all profile batches, then update once
410
410
+
const handleMaps = await Promise.all(profilePromises);
411
411
+
const allHandles = new Map<string, string>();
412
412
+
handleMaps.forEach(map => {
413
413
+
map.forEach((handle, did) => allHandles.set(did, handle));
414
414
+
});
415
415
+
416
416
+
if (allHandles.size > 0) {
417
417
+
this.signatures = this.signatures.map(sig => {
418
418
+
const handle = allHandles.get(sig.author);
419
419
+
return handle ? { ...sig, authorHandle: handle } : sig;
420
420
+
});
421
421
+
this.updateContent();
422
422
+
}
423
423
+
}
424
424
+
}
425
425
+
387
426
} catch (error) {
388
427
console.error('Error fetching signatures:', error);
389
428
this.error = error instanceof Error ? error.message : 'Unknown error occurred';
···
403
442
}
404
443
405
444
private shortenDid(did: string): string {
406
406
-
if (did.startsWith('did:plc:')) {
407
407
-
return `${did.slice(0, 16)}...${did.slice(-4)}`;
445
445
+
if (did.startsWith('did:')) {
446
446
+
const afterPrefix = did.indexOf(':', 4);
447
447
+
if (afterPrefix !== -1) {
448
448
+
return `${did.slice(0, afterPrefix + 9)}...`;
449
449
+
}
408
450
}
409
451
return did;
410
452
}