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: threading logic, video limits (90mb/3min)

jack d292138b 677ab6a8

+12 -2
+12 -2
src/index.ts
··· 62 62 63 63 interface VideoInfo { 64 64 variants?: VideoVariant[]; 65 + duration_millis?: number; 65 66 } 66 67 67 68 interface MediaEntity { ··· 705 706 let replyParentInfo: ProcessedTweetEntry | null = null; 706 707 707 708 if (isReply) { 708 - if (replyStatusId && processedTweets[replyStatusId] && !processedTweets[replyStatusId]?.migrated) { 709 + if (replyStatusId && processedTweets[replyStatusId]) { 709 710 console.log(`[${twitterUsername}] 🧵 Threading reply to post in ${bskyIdentifier}: ${replyStatusId}`); 710 711 replyParentInfo = processedTweets[replyStatusId] ?? null; 711 712 } else { ··· 795 796 } 796 797 } else if (media.type === 'video' || media.type === 'animated_gif') { 797 798 const variants = media.video_info?.variants || []; 799 + const duration = media.video_info?.duration_millis || 0; 800 + 801 + if (duration > 180000) { // 3 minutes 802 + console.warn(`[${twitterUsername}] ⚠️ Video too long (${(duration / 1000).toFixed(1)}s). Fallback to link.`); 803 + const tweetUrl = `https://twitter.com/${twitterUsername}/status/${tweetId}`; 804 + if (!text.includes(tweetUrl)) text += `\n\nVideo: ${tweetUrl}`; 805 + continue; 806 + } 807 + 798 808 const mp4s = variants 799 809 .filter((v) => v.content_type === 'video/mp4') 800 810 .sort((a, b) => (b.bitrate || 0) - (a.bitrate || 0)); ··· 808 818 updateAppStatus({ message: `Downloading video: ${path.basename(videoUrl)}` }); 809 819 const { buffer, mimeType } = await downloadMedia(videoUrl); 810 820 811 - if (buffer.length <= 100 * 1024 * 1024) { 821 + if (buffer.length <= 90 * 1024 * 1024) { 812 822 const filename = videoUrl.split('/').pop() || 'video.mp4'; 813 823 updateAppStatus({ message: `Uploading video to Bluesky...` }); 814 824 videoBlob = await uploadVideoToBluesky(agent, buffer, filename);