102 lines
3.0 KiB
TypeScript
102 lines
3.0 KiB
TypeScript
import type { Request, Response } from 'express';
|
|
import type { Metadata, Twt } from 'twtxt-lib';
|
|
|
|
import {
|
|
generateEtag,
|
|
getQueryParameterArray,
|
|
getValueOrFirstEntry,
|
|
} from '../../lib/utils.js';
|
|
import dayjs from 'dayjs';
|
|
import utc from 'dayjs/plugin/utc.js';
|
|
import NodeCache from '@cacheable/node-cache';
|
|
import { QueryParameters } from '../../types.js';
|
|
|
|
dayjs.extend(utc);
|
|
|
|
/**
|
|
*
|
|
* @param req
|
|
* @param res
|
|
* @param twts
|
|
* @param twtParameter
|
|
* @param twtsParameter
|
|
* @returns
|
|
*/
|
|
export default function twtHandler(
|
|
req: Request,
|
|
res: Response,
|
|
twts: Twt[] = [],
|
|
twtParameter: QueryParameters['twt'],
|
|
twtsParameter: QueryParameters['twts']
|
|
) {
|
|
const twtsToMatch = getQueryParameterArray(req.query[twtsParameter]);
|
|
const showLastTwt = getQueryParameterArray(req.query[twtParameter]);
|
|
const hashesToMatch = getQueryParameterArray(req.query.hash);
|
|
const searchTermsToMatch = [
|
|
...getQueryParameterArray(req.query.search),
|
|
...getQueryParameterArray(req.query.s),
|
|
];
|
|
|
|
const createdDatesToMatch = getQueryParameterArray(req.query.created_date);
|
|
const createdUTCStartDatesToMatch = getQueryParameterArray(
|
|
req.query.created_date_start
|
|
).map((val) => dayjs.utc(val));
|
|
const createdUTCEndDatesToMatch = getQueryParameterArray(
|
|
req.query.created_date_end
|
|
).map((val) => dayjs.utc(val));
|
|
|
|
const wantsJson =
|
|
req.is('json') ||
|
|
getValueOrFirstEntry(getQueryParameterArray(req.query.format)) === 'json';
|
|
if (wantsJson) res.set('content-type', 'application/json');
|
|
else res.set('content-type', 'text/plain');
|
|
|
|
if (showLastTwt.length === 1 && showLastTwt[0] === '') {
|
|
const lastTwt = twts.reduce((matched, curr) =>
|
|
matched?.createdUTC > curr.createdUTC ? matched : curr
|
|
);
|
|
let result = 'No results';
|
|
|
|
if (lastTwt) {
|
|
result = wantsJson
|
|
? JSON.stringify(lastTwt)
|
|
: `${lastTwt?.created || ''}\t${lastTwt?.content || ''}\n`;
|
|
}
|
|
|
|
res.set('etag', generateEtag(result)).send(result);
|
|
return;
|
|
}
|
|
|
|
const matchedTwts = twts.filter(({ content, created, createdUTC, hash }) => {
|
|
return (
|
|
(!twtsToMatch.length ||
|
|
(twtsToMatch.length === 1 && twtsToMatch[0] === '') ||
|
|
twtsToMatch.includes(created) ||
|
|
(hash &&
|
|
(twtsToMatch.includes(hash) || twtsToMatch.includes(`#${hash}`)))) &&
|
|
(!hashesToMatch.length ||
|
|
(hash &&
|
|
(hashesToMatch.includes(hash) ||
|
|
hashesToMatch.includes(`#${hash}`)))) &&
|
|
(!createdDatesToMatch.length ||
|
|
createdDatesToMatch.some((date) => created.includes(date))) &&
|
|
(!createdUTCStartDatesToMatch.length ||
|
|
createdUTCStartDatesToMatch.some(
|
|
(date) => date.diff(createdUTC) < 0
|
|
)) &&
|
|
(!createdUTCEndDatesToMatch.length ||
|
|
createdUTCEndDatesToMatch.some((date) => date.diff(createdUTC) > 0)) &&
|
|
(!searchTermsToMatch.length ||
|
|
searchTermsToMatch.some((term) => content.includes(term)))
|
|
);
|
|
});
|
|
|
|
const result = wantsJson
|
|
? JSON.stringify(matchedTwts)
|
|
: matchedTwts
|
|
.map(({ content, created }) => `${created}\t${content}`)
|
|
.join('\n');
|
|
|
|
res.set('etag', generateEtag(result)).send(result);
|
|
}
|