A simple tool which lets you scrape twitter accounts and crosspost them to bluesky accounts! Comes with a CLI and a webapp for managing profiles! Works with images/videos/link embeds/threads.

Enhancement: Add retry mechanism to fetchUserTweets for improved reliability

jack 1a83f3f5 d98ca96e

+23 -9
+23 -9
src/index.ts
··· 688 688 const client = await getTwitterScraper(); 689 689 if (!client) return []; 690 690 691 - const tweets: Tweet[] = []; 692 - try { 693 - const generator = client.getTweets(username, limit); 694 - for await (const t of generator) { 695 - tweets.push(mapScraperTweetToLocalTweet(t)); 696 - if (tweets.length >= limit) break; 691 + let retries = 3; 692 + while (retries > 0) { 693 + try { 694 + const tweets: Tweet[] = []; 695 + const generator = client.getTweets(username, limit); 696 + for await (const t of generator) { 697 + tweets.push(mapScraperTweetToLocalTweet(t)); 698 + if (tweets.length >= limit) break; 699 + } 700 + return tweets; 701 + } catch (e: any) { 702 + retries--; 703 + const isRetryable = e.message?.includes('ServiceUnavailable') || e.message?.includes('Timeout') || e.message?.includes('429'); 704 + 705 + if (retries > 0 && isRetryable) { 706 + console.warn(`⚠️ Error fetching tweets for ${username} (${e.message}). Retrying in 5s...`); 707 + await new Promise(r => setTimeout(r, 5000)); 708 + continue; 709 + } 710 + 711 + console.warn(`Error fetching tweets for ${username}:`, e); 712 + return []; 697 713 } 698 - } catch (e) { 699 - console.warn(`Error fetching tweets for ${username}:`, e); 700 714 } 701 - return tweets; 715 + return []; 702 716 } 703 717 704 718 // ============================================================================