You must log in to comment.

in reply to @amypercent's post:

// ==UserScript==
// @name         Cohost Follower Count
// @namespace    http://cohost.org/
// @version      0.1
// @description  Calculate and display total follower count on the Cohost followers page
// @author       You
// @match        https://cohost.org/rc/project/followers
// @grant        none
// ==/UserScript==

(async function() {
    'use strict';
    const LIMIT = 50;

    async function getUserNum(offset) {
        const resp = await fetch(`https://cohost.org/api/v1/projects/followers?offset=${offset}&limit=${LIMIT}`, {credentials: "include"});
        const users = await resp.json();
        return users.projects.length;
    }

    async function getUpperBound() {
        // keep doubling the offset until we get a response with 0 users
        // at this point, we know this offset is past the end of the list
        let currentOffset = 0;
        let prevOffset = 0;
        while (true) {
            const userNum = await getUserNum(currentOffset);
            if (userNum === 0) {
                return [prevOffset, currentOffset];
            }
            prevOffset = currentOffset;
            currentOffset = Math.max(currentOffset * 2, currentOffset + LIMIT);
        }
    }

    async function binarySearch(low, high) {
        while (high > low) {
            const currentOffset = Math.floor((low + high) / 2);
            const userNum = await getUserNum(currentOffset);
            if (userNum === 0) {
                // current offset is too high
                high = currentOffset;
            } else if (userNum === LIMIT) {
                // current offset is too low
                low = currentOffset;
            } else {
                return currentOffset + userNum;
            }
        }
        return high;
    }

    const customStyle = `
    .text-2xl.font-bold::after {
        content: ': calculating...';
    }
    `.replace(/\n/g, "");

    const styleSheet = document.createElement("style");
    styleSheet.type = "text/css";
    styleSheet.innerText = customStyle;
    document.head.appendChild(styleSheet);

    const [low, high] = await getUpperBound();
    const count = await binarySearch(low, high);

    styleSheet.innerText = styleSheet.innerText.replace("calculating...", count);
})();