// copy records from a repo (car file) to a new DID, replacing all references to old DID with new DID // for large repos block public access to the PDS while importing and then request crawl after done or pds domain will be banned from relays for flooding firehose var olddid = "did:plc:jhecgykhbxj4nvvqrtv5rtww"; var newdid = "did:plc:64nffy6xrpgn7jypygkvni6t"; var pds = "https://47267fca.nip.io"; var identifier = "jheya.47267fca.nip.io"; var password = ""; import { iterateAtpRepo } from "@atcute/car"; import * as fs from "fs"; var repo = fs.readFileSync("repo.car"); var writes = []; for (let {collection, rkey, record} of iterateAtpRepo(repo)) { let r = JSON.stringify(record); r = r.replaceAll(olddid, newdid); r = JSON.parse(r); writes.push({ collection, rkey, value: r, action: "create", $type: "com.atproto.repo.applyWrites#create" }); } var res = await fetch(pds+"/xrpc/com.atproto.server.createSession", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ identifier, password }) }); var {accessJwt} = await res.json(); console.log(accessJwt); var batchsize = 100; for (let i = 0; i < writes.length; i += batchsize) { let subwrites = writes.slice(i, i + batchsize); try { let res = await fetch(`${pds}/xrpc/com.atproto.repo.applyWrites`,{ method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${accessJwt}` }, body: JSON.stringify({ writes: subwrites, repo: newdid }) }); console.log(res.status, await res.text()); if (!res.ok) er(subwrites); } catch (error) { console.error(error); er(subwrites); } } function er(w) { fs.appendFileSync("failed.txt", JSON.stringify(w) + ',\n'); }