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.

Fix: Enhanced retweet detection using isRetweet flag and text fallback

jack 268c2bcb 078d373d

+10 -1
+10 -1
src/index.ts
··· 99 in_reply_to_status_id?: string; 100 in_reply_to_user_id_str?: string; 101 in_reply_to_user_id?: string; 102 user?: { 103 screen_name?: string; 104 id_str?: string; ··· 256 id_str: scraperTweet.id, 257 text: scraperTweet.text, 258 full_text: scraperTweet.text, 259 // Construct minimal entities from parsed data 260 entities: { 261 urls: scraperTweet.urls.map((url: string) => ({ url, expanded_url: url })), ··· 277 text: raw.full_text, 278 full_text: raw.full_text, 279 created_at: raw.created_at, 280 // biome-ignore lint/suspicious/noExplicitAny: raw types match compatible structure 281 entities: raw.entities as any, 282 // biome-ignore lint/suspicious/noExplicitAny: raw types match compatible structure ··· 817 818 if (processedTweets[tweetId]) continue; 819 820 - if (tweet.retweeted_status_id_str) { 821 console.log(`[${twitterUsername}] ⏩ Skipping retweet ${tweetId}.`); 822 continue; 823 } 824
··· 99 in_reply_to_status_id?: string; 100 in_reply_to_user_id_str?: string; 101 in_reply_to_user_id?: string; 102 + isRetweet?: boolean; 103 user?: { 104 screen_name?: string; 105 id_str?: string; ··· 257 id_str: scraperTweet.id, 258 text: scraperTweet.text, 259 full_text: scraperTweet.text, 260 + isRetweet: scraperTweet.isRetweet, 261 // Construct minimal entities from parsed data 262 entities: { 263 urls: scraperTweet.urls.map((url: string) => ({ url, expanded_url: url })), ··· 279 text: raw.full_text, 280 full_text: raw.full_text, 281 created_at: raw.created_at, 282 + isRetweet: scraperTweet.isRetweet, 283 // biome-ignore lint/suspicious/noExplicitAny: raw types match compatible structure 284 entities: raw.entities as any, 285 // biome-ignore lint/suspicious/noExplicitAny: raw types match compatible structure ··· 820 821 if (processedTweets[tweetId]) continue; 822 823 + const isRetweet = tweet.isRetweet || tweet.retweeted_status_id_str || tweet.text?.startsWith('RT @'); 824 + 825 + if (isRetweet) { 826 console.log(`[${twitterUsername}] ⏩ Skipping retweet ${tweetId}.`); 827 + if (!dryRun) { 828 + // Save as skipped so we don't check it again 829 + saveProcessedTweet(twitterUsername, bskyIdentifier, tweetId, { skipped: true, text: tweet.text }); 830 + } 831 continue; 832 } 833