@animegarden/client
Version:
Anime Garden API client and utils
390 lines (376 loc) • 10.7 kB
TypeScript
import { ParseResult } from 'anipar';
declare const DefaultBaseURL = "https://api.animes.garden/";
declare const SupportProviders: readonly ["dmhy", "moe", "ani"];
type ProviderType = (typeof SupportProviders)[number];
/**
* Transform type to corresponding JSON.parse(JSON.stringify(...))
*/
type Jsonify<T> = T extends string | number | boolean | null ? T : T extends Date ? string : T extends Function | undefined ? null : T extends object ? T extends Array<infer U> ? Jsonify<U>[] : {
[K in keyof T as K extends symbol ? never : K]: Jsonify<T[K]>;
} : never;
interface Resource<T extends {
tracker?: boolean;
metadata?: boolean;
} = {}> {
id: number;
provider: string;
providerId: string;
title: string;
href: string;
type: string;
magnet: string;
tracker: T['tracker'] extends true ? string : T['tracker'] extends false ? null | undefined : string | null | undefined;
size: number;
fansub?: {
id: number;
name: string;
avatar?: string;
};
publisher: {
id: number;
name: string;
avatar?: string;
};
subjectId?: number;
createdAt: Date;
fetchedAt: Date;
metadata?: T['metadata'] extends true ? {
anipar?: ParseResult;
} : T['metadata'] extends false ? null | undefined : {
anipar?: ParseResult;
} | null | undefined;
}
interface ResourceDetail {
description: string;
files: Array<{
name: string;
size: string;
}>;
magnets: Array<{
name: string;
url: string;
}>;
hasMoreFiles: boolean;
}
interface ScrapedResource {
provider: string;
providerId: string;
title: string;
href: string;
type: string;
magnet: string;
tracker: string;
size: string;
publisher?: {
id: string;
name: string;
avatar?: string;
};
fansub?: {
id: string;
name: string;
avatar?: string;
};
/**
* Date.toISOString()
*/
createdAt: string;
}
interface ScrapedResourceDetail extends Omit<ScrapedResource, 'magnet' | 'tracker'>, ResourceDetail {
}
type FetchOptions = {
/**
* Fetch method
*/
fetch?: (request: RequestInfo, init?: RequestInit) => Promise<Response>;
/**
* The base URL of anime garden API
*
* @default 'https://api.animes.garden/'
*/
baseURL?: string;
/**
* The number of retry times
*
* @default 0
*/
retry?: number;
/**
* Timeout for single request
*/
timeout?: number;
/**
* Abort fetch signal
*/
signal?: AbortSignal;
/**
* Extra request headers
*/
headers?: Record<string, string | ReadonlyArray<string>>;
/**
* Hooks
*/
hooks?: {
prefetch?: (path: string, init: RequestInit) => Promise<void> | void;
postfetch?: (path: string, init: RequestInit, response: Response) => Promise<void> | void;
/**
* Sleep 100ms by default
*/
timeout?: () => Promise<void> | void;
};
};
type FetchResourcesOptions = FilterOptions & FetchOptions & {
/**
* Query count resources
* -1 to fetch all the matched resource
*/
count?: number;
/**
* Should return tracker
*
* @default false
*/
tracker?: boolean;
/**
* Should return metadata
*
* @default false
*/
metadata?: boolean;
/**
* Progress callback when querying multiple pages
*/
progress?: (delta: Resource[], payload: {
url: string;
searchParams: URLSearchParams;
page: number;
}) => void | Promise<void>;
};
type FetchResourceDetailOptions = FetchOptions & {};
type FilterOptions = {
/**
* Query the specified page
*
* @default 1
*/
page?: number;
/**
* Page size
*
* @default 100
*/
pageSize?: number;
/**
* Only filter resources in the specific provider
*/
provider?: string;
/**
* Whether include duplicated resources from different platfrom.
*
* @default false
*/
duplicate?: boolean;
/**
* Resources uploaded after the specified date
*/
after?: Date;
/**
* Resources uploaded before the specified date
*/
before?: Date;
/**
* Search in titles
*/
search?: string | string[];
/**
* Include at least one of titles
*/
include?: string | string[];
/**
* Include all the keywords
*/
keywords?: string | string[];
/**
* Exclude keywords
*/
exclude?: string | string[];
} & ({
/**
* Filter by the resource type
*/
type?: string;
/**
* Filter by the resource type
*/
types?: null | undefined;
} | {
/**
* Filter by the resource type
*/
type?: null | undefined;
/**
* Filter by the resource type
*/
types?: string[];
}) & {
/**
* Filter by the bangumi subject id
*/
subject?: number;
/**
* Filter by the bangumi subject ids
*/
subjects?: number[];
} & ({
/**
* Filter by the fansub names
*/
fansub?: string;
/**
* Filter by the fansub names
*/
fansubs?: null | undefined;
} | {
/**
* Filter by the fansub names
*/
fansub?: null | undefined;
/**
* Filter by the fansub names
*/
fansubs?: string[];
}) & ({
/**
* Filter by the publisher names
*/
publisher?: string;
/**
* Filter by the publisher names
*/
publishers?: null | undefined;
} | {
/**
* Filter by the publisher names
*/
publisher?: null | undefined;
/**
* Filter by the publisher names
*/
publishers?: string[];
});
interface ResolvedFilterOptions {
page: number;
pageSize: number;
provider?: ProviderType;
duplicate?: boolean;
types?: string[];
after?: Date;
before?: Date;
fansubs?: string[];
publishers?: string[];
subjects?: number[];
search?: string[];
include?: string[];
keywords?: string[];
exclude?: string[];
}
interface Collection<S extends boolean = boolean> {
hash?: string;
name: string;
authorization: string;
filters: CollectionFilter<S, false>[];
}
interface CollectionResult<S extends boolean = false, R extends boolean = false, T extends {
tracker?: boolean;
metadata?: boolean;
} = {}> {
ok: boolean;
hash: string;
name: string;
createdAt: string;
filters: CollectionFilter<S, R, T>[];
timestamp: Date;
}
interface CollectionResourcesResult<S extends boolean = false, R extends boolean = false, T extends {
tracker?: boolean;
metadata?: boolean;
} = {}> {
ok: boolean;
hash: string;
name: string;
filters: CollectionFilter<S, R, T>[];
createdAt: string;
results: Array<{
resources: Resource<T>[];
complete: boolean;
filter: Omit<ResolvedFilterOptions, 'page'> | undefined;
}>;
timestamp: Date;
}
type CollectionFilter<S extends boolean = false, R extends boolean = true, T extends {
tracker?: boolean;
metadata?: boolean;
} = {}> = Omit<ResolvedFilterOptions, 'page' | 'pageSize'> & {
name: string;
searchParams: S extends true ? string : S extends false ? undefined : string | undefined;
} & (R extends true ? {
resources: Resource<T>[];
complete: boolean;
} : R extends false ? {} : {
resources?: Resource<T>[];
complete?: boolean;
});
declare function parseCollection(collection: unknown): Collection<true> | undefined;
declare function hashCollection(collection: Collection<true>): Promise<string>;
declare function makeResourcesFilter(filter: Omit<ResolvedFilterOptions, 'page' | 'pageSize' | 'duplicate'>): (res: Resource) => boolean;
declare function parseURLSearch(params?: URLSearchParams, body?: FilterOptions): ResolvedFilterOptions;
declare function stringifyURLSearch(options: FilterOptions): URLSearchParams;
declare function transformResourceHref(provider: ProviderType, href?: string): string | undefined;
declare function transformPublisherHref(provider: ProviderType, publisherId?: string): string | undefined;
declare function transformFansubHref(provider: ProviderType, fansubId?: string): string | undefined;
declare function normalizeTitle(title: string): string;
declare function fetchAPI<T>(path: string, init?: RequestInit | undefined, options?: FetchOptions): Promise<T>;
declare function fetchStatus(options?: FetchOptions): Promise<{
ok: boolean;
timestamp: string;
providers: Record<"dmhy" | "moe" | "ani", {
id: ProviderType;
name: string;
refreshedAt: string;
isActive: boolean;
}>;
} | {
ok: boolean;
timestamp: undefined;
providers: undefined;
}>;
declare function generateCollection(collection: Collection<true>, options?: FetchOptions): Promise<CollectionResult<true, false> | undefined>;
declare function fetchCollection(hash: string, options?: FetchOptions): Promise<CollectionResourcesResult<true, false, {
tracker: true;
}> | undefined>;
interface FetchResourceDetailResult {
ok: boolean;
resource: Resource<{
tracker: true;
metadata: true;
}> | undefined;
detail: ResourceDetail | undefined;
timestamp: Date | undefined;
}
/**
* Fetch resource detail from anime garden
*/
declare function fetchResourceDetail(provider: ProviderType, href: string, options?: FetchResourceDetailOptions): Promise<FetchResourceDetailResult>;
interface FetchResourcesResult<T extends FetchResourcesOptions> {
ok: boolean;
resources: Resource<T>[];
complete: boolean;
filter: Omit<ResolvedFilterOptions, 'page'> | undefined;
timestamp: Date | undefined;
}
/**
* Fetch resources list data from anime garden
*/
declare function fetchResources<T extends FetchResourcesOptions = FetchResourcesOptions>(options?: T): Promise<FetchResourcesResult<T>>;
export { DefaultBaseURL, SupportProviders, fetchAPI, fetchCollection, fetchResourceDetail, fetchResources, fetchStatus, generateCollection, hashCollection, makeResourcesFilter, normalizeTitle, parseCollection, parseURLSearch, stringifyURLSearch, transformFansubHref, transformPublisherHref, transformResourceHref };
export type { Collection, CollectionFilter, CollectionResourcesResult, CollectionResult, FetchOptions, FetchResourceDetailOptions, FetchResourceDetailResult, FetchResourcesOptions, FetchResourcesResult, FilterOptions, Jsonify, ProviderType, ResolvedFilterOptions, Resource, ResourceDetail, ScrapedResource, ScrapedResourceDetail };