List a user’s followers and follows

Why?

A user’s followers and follows are available via their profile in the Bluesky app. However, pulling them programmatically via the API allows the list to be processed, e.g. to list them in date order or to compare the two lists to identify users who are on one last but not the other.

How?

Add these functions to the Apps Script Editor. The parent function provides an example for how to output a comparison of the lists to a container Sheet.

function getFollowers(handle) {
  const API_URL = "https://public.api.bsky.app/xrpc/app.bsky.graph.getFollowers";
  let followers = [];
  let cursor = '';
  do {
    let url = encodeURI(API_URL + "?actor=" + handle + "&cursor=" + cursor);
    let urlParams = {
      "method" : "get"
    };
    let response = UrlFetchApp.fetch(url, urlParams);
    response = JSON.parse(response.getContentText());
    cursor = response.cursor;
    if (response && response.followers) {
      for (const follower of response.followers) {
        followers.push([follower.createdAt, follower.handle, follower.displayName, follower.description]);
      }
    }
  } while (cursor);
  return followers.sort((a, b) => a[0] < b[0] ? 1 : -1); // Sorted alphabetically by handle
}
function getFollows(handle) {
  const API_URL = "https://public.api.bsky.app/xrpc/app.bsky.graph.getFollows";
  let follows = [];
  let cursor = '';
  do {
    let url = encodeURI(API_URL + "?actor=" + handle + "&cursor=" + cursor);
    let urlParams = {
      "method" : "get"
    };
    let response = UrlFetchApp.fetch(url, urlParams);
    response = JSON.parse(response.getContentText());
    cursor = response.cursor;
    if (response && response.follows) {
      for (const follow of response.follows) {
        follows.push([follow.createdAt, follow.handle, follow.displayName, follow.description]);
      }
    }
  } while (cursor);
  return follows.sort((a, b) => a[0] < b[0] ? 1 : -1); // Sorted alphabetically by handle
}
function updateFollowers(handle) {

  // Clear the sheet
  const sheet = SpreadsheetApp.getActive().getSheetByName('Followers');
  sheet.getRange(2, 2, sheet.getLastRow(), 9).clearContent();

  // Query Bluesky API to get user's followers and user's follows
  let followers = getFollowers(handle);
  let follows = getFollows(handle);

  // Filter the user's followers to those the user isn't following back. Sort by handle. Hyperlink the handle to the profile. Write to the sheet.
  let notFollowedByMe = followers.filter(a => !follows.some(b => a[1] === b[1]));
  notFollowedByMe = notFollowedByMe.map(a => [a[0].substr(0, 10), `=hyperlink("https://bsky.app/profile/${a[1]}","${a[1]}")`, a[2], a[3]]);
  sheet.getRange(2, 2, notFollowedByMe.length, 4).setValues(notFollowedByMe);

  // Filter user's follows to those not following the user back. Sort by handle. Hyperlink the handle to the profile. Write to the sheet.
  let notFollowingMeBack = follows.filter(a => !followers.some(b => a[1] === b[1]));
  notFollowingMeBack = notFollowingMeBack.map(a => [a[0].substr(0, 10), `=hyperlink("https://bsky.app/profile/${a[1]}","${a[1]}")`, a[2], a[3]]);
  sheet.getRange(2, 7, notFollowingMeBack.length, 4).setValues(notFollowingMeBack);

}

Notes

The Followers sheet utilised by updateFollowers(), above, has two halves: columns B to E (“Followers I don’t follow back”) and G to J (“Follows who don’t follow me back”). For each, the four columns are the date of the follow and the user’s handle, name and bio.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x