Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157#!/usr/bin/env node// sync-mongodb-from-atproto.mjs// Sync MongoDB moods with existing ATProto records by reading ATProto and updating MongoDB with rkeys
import { ObjectId } from "mongodb";import { AtpAgent } from "@atproto/api";import { connect } from "../../system/backend/database.mjs";import { userIDFromHandle } from "./authorization.mjs";
const PDS_URL = process.env.PDS_URL || "https://at.aesthetic.computer";
// Parse command line argumentsconst handle = process.argv[2];
if (!handle) { console.error("Usage: node sync-mongodb-from-atproto.mjs <handle>"); console.error("Example: node sync-mongodb-from-atproto.mjs jeffrey"); process.exit(1);}
async function main() { console.log("=".repeat(80)); console.log(`๐ SYNCING MONGODB WITH ATPROTO FOR @${handle}`); console.log("=".repeat(80));
// 1. Connect to MongoDB console.log("\n๐ Step 1: Connecting to MongoDB..."); const database = await connect(); const users = database.db.collection("users"); const moods = database.db.collection("moods");
// 2. Look up user console.log(`\n๐ Step 2: Looking up user @${handle}...`); const sub = await userIDFromHandle(handle, database); if (!sub) { console.error(`โ User @${handle} not found`); await database.disconnect(); process.exit(1); } console.log(` User sub: ${sub}`);
// 3. Check ATProto credentials console.log("\n๐ Step 3: Getting ATProto credentials..."); const user = await users.findOne({ _id: sub }); if (!user?.atproto?.did || !user?.atproto?.password) { console.error(`โ User @${handle} has no ATProto account`); await database.disconnect(); process.exit(1); } const { did, password: appPassword } = user.atproto; console.log(` DID: ${did}`);
// 4. Login to ATProto console.log("\n๐ Step 4: Logging into ATProto PDS..."); const agent = new AtpAgent({ service: PDS_URL }); await agent.login({ identifier: did, password: appPassword, }); console.log(" โ
Logged in to PDS");
// 5. Fetch all ATProto moods console.log("\n๐ Step 5: Fetching all ATProto moods..."); const atprotoMoods = []; let cursor;
do { const response = await agent.com.atproto.repo.listRecords({ repo: did, collection: "computer.aesthetic.mood", limit: 100, cursor, });
atprotoMoods.push(...response.data.records); cursor = response.data.cursor; console.log(` Fetched ${response.data.records.length} moods (total: ${atprotoMoods.length})`); } while (cursor);
console.log(` Total ATProto moods: ${atprotoMoods.length}`);
// 6. Build ref โ rkey mapping (support both old mongoId and new ref fields) console.log("\n๐ Step 6: Building ref โ rkey mapping..."); const refToRkey = new Map();
for (const record of atprotoMoods) { const ref = record.value.ref || record.value.mongoId; // Support both old and new const rkey = record.uri.split("/").pop();
if (ref) { refToRkey.set(ref, rkey); } }
console.log(` Mapped ${refToRkey.size} moods`);
// 7. Update MongoDB with rkeys console.log("\n๐ Step 7: Updating MongoDB with rkeys..."); let updateCount = 0; let skipCount = 0; let notFoundCount = 0;
for (const [refStr, rkey] of refToRkey.entries()) { try { const ref = new ObjectId(refStr);
// Check if mood exists const mood = await moods.findOne({ _id: ref });
if (!mood) { console.log(` โ ๏ธ Mood ${refStr} not found in MongoDB`); notFoundCount++; continue; }
// Skip if already has rkey if (mood.atproto?.rkey === rkey) { skipCount++; continue; }
// Update with rkey await moods.updateOne( { _id: ref }, { $set: { atproto: { rkey } } } );
updateCount++;
if (updateCount % 50 === 0) { console.log(` Updated ${updateCount} moods...`); } } catch (error) { console.error(` โ Failed to update ${refStr}: ${error.message}`); } }
// 8. Summary console.log("\n" + "=".repeat(80)); console.log("\n๐ Summary:"); console.log(` Total ATProto moods: ${atprotoMoods.length}`); console.log(` MongoDB moods updated: ${updateCount}`); console.log(` Already synced (skipped): ${skipCount}`); if (notFoundCount > 0) { console.log(` Not found in MongoDB: ${notFoundCount}`); } console.log("=".repeat(80) + "\n");
await database.disconnect(); process.exit(0);}
main().catch((error) => { console.error("\nโ Error:", error); process.exit(1);});