get-hackathons
Version:
Easy retrieval of Hackathon data from the Devpost website
76 lines (75 loc) • 2.98 kB
JavaScript
import { JSDOM } from "jsdom";
import { CONFIG } from "./config";
export async function getHackathons(username) {
let res = {
username,
total: 0,
wins: 0,
rate: "0%",
hackathons: [],
};
try {
res = await fetchHackathons(res);
res["hackathons"] = await getWins(res);
return res;
}
catch (e) {
console.error(e);
return res;
}
}
function calculateWinRate(total, wins) {
return Math.floor((wins / total) * 100);
}
function processHackathons(hackathons, res) {
hackathons.forEach((hackathon) => {
const id = hackathon.attributes.getNamedItem("data-software-id")?.textContent || "";
const title = hackathon.querySelector("h5")?.textContent?.trim() || "";
const link = hackathon.querySelector("a")?.href || "";
const tag = hackathon.querySelector("p")?.textContent?.trim() || "";
const img = hackathon.querySelector("img")?.src || "";
let winner = hackathon.contains(hackathon.querySelector('img[alt="Winner"]'));
res["wins"] += winner ? 1 : 0;
res["total"] += 1;
res["hackathons"].push({ id, link, title, tag, img, winner });
});
return res;
}
export async function fetchHackathons(res, page = 1) {
const response = await fetch(`${CONFIG.BASE_URL}/${res.username}?page=${page}`, CONFIG.HEADERS);
if (response.status != 200) {
throw new Error(`Hackathon Retrieval Error! ${response.status}`);
}
const result = await response.text();
const dom = new JSDOM(result);
let hackathons_split = dom.window.document.querySelectorAll("[data-software-id]");
res = processHackathons(hackathons_split, res);
const next_page = dom.window.document.querySelector("ul.pagination > li.next_page");
const available = dom.window.document.querySelector("ul.pagination > li.next_page:not(.unavailable)");
if (next_page && available) {
res = await fetchHackathons(res, page + 1);
}
res["rate"] = `${calculateWinRate(res["total"], res["wins"])}%`;
return res;
}
export async function getWins(res) {
return Promise.all(res["hackathons"].map(async (hackathon) => {
if (hackathon.winner) {
const software = await fetch(hackathon.link, CONFIG.HEADERS);
if (software.status != 200) {
throw new Error(`Software Retrieval Error! ${software.status}`);
}
const software_result = await software.text();
const software_dom = new JSDOM(software_result);
const wins_split = software_dom.window.document.querySelectorAll("div.software-list-content > ul > li");
let wins = [];
wins_split.forEach((e) => {
wins.push(e.textContent.split("Winner")[1].trim());
});
// TODO techstack
// TODO add project bio
hackathon.winner = wins;
}
return hackathon;
}));
}