2020-10-31 13:33:59 -07:00
|
|
|
import { Router } from 'express';
|
|
|
|
import SQL from 'sql-template-strings';
|
|
|
|
import {createCanvas, loadImage, registerFont} from "canvas";
|
2020-11-10 14:41:56 -08:00
|
|
|
import { loadSuml } from '../loader';
|
2020-11-04 06:41:31 -08:00
|
|
|
import avatar from '../avatar';
|
2020-11-10 15:47:44 -08:00
|
|
|
import {buildPronoun, parsePronouns} from "../../src/buildPronoun";
|
2020-10-31 13:33:59 -07:00
|
|
|
import {loadTsv} from "../../src/tsv";
|
2021-06-09 05:47:08 -07:00
|
|
|
import {handleErrorAsync} from "../../src/helpers";
|
2021-07-02 16:15:44 -07:00
|
|
|
import { CacheObject } from "../../src/cache";
|
2021-12-03 01:24:21 -08:00
|
|
|
import {registerLocaleFont} from "../localeFont";
|
2020-10-16 14:32:51 -07:00
|
|
|
|
2020-11-10 14:41:56 -08:00
|
|
|
const translations = loadSuml('translations');
|
|
|
|
|
2020-10-16 14:32:51 -07:00
|
|
|
const drawCircle = (context, image, x, y, size) => {
|
|
|
|
context.save();
|
|
|
|
context.beginPath();
|
|
|
|
context.arc(x + size / 2, y + size / 2, size / 2, 0, Math.PI * 2, true);
|
|
|
|
context.closePath();
|
|
|
|
context.clip();
|
|
|
|
|
|
|
|
context.drawImage(image, x, y, size, size)
|
|
|
|
|
|
|
|
context.beginPath();
|
|
|
|
context.arc(x, y, size / 2, 0, Math.PI * 2, true);
|
|
|
|
context.clip();
|
|
|
|
context.closePath();
|
|
|
|
context.restore();
|
|
|
|
}
|
2020-07-26 03:59:49 -07:00
|
|
|
|
2020-10-31 13:33:59 -07:00
|
|
|
const router = Router();
|
2020-07-22 13:19:23 -07:00
|
|
|
|
2021-06-09 05:47:08 -07:00
|
|
|
router.get('/banner/:pronounName*.png', handleErrorAsync(async (req, res) => {
|
2020-07-22 13:19:23 -07:00
|
|
|
const width = 1200
|
|
|
|
const height = 600
|
|
|
|
const mime = 'image/png';
|
|
|
|
const imageSize = 200;
|
2020-10-16 14:32:51 -07:00
|
|
|
let leftRatio = 4;
|
2020-07-22 13:19:23 -07:00
|
|
|
|
2021-06-17 13:54:08 -07:00
|
|
|
const pronounName = req.params.pronounName + req.params[0];
|
|
|
|
|
2021-07-02 16:15:44 -07:00
|
|
|
const result = await new CacheObject('banner', `${pronounName}.png`, 24 * 60).fetch(async () => {
|
2021-12-03 01:24:21 -08:00
|
|
|
const fontName = registerLocaleFont('fontHeadings', ['regular', 'bold']);
|
2021-06-17 13:54:08 -07:00
|
|
|
|
2021-06-17 14:20:40 -07:00
|
|
|
const canvas = createCanvas(width, height)
|
|
|
|
const context = canvas.getContext('2d')
|
2021-06-17 13:54:08 -07:00
|
|
|
|
2021-06-17 14:20:40 -07:00
|
|
|
const bg = await loadImage('static/bg.png');
|
|
|
|
context.drawImage(bg, 0, 0, width, height);
|
2020-07-22 13:19:23 -07:00
|
|
|
|
2022-01-25 13:40:43 -08:00
|
|
|
const logo = await loadImage('static/logo/logo.svg');
|
|
|
|
const logoPrimary = await loadImage('static/logo/logo-primary.svg');
|
|
|
|
|
2021-06-17 14:20:40 -07:00
|
|
|
const fallback = async _ => {
|
|
|
|
leftRatio = 5;
|
2022-01-25 13:40:43 -08:00
|
|
|
context.drawImage(logo, width / leftRatio - imageSize / 2, height / 2 - imageSize / 2, imageSize, imageSize);
|
2021-12-03 01:24:21 -08:00
|
|
|
context.font = `regular ${translations.title.length < 10 ? 120 : translations.title.length < 14 ? 80 : 72}pt '${fontName}'`;
|
2022-01-26 07:28:08 -08:00
|
|
|
context.fillText(translations.title, width / leftRatio + imageSize / 1.5, height / 2 + (translations.title.length < 10 ? 48 : translations.title.length < 14 ? 36 : 24));
|
2021-06-17 14:20:40 -07:00
|
|
|
}
|
2020-07-22 13:19:23 -07:00
|
|
|
|
2021-06-17 14:20:40 -07:00
|
|
|
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);
|
|
|
|
}
|
2020-07-22 13:19:23 -07:00
|
|
|
|
2021-06-17 14:20:40 -07:00
|
|
|
const avatarImage = await loadImage(await avatar(req.db, user));
|
2020-10-16 14:32:51 -07:00
|
|
|
|
2021-06-17 14:20:40 -07:00
|
|
|
drawCircle(context, avatarImage, width / leftRatio - imageSize / 2, height / 2 - imageSize / 2, imageSize);
|
2020-07-22 13:19:23 -07:00
|
|
|
|
2021-12-03 01:24:21 -08:00
|
|
|
context.font = `regular 48pt '${fontName}'`
|
2021-06-17 14:20:40 -07:00
|
|
|
context.fillText('@' + user.username, width / leftRatio + imageSize, height / 2)
|
2020-07-22 13:19:23 -07:00
|
|
|
|
2021-12-03 01:24:21 -08:00
|
|
|
context.font = `regular 24pt '${fontName}'`
|
2021-06-17 14:20:40 -07:00
|
|
|
context.fillStyle = '#C71585';
|
|
|
|
const logoSize = 24 * 1.25;
|
2022-01-25 13:40:43 -08:00
|
|
|
context.drawImage(logoPrimary, width / leftRatio + imageSize, height / 2 + logoSize - 8, logoSize, logoSize)
|
2021-06-17 14:20:40 -07:00
|
|
|
context.fillText(translations.title, width / leftRatio + imageSize + 36, height / 2 + 48);
|
2020-10-16 14:32:51 -07:00
|
|
|
|
2021-06-17 14:20:40 -07:00
|
|
|
return canvas.toBuffer(mime);
|
|
|
|
}
|
2020-10-16 14:32:51 -07:00
|
|
|
|
2021-06-17 14:20:40 -07:00
|
|
|
const pronoun = buildPronoun(
|
|
|
|
parsePronouns(loadTsv(__dirname + '/../../data/pronouns/pronouns.tsv')),
|
|
|
|
pronounName,
|
|
|
|
);
|
2020-10-16 14:32:51 -07:00
|
|
|
|
2022-01-25 13:40:43 -08:00
|
|
|
if (pronounName === 'zaimki' || (!pronoun && pronounName !== global.config.pronouns.any && (!global.config.pronouns || pronounName !== global.config.pronouns.mirror))) {
|
2021-06-17 14:20:40 -07:00
|
|
|
await fallback();
|
|
|
|
return canvas.toBuffer(mime);
|
|
|
|
}
|
2020-10-16 14:32:51 -07:00
|
|
|
|
2022-01-25 13:40:43 -08:00
|
|
|
context.drawImage(logo, width / leftRatio - imageSize / 2, height / 2 - imageSize / 2, imageSize, imageSize)
|
2021-12-03 01:24:21 -08:00
|
|
|
context.font = `regular 48pt '${fontName}'`;
|
2021-06-17 14:20:40 -07:00
|
|
|
context.fillText(translations.pronouns.intro + ':', width / leftRatio + imageSize / 1.5, height / 2 - 36)
|
2020-07-22 13:19:23 -07:00
|
|
|
|
2021-06-17 16:10:59 -07:00
|
|
|
const pronounNameOptions = pronounName === global.config.pronouns.any ? [global.config.pronouns.any] : pronoun.nameOptions();
|
2021-12-03 01:24:21 -08:00
|
|
|
context.font = `bold ${pronounNameOptions.length <= 2 ? '70' : '36'}pt '${fontName}'`;
|
2021-09-13 11:45:06 -07:00
|
|
|
context.fillText(
|
|
|
|
pronounNameOptions.map(o => o.replace(/ ?\[[^\]]+] ?/g, '').trim()).join('\n'),
|
|
|
|
width / leftRatio + imageSize / 1.5,
|
|
|
|
height / 2 + (pronounNameOptions.length <= 2 ? 72 : 24)
|
|
|
|
);
|
2020-10-16 14:32:51 -07:00
|
|
|
|
2021-06-17 14:20:40 -07:00
|
|
|
return canvas.toBuffer(mime);
|
|
|
|
});
|
2020-10-16 14:32:51 -07:00
|
|
|
|
2021-06-17 14:20:40 -07:00
|
|
|
return res.set('content-type', mime).send(result);
|
2021-06-09 05:47:08 -07:00
|
|
|
}));
|
2020-10-31 13:33:59 -07:00
|
|
|
|
|
|
|
export default router;
|