import fs from 'node:fs'; import { Resvg } from '@resvg/resvg-js'; import moment from 'moment-timezone'; import * as tests from './speedtests.js'; import htm from 'htm'; import satori from 'satori'; const html = htm.bind((type, props, ...children) => ({type, props: {...props, children: children.flat()}})); const hasValues = (test) => Boolean(test?.download.avg && test?.upload.avg && test?.ping.avg); const readStatistics = async () => { const formatDate = (d) => d.toISOString().split('T')[0]; const yesterday = new Date(); yesterday.setDate(yesterday.getDate() - 1); const stats = await tests.listStatistics(formatDate(yesterday), formatDate(new Date())); if (hasValues(stats)) return stats; const latest = await tests.getLatest(); if (!latest || latest.error || latest.ping === -1) return null; return {ping: {avg: latest.ping}, download: {avg: latest.download}, upload: {avg: latest.upload}}; }; const readAsset = async (req, path) => { const local = [`build${path}`, `client/public${path}`].find(candidate => fs.existsSync(candidate)); if (local) return fs.promises.readFile(local); const url = `${req.protocol}://${req.headers.host || req.hostname}${path}`; return Buffer.from(await fetch(url).then(res => res.arrayBuffer())); }; async function generateOpenGraphImage(req) { const test = await readStatistics(); if (!hasValues(test)) return null; const font = await readAsset(req, "/assets/fonts/inter-v12-latin-regular.ttf"); const logo = await readAsset(req, "/assets/img/logo192.png"); const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone; const date = moment().tz(timeZone).format("MM/DD/YYYY"); const time = moment().tz(timeZone).format("h:mm A z"); const markup = html`

Pixies

${date}

${time}

DOWNLOAD

Mbps

${String(test.download.avg)}

UPLOAD

Mbps

${String(test.upload.avg)}

Ping

ms

${String(test.ping.avg)}

`; const image = await satori(markup, { width: 1200, height: 600, fonts: [ { name: "Inter", data: font, weight: 400, style: "normal", }, ], }); const svg = new Resvg(image); return svg.render().asPng(); } export default generateOpenGraphImage;