Files
express-twtkpr/src/middlewares/queryHandler/twtHandler.ts
2026-03-17 22:49:38 -04:00

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);
}