Skip to content

Instantly share code, notes, and snippets.

@josephrocca
Last active December 10, 2024 06:16
Show Gist options
  • Save josephrocca/d67bfab87502d74a76a9e310b89223eb to your computer and use it in GitHub Desktop.
Save josephrocca/d67bfab87502d74a76a9e310b89223eb to your computer and use it in GitHub Desktop.
Mute all likers of a specific post, based on the post's URL - bookmarklet for bluesky (bsky.app) - you can use https://chriszarate.github.io/bookmarkleter/ to turn it into a bookmarklet
// You can turn this code into a bookmarklet by pasting all the code here into this bookmarklet maker: https://chriszarate.github.io/bookmarkleter/
// Then just visit the post URL that you want to use it on, and click the bookmarklet.
// Or just manually copy-paste all of the code in this file into the browser console while on the bsky.app site (use Ctrl+Shift+J to open browser console in Chrome)
// CAUTION(!!!): You should be vary wary of running random code you find on the internet within authenticated applications like Bluesky, since the code could steal your login details.
// Always ensure that either you've read and understood the code, or that someone you trust has confirmed that it's safe.
if(confirm("This will mute everyone who liked the post you're currently viewing. Make sure you've clicked into the post, so the post URL is in your browser address bar. You can check your browser console with Ctrl+Shift+J for progress/errors if needed.")) {
muteAllLikersByPostUrl(window.location.href);
}
async function muteAllLikersByPostUrl(postUrl) {
// Extract author and post id from URL:
let postAuthorIdentifier = postUrl.match(/\/profile\/(.+?)\/post\//)[1];
let postId = postUrl.match(/\/post\/([^?/]+)/)[1];
let postAuthorDid = postAuthorIdentifier.startsWith("did:") ? postAuthorIdentifier : await fetch(`https://public.api.bsky.app/xrpc/com.atproto.identity.resolveHandle?handle=${postAuthorIdentifier}`).then(r => r.json()).then(o => o.did);
// Get likers:
let likers = [];
let cursor = "";
while(1) {
let uri = `at://${postAuthorDid}/app.bsky.feed.post/${postId}`;
let response = await fetch(`https://public.api.bsky.app/xrpc/app.bsky.feed.getLikes?uri=${uri}&limit=100&cursor=${cursor}`);
if(response.status === 429) {
await new Promise(r => setTimeout(r, 5*60*1000));
continue;
}
let likesData = await response.json();
cursor = likesData.cursor;
likers.push(...likesData.likes.map(l => ({did:l.actor.did, handle:l.actor.handle})));
console.log(`Collected ${likers.length} likers so far...`);
if(!cursor) break;
}
// Mute likers:
let maxConcurrent = 5;
let activeConcurrent = 0;
for(let {did, handle} of likers) {
while(activeConcurrent >= maxConcurrent) await new Promise(r => setTimeout(r, 50));
activeConcurrent++;
(async () => {
let session = JSON.parse(localStorage.BSKY_STORAGE).session;
let response = await fetch(`${session.currentAccount.pdsUrl}xrpc/app.bsky.graph.muteActor`, {method: "POST", body: JSON.stringify({actor:did}), headers: {"Content-Type": "application/json", "Authorization":`Bearer ${session.currentAccount.accessJwt}`}});
if(response.status === 429) {
console.log("Waiting a bit due to rate limit...")
await new Promise(r => setTimeout(r, 5*60*1000));
return;
}
let result = await response.text().catch(console.error);
if(result === "") {
console.log(`Muted ${handle}`);
} else {
console.error(`Failed to mute ${handle} for some reason`);
await new Promise(r => setTimeout(r, 5000));
}
})().finally(_ => activeConcurrent--);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment