Last active
November 25, 2024 22:19
-
-
Save alexiza/70712a8c1cf3c712e249ec2230bc520f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict' | |
import { BskyAgent } from '@atproto/api' | |
import { AtUri } from '@atproto/syntax' | |
import { config } from 'dotenv' | |
config() | |
const credentials = { | |
identifier: process.env.BSKY_IDENTIFIER, // use your Bluesky identifier | |
password: process.env.BSKY_PASSWORD, // use your Bluesky password | |
} | |
const publicAgent = new BskyAgent({ service: 'https://public.api.bsky.app' }) | |
const agent = new BskyAgent({ service: 'https://bsky.social' }) | |
await agent.login(credentials) | |
const getList = async uri => { | |
const list = [] | |
let cursor = undefined | |
do { | |
const response = await publicAgent.app.bsky.graph.getList({ list: uri, limit: 100, cursor }) | |
response.data.items | |
.map(item => ({ | |
uri: item.uri, | |
did: item.subject.did, | |
handle: item.subject.handle, | |
displayName: item.subject.displayName | |
})) | |
.forEach(user => list.push(user)) | |
cursor = response.data.cursor | |
} while(cursor) | |
return list | |
} | |
const getLists = async actor => { | |
const lists = [] | |
let cursor = undefined | |
do { | |
const response = await publicAgent.app.bsky.graph.getLists({ actor, limit: 100, cursor }) | |
response.data.lists | |
.map(list => ({ | |
uri: list.uri, | |
cid: list.cid, | |
name: list.name, | |
description: list.description, | |
})) | |
.forEach(list => lists.push(list)) | |
cursor = response.data.cursor | |
} while(cursor) | |
return lists | |
} | |
const getFollowers = async actor => { | |
const followers = [] | |
let cursor = undefined | |
do { | |
const response = await publicAgent.app.bsky.graph.getFollowers({ actor, limit: 100, cursor }) | |
response.data.followers.forEach(user => followers.push(user)) | |
cursor = response.data.cursor | |
} while(cursor) | |
return followers | |
} | |
const createList = async user => { | |
const name = `Seguidores de @${user.handle}` | |
const description = `Seguidores de ${user.displayName.length ? user.displayName : user.handle} (@${user.handle})`; | |
const result = await agent.com.atproto.repo.createRecord({ | |
repo: agent.session.did, | |
collection: 'app.bsky.graph.list', | |
record: { | |
$type: 'app.bsky.graph.list', | |
purpose: 'app.bsky.graph.defs#modlist', | |
name, | |
description, | |
createdAt: new Date().toISOString() | |
} | |
}) | |
if (!result.success) console.error(`createList failed for ${description}`) | |
} | |
const deleteMember = async atUri => { | |
const { repo, collection, rkey } = new AtUri(atUri) | |
const result = await agent.com.atproto.repo.deleteRecord({ | |
repo: agent.session.did, | |
collection, | |
rkey | |
}) | |
if (!result.success) console.error(`deleteMember failed for ${atUri}`) | |
} | |
const addMember = async (listUri, did) => { | |
const result = await agent.com.atproto.repo.createRecord({ | |
repo: agent.session.did, | |
collection: 'app.bsky.graph.listitem', | |
record: { | |
$type: 'app.bsky.graph.listitem', | |
subject: did, | |
list: listUri, | |
createdAt: new Date().toISOString() | |
} | |
}) | |
if (!result.success) console.error(`addMember failed for ${listUri}, member ${did}`) | |
} | |
const handle = `srliberal.bsky.social` | |
const { data: user } = await agent.app.bsky.actor.getProfile({ actor:handle }) | |
const lists = await getLists(credentials.identifier) | |
if (lists.filter(v => v.name === `Seguidores de @${handle}`).length === 0) { | |
await createList(user) | |
lists.length = 0 | |
const newLists = await getLists(credentials.identifier) | |
newLists.forEach(list => lists.push(list)) | |
} | |
console.log(`Updating followers list for ${user.displayName.length ? user.displayName : user.handle} (${user.handle})`) | |
const listUri = lists.filter(l => l.name === `Seguidores de @${user.handle}`)[0].uri | |
const oldMembers = new Set() | |
const atUris = {} | |
const items = await getList(listUri) | |
items.forEach(item => { | |
oldMembers.add(item.did) | |
atUris[item.did] = item.uri | |
}) | |
console.log(`The list contains ${oldMembers.size} users`) | |
const followers = (await getFollowers(user.handle)).map(follower => follower.did) | |
const newMembers = followers.filter(did => !oldMembers.has(did)) | |
followers.filter(did => oldMembers.has(did)).forEach(did => oldMembers.delete(did)) | |
console.log(`The account has ${followers.length} followers`) | |
console.log(`Adding ${newMembers.length} new users to the list`) | |
newMembers.forEach(async did => await addMember(listUri, did)) | |
console.log(`Removing ${oldMembers.size} users from the list`) | |
oldMembers.forEach(async did => await deleteMember(atUris[did])) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment