import { renderTopLanguages } from "../src/cards/top-languages-card.js"; import { blacklist } from "../src/common/blacklist.js"; import { clampValue, CONSTANTS, parseArray, parseBoolean, renderError, } from "../src/common/utils.js"; import { fetchTopLanguages } from "../src/fetchers/top-languages-fetcher.js"; import { isLocaleAvailable } from "../src/translations.js"; export default async (req, res) => { const { username, hide, hide_title, hide_border, card_width, title_color, text_color, bg_color, theme, cache_seconds, layout, langs_count, exclude_repo, size_weight, count_weight, custom_title, locale, border_radius, border_color, disable_animations, hide_progress, } = req.query; res.setHeader("Content-Type", "image/svg+xml"); if (blacklist.includes(username)) { return res.send(renderError("Something went wrong")); } if (locale && !isLocaleAvailable(locale)) { return res.send(renderError("Something went wrong", "Locale not found")); } if ( layout !== undefined && (typeof layout !== "string" || !["compact", "normal", "donut", "donut-vertical", "pie"].includes(layout)) ) { return res.send( renderError("Something went wrong", "Incorrect layout input"), ); } try { const topLangs = await fetchTopLanguages( username, parseArray(exclude_repo), size_weight, count_weight, ); let cacheSeconds = clampValue( parseInt(cache_seconds || CONSTANTS.FOUR_HOURS, 10), CONSTANTS.FOUR_HOURS, CONSTANTS.ONE_DAY, ); cacheSeconds = process.env.CACHE_SECONDS ? parseInt(process.env.CACHE_SECONDS, 10) || cacheSeconds : cacheSeconds; res.setHeader( "Cache-Control", `max-age=${ cacheSeconds / 2 }, s-maxage=${cacheSeconds}, stale-while-revalidate=${CONSTANTS.ONE_DAY}`, ); return res.send( renderTopLanguages(topLangs, { custom_title, hide_title: parseBoolean(hide_title), hide_border: parseBoolean(hide_border), card_width: parseInt(card_width, 10), hide: parseArray(hide), title_color, text_color, bg_color, theme, layout, langs_count, border_radius, border_color, locale: locale ? locale.toLowerCase() : null, disable_animations: parseBoolean(disable_animations), hide_progress: parseBoolean(hide_progress), }), ); } catch (err) { res.setHeader("Cache-Control", `no-cache, no-store, must-revalidate`); // Don't cache error responses. return res.send(renderError(err.message, err.secondaryMessage)); } };