···
16
16
let results = [];
17
17
let cursor = initialParams.cursor;
18
18
const params = { ...initialParams };
19
19
-
let operationName = apiMethod.name.replace('bound ', '');
19
19
+
// Attempt to log the intended operation more reliably
20
20
+
const operationName = apiMethod.name.includes('bound ') ? apiMethod.name.split('bound ')[1].trim() : apiMethod.name;
21
21
+
console.log(`fetchAllPaginated: Starting ${operationName} with params:`, initialParams);
20
22
21
23
do {
22
24
try {
23
25
if (cursor) {
24
26
params.cursor = cursor;
25
27
}
28
28
+
// Call the method. Assumes namespaced methods return { data: { records: [], cursor: '...' } }
29
29
+
// or similar structure where records are in an array under `data`.
26
30
const response = await apiMethod(params);
27
27
-
const listKey = Object.keys(response.data || response).find(key => Array.isArray((response.data || response)[key]));
28
28
-
if (listKey && (response.data || response)[listKey]) {
29
29
-
results = results.concat((response.data || response)[listKey]);
31
31
+
32
32
+
// Check if response and response.data exist
33
33
+
if (!response || !response.data) {
34
34
+
console.warn(`fetchAllPaginated: Invalid response structure for ${operationName}`, response);
35
35
+
break; // Stop pagination if structure is unexpected
36
36
+
}
37
37
+
38
38
+
// Find the key containing the array of results (e.g., 'records', 'follows', 'followers', 'actors')
39
39
+
const listKey = Object.keys(response.data).find(key => Array.isArray(response.data[key]));
40
40
+
41
41
+
if (listKey && response.data[listKey]) {
42
42
+
results = results.concat(response.data[listKey]);
43
43
+
} else {
44
44
+
console.warn(`fetchAllPaginated: Could not find results array key in response.data for ${operationName}`, response.data);
30
45
}
31
31
-
cursor = (response.data || response).cursor;
46
46
+
47
47
+
cursor = response.data.cursor;
48
48
+
// console.log(`fetchAllPaginated: Fetched page for ${operationName}, got ${response.data[listKey]?.length || 0} items, cursor: ${cursor}`);
49
49
+
32
50
} catch (error) {
33
51
console.error(`Error during paginated fetch for ${operationName}:`, error);
34
34
-
cursor = undefined;
52
52
+
cursor = undefined; // Stop pagination on error
35
53
}
36
54
} while (cursor);
37
55
56
56
+
console.log(`fetchAllPaginated: Finished ${operationName}, total items: ${results.length}`);
38
57
return results;
39
58
}
40
59
···
240
259
}, []); // Removed agent dependency as it's no longer used directly here
241
260
242
261
const checkNetworkVerifications = useCallback(async () => {
243
243
-
if (!agent || !session || !userInfo) return;
262
262
+
if (!agent || !session || !userInfo) {
263
263
+
console.warn("checkNetworkVerifications: Agent, session, or userInfo not available.");
264
264
+
return;
265
265
+
}
244
266
setIsLoadingNetwork(true);
245
267
setNetworkChecked(false);
246
268
setNetworkVerifications({ mutualsVerifiedMe: [], followsVerifiedMe: [], mutualsVerifiedAnyone: 0, followsVerifiedAnyone: 0, fetchedMutualsCount: 0, fetchedFollowsCount: 0 });
···
249
271
const publicAgent = new Agent({ service: 'https://public.api.bsky.app' });
250
272
251
273
try {
274
274
+
console.log("checkNetworkVerifications: Fetching follows and mutuals...");
275
275
+
// Ensure correct agent and bound namespaced methods are used
252
276
const [follows, mutuals] = await Promise.all([
253
277
fetchAllPaginated(publicAgent, publicAgent.api.app.bsky.graph.getFollows.bind(publicAgent.api.app.bsky.graph), { actor: session.did, limit: 100 }),
254
278
fetchAllPaginated(agent, agent.api.app.bsky.graph.getKnownFollowers.bind(agent.api.app.bsky.graph), { actor: session.did, limit: 100 })
255
279
]);
256
280
257
257
-
console.log(`Fetched ${follows.length} follows, ${mutuals.length} mutuals.`);
258
258
-
setNetworkStatusMessage(`Fetched ${follows.length} follows, ${mutuals.length} mutuals. Checking verifications...`);
281
281
+
console.log(`checkNetworkVerifications: Fetched ${follows.length} follows, ${mutuals.length} mutuals.`);
282
282
+
setNetworkStatusMessage(`Processing ${follows.length} follows and ${mutuals.length} mutuals...`);
259
283
setNetworkVerifications(prev => ({ ...prev, fetchedMutualsCount: mutuals.length, fetchedFollowsCount: follows.length }));
260
284
261
285
const followsSet = new Set(follows.map(f => f.did));
262
286
const mutualsSet = new Set(mutuals.map(m => m.did));
263
287
const allProfilesMap = new Map();
264
264
-
[...follows, ...mutuals].forEach(user => { if (!allProfilesMap.has(user.did)) allProfilesMap.set(user.did, user); });
288
288
+
[...follows, ...mutuals].forEach(user => { if (user && user.did && !allProfilesMap.has(user.did)) allProfilesMap.set(user.did, user); });
265
289
const uniqueUserDids = Array.from(allProfilesMap.keys());
266
290
267
291
if (uniqueUserDids.length === 0) {
···
271
295
return;
272
296
}
273
297
298
298
+
console.log(`checkNetworkVerifications: Checking ${uniqueUserDids.length} unique users...`);
274
299
let results = { mutualsVerifiedMe: [], followsVerifiedMe: [], mutualsVerifiedAnyone: 0, followsVerifiedAnyone: 0 };
275
300
const batchSize = 10;
301
301
+
276
302
for (let i = 0; i < uniqueUserDids.length; i += batchSize) {
277
303
const batchDids = uniqueUserDids.slice(i, i + batchSize);
278
278
-
setNetworkStatusMessage(`Checking network... (${i + batchDids.length}/${uniqueUserDids.length})`);
304
304
+
setNetworkStatusMessage(`Checking verification records... (${i + batchDids.length}/${uniqueUserDids.length})`);
279
305
280
280
-
await Promise.all(batchDids.map(async (did) => {
306
306
+
const batchPromises = batchDids.map(async (did) => {
281
307
const profile = allProfilesMap.get(did);
282
282
-
if (!profile) return;
308
308
+
if (!profile) return null;
283
309
const isMutual = mutualsSet.has(did);
284
310
const isFollow = followsSet.has(did);
311
311
+
285
312
const pdsEndpoint = await getPdsEndpoint(did);
286
313
if (!pdsEndpoint) {
287
287
-
console.warn(`Skipping verification check for ${profile?.handle || did} (no PDS found).`);
288
288
-
return;
314
314
+
console.warn(`Skipping verification check for ${profile.handle || did} (no PDS found).`);
315
315
+
return null;
289
316
}
290
317
318
318
+
// Create a temporary agent specifically for this user's PDS
319
319
+
const tempUserAgent = new Agent({ service: pdsEndpoint });
291
320
let foundVerificationForMe = null;
292
321
let hasVerifiedAnyone = false;
293
293
-
let listRecordsCursor = undefined;
294
294
-
const tempPublicAgent = new Agent({ service: pdsEndpoint });
322
322
+
323
323
+
try {
324
324
+
// Use fetchAllPaginated to handle listing records from the specific PDS
325
325
+
const verificationRecords = await fetchAllPaginated(
326
326
+
tempUserAgent,
327
327
+
tempUserAgent.api.com.atproto.repo.listRecords.bind(tempUserAgent.api.com.atproto.repo), // Bind namespaced method
328
328
+
{ repo: did, collection: 'app.bsky.graph.verification', limit: 100 }
329
329
+
);
295
330
296
296
-
do {
297
297
-
try {
298
298
-
const response = await tempPublicAgent.api.com.atproto.repo.listRecords({
299
299
-
repo: did,
300
300
-
collection: 'app.bsky.graph.verification',
301
301
-
limit: 100,
302
302
-
cursor: listRecordsCursor
303
303
-
});
304
304
-
const records = response.data.records || [];
305
305
-
if (records.length > 0) {
306
306
-
hasVerifiedAnyone = true;
307
307
-
const matchingRecord = records.find(record => record.value?.subject === session.did);
308
308
-
if (matchingRecord) { foundVerificationForMe = matchingRecord; break; }
331
331
+
if (verificationRecords.length > 0) {
332
332
+
hasVerifiedAnyone = true;
333
333
+
// Check if any record verifies the logged-in user
334
334
+
const matchingRecord = verificationRecords.find(record => record.value?.subject === session.did);
335
335
+
if (matchingRecord) {
336
336
+
foundVerificationForMe = matchingRecord;
309
337
}
310
310
-
listRecordsCursor = response.data.cursor;
311
311
-
} catch (err) {
312
312
-
console.warn(`Could not listRecords for ${did} on ${pdsEndpoint}:`, err.message);
313
313
-
listRecordsCursor = undefined;
314
314
-
break;
315
338
}
316
316
-
} while (listRecordsCursor);
339
339
+
} catch (err) {
340
340
+
// fetchAllPaginated already logs errors, just skip this user on error
341
341
+
console.warn(`Error processing records for ${profile.handle || did} on ${pdsEndpoint}`);
342
342
+
}
343
343
+
344
344
+
// Return data for aggregation
345
345
+
return {
346
346
+
isMutual,
347
347
+
isFollow,
348
348
+
profile,
349
349
+
hasVerifiedAnyone,
350
350
+
foundVerificationForMe
351
351
+
};
352
352
+
});
353
353
+
354
354
+
// Process results from the batch
355
355
+
const batchResults = await Promise.all(batchPromises);
356
356
+
batchResults.forEach(result => {
357
357
+
if (!result) return; // Skip if PDS lookup failed or other issue
358
358
+
if (result.hasVerifiedAnyone) {
359
359
+
if (result.isMutual) results.mutualsVerifiedAnyone++;
360
360
+
if (result.isFollow) results.followsVerifiedAnyone++;
361
361
+
}
362
362
+
if (result.foundVerificationForMe) {
363
363
+
const accountInfo = { ...result.profile, verification: result.foundVerificationForMe };
364
364
+
if (result.isMutual) results.mutualsVerifiedMe.push(accountInfo);
365
365
+
if (result.isFollow) results.followsVerifiedMe.push(accountInfo);
366
366
+
}
367
367
+
});
317
368
318
318
-
if (hasVerifiedAnyone) {
319
319
-
if (isMutual) results.mutualsVerifiedAnyone++;
320
320
-
if (isFollow) results.followsVerifiedAnyone++;
321
321
-
}
322
322
-
if (foundVerificationForMe) {
323
323
-
const accountInfo = { ...profile, verification: foundVerificationForMe };
324
324
-
if (isMutual) results.mutualsVerifiedMe.push(accountInfo);
325
325
-
if (isFollow) results.followsVerifiedMe.push(accountInfo);
326
326
-
}
369
369
+
// Update state incrementally after each batch
370
370
+
setNetworkVerifications(prev => ({
371
371
+
...prev,
372
372
+
mutualsVerifiedMe: [...results.mutualsVerifiedMe],
373
373
+
followsVerifiedMe: [...results.followsVerifiedMe],
374
374
+
mutualsVerifiedAnyone: results.mutualsVerifiedAnyone,
375
375
+
followsVerifiedAnyone: results.followsVerifiedAnyone,
327
376
}));
328
328
-
setNetworkVerifications(prev => ({ ...prev, ...results }));
329
377
}
378
378
+
379
379
+
console.log('checkNetworkVerifications: Check complete.', results);
330
380
setNetworkStatusMessage("Network verification check complete.");
381
381
+
331
382
} catch (error) {
332
383
console.error('Error during network verification check:', error);
333
384
setStatusMessage(`Error checking network: ${error.message || 'Unknown error'}`);
···
336
387
setIsLoadingNetwork(false);
337
388
setNetworkChecked(true);
338
389
}
339
339
-
}, [agent, session, userInfo]);
390
390
+
}, [agent, session, userInfo]); // Keep dependencies
340
391
341
392
useEffect(() => {
342
393
if (agent) {