···
113
113
}
114
114
115
115
// Step 2: Get the PDS service endpoint from PLC directory
116
116
-
let serviceEndpoint = 'https://public.api.bsky.app'; // Default fallback
116
116
+
let serviceEndpoint = 'https://bsky.social'; // Start with bsky.social as fallback
117
117
try {
118
118
const plcResponse = await fetch(`https://plc.directory/${did}/data`);
119
119
···
149
149
});
150
150
151
151
if (!recordsResponse.ok) {
152
152
-
// If failed with custom PDS service endpoint, try with the default public API endpoint
152
152
+
// Special case for handling third-party PDS
153
153
+
if (handle.includes('.') && !handle.endsWith('bsky.social') && !handle.endsWith('flushes.app') && !handle.endsWith('flushing.im')) {
154
154
+
const domain = handle.split('.').slice(1).join('.');
155
155
+
156
156
+
console.log(`Trying direct domain access before falling back: ${domain}`);
157
157
+
try {
158
158
+
const directUrl = `https://${domain}/xrpc/com.atproto.repo.listRecords?repo=${encodeURIComponent(did)}&collection=${encodeURIComponent(FLUSHING_STATUS_NSID)}&limit=${MAX_ENTRIES}`;
159
159
+
160
160
+
const directResponse = await fetch(directUrl, {
161
161
+
headers: { 'Accept': 'application/json' }
162
162
+
});
163
163
+
164
164
+
if (directResponse.ok) {
165
165
+
console.log(`Successfully accessed records directly from ${domain}`);
166
166
+
const directData = await directResponse.json();
167
167
+
168
168
+
// Process the direct response...
169
169
+
// Process the direct response...
170
170
+
const directEntries = directData.records
171
171
+
.map((record: any) => {
172
172
+
const text = record.value.text || '';
173
173
+
if (containsBannedWords(text)) return null;
174
174
+
175
175
+
return {
176
176
+
id: record.uri,
177
177
+
uri: record.uri,
178
178
+
cid: record.cid,
179
179
+
did: did,
180
180
+
text: sanitizeText(text),
181
181
+
emoji: record.value.emoji || '🚽',
182
182
+
created_at: record.value.createdAt
183
183
+
};
184
184
+
})
185
185
+
.filter((entry: ProfileEntry | null): entry is ProfileEntry => entry !== null);
186
186
+
187
187
+
// Calculate emoji stats
188
188
+
const directEmojiCounts = new Map<string, number>();
189
189
+
directEntries.forEach((entry: ProfileEntry) => {
190
190
+
const emoji = entry.emoji?.trim() || '🚽';
191
191
+
if (APPROVED_EMOJIS.includes(emoji)) {
192
192
+
directEmojiCounts.set(emoji, (directEmojiCounts.get(emoji) || 0) + 1);
193
193
+
} else {
194
194
+
directEmojiCounts.set('🚽', (directEmojiCounts.get('🚽') || 0) + 1);
195
195
+
}
196
196
+
});
197
197
+
198
198
+
const directEmojiStats = Array.from(directEmojiCounts.entries())
199
199
+
.map(([emoji, count]): EmojiStat => ({ emoji, count }))
200
200
+
.sort((a, b) => b.count - a.count);
201
201
+
202
202
+
return NextResponse.json({
203
203
+
entries: directEntries,
204
204
+
count: directEntries.length,
205
205
+
cursor: directData.cursor,
206
206
+
profile: userProfile,
207
207
+
emojiStats: directEmojiStats,
208
208
+
serviceEndpoint: `https://${domain}`,
209
209
+
directPds: true
210
210
+
});
211
211
+
} else {
212
212
+
console.warn(`Direct access failed: ${await directResponse.text()}`);
213
213
+
}
214
214
+
} catch (directErr) {
215
215
+
console.error(`Error with direct domain access: ${directErr}`);
216
216
+
}
217
217
+
}
218
218
+
219
219
+
// If direct access failed or not applicable, try with public API endpoint
153
220
if (serviceEndpoint !== 'https://public.api.bsky.app') {
154
221
console.warn(`Failed to get records from ${serviceEndpoint}, trying public API endpoint`);
155
222
// Log the error for debugging third-party PDS issues
···
229
296
count: transformedEntries.length,
230
297
cursor: fallbackData.cursor,
231
298
profile: userProfile,
232
232
-
emojiStats
299
299
+
emojiStats,
300
300
+
serviceEndpoint: 'https://public.api.bsky.app', // Record which endpoint was used
301
301
+
fallback: true
233
302
});
234
303
}
235
304
···
289
358
.map(([emoji, count]): EmojiStat => ({ emoji, count }))
290
359
.sort((a, b) => b.count - a.count);
291
360
361
361
+
292
362
return NextResponse.json({
293
363
entries: transformedEntries,
294
364
count: transformedEntries.length,
295
365
cursor: recordsData.cursor,
296
366
profile: userProfile,
297
297
-
emojiStats
367
367
+
emojiStats,
368
368
+
serviceEndpoint // Include the endpoint we used for debugging
298
369
});
299
370
} catch (error: any) {
300
371
console.error('Error fetching records:', error);
···
364
435
entries: filteredEntries,
365
436
count: filteredEntries.length, // Update count to reflect filtered entries
366
437
profile: userProfile,
367
367
-
emojiStats
438
438
+
emojiStats,
439
439
+
source: 'supabase', // Record the data source
440
440
+
did
368
441
});
369
442
}
370
443