Import Instagram archive to a Bluesky account
9
fork

Configure Feed

Select the types of activity you want to include in your feed.

Complete TODO for adding debug logs for split posts.

+294 -2
+218
src/media/processors/InstagramMediaProcessor.test.ts
··· 2 2 3 3 import { InstagramMediaProcessor } from "./InstagramMediaProcessor"; 4 4 import { InstagramExportedPost, VideoMedia, ImageMedia } from "../InstagramExportedPost"; 5 + import { logger } from "../../logger/logger"; 5 6 6 7 // Mock the file system 7 8 jest.mock("fs", () => ({ ··· 554 555 // Verify post numbering 555 556 expect(result[0].postText).toContain("(Part 1/2)"); 556 557 expect(result[1].postText).toContain("(Part 2/2)"); 558 + }); 559 + 560 + test("should log debug messages when splitting media", async () => { 561 + const mockPost: InstagramExportedPost = { 562 + creation_timestamp: 1234567890, 563 + title: "Test Mixed Media Post", 564 + media: [ 565 + { 566 + uri: "photo1.jpg", 567 + title: "Image 1", 568 + creation_timestamp: 1234567890, 569 + media_metadata: {}, 570 + cross_post_source: { source_app: "Instagram" }, 571 + backup_uri: "backup1.jpg", 572 + } as ImageMedia, 573 + { 574 + uri: "video1.mp4", 575 + title: "Video 1", 576 + creation_timestamp: 1234567890, 577 + media_metadata: {}, 578 + cross_post_source: { source_app: "Instagram" }, 579 + backup_uri: "backup_video1.mp4", 580 + dubbing_info: [], 581 + media_variants: [], 582 + } as VideoMedia, 583 + ], 584 + }; 585 + 586 + const processor = new InstagramMediaProcessor([mockPost], mockArchiveFolder); 587 + await processor.process(); 588 + 589 + // Verify overall process start logging 590 + expect(logger.debug).toHaveBeenCalledWith( 591 + "Starting to process 1 Instagram posts" 592 + ); 593 + 594 + // Verify individual post processing start 595 + expect(logger.debug).toHaveBeenCalledWith( 596 + { 597 + title: "Test Mixed Media Post", 598 + timestamp: 1234567890, 599 + mediaCount: 2, 600 + firstMediaUri: "photo1.jpg" 601 + }, 602 + "Processing Instagram post" 603 + ); 604 + 605 + // Verify initial split logging 606 + expect(logger.debug).toHaveBeenCalledWith( 607 + "Starting to split 2 media items by type" 608 + ); 609 + 610 + // Verify split complete logging 611 + expect(logger.debug).toHaveBeenCalledWith( 612 + { 613 + totalMedia: 2, 614 + images: 1, 615 + videos: 1 616 + }, 617 + "Media split complete" 618 + ); 619 + 620 + // Verify post creation start logging 621 + expect(logger.debug).toHaveBeenCalledWith( 622 + { 623 + title: "Test Mixed Media Post", 624 + imageCount: 1, 625 + videoCount: 1, 626 + firstMediaUri: "photo1.jpg" 627 + }, 628 + "Starting to create posts from media" 629 + ); 630 + 631 + // Verify post distribution logging 632 + expect(logger.debug).toHaveBeenCalledWith( 633 + { 634 + title: "Test Mixed Media Post", 635 + imageChunks: 1, 636 + totalPosts: 2, 637 + firstMediaUri: "photo1.jpg" 638 + }, 639 + "Calculated post distribution" 640 + ); 641 + 642 + // Verify image post creation logging 643 + expect(logger.debug).toHaveBeenCalledWith( 644 + { 645 + title: "Test Mixed Media Post", 646 + postNumber: 1, 647 + totalPosts: 2, 648 + type: "image", 649 + imageCount: 1, 650 + postDate: expect.any(String), 651 + mediaUris: ["photo1.jpg"] 652 + }, 653 + "Created image post" 654 + ); 655 + 656 + // Verify video post creation logging 657 + expect(logger.debug).toHaveBeenCalledWith( 658 + { 659 + title: "Test Mixed Media Post", 660 + postNumber: 2, 661 + totalPosts: 2, 662 + type: "video", 663 + postDate: expect.any(String), 664 + mediaUri: "video1.mp4" 665 + }, 666 + "Created video post" 667 + ); 668 + 669 + // Verify individual post completion logging 670 + expect(logger.debug).toHaveBeenCalledWith( 671 + { 672 + title: "Test Mixed Media Post", 673 + resultingPosts: 2, 674 + imageCount: 1, 675 + videoCount: 1, 676 + firstMediaUri: "photo1.jpg" 677 + }, 678 + "Finished processing Instagram post" 679 + ); 680 + 681 + // Verify final summary logging 682 + expect(logger.debug).toHaveBeenCalledWith( 683 + { 684 + totalInputPosts: 1, 685 + totalOutputPosts: 2 686 + }, 687 + "Completed processing all Instagram posts" 688 + ); 689 + }); 690 + 691 + test("should log debug messages for single image post", async () => { 692 + const mockPost: InstagramExportedPost = { 693 + creation_timestamp: 1234567890, 694 + title: "Test Single Image Post", 695 + media: [ 696 + { 697 + uri: "photo1.jpg", 698 + title: "Image 1", 699 + creation_timestamp: 1234567890, 700 + media_metadata: {}, 701 + cross_post_source: { source_app: "Instagram" }, 702 + backup_uri: "backup1.jpg", 703 + } as ImageMedia, 704 + ], 705 + }; 706 + 707 + const processor = new InstagramMediaProcessor([mockPost], mockArchiveFolder); 708 + await processor.process(); 709 + 710 + // Verify overall process start logging 711 + expect(logger.debug).toHaveBeenCalledWith( 712 + "Starting to process 1 Instagram posts" 713 + ); 714 + 715 + // Verify individual post processing start 716 + expect(logger.debug).toHaveBeenCalledWith( 717 + { 718 + title: "Test Single Image Post", 719 + timestamp: 1234567890, 720 + mediaCount: 1, 721 + firstMediaUri: "photo1.jpg" 722 + }, 723 + "Processing Instagram post" 724 + ); 725 + 726 + // Verify initial split logging 727 + expect(logger.debug).toHaveBeenCalledWith( 728 + "Starting to split 1 media items by type" 729 + ); 730 + 731 + // Verify split complete logging 732 + expect(logger.debug).toHaveBeenCalledWith( 733 + { 734 + totalMedia: 1, 735 + images: 1, 736 + videos: 0 737 + }, 738 + "Media split complete" 739 + ); 740 + 741 + // Verify single post creation logging 742 + expect(logger.debug).toHaveBeenCalledWith( 743 + { 744 + title: "Test Single Image Post", 745 + postNumber: 1, 746 + totalPosts: 1, 747 + type: "image", 748 + imageCount: 1, 749 + postDate: expect.any(String), 750 + mediaUris: ["photo1.jpg"] 751 + }, 752 + "Created image post" 753 + ); 754 + 755 + // Verify individual post completion logging 756 + expect(logger.debug).toHaveBeenCalledWith( 757 + { 758 + title: "Test Single Image Post", 759 + resultingPosts: 1, 760 + imageCount: 1, 761 + videoCount: 0, 762 + firstMediaUri: "photo1.jpg" 763 + }, 764 + "Finished processing Instagram post" 765 + ); 766 + 767 + // Verify final summary logging 768 + expect(logger.debug).toHaveBeenCalledWith( 769 + { 770 + totalInputPosts: 1, 771 + totalOutputPosts: 1 772 + }, 773 + "Completed processing all Instagram posts" 774 + ); 557 775 }); 558 776 });
+76 -2
src/media/processors/InstagramMediaProcessor.ts
··· 13 13 const POST_TEXT_LIMIT = 300; 14 14 const POST_TEXT_TRUNCATE_SUFFIX = "..."; 15 15 16 - // TODO log split in debug. 17 16 export class InstagramMediaProcessor implements InstagramPostProcessingStrategy { 18 17 readonly mediaProcessorFactory: MediaProcessorFactory; 19 18 ··· 30 29 } 31 30 32 31 private splitMediaByType(media: Media[]): { images: ImageMedia[], videos: VideoMedia[] } { 33 - return media.reduce((acc, curr) => { 32 + logger.debug(`Starting to split ${media.length} media items by type`); 33 + 34 + const result = media.reduce((acc, curr) => { 34 35 if (this.isVideoMedia(curr)) { 35 36 acc.videos.push(curr); 36 37 } else { ··· 38 39 } 39 40 return acc; 40 41 }, { images: [] as ImageMedia[], videos: [] as VideoMedia[] }); 42 + 43 + logger.debug({ 44 + totalMedia: media.length, 45 + images: result.images.length, 46 + videos: result.videos.length 47 + }, 'Media split complete'); 48 + 49 + return result; 41 50 } 42 51 43 52 private async createPostsFromMedia( ··· 45 54 images: ImageMedia[], 46 55 videos: VideoMedia[] 47 56 ): Promise<ProcessedPost[]> { 57 + const postTitle = originalPost.title || originalPost.media[0]?.title || 'Untitled post'; 58 + logger.debug({ 59 + title: postTitle, 60 + imageCount: images.length, 61 + videoCount: videos.length, 62 + firstMediaUri: originalPost.media[0]?.uri 63 + }, 'Starting to create posts from media'); 64 + 48 65 const posts: ProcessedPost[] = []; 49 66 const timestamp = originalPost.creation_timestamp || originalPost.media[0].creation_timestamp; 50 67 const basePostDate = new Date(timestamp * 1000); ··· 57 74 58 75 // Calculate total number of posts 59 76 const totalPosts = imageChunks.length + videos.length; 77 + logger.debug({ 78 + title: postTitle, 79 + imageChunks: imageChunks.length, 80 + totalPosts, 81 + firstMediaUri: originalPost.media[0]?.uri 82 + }, 'Calculated post distribution'); 83 + 60 84 let currentPostNumber = 1; 61 85 62 86 // Create posts for image chunks ··· 89 113 post.embeddedMedia = await mediaProcessor.process(); 90 114 posts.push(post); 91 115 116 + logger.debug({ 117 + title: postTitle, 118 + postNumber: currentPostNumber, 119 + totalPosts, 120 + type: 'image', 121 + imageCount: imageChunk.length, 122 + postDate: postDate.toISOString(), 123 + mediaUris: imageChunk.map(img => img.uri) 124 + }, 'Created image post'); 125 + 92 126 currentPostNumber++; 93 127 } 94 128 ··· 122 156 post.embeddedMedia = await mediaProcessor.process(); 123 157 posts.push(post); 124 158 159 + logger.debug({ 160 + title: postTitle, 161 + postNumber: currentPostNumber, 162 + totalPosts, 163 + type: 'video', 164 + postDate: postDate.toISOString(), 165 + mediaUri: video.uri 166 + }, 'Created video post'); 167 + 125 168 currentPostNumber++; 126 169 } 127 170 171 + logger.debug({ 172 + title: postTitle, 173 + totalPostsCreated: posts.length, 174 + firstMediaUri: originalPost.media[0]?.uri 175 + }, 'Finished creating all posts for media'); 176 + 128 177 return posts; 129 178 } 130 179 ··· 142 191 public async process(): Promise<ProcessedPost[]> { 143 192 const allProcessedPosts: ProcessedPost[] = []; 144 193 194 + logger.debug(`Starting to process ${this.instagramPosts.length} Instagram posts`); 195 + 145 196 for (const post of this.instagramPosts) { 197 + const postTitle = post.title || post.media[0]?.title || 'Untitled post'; 198 + // Log the start of processing for this specific post 199 + logger.debug({ 200 + title: postTitle, 201 + timestamp: post.creation_timestamp, 202 + mediaCount: Array.isArray(post.media) ? post.media.length : 1, 203 + firstMediaUri: post.media[0]?.uri 204 + }, 'Processing Instagram post'); 205 + 146 206 // Ensure media is always an array 147 207 const mediaArray = Array.isArray(post.media) ? post.media : [post.media]; 148 208 ··· 152 212 // Create posts based on the split media 153 213 const posts = await this.createPostsFromMedia(post, images, videos); 154 214 allProcessedPosts.push(...posts); 215 + 216 + // Log completion of this post's processing 217 + logger.debug({ 218 + title: postTitle, 219 + resultingPosts: posts.length, 220 + imageCount: images.length, 221 + videoCount: videos.length, 222 + firstMediaUri: post.media[0]?.uri 223 + }, 'Finished processing Instagram post'); 155 224 } 225 + 226 + logger.debug({ 227 + totalInputPosts: this.instagramPosts.length, 228 + totalOutputPosts: allProcessedPosts.length 229 + }, 'Completed processing all Instagram posts'); 156 230 157 231 return allProcessedPosts; 158 232 }