PronounsPage/server/routes/pronouns.ts
2024-06-26 13:59:53 +02:00

111 lines
3.8 KiB
TypeScript

import { Router } from 'express';
import { loadSuml, loadSumlFromBase, loadTsv } from '../loader.ts';
import { buildPronoun, parsePronouns } from '../../src/buildPronoun.ts';
import { buildList, handleErrorAsync } from '../../src/helpers.ts';
import { Example } from '../../src/classes.ts';
import { caches } from '../../src/cache.ts';
import { Translator } from '../../src/translator.ts';
import type { Pronoun } from '../../src/classes.ts';
import md5 from 'js-md5';
import assert from 'assert';
import fetch from 'node-fetch';
import type { PronounExamplesData } from '../../locale/data.ts';
const translations = loadSuml('translations');
const baseTranslations = loadSumlFromBase('locale/_base/translations');
const translator = new Translator(translations, baseTranslations, global.config);
const buildExample = (e: PronounExamplesData): Example => new Example(
Example.parse(e.singular),
Example.parse(e.plural || e.singular),
e.isHonorific,
);
const requestExamples = (r: string[] | undefined): PronounExamplesData[] => {
if (!r || !r.length) {
return loadTsv('pronouns/examples');
}
return buildList(function* () {
for (const rr of r) {
const [singular, plural, isHonorific] = rr.split('|');
yield { singular, plural, isHonorific: !!isHonorific };
}
});
};
const addExamples = (pronoun: Pronoun, examples: PronounExamplesData[]): string[] => {
return buildList(function* () {
for (const example of examples) {
yield buildExample(example).format(pronoun);
}
});
};
const modifyPronoun = (pronoun: Pronoun, examples: string[] | undefined) => {
const modifiedPronoun: any = pronoun;
modifiedPronoun.examples = addExamples(pronoun, requestExamples(examples));
modifiedPronoun.name = pronoun.name();
delete modifiedPronoun.config;
delete modifiedPronoun.hidden;
};
const router = Router();
router.get('/pronouns', handleErrorAsync(async (req, res) => {
const pronouns: Record<string, Pronoun> = {};
for (const [name, pronoun] of Object.entries(parsePronouns(global.config, loadTsv('pronouns/pronouns')))) {
if (pronoun.hidden) {
continue;
}
pronouns[name] = pronoun;
}
for (const pronoun of Object.values(pronouns)) {
modifyPronoun(pronoun, req.query.examples as string[] | undefined);
}
return res.json(pronouns);
}));
router.get('/pronouns/:pronoun*', handleErrorAsync(async (req, res) => {
const pronoun = buildPronoun(
parsePronouns(global.config, loadTsv('pronouns/pronouns')),
req.params.pronoun + req.params[0],
global.config,
translator,
);
if (pronoun) {
modifyPronoun(pronoun, req.query.examples as string[] | undefined);
}
return res.json(pronoun);
}));
router.get('/pronouns-name/:pronoun*', handleErrorAsync(async (req, res) => {
const pronoun = buildPronoun(
parsePronouns(global.config, loadTsv('pronouns/pronouns')),
(req.params.pronoun + req.params[0]).toLowerCase(),
global.config,
translator,
);
if (!pronoun) {
return res.status(404).json({ error: 'Not found' });
}
return res.json(pronoun.name());
}));
router.get('/remote-pronouns-name/:locale/:pronoun*', handleErrorAsync(async (req, res) => {
assert(req.locales.hasOwnProperty(req.params.locale));
const pronoun = req.params.pronoun + req.params[0];
const name = await caches.pronounNames(`${req.params.locale}/${md5(pronoun)}.txt`).fetch(async () => {
const res = await (await fetch(`${req.locales[req.params.locale].url}/api/pronouns-name/${pronoun.split('/').map((p) => encodeURIComponent(p))}`)).json();
if (typeof res === 'object' && res.error) {
return pronoun;
}
return res;
});
return res.json(name);
}));
export default router;