AGI / src /huggingface.ts
ftfty76's picture
Upload 8 files
df9b14f verified
import { delay } from '@std/async/delay';
import { shuffle } from '@std/random';
type User = {
user: string;
fullname: string;
type: string;
isFollowing?: true;
_id: string;
isPro: boolean;
avatarUrl: string;
};
export class HuggingFace {
constructor(public cookie: string) {
}
async getOrganizationFollowers(organization: string, cursor?: string) {
const url = new URL(`https://huggingface.co/api/organizations/${organization}/followers`);
cursor && url.searchParams.append('cursor', cursor);
const response = await fetch(url, {
headers: {
'Cookie': this.cookie,
},
});
if (!response.ok) throw Error(`${response.status} ${response.statusText}`);
return await response.json() as User[];
}
async getNonFollowingUsers(organization: string) {
let cursor: string | undefined = undefined;
while (true) {
const users = await this.getOrganizationFollowers(organization, cursor);
if (!users.length) throw Error('No users found');
const nonFollowing = users.filter((user) => !user.isFollowing);
if (nonFollowing.length) return nonFollowing;
cursor = users[users.length - 1]._id;
}
}
async followRandomUsers(organization: string) {
const users = await this.getNonFollowingUsers(organization);
const shuffled = shuffle(users);
for (let i = 0; i < shuffled.length; i++) {
await delay(1000);
const user = shuffled[i];
const res = await this.follow(user.user);
if (res.status === 429) {
console.error((await res.json()).error);
return i;
}
const body = await res.text();
if (body.trim().toLowerCase() === 'ok') {
console.log(`Followed ${user.user}`);
} else {
console.warn(`Failed to follow ${user.user}`);
continue;
}
}
}
async follow(user: string) {
return await fetch(`https://huggingface.co/api/users/${user}/follow`, {
method: 'post',
headers: {
'content-type': 'application/json',
'Cookie': this.cookie,
},
});
}
}