Skip to content

Instantly share code, notes, and snippets.

@alexiza
Last active November 25, 2024 22:19
Show Gist options
  • Save alexiza/70712a8c1cf3c712e249ec2230bc520f to your computer and use it in GitHub Desktop.
Save alexiza/70712a8c1cf3c712e249ec2230bc520f to your computer and use it in GitHub Desktop.
'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