(Arguably this is against Cohost's design intentions, but I thought making it available probably wouldn't hurt)

cringe (trans) software developer
(Arguably this is against Cohost's design intentions, but I thought making it available probably wouldn't hurt)
// ==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);
})();
you might want to prepend onto the first line // ==UserScript== without which it will complain it isn't a valid userscript :)
Fixed, I had it on the same line as the backticks so it was disappearing