/bots.ts Secret
Created
February 27, 2025 03:08
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import axios, { type AxiosResponse } from "axios"; | |
import fs from "node:fs/promises"; | |
import "dotenv/config"; | |
const GTIHUB_API_KEY = process.env.GTIHUB_API_KEY; | |
if (!GTIHUB_API_KEY) { | |
throw new Error("Missing 'GTIHUB_API_KEY'"); | |
} | |
async function getUserRepositories(username: string) { | |
let hasMore = true; | |
let pageIndex = 0; | |
const url = new URL(`https://api.github.com/users/${username}/repos`); | |
url.searchParams.set("per_page", "100"); | |
type Repo = { | |
name: string; | |
full_name: string; | |
owner: { login: string }; | |
fork: boolean; | |
}; | |
const repositories: Array<Repo> = []; | |
while (hasMore) { | |
pageIndex += 1; | |
url.searchParams.set("page", pageIndex.toString()); | |
const packages = await axios | |
.get(url.href, { | |
headers: { | |
Authorization: `Bearer ${GTIHUB_API_KEY}`, | |
"user-agent": "MadsHougesen +http://mhouge.dk", | |
"X-GitHub-Api-Version": "2022-11-28", | |
}, | |
}) | |
.then((res: AxiosResponse<Array<Repo>>) => res?.data ?? []); | |
if (packages?.length) { | |
repositories.push(...(packages ?? []).filter((p) => !p.fork)); | |
} else { | |
hasMore = false; | |
} | |
} | |
return repositories; | |
} | |
async function getRepositoryStargazers( | |
username: string, | |
repository: string | |
): Promise<Array<string>> { | |
let hasMore = true; | |
let pageIndex = 0; | |
const url = new URL( | |
`https://api.github.com/repos/${username}/${repository}/stargazers` | |
); | |
const usernames: Array<string> = []; | |
url.searchParams.set("per_page", "100"); | |
while (hasMore) { | |
pageIndex += 1; | |
url.searchParams.set("page", pageIndex.toString()); | |
const u = await axios | |
.get(url.href, { | |
headers: { | |
Authorization: `Bearer ${GTIHUB_API_KEY}`, | |
"user-agent": "MadsHougesen +http://mhouge.dk", | |
"X-GitHub-Api-Version": "2022-11-28", | |
}, | |
}) | |
.then((res: AxiosResponse<Array<{ login: string }>>) => res?.data ?? []); | |
if (u?.length) { | |
usernames.push(...(u ?? []).map((c) => c.login)); | |
} else { | |
hasMore = false; | |
} | |
} | |
return usernames; | |
} | |
(async () => { | |
const checkedUsers = new Set<string>(); | |
const checkedRepositories = new Set<string>(); | |
const usersToCheck = ["unfitpercen"]; | |
while (usersToCheck.length) { | |
const user = usersToCheck.pop(); | |
if (checkedUsers.has(user)) { | |
continue; | |
} | |
checkedUsers.add(user); | |
const repositories = await getUserRepositories(user); | |
for (const repository of repositories) { | |
if (checkedRepositories.has(repository.full_name)) { | |
continue; | |
} | |
checkedRepositories.add(repository.full_name); | |
const stargazers = await getRepositoryStargazers(user, repository.name); | |
usersToCheck.push(...stargazers); | |
} | |
} | |
await fs.writeFile( | |
"output.json", | |
JSON.stringify(Array.from(checkedRepositories).sort()) | |
); | |
process.exit(0); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
(This is a script from article Rogue One: A Malware Story for Deno. This script gets the repositories of all the users that starred infected repo
unfitpercen/jqfmt
)