From 2ee5d89e5f18c11db52159bbca3deb37e821351b Mon Sep 17 00:00:00 2001 From: Avris Date: Thu, 17 Jun 2021 23:20:40 +0200 Subject: [PATCH] [optim] extract cache as component --- server/routes/banner.js | 114 +++++++++++++++++++--------------------- src/cache.js | 17 ++++++ 2 files changed, 70 insertions(+), 61 deletions(-) create mode 100644 src/cache.js diff --git a/server/routes/banner.js b/server/routes/banner.js index c280c0ec..84cf767a 100644 --- a/server/routes/banner.js +++ b/server/routes/banner.js @@ -6,7 +6,8 @@ import avatar from '../avatar'; import {buildPronoun, parsePronouns} from "../../src/buildPronoun"; import {loadTsv} from "../../src/tsv"; import {handleErrorAsync} from "../../src/helpers"; -import fs from 'fs'; +import cache from "../../src/cache"; +import fs from "fs"; const translations = loadSuml('translations'); @@ -37,82 +38,73 @@ router.get('/banner/:pronounName*.png', handleErrorAsync(async (req, res) => { const pronounName = req.params.pronounName + req.params[0]; - const cacheDir = `${__dirname}/../../cache/banner`; - fs.mkdirSync(cacheDir, { recursive: true }); - const cacheFilename = `${cacheDir}/${pronounName}.png`; - if (fs.existsSync(cacheFilename) && fs.statSync(cacheFilename).mtimeMs >= (new Date() - 24*60*60*1000)) { - return res.set('content-type', mime).send(fs.readFileSync(cacheFilename)); - } + const result = await cache('banner', `${pronounName}.png`, 24 * 60, async () => { + registerFont('static/fonts/quicksand-v21-latin-ext_latin-regular.ttf', {family: 'Quicksand', weight: 'regular'}); + registerFont('static/fonts/quicksand-v21-latin-ext_latin-700.ttf', {family: 'Quicksand', weight: 'bold'}); - const saveToCacheAndReturn = (canvas) => { - const buffer = canvas.toBuffer(mime); - fs.writeFileSync(cacheFilename, buffer); - return res.set('content-type', mime).send(buffer); - } + const canvas = createCanvas(width, height) + const context = canvas.getContext('2d') - registerFont('static/fonts/quicksand-v21-latin-ext_latin-regular.ttf', { family: 'Quicksand', weight: 'regular'}); - registerFont('static/fonts/quicksand-v21-latin-ext_latin-700.ttf', { family: 'Quicksand', weight: 'bold'}); + const bg = await loadImage('static/bg.png'); + context.drawImage(bg, 0, 0, width, height); - const canvas = createCanvas(width, height) - const context = canvas.getContext('2d') - - const bg = await loadImage('static/bg.png'); - context.drawImage(bg, 0, 0, width, height); - - const fallback = async _ => { - const logo = await loadImage('node_modules/@fortawesome/fontawesome-pro/svgs/light/tags.svg'); - leftRatio = 5; - context.drawImage(logo, width / leftRatio - imageSize / 2, height / 2 - imageSize / 1.25 / 2, imageSize, imageSize / 1.25); - context.font = `regular ${translations.title.length < 10 ? 120 : translations.title.length < 14 ? 80 : 72}pt Quicksand`; - context.fillText(translations.title, width / leftRatio + imageSize / 1.5, height / 2 + (translations.title.length < 10 ? 48 : translations.title.length < 14 ? 24 : 24)); - } - - if (pronounName.startsWith('@')) { - const user = await req.db.get(SQL`SELECT id, username, email, avatarSource FROM users WHERE username=${pronounName.substring(1)}`); - if (!user) { - await fallback(); - return saveToCacheAndReturn(canvas); + const fallback = async _ => { + const logo = await loadImage('node_modules/@fortawesome/fontawesome-pro/svgs/light/tags.svg'); + leftRatio = 5; + context.drawImage(logo, width / leftRatio - imageSize / 2, height / 2 - imageSize / 1.25 / 2, imageSize, imageSize / 1.25); + context.font = `regular ${translations.title.length < 10 ? 120 : translations.title.length < 14 ? 80 : 72}pt Quicksand`; + context.fillText(translations.title, width / leftRatio + imageSize / 1.5, height / 2 + (translations.title.length < 10 ? 48 : translations.title.length < 14 ? 24 : 24)); } - const avatarImage = await loadImage(await avatar(req.db, user)); + if (pronounName.startsWith('@')) { + const user = await req.db.get(SQL`SELECT id, username, email, avatarSource FROM users WHERE username=${pronounName.substring(1)}`); + if (!user) { + await fallback(); + return canvas.toBuffer(mime); + } - drawCircle(context, avatarImage, width / leftRatio - imageSize / 2, height / 2 - imageSize / 2, imageSize); + const avatarImage = await loadImage(await avatar(req.db, user)); - context.font = `regular 48pt Quicksand` - context.fillText('@' + user.username, width / leftRatio + imageSize, height / 2) + drawCircle(context, avatarImage, width / leftRatio - imageSize / 2, height / 2 - imageSize / 2, imageSize); - const logo = await loadImage('static/favicon.svg'); + context.font = `regular 48pt Quicksand` + context.fillText('@' + user.username, width / leftRatio + imageSize, height / 2) - context.font = 'regular 24pt Quicksand' - context.fillStyle = '#C71585'; - const logoSize = 24 * 1.25; - context.drawImage(logo, width / leftRatio + imageSize, height / 2 + logoSize - 4, logoSize, logoSize / 1.25) - context.fillText(translations.title, width / leftRatio + imageSize + 36, height / 2 + 48); + const logo = await loadImage('static/favicon.svg'); - return saveToCacheAndReturn(canvas); - } + context.font = 'regular 24pt Quicksand' + context.fillStyle = '#C71585'; + const logoSize = 24 * 1.25; + context.drawImage(logo, width / leftRatio + imageSize, height / 2 + logoSize - 4, logoSize, logoSize / 1.25) + context.fillText(translations.title, width / leftRatio + imageSize + 36, height / 2 + 48); - const pronoun = buildPronoun( - parsePronouns(loadTsv(__dirname + '/../../data/pronouns/pronouns.tsv')), - pronounName, - ); + return canvas.toBuffer(mime); + } - const logo = await loadImage('node_modules/@fortawesome/fontawesome-pro/svgs/light/tags.svg'); + const pronoun = buildPronoun( + parsePronouns(loadTsv(__dirname + '/../../data/pronouns/pronouns.tsv')), + pronounName, + ); - if (!pronoun && pronounName !== req.config.pronouns.any) { - await fallback(); - return saveToCacheAndReturn(canvas); - } + const logo = await loadImage('node_modules/@fortawesome/fontawesome-pro/svgs/light/tags.svg'); - context.drawImage(logo, width / leftRatio - imageSize / 2, height / 2 - imageSize / 1.25 / 2, imageSize, imageSize / 1.25) - context.font = 'regular 48pt Quicksand' - context.fillText(translations.pronouns.intro + ':', width / leftRatio + imageSize / 1.5, height / 2 - 36) + if (!pronoun && pronounName !== req.config.pronouns.any) { + await fallback(); + return canvas.toBuffer(mime); + } - const pronounNameOptions = pronounName === req.config.pronouns.any ? [req.config.pronouns.any] : pronoun.nameOptions(); - context.font = `bold ${pronounNameOptions.length <= 2 ? '70' : '36'}pt Quicksand` - context.fillText(pronounNameOptions.join('\n'), width / leftRatio + imageSize / 1.5, height / 2 + (pronounNameOptions.length <= 2 ? 72 : 24)); + context.drawImage(logo, width / leftRatio - imageSize / 2, height / 2 - imageSize / 1.25 / 2, imageSize, imageSize / 1.25) + context.font = 'regular 48pt Quicksand' + context.fillText(translations.pronouns.intro + ':', width / leftRatio + imageSize / 1.5, height / 2 - 36) - return saveToCacheAndReturn(canvas); + const pronounNameOptions = pronounName === req.config.pronouns.any ? [req.config.pronouns.any] : pronoun.nameOptions(); + context.font = `bold ${pronounNameOptions.length <= 2 ? '70' : '36'}pt Quicksand` + context.fillText(pronounNameOptions.join('\n'), width / leftRatio + imageSize / 1.5, height / 2 + (pronounNameOptions.length <= 2 ? 72 : 24)); + + return canvas.toBuffer(mime); + }); + + return res.set('content-type', mime).send(result); })); export default router; diff --git a/src/cache.js b/src/cache.js new file mode 100644 index 00000000..64b9b0f3 --- /dev/null +++ b/src/cache.js @@ -0,0 +1,17 @@ +import fs from 'fs'; + +export default async (dir, filename, maxAgeMinutes, generator) => { + const cacheDir = `${__dirname}/../cache/${dir}` + fs.mkdirSync(cacheDir, { recursive: true }); + const cacheFilename = `${cacheDir}/${filename}`; + + if (fs.existsSync(cacheFilename) && fs.statSync(cacheFilename).mtimeMs >= (new Date() - maxAgeMinutes*60*1000)) { + return fs.readFileSync(cacheFilename); + } + + const result = await generator(); + + fs.writeFileSync(cacheFilename, result); + + return result; +}