import { renderStatsCard } from "../src/cards/stats-card.js"; import { blacklist } from "../src/common/blacklist.js"; import { clampValue, CONSTANTS, parseArray, parseBoolean, renderError, } from "../src/common/utils.js"; import { fetchStats } from "../src/fetchers/stats-fetcher.js"; import { validateQueryStringParams } from "../src/common/validate.js"; const QUERYSTRING_PARAMS_DATA_TYPE_MAP = new Map([ ["username", "string"], ["hide", "enum-array"], ["hide_title", "boolean"], ["hide_border", "boolean"], ["card_width", "number"], ["hide_rank", "boolean"], ["show_icons", "boolean"], ["include_all_commits", "boolean"], ["line_height", "number"], ["title_color", "string"], ["ring_color", "string"], ["icon_color", "string"], ["text_color", "string"], ["text_bold", "boolean"], ["bg_color", "string"], ["theme", "enum"], ["cache_seconds", "number"], ["exclude_repo", "array"], ["custom_title", "string"], ["locale", "enum"], ["disable_animations", "boolean"], ["border_radius", "number"], ["border_color", "string"], ["number_format", "enum"], ["rank_icon", "enum"], ["show", "enum-array"], ]); export default async (req, res) => { const { username, hide, hide_title, hide_border, card_width, hide_rank, show_icons, include_all_commits, line_height, title_color, ring_color, icon_color, text_color, text_bold, bg_color, theme, cache_seconds, exclude_repo, custom_title, locale, disable_animations, border_radius, number_format, border_color, rank_icon, show, } = req.query; res.setHeader("Content-Type", "image/svg+xml"); if (blacklist.includes(username)) { return res.send(renderError("Something went wrong")); } try { validateQueryStringParams(req.query, QUERYSTRING_PARAMS_DATA_TYPE_MAP); const showStats = parseArray(show); const stats = await fetchStats( username, parseBoolean(include_all_commits), parseArray(exclude_repo), showStats.includes("prs_merged") || showStats.includes("prs_merged_percentage"), showStats.includes("discussions_started"), showStats.includes("discussions_answered"), ); let cacheSeconds = clampValue( parseInt(cache_seconds || CONSTANTS.CARD_CACHE_SECONDS, 10), CONSTANTS.SIX_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( renderStatsCard(stats, { hide: parseArray(hide), show_icons: parseBoolean(show_icons), hide_title: parseBoolean(hide_title), hide_border: parseBoolean(hide_border), card_width: parseInt(card_width, 10), hide_rank: parseBoolean(hide_rank), include_all_commits: parseBoolean(include_all_commits), line_height, title_color, ring_color, icon_color, text_color, text_bold: parseBoolean(text_bold), bg_color, theme, custom_title, border_radius, border_color, number_format, locale: locale ? locale.toLowerCase() : null, disable_animations: parseBoolean(disable_animations), rank_icon, show: showStats, }), ); } catch (err) { res.setHeader( "Cache-Control", `max-age=${CONSTANTS.ERROR_CACHE_SECONDS / 2}, s-maxage=${ CONSTANTS.ERROR_CACHE_SECONDS }, stale-while-revalidate=${CONSTANTS.ONE_DAY}`, ); // Use lower cache period for errors. return res.send(renderError(err.message, err.secondaryMessage)); } };