Something went wrong. Try again.
visualize bsky quote trends sites.wisp.place/zzstoatzz.io/quotree
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546const SERVICE_NAMES = { 'slingshot.microcosm.blue': 'Slingshot', 'constellation.microcosm.blue': 'Constellation', 'public.api.bsky.app': 'Bluesky AppView',};
export class RateLimitError extends Error { constructor(url, response) { const target = new URL(url); const service = SERVICE_NAMES[target.hostname] || target.hostname; const endpoint = target.pathname.split('/').pop(); const retryAfter = response.headers.get('retry-after'); const seconds = retryAfter && /^\d+$/.test(retryAfter) ? Number(retryAfter) : null; const date = retryAfter && seconds === null ? Date.parse(retryAfter) : NaN; const guidance = seconds !== null ? ` Retry after ${seconds} seconds.` : Number.isFinite(date) ? ` Retry after ${new Date(date).toUTCString()}.` : ''; super(`${service} (${target.hostname}) returned HTTP 429 on ${endpoint}. Crawl stopped.${guidance}`); this.name = 'RateLimitError'; this.service = service; this.status = 429; this.endpoint = endpoint; this.origin = target.origin; this.retryAfter = retryAfter; }}
export function createPacedFetch(intervalMs = 250) { const services = new Map(); return async (url, options) => { const origin = new URL(url).origin; if (!services.has(origin)) services.set(origin, { ready: Promise.resolve(), lastStart: 0 }); const service = services.get(origin); service.ready = service.ready.then(async () => { const delay = service.lastStart + intervalMs - Date.now(); if (delay > 0) await new Promise((resolve) => setTimeout(resolve, delay)); service.lastStart = Date.now(); }); await service.ready; const response = await fetch(url, options); if (response.status === 429) throw new RateLimitError(url, response); return response; };}
export const pacedFetch = createPacedFetch();