Skip to content

Commit

Permalink
feat(animegarden)!: change filter api
Browse files Browse the repository at this point in the history
  • Loading branch information
yjl9903 committed Jan 16, 2024
1 parent c966c8a commit d4ffb4c
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 77 deletions.
31 changes: 18 additions & 13 deletions packages/animegarden/src/garden/filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export function makeResourcesFilter(
const resolved = parseSearchURL(new URLSearchParams(), options);
const chains: Array<(resource: Resource) => boolean> = [];

if (resolved.provider) {
const providers = resolved.provider;
chains.push((r) => providers.includes(r.provider));
}
if (resolved.fansubId) {
const fansubId = resolved.fansubId.map((id) => '' + id);
chains.push((r) => (r.fansub ? fansubId.includes(r.fansub.id) : false));
Expand All @@ -36,24 +40,25 @@ export function makeResourcesFilter(
chains.push((r) => new Date(r.createdAt).getTime() >= after);
}

if (resolved.include || resolved.search) {
const include = resolved.include ?? [];
if (resolved.search) {
include.push(resolved.search);
}
for (const arr of include) {
arr.splice(0, arr.length, ...arr.map((k) => normalizeTitle(k).toLowerCase()));
}
if (resolved.search) {
// Match at least one search keyword
const search = resolved.search.map((k) => normalizeTitle(k).toLowerCase());
chains.push((r) => {
const titleAlt = normalizeTitle(r.title).toLowerCase();
return include.every((keys) => keys.some((key) => titleAlt.indexOf(key) !== -1));
return search.some((key) => titleAlt.indexOf(key) !== -1);
});
}
if (resolved.exclude) {
const exclude = resolved.exclude.map((k) => normalizeTitle(k).toLowerCase());
} else if (resolved.include) {
// Match exact at least one of the keywords, and no excluded keywords
const include = resolved.include.map((k) => normalizeTitle(k).toLowerCase());
const exclude = (resolved.exclude ?? []).map((k) => normalizeTitle(k).toLowerCase());
chains.push((r) => {
const titleAlt = normalizeTitle(r.title).toLowerCase();
return exclude.every((key) => titleAlt.indexOf(key) === -1);
const matched = include.some((key) => titleAlt.indexOf(key) !== -1);
if (matched) {
return exclude.every((key) => titleAlt.indexOf(key) === -1);
} else {
return false;
}
});
}

Expand Down
11 changes: 9 additions & 2 deletions packages/animegarden/src/garden/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import type { Resource } from '../types';

export interface FilterOptions {
/**
* Only filter resources in the specific provider
*/
provider?: string | string[];

/**
* Filter by the group id of fansub
*/
Expand Down Expand Up @@ -41,7 +46,7 @@ export interface FilterOptions {
/**
* Include keywords
*/
include?: (string | string[])[];
include?: string | string[];

/**
* Exclude keywords
Expand All @@ -60,6 +65,8 @@ export interface FilterOptions {
}

export interface ResolvedFilterOptions {
provider: string[];

/**
* Filter by the group id of fansub
*/
Expand Down Expand Up @@ -100,7 +107,7 @@ export interface ResolvedFilterOptions {
/**
* Include keywords
*/
include?: string[][];
include?: string[];

/**
* Exclude keywords
Expand Down
76 changes: 16 additions & 60 deletions packages/animegarden/src/garden/url.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { z } from 'zod';

import { QueryType } from './constant';
import { normalizeTitle } from './utils';
// import { normalizeTitle } from './utils';
import { FilterOptions, ResolvedFilterOptions } from './types';

const dateLike = z
Expand All @@ -15,10 +15,10 @@ const stringArrayLike = z.coerce
.catch(undefined)
.pipe(stringArray)
.optional();
const stringArrayArray = z.union([
z.string().transform((s) => [[s]]),
z.array(stringArray).default([])
]);
// const stringArrayArray = z.union([
// z.string().transform((s) => [[s]]),
// z.array(stringArray).default([])
// ]);

const numberArray = z.union([z.array(z.coerce.number()), z.coerce.number().transform((n) => [n])]);
const numberArrayLike = z.coerce
Expand All @@ -28,7 +28,10 @@ const numberArrayLike = z.coerce
.pipe(numberArray)
.optional();

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

export const FilterSchema = z.object({
provider: providerEnum,
page: z
.number()
.default(1)
Expand All @@ -44,11 +47,12 @@ export const FilterSchema = z.object({
before: dateLike,
after: dateLike,
search: stringArray.optional(),
include: stringArrayArray.optional(),
include: stringArray.optional(),
exclude: stringArray.optional()
});

const parser = {
provider: providerEnum,
page: z.coerce
.number()
.default(1)
Expand All @@ -64,12 +68,7 @@ const parser = {
before: dateLike,
after: dateLike,
search: stringArrayLike,
include: z.coerce
.string()
.transform((t) => JSON.parse(t))
.catch(undefined)
.pipe(stringArrayArray)
.optional(),
include: stringArrayLike,
exclude: stringArrayLike
};

Expand All @@ -80,6 +79,7 @@ export function parseSearchURL(
body?: FilterOptions
): ResolvedFilterOptions {
const entries = [...Object.entries(parser)].map(([key, parser]) => {
// Try parsing body
if (body && typeof body === 'object') {
const content = body[key as ParserKey];
if (content !== null && content !== undefined) {
Expand All @@ -90,6 +90,7 @@ export function parseSearchURL(
}
}
}
// Try parsing params
{
const content = params.get(key);
if (content !== null && content !== '') {
Expand All @@ -104,54 +105,6 @@ export function parseSearchURL(

const filtered = Object.fromEntries(entries) as ResolvedFilterOptions;

if (filtered.search) {
const MIN_LEN = 4;

const newSearch: string[] = [];
const newInclude: string[][] = filtered.include ?? [];
const newExclude: string[] = filtered.exclude ?? [];

for (const text of filtered.search) {
const word = normalizeTitle(text)
.replace(/^(\+|-)?"([^"]*)"$/, '$1$2')
.replace(/%2b/g, '+');
if (word[0] === '+') {
if (word.length - 1 <= MIN_LEN) {
newInclude.push([word.slice(1)]);
} else {
newExclude.push(`+"${word.slice(1)}"`);
}
} else if (word[0] === '-') {
if (word.length - 1 <= MIN_LEN) {
newExclude.push(word.slice(1));
} else {
newSearch.push(`-"${word.slice(1)}"`);
}
} else {
if (word.length <= MIN_LEN) {
newInclude.push([word]);
} else {
newSearch.push(`"${word}"`);
}
}
}

filtered.search = newSearch;
if (newInclude.length > 0) {
filtered.include = newInclude;
}
if (newExclude.length > 0) {
filtered.exclude = newExclude;
}
} else {
if (filtered.include) {
filtered.include = filtered.include.map((arr) => arr.map((t) => normalizeTitle(t)));
}
if (filtered.exclude) {
filtered.exclude = filtered.exclude.map((t) => normalizeTitle(t));
}
}

const isNaN = (d: unknown): boolean => d === undefined || d === null || Number.isNaN(d);
if (isNaN(filtered.page)) {
filtered.page = 1;
Expand All @@ -166,6 +119,9 @@ export function parseSearchURL(
export function stringifySearchURL(baseURL: string, options: FilterOptions): URL {
const url = new URL('resources', baseURL);

if (options.provider && options.provider.length > 0) {
url.searchParams.set('provider', JSON.stringify(options.provider));
}
if (options.page) {
url.searchParams.set('page', '' + options.page);
}
Expand Down
10 changes: 8 additions & 2 deletions packages/animegarden/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ export type ResourceType =
| '其他';

export interface Resource {
provider: string;

providerId: string;

title: string;

href: string;
Expand All @@ -45,13 +49,15 @@ export interface Resource {
createdAt: string;

fetchedAt: string;

provider: string;
}

export type FetchedResource = Omit<Resource, 'fetchedAt'>;

export interface ResourceDetail {
provider: string;

providerId: string;

title: string;

href: string;
Expand Down
9 changes: 9 additions & 0 deletions packages/scraper/src/dmhy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export async function fetchDmhyPage(
throw new Error('dmhy server is down');
}

const now = new Date();
const res: FetchedResource[] = [];
$('#topic_list tbody tr').each((_idx, row) => {
const tds = $(row).find('td');
Expand All @@ -55,8 +56,14 @@ export async function fetchDmhyPage(
const publisherName = publisher.text();
const publisherId = publisher.attr('href')!.split('/').at(-1)!;

const lastHref = href.split('/').at(-1);
if (!lastHref) return;
const matchId = /^(\d+)/.exec(lastHref);
if (!matchId) return;

res.push({
provider: 'dmhy',
providerId: matchId[1],
title,
href,
type,
Expand Down Expand Up @@ -155,6 +162,8 @@ export async function fetchDmhyDetail(
});

return {
provider: 'dmhy',
providerId: matchId[1],
title,
href: url.href,
type,
Expand Down

0 comments on commit d4ffb4c

Please sign in to comment.