// copy records to a new did, slow version var olddid = ""; var newdid = ""; var pds = ""; var password = ""; var delay = 2161; // milliseconds between records, 2161 minimum to stay within bsky limit of 1666 records per hour import { iterateAtpRepo } from "@atcute/car"; import * as fs from "fs"; var repo = fs.readFileSync("repo.car"); async function fetch(url, options) { do { console.log("fetch", url); var res = await global.fetch(url, options); console.log("status", res.status); if (res.ok) return res; await new Promise(r => setTimeout(r, 3000)); } while (true); } var res = await fetch(pds+"/xrpc/com.atproto.server.createSession", { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({identifier: newdid, password}) }); var session = await res.json(); console.log(session); var {accessJwt} = session; try { var resume_index = Number(fs.readFileSync("index", "utf8")); } catch (e) {} var index = -1; for (let {collection, rkey, record} of iterateAtpRepo(repo)) { ++index; if (index <= resume_index) continue; record = JSON.stringify(record); record = record.replaceAll(olddid, newdid); record = JSON.parse(record); // if (record.createdAt) record.createdAt = new Date().toISOString(); // remove "archived from" let res = await fetch(`${pds}/xrpc/com.atproto.repo.createRecord`, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${accessJwt}` }, body: JSON.stringify({ repo: newdid, collection, rkey, record }) }); console.log(await res.text()); fs.writeFileSync("index", String(index)); await new Promise(r => setTimeout(r, delay)); } console.log("end of script");