Make pipeline take tuples with opts

This commit is contained in:
Alex Gleason 2023-03-24 19:55:58 -05:00
parent b5fe0c5e67
commit 2d7d2da964
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
4 changed files with 23 additions and 12 deletions

View File

@ -13,10 +13,10 @@ import {
const msg = await readStdin(); const msg = await readStdin();
const result = await pipeline(msg, [ const result = await pipeline(msg, [
noopPolicy, [noopPolicy],
hellthreadPolicy, [hellthreadPolicy, { limit: 100 }],
antiDuplicationPolicy, [antiDuplicationPolicy],
rateLimitPolicy, [rateLimitPolicy],
]); ]);
writeStdout(result); writeStdout(result);

View File

@ -1,9 +1,16 @@
import { InputMessage, OutputMessage, Policy } from './types.ts'; import { InputMessage, OutputMessage, Policy } from './types.ts';
type PolicyTuple<Opts = any> = [policy: Policy<Opts>, opts?: Opts];
type PolicyTuplesRest<T extends PolicyTuple[]> = {
[K in keyof T]: PolicyTuple<T[K]>
}
/** Processes messages through multiple policies, bailing early on rejection. */ /** Processes messages through multiple policies, bailing early on rejection. */
async function pipeline(msg: InputMessage, policies: Policy[]): Promise<OutputMessage> { async function pipeline<P extends any[]>(msg: InputMessage, policies: [...PolicyTuplesRest<P>]): Promise<OutputMessage> {
for (const policy of policies) { for (const tuple of policies) {
const result = await policy(msg); const [policy, opts] = tuple;
const result = await policy(msg, opts);
if (result.action !== 'accept') { if (result.action !== 'accept') {
return result; return result;
} }

View File

@ -1,17 +1,21 @@
import type { Policy } from '../types.ts'; import type { Policy } from '../types.ts';
const HELLTHREAD_LIMIT = Number(Deno.env.get('HELLTHREAD_LIMIT') || 100); interface Hellthread {
limit: number;
}
/** Reject messages that tag too many participants. */ /** Reject messages that tag too many participants. */
const hellthreadPolicy: Policy = (msg) => { const hellthreadPolicy: Policy<Hellthread> = (msg, opts) => {
const limit = opts?.limit || 100;
if (msg.event.kind === 1) { if (msg.event.kind === 1) {
const p = msg.event.tags.filter((tag) => tag[0] === 'p'); const p = msg.event.tags.filter((tag) => tag[0] === 'p');
if (p.length > HELLTHREAD_LIMIT) { if (p.length > limit) {
return { return {
id: msg.event.id, id: msg.event.id,
action: 'reject', action: 'reject',
msg: `Event rejected due to ${p.length} "p" tags (${HELLTHREAD_LIMIT} is the limit).`, msg: `Event rejected due to ${p.length} "p" tags (${limit} is the limit).`,
}; };
} }
} }

View File

@ -22,6 +22,6 @@ interface Event<K extends number = number> {
created_at: number; created_at: number;
} }
type Policy = (msg: InputMessage) => Promise<OutputMessage> | OutputMessage; type Policy<Opts = unknown> = (msg: InputMessage, opts?: Opts) => Promise<OutputMessage> | OutputMessage;
export type { Event, InputMessage, OutputMessage, Policy }; export type { Event, InputMessage, OutputMessage, Policy };