Import Instagram archive to a Bluesky account

Upodate atproto lib #1

merged opened by marcomaroni.it targeting main from added_custom_psd_support
Labels

None yet.

assignee

None yet.

Participants 1
AT URI
at://did:plc:iny5qr4bzmkcex5vxrxz6sks/sh.tangled.repo.pull/3mf7bj57prz22
+62 -68
Diff #0
+2 -1
.env.dist
··· 12 12 TEST_IMAGES_MODE=0 # 5 images in a post (only 4 should upload) 13 13 TEST_MIXED_MEDIA_MODE=0 # 5 images in a post (uploads two posts, one with 4 and a second with 1) 14 14 # Logging level 15 - LOG_LEVEL=info 15 + LOG_LEVEL=info 16 + ATPROTO_PDS=https://bsky.social
+1
README.md
··· 63 63 MIN_DATE=2020-01-01 # Only import posts after this date 64 64 MAX_DATE=2025-01-01 # Only import posts before this date 65 65 LOG_LEVEL=debug # Set logging verbosity (debug, info, warn, error) 66 + ATPROTO_PDS=https://mypds.net #Set a custom PDS for authentication, the default is https://bsky.social 66 67 ``` 67 68 68 69 ## Running the Import
+28 -28
package-lock.json
··· 1 1 { 2 2 "name": "instagramtobluesky", 3 - "version": "0.7.4", 3 + "version": "0.7.5", 4 4 "lockfileVersion": 3, 5 5 "requires": true, 6 6 "packages": { 7 7 "": { 8 8 "name": "instagramtobluesky", 9 - "version": "0.7.4", 9 + "version": "0.7.5", 10 10 "dependencies": { 11 - "@atproto/api": "^0.13.31", 11 + "@atproto/api": "^0.16.1", 12 12 "@ffprobe-installer/ffprobe": "^2.1.2", 13 13 "byte-size": "^9.0.1", 14 14 "dotenv": "^16.4.7", ··· 57 57 } 58 58 }, 59 59 "node_modules/@atproto/api": { 60 - "version": "0.13.31", 61 - "resolved": "https://registry.npmjs.org/@atproto/api/-/api-0.13.31.tgz", 62 - "integrity": "sha512-i2cUQuwe+3j8rgPJj4YWRjSQeJunGqJ3IzesnvbODjjZh3IS9jB80BZ/pTe/AvNg6JCBbqeWJjWDVKeFHaiZAw==", 60 + "version": "0.16.9", 61 + "resolved": "https://registry.npmjs.org/@atproto/api/-/api-0.16.9.tgz", 62 + "integrity": "sha512-hXbnBIDEIwXxxyduxxZsf0aP8Z+JKyfG7L47FZqAYOI6uNm8oBTLLrHQ2RmJZZeyMIMM17gvxNtPDoULKQfupw==", 63 63 "license": "MIT", 64 64 "dependencies": { 65 - "@atproto/common-web": "^0.3.2", 66 - "@atproto/lexicon": "^0.4.5", 67 - "@atproto/syntax": "^0.3.1", 68 - "@atproto/xrpc": "^0.6.6", 65 + "@atproto/common-web": "^0.4.3", 66 + "@atproto/lexicon": "^0.5.1", 67 + "@atproto/syntax": "^0.4.1", 68 + "@atproto/xrpc": "^0.7.5", 69 69 "await-lock": "^2.2.2", 70 70 "multiformats": "^9.9.0", 71 71 "tlds": "^1.234.0", ··· 79 79 "license": "(Apache-2.0 AND MIT)" 80 80 }, 81 81 "node_modules/@atproto/common-web": { 82 - "version": "0.3.2", 83 - "resolved": "https://registry.npmjs.org/@atproto/common-web/-/common-web-0.3.2.tgz", 84 - "integrity": "sha512-Vx0JtL1/CssJbFAb0UOdvTrkbUautsDfHNOXNTcX2vyPIxH9xOameSqLLunM1hZnOQbJwyjmQCt6TV+bhnanDg==", 82 + "version": "0.4.3", 83 + "resolved": "https://registry.npmjs.org/@atproto/common-web/-/common-web-0.4.3.tgz", 84 + "integrity": "sha512-nRDINmSe4VycJzPo6fP/hEltBcULFxt9Kw7fQk6405FyAWZiTluYHlXOnU7GkQfeUK44OENG1qFTBcmCJ7e8pg==", 85 85 "license": "MIT", 86 86 "dependencies": { 87 87 "graphemer": "^1.4.0", ··· 97 97 "license": "(Apache-2.0 AND MIT)" 98 98 }, 99 99 "node_modules/@atproto/lexicon": { 100 - "version": "0.4.5", 101 - "resolved": "https://registry.npmjs.org/@atproto/lexicon/-/lexicon-0.4.5.tgz", 102 - "integrity": "sha512-fljWqMGKn+XWtTprBcS3F1hGBREnQYh6qYHv2sjENucc7REms1gtmZXSerB9N6pVeHVNOnXiILdukeAcic5OEw==", 100 + "version": "0.5.1", 101 + "resolved": "https://registry.npmjs.org/@atproto/lexicon/-/lexicon-0.5.1.tgz", 102 + "integrity": "sha512-y8AEtYmfgVl4fqFxqXAeGvhesiGkxiy3CWoJIfsFDDdTlZUC8DFnZrYhcqkIop3OlCkkljvpSJi1hbeC1tbi8A==", 103 103 "license": "MIT", 104 104 "dependencies": { 105 - "@atproto/common-web": "^0.3.2", 106 - "@atproto/syntax": "^0.3.1", 105 + "@atproto/common-web": "^0.4.3", 106 + "@atproto/syntax": "^0.4.1", 107 107 "iso-datestring-validator": "^2.2.2", 108 108 "multiformats": "^9.9.0", 109 109 "zod": "^3.23.8" ··· 116 116 "license": "(Apache-2.0 AND MIT)" 117 117 }, 118 118 "node_modules/@atproto/syntax": { 119 - "version": "0.3.1", 120 - "resolved": "https://registry.npmjs.org/@atproto/syntax/-/syntax-0.3.1.tgz", 121 - "integrity": "sha512-fzW0Mg1QUOVCWUD3RgEsDt6d1OZ6DdFmbKcDdbzUfh0t4rhtRAC05KbZYmxuMPWDAiJ4BbbQ5dkAc/mNypMXkw==", 119 + "version": "0.4.1", 120 + "resolved": "https://registry.npmjs.org/@atproto/syntax/-/syntax-0.4.1.tgz", 121 + "integrity": "sha512-CJdImtLAiFO+0z3BWTtxwk6aY5w4t8orHTMVJgkf++QRJWTxPbIFko/0hrkADB7n2EruDxDSeAgfUGehpH6ngw==", 122 122 "license": "MIT" 123 123 }, 124 124 "node_modules/@atproto/xrpc": { 125 - "version": "0.6.6", 126 - "resolved": "https://registry.npmjs.org/@atproto/xrpc/-/xrpc-0.6.6.tgz", 127 - "integrity": "sha512-umXEYVMo9/pyIBoKmIAIi64RXDW9tSXY+wqztlQ6I2GZtjLfNZqmAWU+wADk3SxUe54mvjxxGyA4TtyGtDMfhA==", 125 + "version": "0.7.5", 126 + "resolved": "https://registry.npmjs.org/@atproto/xrpc/-/xrpc-0.7.5.tgz", 127 + "integrity": "sha512-MUYNn5d2hv8yVegRL0ccHvTHAVj5JSnW07bkbiaz96UH45lvYNRVwt44z+yYVnb0/mvBzyD3/ZQ55TRGt7fHkA==", 128 128 "license": "MIT", 129 129 "dependencies": { 130 - "@atproto/lexicon": "^0.4.5", 130 + "@atproto/lexicon": "^0.5.1", 131 131 "zod": "^3.23.8" 132 132 } 133 133 }, ··· 8141 8141 } 8142 8142 }, 8143 8143 "node_modules/zod": { 8144 - "version": "3.24.1", 8145 - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", 8146 - "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", 8144 + "version": "3.25.76", 8145 + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", 8146 + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", 8147 8147 "license": "MIT", 8148 8148 "funding": { 8149 8149 "url": "https://github.com/sponsors/colinhacks"
+1 -1
package.json
··· 20 20 "lint:fix": "eslint . --ext .ts --fix" 21 21 }, 22 22 "dependencies": { 23 - "@atproto/api": "^0.13.31", 23 + "@atproto/api": "^0.16.1", 24 24 "@ffprobe-installer/ffprobe": "^2.1.2", 25 25 "byte-size": "^9.0.1", 26 26 "dotenv": "^16.4.7",
+6 -14
src/bluesky/bluesky.ts
··· 1 - import { 2 - AtpAgent, 3 - RichText, 4 - BlobRef 5 - } from "@atproto/api"; 6 - 7 - import { 8 - EmbeddedMedia, 9 - PostRecordImpl 10 - } from "./types"; 11 - import { logger } from "../logger/logger"; 1 + import { AtpAgent, BlobRef, RichText } from '@atproto/api'; 12 2 13 - 3 + import { logger } from '../logger/logger'; 4 + // eslint-disable-next-line import/order 5 + import { EmbeddedMedia, PostRecordImpl } from './types'; 14 6 15 7 export class BlueskyClient { 16 8 private readonly agent: AtpAgent; 17 9 private readonly username: string; 18 10 private readonly password: string; 19 11 20 - constructor(username: string, password: string) { 21 - this.agent = new AtpAgent({ service: "https://bsky.social" }); 12 + constructor(username: string, password: string, atProtoPDS: string) { 13 + this.agent = new AtpAgent({ service: atProtoPDS }); 22 14 this.username = username; 23 15 this.password = password; 24 16 }
+12 -3
src/config.ts
··· 1 - import path from 'path'; 2 - 1 + // eslint-disable-next-line import/order 3 2 import * as dotenv from 'dotenv'; 3 + // eslint-disable-next-line import/order 4 + import path from 'path'; 4 5 5 6 dotenv.config(); 6 7 ··· 19 20 private readonly blueskyUsername: string; 20 21 private readonly blueskyPassword: string; 21 22 private readonly archiveFolder: string; 23 + private readonly atProtoPDS: string 22 24 23 25 constructor(config: { 24 26 testVideoMode: boolean; ··· 31 33 blueskyUsername: string; 32 34 blueskyPassword: string; 33 35 archiveFolder: string; 36 + atProtoPDS: string 34 37 }) { 35 38 this.testVideoMode = config.testVideoMode; 36 39 this.testImageMode = config.testImageMode; ··· 42 45 this.blueskyUsername = config.blueskyUsername; 43 46 this.blueskyPassword = config.blueskyPassword; 44 47 this.archiveFolder = config.archiveFolder; 48 + this.atProtoPDS = config.atProtoPDS 45 49 } 46 50 47 51 /** ··· 58 62 maxDate: process.env.MAX_DATE ? new Date(process.env.MAX_DATE) : undefined, 59 63 blueskyUsername: process.env.BLUESKY_USERNAME ?? '', 60 64 blueskyPassword: process.env.BLUESKY_PASSWORD ?? '', 61 - archiveFolder: process.env.ARCHIVE_FOLDER ?? '' 65 + archiveFolder: process.env.ARCHIVE_FOLDER ?? '', 66 + atProtoPDS: process.env.ATPROTO_PDS ?? 'https://bsky.social' 62 67 }); 63 68 } 64 69 ··· 102 107 */ 103 108 getBlueskyPassword(): string { 104 109 return this.blueskyPassword; 110 + } 111 + 112 + getAtProtoPDS(): string { 113 + return this.atProtoPDS 105 114 } 106 115 107 116 /**
+12 -21
src/instagram-to-bluesky.ts
··· 1 - import path from "path"; 1 + import path from 'path'; 2 2 3 - import { BlobRef } from "@atproto/api"; 3 + import { BlobRef } from '@atproto/api'; 4 4 5 - import { BlueskyClient } from "./bluesky/bluesky"; 5 + import { BlueskyClient } from './bluesky/bluesky'; 6 6 import { 7 - EmbeddedMedia, 8 - ImageEmbed, 9 - ImageEmbedImpl, 10 - ImagesEmbedImpl, 11 - VideoEmbedImpl, 12 - } from "./bluesky/index"; 13 - import { AppConfig } from "./config"; 14 - import { logger } from "./logger/logger"; 7 + EmbeddedMedia, ImageEmbed, ImageEmbedImpl, ImagesEmbedImpl, VideoEmbedImpl 8 + } from './bluesky/index'; 9 + import { AppConfig } from './config'; 10 + import { logger } from './logger/logger'; 15 11 import { 16 - ImageMediaProcessResultImpl, 17 - MediaProcessResult, 18 - VideoMediaProcessResultImpl, 19 - decodeUTF8, 20 - InstagramMediaProcessor, 21 - InstagramExportedPost, 22 - readJsonFile, 23 - sortPostsByCreationTime, 24 - } from "./media"; 12 + decodeUTF8, ImageMediaProcessResultImpl, InstagramExportedPost, InstagramMediaProcessor, 13 + MediaProcessResult, readJsonFile, sortPostsByCreationTime, VideoMediaProcessResultImpl 14 + } from './media'; 25 15 26 16 const API_RATE_LIMIT_DELAY = 3000; // https://docs.bsky.app/docs/advanced-guides/rate-limits 27 17 ··· 145 135 logger.info("--- SIMULATE mode is disabled, posts will be imported ---"); 146 136 bluesky = new BlueskyClient( 147 137 config.getBlueskyUsername(), 148 - config.getBlueskyPassword() 138 + config.getBlueskyPassword(), 139 + config.getAtProtoPDS() 149 140 ); 150 141 await bluesky.login(); 151 142 } else {

History

1 round 0 comments
sign up or login to add to the discussion
marcomaroni.it submitted #0
2 commits
expand
Upodate atproto lib
Added custom PDS support
expand 0 comments
pull request successfully merged