Skip to content

Commit

Permalink
feat(server): search resources with fansub filter
Browse files Browse the repository at this point in the history
  • Loading branch information
yjl9903 committed Jan 16, 2024
1 parent 351a702 commit 33abca2
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 65 deletions.
4 changes: 2 additions & 2 deletions packages/animegarden/src/garden/filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ export function makeResourcesFilter(
chains.push((r) => providers.includes(r.provider));
}
if (resolved.fansubId) {
const fansubId = resolved.fansubId.map((id) => '' + id);
const fansubId = resolved.fansubId;
chains.push((r) => (r.fansub ? fansubId.includes(r.fansub.id) : false));
}
if (resolved.fansubName) {
const fansubName = resolved.fansubName;
chains.push((r) => (r.fansub ? fansubName.includes(r.fansub.name) : false));
}
if (resolved.publisherId) {
const publisherId = resolved.publisherId.map((id) => '' + id);
const publisherId = resolved.publisherId;
chains.push((r) => publisherId.includes(r.publisher.id));
}
if (resolved.type) {
Expand Down
4 changes: 2 additions & 2 deletions packages/animegarden/src/garden/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export interface ResolvedFilterOptions {
/**
* Filter by the group id of fansub
*/
fansubId?: number[];
fansubId?: string[];

/**
* Filter by the group name of fansub
Expand All @@ -80,7 +80,7 @@ export interface ResolvedFilterOptions {
/**
* Filter by the user id of publisher
*/
publisherId?: number[];
publisherId?: string[];

/**
* Filter by the resource type
Expand Down
26 changes: 13 additions & 13 deletions packages/animegarden/src/garden/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ const stringArrayLike = z.coerce
// z.array(stringArray).default([])
// ]);

const numberArray = z.union([z.array(z.coerce.number()), z.coerce.number().transform((n) => [n])]);
const numberArrayLike = z.coerce
.string()
.transform((t) => JSON.parse(t))
.catch(undefined)
.pipe(numberArray)
.optional();
// const numberArray = z.union([z.array(z.coerce.number()), z.coerce.number().transform((n) => [n])]);
// const numberArrayLike = z.coerce
// .string()
// .transform((t) => JSON.parse(t))
// .catch(undefined)
// .pipe(numberArray)
// .optional();

const providerEnum = z.array(z.enum(['dmhy', 'moe'])).default(['dmhy', 'moe']);

Expand All @@ -40,9 +40,9 @@ export const FilterSchema = z.object({
.number()
.default(100)
.refine((ps) => 1 <= ps && ps <= 1000),
fansubId: z.number().array().optional(),
fansubId: z.string().array().optional(),
fansubName: z.string().array().optional(),
publisherId: z.number().array().optional(),
publisherId: z.string().array().optional(),
type: z.string().optional(),
before: dateLike,
after: dateLike,
Expand All @@ -61,9 +61,9 @@ const parser = {
.number()
.default(100)
.transform((ps) => Math.round(Math.max(1, Math.min(1000, ps)))),
fansubId: numberArrayLike,
fansubId: stringArrayLike,
fansubName: stringArrayLike,
publisherId: numberArrayLike,
publisherId: stringArrayLike,
type: z.coerce.string().optional(),
before: dateLike,
after: dateLike,
Expand Down Expand Up @@ -131,7 +131,7 @@ export function stringifySearchURL(baseURL: string, options: FilterOptions): URL

if (options.fansubId) {
const fansubId = options.fansubId;
const parsed = numberArray.safeParse(fansubId);
const parsed = stringArray.safeParse(fansubId);
if (parsed.success) {
const data = parsed.data;
if (data.length > 0) {
Expand All @@ -148,7 +148,7 @@ export function stringifySearchURL(baseURL: string, options: FilterOptions): URL
}
if (options.publisherId) {
const publisherId = options.publisherId;
const parsed = numberArray.safeParse(publisherId);
const parsed = stringArray.safeParse(publisherId);
if (parsed.success) {
const data = parsed.data;
if (data.length > 0) {
Expand Down
7 changes: 0 additions & 7 deletions packages/animegarden/test/index.test.ts

This file was deleted.

61 changes: 25 additions & 36 deletions packages/animegarden/test/url.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ describe('parse url', () => {
"include": undefined,
"page": 1,
"pageSize": 10,
"provider": undefined,
"publisherId": undefined,
"search": undefined,
"type": undefined,
Expand All @@ -30,6 +31,7 @@ describe('parse url', () => {
"include": undefined,
"page": 2,
"pageSize": 1000,
"provider": undefined,
"publisherId": undefined,
"search": undefined,
"type": undefined,
Expand All @@ -46,6 +48,7 @@ describe('parse url', () => {
"include": undefined,
"page": 2,
"pageSize": 5,
"provider": undefined,
"publisherId": undefined,
"search": undefined,
"type": undefined,
Expand All @@ -62,6 +65,7 @@ describe('parse url', () => {
"include": undefined,
"page": 1,
"pageSize": 1000,
"provider": undefined,
"publisherId": undefined,
"search": undefined,
"type": undefined,
Expand All @@ -80,6 +84,7 @@ describe('parse url', () => {
"include": undefined,
"page": 1,
"pageSize": 100,
"provider": undefined,
"publisherId": undefined,
"search": undefined,
"type": undefined,
Expand All @@ -97,6 +102,7 @@ describe('parse url', () => {
"include": undefined,
"page": 1,
"pageSize": 100,
"provider": undefined,
"publisherId": undefined,
"search": undefined,
"type": undefined,
Expand All @@ -105,34 +111,24 @@ describe('parse url', () => {
});

it('complex include', () => {
const wrap = (o: string | (string | string[])[]) =>
new URLSearchParams('include=' + JSON.stringify(o));
const wrap = (o: string | string[]) => new URLSearchParams('include=' + JSON.stringify(o));

expect(parseSearchURL(wrap(['hello', 'world'])).include).toMatchInlineSnapshot(`
[
[
"hello",
],
[
"world",
],
"hello",
"world",
]
`);
expect(parseSearchURL(wrap(['hello', ['world1', 'world2']])).include).toMatchInlineSnapshot(`
expect(parseSearchURL(wrap(['hello', 'world1', 'world2'])).include).toMatchInlineSnapshot(`
[
[
"hello",
],
[
"world1",
"world2",
],
"hello",
"world1",
"world2",
]
`);
expect(parseSearchURL(wrap('world')).include).toMatchInlineSnapshot(`
[
[
"world",
],
"world",
]
`);
});
Expand All @@ -147,7 +143,7 @@ describe('parse url', () => {
'page=2',
'pageSize=100',
'search=' + JSON.stringify(['hello', 'world']),
'include=' + JSON.stringify(['hello', ['world1', 'world3']]),
'include=' + JSON.stringify(['hello', 'world1', 'world3']),
'exclude=' + JSON.stringify(['hi']),
'type=动画'
];
Expand All @@ -159,29 +155,22 @@ describe('parse url', () => {
"exclude": [
"hi",
],
"fansubId": [
123,
],
"fansubId": undefined,
"fansubName": [
"字幕组",
],
"include": [
[
"hello",
],
[
"world1",
"world3",
],
"hello",
"world1",
"world3",
],
"page": 2,
"pageSize": 100,
"publisherId": [
456,
],
"provider": undefined,
"publisherId": undefined,
"search": [
""hello"",
""world"",
"hello",
"world",
],
"type": "动画",
}
Expand All @@ -193,7 +182,7 @@ describe('parse url', () => {
parseSearchURL(new URLSearchParams(params.join('&')))
)
).toMatchInlineSnapshot(
'"https://garden.onekuma.cn/api/resources?page=2&pageSize=100&fansubId=123&fansubName=%5B%22%E5%AD%97%E5%B9%95%E7%BB%84%22%5D&publisherId=456&type=%E5%8B%95%E7%95%AB&before=1686614400000&after=1686355200000&search=%5B%22%5C%22hello%5C%22%22%2C%22%5C%22world%5C%22%22%5D&include=%5B%5B%22hello%22%5D%2C%5B%22world1%22%2C%22world3%22%5D%5D&exclude=%5B%22hi%22%5D"'
`"https://garden.onekuma.cn/api/resources?page=2&pageSize=100&fansubName=%5B%22%E5%AD%97%E5%B9%95%E7%BB%84%22%5D&type=%E5%8B%95%E7%95%AB&before=1686614400000&after=1686355200000&search=%5B%22hello%22%2C%22world%22%5D&include=%5B%22hello%22%2C%22world1%22%2C%22world3%22%5D&exclude=%5B%22hi%22%5D"`
);
});
});
24 changes: 24 additions & 0 deletions packages/database/src/operations/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,33 @@ export async function getUser(database: Database, provider: string, providerId:
return AllUsers.get(provider)?.get(providerId);
}

export async function getUserByProviderId(database: Database, id: string) {
if (AllUsers.size === 0) {
await getAllUsers(database);
}
const all = [...AllUsers.values()].flatMap((t) => [...t.values()]);
return all.filter((t) => t.providerId === id);
}

export async function getTeam(database: Database, provider: string, providerId: string) {
if (AllTeams.size === 0) {
await getAllTeams(database);
}
return AllTeams.get(provider)?.get(providerId);
}

export async function getTeamByProviderId(database: Database, id: string) {
if (AllTeams.size === 0) {
await getAllTeams(database);
}
const all = [...AllTeams.values()].flatMap((t) => [...t.values()]);
return all.filter((t) => t.providerId === id);
}

export async function getTeamByName(database: Database, name: string) {
if (AllTeams.size === 0) {
await getAllTeams(database);
}
const all = [...AllTeams.values()].flatMap((t) => [...t.values()]);
return all.filter((t) => t.name === name);
}
37 changes: 32 additions & 5 deletions packages/server/src/query/search.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import type { ResolvedFilterOptions, ResourceType } from 'animegarden';
import { type ResourceDocument, getTeam, getUser } from '@animegarden/database';
import {
type ResourceDocument,
getTeam,
getUser,
getTeamByProviderId,
getTeamByName,
getUserByProviderId
} from '@animegarden/database';

import { hash } from 'ohash';
import { Resource } from 'animegarden';
Expand All @@ -23,11 +30,31 @@ export async function searchResources(search: string, filter: ResolvedFilterOpti
if (filter.before) {
filters.push(`createdAt <= ${filter.before.getTime()}`);
}
if (filter.publisherId) {
const publishers: string[] = [];
for (const id of filter.fansubId ?? []) {
const users = await getUserByProviderId(database, id);
publishers.push(...users.map((t) => t.providerId));
}
if (publishers.length > 0) {
const array = publishers.map((t) => `'${t}'`).join(',');
filters.push(`publisherId in [${array}]`);
}
}
if (filter.fansubId || filter.fansubName) {
// TODO: how to model?
// const fansubs = [];
// for (const f of filter.fansubId ?? []) {
// }
const fansubs: string[] = [];
for (const id of filter.fansubId ?? []) {
const teams = await getTeamByProviderId(database, id);
fansubs.push(...teams.map((t) => t.providerId));
}
for (const name of filter.fansubName ?? []) {
const teams = await getTeamByName(database, name);
fansubs.push(...teams.map((t) => t.providerId));
}
if (fansubs.length > 0) {
const array = fansubs.map((t) => `'${t}'`).join(',');
filters.push(`fansubId in [${array}]`);
}
}

const resp = await meiliSearch.index('resources').search<ResourceDocument>(search, {
Expand Down

0 comments on commit 33abca2

Please sign in to comment.