feat(route/4chan): add filters for sticky threads and reply count (#21964)

* feat(route/4chan): add filters for sticky threads and reply count

* Revert formatting

* Applied suggestion
This commit is contained in:
Shoggomo 2026-05-11 18:25:01 +02:00 committed by GitHub
parent 898b320644
commit 5cf0d2b133
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 30 additions and 5 deletions

View File

@ -41,12 +41,15 @@ export const route: Route = {
target: '/:board/catalog',
},
],
description: `Specify options (in the format of query string) in parameter \`routeParams\` to control some extra features for Tweets
description: `Specify options (in the format of query string) in parameter \`routeParams\` to control extra features for threads
| Key | Description | Accepts | Defaults to |
| ----------------- | ------------------------------------------------ | ---------------------- | ----------- |
| \`showReplyCount\` | Show number of replies of each thread in catalog | \`0\`/\`1\`/\`true\`/\`false\` | \`false\` |
| \`showLastReplies\` | Show last 5 replies of each thread | \`0\`/\`1\`/\`true\`/\`false\` | \`false\` |
| \`revealSpoilers\` | Don't wrap images tagged as spoilers | \`0\`/\`1\`/\`true\`/\`false\` | \`false\` |`,
| \`revealSpoilers\` | Don't wrap images tagged as spoilers | \`0\`/\`1\`/\`true\`/\`false\` | \`false\` |
| \`excludeSticky\` | Filter out sticky threads | \`0\`/\`1\`/\`true\`/\`false\` | \`false\` |
| \`minReplies\` | Minimum replies per thread | Integer | None |
| \`maxReplies\` | Maximum replies per thread | Integer | None |`,
handler,
};

View File

@ -5,11 +5,18 @@ import sanitizeHtml from 'sanitize-html';
import { parseDate } from '@/utils/parse-date';
import { queryToBoolean } from '@/utils/readable-social';
const parseParams = (routeParams: string) => {
const parsed = new URLSearchParams(routeParams);
const parseParams = (routeParams?: string) => {
const parsed = new URLSearchParams(routeParams ?? '');
const minRepliesRaw = parsed.get('minReplies');
const maxRepliesRaw = parsed.get('maxReplies');
const minReplies = minRepliesRaw === null ? undefined : Number(minRepliesRaw);
const maxReplies = maxRepliesRaw === null ? undefined : Number(maxRepliesRaw);
const viewOptions = {
excludeSticky: !!queryToBoolean(parsed.get('excludeSticky')),
includeLastReplies: !!queryToBoolean(parsed.get('showLastReplies')),
includeReplyCount: !!queryToBoolean(parsed.get('showReplyCount')),
maxReplies: Number.isFinite(maxReplies) ? maxReplies : undefined,
minReplies: Number.isFinite(minReplies) ? minReplies : undefined,
revealSpoilers: !!queryToBoolean(parsed.get('revealSpoilers')),
};
return viewOptions;
@ -17,7 +24,22 @@ const parseParams = (routeParams: string) => {
const processCatalog = ({ data, board, viewOptions }: { data: CatalogApiReturn; board: string; viewOptions: ViewOptions }) => {
const transformedData = data.flatMap((page) => page.threads);
return transformedData.map((thread) => ({
return transformedData.filter((thread) => {
if (viewOptions.excludeSticky && thread.sticky) {
return false;
}
const replies = thread.replies ?? 0;
if (viewOptions.minReplies !== undefined && replies < viewOptions.minReplies) {
return false;
}
if (viewOptions.maxReplies !== undefined && replies > viewOptions.maxReplies) {
return false;
}
return true;
}).map((thread) => ({
author: `${thread.name} ${thread.trip ?? thread.no}`,
description: renderToString(renderPost({ post: thread, board, viewOptions })),
link: `https://boards.4chan.org/${board}/thread/${thread.no}`,