Skip to content

Instantly share code, notes, and snippets.

@PSingletary
Last active March 12, 2024 10:21
Show Gist options
  • Save PSingletary/bb457eb876f21129819765610cb3c432 to your computer and use it in GitHub Desktop.
Save PSingletary/bb457eb876f21129819765610cb3c432 to your computer and use it in GitHub Desktop.
BlueSky list copy
// ORIGINAL https://gist.githubusercontent.com/Bossett/c012ed574d96114569af7ba3b25693f1/raw/copyList.js
// COPIES ALL MEMBERS OF A LIST TO ANOTHER LIST
// --------------------------------------------
// 1. Navigate from https://bsky.app/ to the list you want to copy TO and copy its url
// (e.g. https://bsky.app/profile/bossett.social/lists/3k22v6pbfk32t)
// 2. Change the value of DESTINATION_LIST to your value from 1.
// 3. Navigate from https://bsky.app/ to the list you want to copy FROM
// 4. Open the developer tools, and copy/paste this into the console tab & ENTER
// It may take a little while to run - the page will reload when finished
(async () => {
const DESTINATION_LIST = "https://bsky.app/profile/bossett.social/lists/3k22v6pbfk32t";
const [unused_1, src_handle, src_rkey] = window.location.href.match(/https:\/\/bsky.app\/profile\/(.*?)\/lists\/(.*?)(?:\/|$)/) || [];
if (!src_handle || !src_rkey) return console.error("The source URL doesn't match the expected format.");
const [unused_2, dst_handle, dst_rkey] = DESTINATION_LIST.match(/https:\/\/bsky.app\/profile\/(.*?)\/lists\/(.*?)(?:\/|$)/) || [];
if (!dst_handle || !dst_rkey) return console.error("The destination URL doesn't match the expected format.");
const { session } = JSON.parse(localStorage.BSKY_STORAGE);
const { accessJwt, did: repo } = session.accounts.find((a) => a.did === session.currentAccount.did) || {};
const src_did = !src_handle.startsWith("did:") ? (await (await fetch(`https://bsky.social/xrpc/com.atproto.identity.resolveHandle?handle=${src_handle}`)).json()).did : src_handle;
let totalRetrieved = 0, currentCursor = "", members = [];
do {
const list = await (await fetch(`https://bsky.social/xrpc/app.bsky.graph.getList?list=at://${src_did}/app.bsky.graph.list/${src_rkey}&limit=100&cursor=${currentCursor}`, {
headers: { "Content-Type": "application/json", Authorization: `Bearer ${accessJwt}` }
})).json();
currentCursor = list.cursor;
totalRetrieved = list.items.length;
members = [...members, ...list.items];
} while (currentCursor !== undefined && currentCursor !== '');
for (let i = 0; i < members.length; i += 3) {
await Promise.all(members.slice(i, i + 3).map((member) => fetch("https://bsky.social/xrpc/com.atproto.repo.createRecord", {
method: "POST",
headers: { "Content-Type": "application/json", Authorization: `Bearer ${accessJwt}` },
body: JSON.stringify({ collection: "app.bsky.graph.listitem", repo, record: { subject: member.subject.did, list: `at://${repo}/app.bsky.graph.list/${dst_rkey}` ,createdAt: new Date().toISOString() } })
})));
}
location.reload();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment