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: add database migration for bsky_identifier column

jack 04283f0f b1805e00

+51 -13
+51 -13
src/db.ts
··· 16 16 // Enable WAL mode for better concurrency 17 17 db.pragma('journal_mode = WAL'); 18 18 19 - // Initialize schema 19 + // --- Migration Support --- 20 + const tableInfo = db.prepare("PRAGMA table_info(processed_tweets)").all() as any[]; 21 + 22 + if (tableInfo.length > 0) { 23 + const hasBskyIdentifier = tableInfo.some(col => col.name === 'bsky_identifier'); 24 + 25 + if (!hasBskyIdentifier) { 26 + console.log('🔄 Upgrading database schema to support multiple accounts...'); 27 + // SQLite doesn't support easy PK changes, so we recreate the table 28 + db.transaction(() => { 29 + db.exec(` 30 + ALTER TABLE processed_tweets RENAME TO processed_tweets_old; 31 + CREATE TABLE processed_tweets ( 32 + twitter_id TEXT NOT NULL, 33 + twitter_username TEXT NOT NULL, 34 + bsky_identifier TEXT NOT NULL, 35 + bsky_uri TEXT, 36 + bsky_cid TEXT, 37 + bsky_root_uri TEXT, 38 + bsky_root_cid TEXT, 39 + status TEXT NOT NULL, 40 + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, 41 + PRIMARY KEY (twitter_id, bsky_identifier) 42 + ); 43 + -- Copy old data, assuming 'unknown' or trying to infer for bsky_identifier is handled during first run migration 44 + INSERT INTO processed_tweets (twitter_id, twitter_username, bsky_identifier, bsky_uri, bsky_cid, bsky_root_uri, bsky_root_cid, status, created_at) 45 + SELECT twitter_id, twitter_username, 'unknown', bsky_uri, bsky_cid, bsky_root_uri, bsky_root_cid, status, created_at 46 + FROM processed_tweets_old; 47 + DROP TABLE processed_tweets_old; 48 + `); 49 + })(); 50 + console.log('✅ Database upgraded successfully.'); 51 + } 52 + } else { 53 + // Initialize fresh schema 54 + db.exec(` 55 + CREATE TABLE IF NOT EXISTS processed_tweets ( 56 + twitter_id TEXT NOT NULL, 57 + twitter_username TEXT NOT NULL, 58 + bsky_identifier TEXT NOT NULL, 59 + bsky_uri TEXT, 60 + bsky_cid TEXT, 61 + bsky_root_uri TEXT, 62 + bsky_root_cid TEXT, 63 + status TEXT NOT NULL, -- 'migrated', 'skipped', 'failed' 64 + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, 65 + PRIMARY KEY (twitter_id, bsky_identifier) 66 + ); 67 + `); 68 + } 69 + 20 70 db.exec(` 21 - CREATE TABLE IF NOT EXISTS processed_tweets ( 22 - twitter_id TEXT NOT NULL, 23 - twitter_username TEXT NOT NULL, 24 - bsky_identifier TEXT NOT NULL, 25 - bsky_uri TEXT, 26 - bsky_cid TEXT, 27 - bsky_root_uri TEXT, 28 - bsky_root_cid TEXT, 29 - status TEXT NOT NULL, -- 'migrated', 'skipped', 'failed' 30 - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, 31 - PRIMARY KEY (twitter_id, bsky_identifier) 32 - ); 33 71 CREATE INDEX IF NOT EXISTS idx_twitter_username ON processed_tweets(twitter_username); 34 72 CREATE INDEX IF NOT EXISTS idx_bsky_identifier ON processed_tweets(bsky_identifier); 35 73 `);