···1111 'theathletic.bsky.social'
1212];
13131414-// Helper function to fetch all paginated results using a specific agent instance
1515-async function fetchAllPaginated(agentInstance, apiMethod, initialParams) {
1414+// Helper function modified to handle direct fetch or agent calls
1515+// Now accepts an optional 'useDirectFetch' flag and the direct URL if needed
1616+async function fetchAllPaginated(agentInstance, apiMethod, initialParams, useDirectFetch = false, directUrl = null) {
1617 let results = [];
1718 let cursor = initialParams.cursor;
1818- const params = { ...initialParams };
1919- // Attempt to log the intended operation more reliably
2020- const operationName = apiMethod.name.includes('bound ') ? apiMethod.name.split('bound ')[1].trim() : apiMethod.name;
2121- console.log(`fetchAllPaginated: Starting ${operationName} with params:`, initialParams);
1919+ const params = { ...initialParams }; // Copy initial params
2020+ // Determine operation name
2121+ const operationName = apiMethod ? (apiMethod.name.includes('bound ') ? apiMethod.name.split('bound ')[1].trim() : apiMethod.name) : (directUrl || 'directFetch');
2222+ console.log(`fetchAllPaginated: Starting ${operationName} with initialParams:`, initialParams);
2323+2424+ let currentUrl = directUrl; // Use direct URL if provided
22252326 do {
2427 try {
2525- if (cursor) {
2626- params.cursor = cursor;
2727- }
2828- // Call the method. Assumes namespaced methods return { data: { records: [], cursor: '...' } }
2929- // or similar structure where records are in an array under `data`.
3030- const response = await apiMethod(params);
3131-3232- // Check if response and response.data exist
3333- if (!response || !response.data) {
3434- console.warn(`fetchAllPaginated: Invalid response structure for ${operationName}`, response);
3535- break; // Stop pagination if structure is unexpected
3636- }
3737-3838- // Find the key containing the array of results (e.g., 'records', 'follows', 'followers', 'actors')
3939- const listKey = Object.keys(response.data).find(key => Array.isArray(response.data[key]));
4040-4141- if (listKey && response.data[listKey]) {
4242- results = results.concat(response.data[listKey]);
2828+ let responseData;
2929+ if (useDirectFetch && currentUrl) {
3030+ // Handle pagination for direct fetch
3131+ const url = new URL(currentUrl);
3232+ if (cursor) {
3333+ url.searchParams.set('cursor', cursor);
3434+ }
3535+ // Add other params like limit (ensure initialParams doesn't duplicate)
3636+ Object.entries(params).forEach(([key, value]) => {
3737+ if (key !== 'cursor' && !url.searchParams.has(key)) {
3838+ url.searchParams.set(key, value);
3939+ }
4040+ });
4141+ // console.log(`fetchAllPaginated: Direct fetch URL: ${url.toString()}`);
4242+ const response = await fetch(url.toString());
4343+ if (!response.ok) throw new Error(`HTTP error ${response.status}`);
4444+ responseData = await response.json();
4545+ } else if (apiMethod) {
4646+ // Use agent method
4747+ if (cursor) {
4848+ params.cursor = cursor;
4949+ }
5050+ const response = await apiMethod(params);
5151+ if (!response || !response.data) {
5252+ console.warn(`fetchAllPaginated: Invalid agent response for ${operationName}`, response);
5353+ break;
5454+ }
5555+ responseData = response.data;
4356 } else {
4444- console.warn(`fetchAllPaginated: Could not find results array key in response.data for ${operationName}`, response.data);
5757+ console.error("fetchAllPaginated: Called without agent method or direct URL");
5858+ break;
4559 }
46604747- cursor = response.data.cursor;
4848- // console.log(`fetchAllPaginated: Fetched page for ${operationName}, got ${response.data[listKey]?.length || 0} items, cursor: ${cursor}`);
6161+ // Find results array
6262+ const listKey = Object.keys(responseData).find(key => Array.isArray(responseData[key]));
6363+ if (listKey && responseData[listKey]) {
6464+ results = results.concat(responseData[listKey]);
6565+ }
6666+ cursor = responseData.cursor;
49675068 } catch (error) {
5169 console.error(`Error during paginated fetch for ${operationName}:`, error);
5252- cursor = undefined; // Stop pagination on error
7070+ cursor = undefined;
5371 }
5472 } while (cursor);
5573···268286 setNetworkVerifications({ mutualsVerifiedMe: [], followsVerifiedMe: [], mutualsVerifiedAnyone: 0, followsVerifiedAnyone: 0, fetchedMutualsCount: 0, fetchedFollowsCount: 0 });
269287 setNetworkStatusMessage("Fetching network lists (mutuals, follows)...");
270288271271- const publicAgent = new Agent({ service: 'https://public.api.bsky.app' });
289289+ try {
290290+ console.log("checkNetworkVerifications: Fetching follows (public) and mutuals (authenticated)...");
272291273273- try {
274274- console.log("checkNetworkVerifications: Fetching follows and mutuals...");
275275- // Ensure correct agent and bound namespaced methods are used
292292+ // *** Fetch follows using direct fetch ***
293293+ const followsUrl = `https://public.api.bsky.app/xrpc/app.bsky.graph.getFollows`;
294294+ const followsParams = { actor: session.did, limit: 100 };
295295+296296+ // *** Fetch known followers using authenticated agent ***
297297+ const knownFollowersMethod = agent.api.app.bsky.graph.getKnownFollowers.bind(agent.api.app.bsky.graph);
298298+ const knownFollowersParams = { actor: session.did, limit: 100 };
299299+276300 const [follows, mutuals] = await Promise.all([
277277- fetchAllPaginated(publicAgent, publicAgent.api.app.bsky.graph.getFollows.bind(publicAgent.api.app.bsky.graph), { actor: session.did, limit: 100 }),
278278- fetchAllPaginated(agent, agent.api.app.bsky.graph.getKnownFollowers.bind(agent.api.app.bsky.graph), { actor: session.did, limit: 100 })
301301+ fetchAllPaginated(null, null, followsParams, true, followsUrl),
302302+ fetchAllPaginated(agent, knownFollowersMethod, knownFollowersParams)
279303 ]);
280304281305 console.log(`checkNetworkVerifications: Fetched ${follows.length} follows, ${mutuals.length} mutuals.`);
···315339 return null;
316340 }
317341318318- // Create a temporary agent specifically for this user's PDS
319319- const tempUserAgent = new Agent({ service: pdsEndpoint });
320342 let foundVerificationForMe = null;
321343 let hasVerifiedAnyone = false;
322344323345 try {
324324- // Use fetchAllPaginated to handle listing records from the specific PDS
346346+ // *** Use fetchAllPaginated with direct fetch for listRecords ***
347347+ const listRecordsUrl = `${pdsEndpoint}/xrpc/com.atproto.repo.listRecords`;
348348+ const listRecordsParams = { repo: did, collection: 'app.bsky.graph.verification', limit: 100 };
349349+325350 const verificationRecords = await fetchAllPaginated(
326326- tempUserAgent,
327327- tempUserAgent.api.com.atproto.repo.listRecords.bind(tempUserAgent.api.com.atproto.repo), // Bind namespaced method
328328- { repo: did, collection: 'app.bsky.graph.verification', limit: 100 }
351351+ null,
352352+ null,
353353+ listRecordsParams,
354354+ true, // Use direct fetch
355355+ listRecordsUrl
329356 );
330357331358 if (verificationRecords.length > 0) {
···337364 }
338365 }
339366 } catch (err) {
340340- // fetchAllPaginated already logs errors, just skip this user on error
341341- console.warn(`Error processing records for ${profile.handle || did} on ${pdsEndpoint}`);
367367+ console.warn(`Error processing records for ${profile?.handle || did} on ${pdsEndpoint}:`, err);
342368 }
343369344370 // Return data for aggregation
···387413 setIsLoadingNetwork(false);
388414 setNetworkChecked(true);
389415 }
390390- }, [agent, session, userInfo]); // Keep dependencies
416416+ }, [agent, session, userInfo]);
391417392418 useEffect(() => {
393419 if (agent) {
+1
src/contexts/AuthContext.js
···4646 const oauthClient = new BrowserOAuthClient({
4747 clientMetadata: clientMetadata,
4848 handleResolver: 'https://bsky.social', // Use Bluesky's resolver or your own
4949+ scope: 'atproto transition:generic'
4950 });
50515152 setClient(oauthClient); // Store the client instance