Skip to content

Instantly share code, notes, and snippets.

@mary-ext
Last active June 14, 2024 13:32
Show Gist options
  • Save mary-ext/6365ac524859522e63f9363ad7eeb583 to your computer and use it in GitHub Desktop.
Save mary-ext/6365ac524859522e63f9363ad7eeb583 to your computer and use it in GitHub Desktop.
bluesky delete orphaned follows
import { Agent } from '@externdefs/bluesky-client/agent';
import type { Records, RefOf } from '@externdefs/bluesky-client/atp-schema';
const BSKY_USERNAME = '';
const BSKY_PASSWORD = '';
const agent = new Agent({ serviceUri: 'https://bsky.social' });
await agent.login({ identifier: BSKY_USERNAME, password: BSKY_PASSWORD });
const did = agent.session!.did;
type FollowRecord = Records['app.bsky.graph.follow'];
let records: { uri: string; value: FollowRecord }[] = [];
{
let cursor: string | undefined;
do {
const response = await agent.rpc.get('com.atproto.repo.listRecords', {
params: {
repo: did,
collection: 'app.bsky.graph.follow',
limit: 100,
cursor: cursor,
},
});
const data = response.data;
records = records.concat(data.records.map((r) => ({ uri: r.uri, value: r.value as any })));
cursor = data.cursor;
} while (cursor !== undefined);
}
let profiles: RefOf<'app.bsky.actor.defs#profileView'>[] = [];
{
let cursor: string | undefined;
do {
const response = await agent.rpc.get('app.bsky.graph.getFollows', {
params: {
actor: did,
limit: 100,
cursor: cursor,
},
});
const data = response.data;
profiles = profiles.concat(data.follows);
cursor = data.cursor;
} while (cursor !== undefined);
}
const unknowns = new Map<string, string>(records.map((r) => [r.value.subject, r.uri]));
{
for (const profile of profiles) {
unknowns.delete(profile.did);
}
}
{
const chunked = <T>(arr: T[], size: number): T[][] => {
const chunks: T[][] = [];
for (let i = 0, il = arr.length; i < il; i += size) {
chunks.push(arr.slice(i, i + size));
}
return chunks;
};
const getRecordId = (uri: string) => {
const idx = uri.lastIndexOf('/');
return uri.slice(idx + 1);
};
const uris = Array.from(unknowns.values());
const promises = chunked(uris, 10).map((chunk) => {
return agent.rpc.call('com.atproto.repo.applyWrites', {
data: {
repo: did,
writes: chunk.map((uri) => {
return {
$type: 'com.atproto.repo.applyWrites#delete',
collection: 'app.bsky.graph.follow',
rkey: getRecordId(uri),
};
}),
},
});
});
await Promise.all(promises);
console.log(`deleted ${uris.length} orphans`);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment