// Generated by dts-bundle-generator v9.5.1

import { AxiosInstance } from 'axios';
import { Browser, Page } from 'puppeteer';
import UserAgent from 'user-agents';

export declare abstract class Method<RunTime extends RunTimes, const in out AdditionalDetails extends (DetailsOptions | boolean) = false> {
	readonly job: Job<RunTime>;
	readonly url: string;
	readonly loadAdditionalInfo: AdditionalDetails;
	constructor({ job, url, loadAdditionalInfo }: MethodOptions<RunTime, AdditionalDetails>);
	abstract extract(params: string): Promise<ListData<AdditionalDetails>>;
	abstract details<AdditionalDetails extends (DetailsOptions | boolean)>(id: number | string | TorrentData, options?: AdditionalDetails): Promise<MapDetailsOptions<AdditionalDetails>>;
}
export declare class Cheerio<RunTime extends RunTimes.Cheerio, const in out AdditionalDetails extends (DetailsOptions | boolean) = false> extends Method<RunTime, AdditionalDetails> {
	extract(params: string): Promise<ListData<AdditionalDetails>>;
	details<AdditionalDetails extends (DetailsOptions | boolean)>(url: string, options?: AdditionalDetails): Promise<MapDetailsOptions<AdditionalDetails>>;
	static parseTorrentComponents(parent: string | null): (FileEntity | FolderEntity)[];
	static parseSizeToBytes(sizeString: string): number;
	static extractPageNumber(url: string): number | undefined;
}
export declare class Client<const in out RunTime extends RunTimes = RunTimes.Cheerio> {
	static session: SessionManager;
	readonly runTime: RunTime;
	browser: BrowserInstance<RunTime>;
	readonly jobs: Map<string, Job<RunTime>>;
	readonly timeout: number;
	readonly showNavigator: boolean;
	readonly concurrentJobs: number;
	readonly requestQueue: ((job: Job<RunTime>) => void)[];
	private host;
	private readonly emitter;
	on<K extends keyof JobEvents<RunTime>>(event: K, listener: (...args: JobEvents<RunTime>[K]) => void): void;
	emit<K extends keyof JobEvents<RunTime>>(event: K, ...args: JobEvents<RunTime>[K]): void;
	constructor(options?: ClientOptions<RunTime>);
	initialize(): Promise<void>;
	setupPuppeteer(): Promise<this>;
	setupCheerio(): this;
	set setURL(url: string);
	getURL(): string;
	newAxiosInstance(): {
		instance: import("axios").AxiosInstance;
		instanceId: string;
	};
	newPage(): Promise<{
		page: import("puppeteer").Page;
		pageId: string;
	}>;
	requestJob(): Promise<Job<RunTime>>;
	private setupQueueListener;
}
export declare class Exporter<AdditionalDetails extends (DetailsOptions | boolean), RunTime extends RunTimes> {
	private scraper;
	private search;
	private data;
	constructor(options: ExporterProps<AdditionalDetails, RunTime>);
	getData(): ListData<AdditionalDetails>;
	private setData;
	addNextPage(loadPages?: number): Promise<this>;
	getNextPage(loadPages?: number): Promise<Exporter<AdditionalDetails, RunTime>>;
}
export declare class Job<RunTime extends RunTimes> {
	id: string;
	status: JobStatus;
	readonly timeout: number;
	readonly runTime: RunTime;
	api: RunTimeAPI<RunTime>;
	client: Client<RunTime>;
	constructor({ runTime, timeout, client, api, id }: JobProps<RunTime>);
	finishedTask(): Promise<void>;
	stop(): void;
}
export declare class Puppeteer<RunTime extends RunTimes.Puppeteer, const in out AdditionalDetails extends (DetailsOptions | boolean) = false> extends Method<RunTime, AdditionalDetails> {
	extract(params: string): Promise<ListData<AdditionalDetails>>;
	details<AdditionalDetails extends (DetailsOptions | boolean)>(id: number | string | TorrentData, options?: AdditionalDetails): Promise<MapDetailsOptions<AdditionalDetails>>;
	private waitForConnect;
}
export declare class Scraper<AdditionalDetails extends (DetailsOptions | boolean), RunTime extends RunTimes> {
	readonly pagesToLoad: number;
	readonly loadAdditionalInfo: AdditionalDetails;
	readonly client: Client<RunTime>;
	constructor(options: ({
		client: Client<RunTime>;
	}) & ScraperProps<AdditionalDetails>);
	search<PageNumber extends number | undefined = undefined>(content: string, options?: {
		filter?: FilterParams;
		page?: PageNumber;
		loadOnlyPage?: PageNumber extends number ? boolean : never;
	}, cache?: Exporter<AdditionalDetails, RunTime>): Promise<Exporter<AdditionalDetails, RunTime>>;
	/**
	 * @example
	 *
	 * const scraper = new Scraper()
	 *
	 * await scraper.details(1918530)
	 * await scraper.details('1918530')
	 * await scraper.details('https://nyaa.si/view/1918530')
	 *
	 * const extract = await scraper.search('re: zero')
	 * scraper.details(extract.getData().torrents[0])
	 *
	 * @public
	 * @param {(number | string | TorrentData)} id - Identifier for the torrent (ID, URL, or object).
	 * @param {DetailsOptions} options - Options for fetching details.
	 */
	details(id: number | string | TorrentData, options?: AdditionalDetails): Promise<MapDetailsOptions<AdditionalDetails>>;
	static getSearchParams(content: string, page?: number | undefined, filter?: FilterParams): string;
	/**
   * Normalizes various input types into a numeric ID.
   *
   * @private
   * @param {(number | string | TorrentData)} id - Input data to normalize.
   * @returns {(number | null)} - Normalized numeric ID, or `null` if invalid.
   */
	static normalizeId(id: number | string | TorrentData): number | null;
	/**
	 * Extracts the Id from a url
	 *
	 * @example
	 *
	 * Scraper.extractId('https://nyaa.si/view/1918510') // 1918510
	 *
	 * @param {string} url
	 * @returns {*}
	 */
	static extractId(url: string): number | undefined;
}
export declare class SessionManager {
	private options?;
	private sessions;
	constructor(options?: SessionOptions | undefined);
	create(id: string, filter?: SessionOptions["userAgentOptions"]): string;
	get(id: string): string | undefined;
	createOrGet(id: string, filter?: SessionOptions["userAgentOptions"]): string;
	clear(id: string): boolean;
}
export declare class TypedEventEmitter<Events extends Record<string, unknown[]>> {
	private readonly emitter;
	on<K extends keyof Events>(event: K, listener: (...args: Events[K]) => void): this;
	emit<K extends keyof Events>(event: K, ...args: Events[K]): boolean;
	off<K extends keyof Events>(event: K, listener: (...args: Events[K]) => void): this;
}
export declare const FilterObject: {
	readonly anime: readonly [
		"anime_music_video",
		"english_translated",
		"non_english_translated",
		"raw"
	];
	readonly audio: readonly [
		"lossless",
		"lossy"
	];
	readonly literature: readonly [
		"english_translated",
		"non_english_translated",
		"raw"
	];
	readonly live_action: readonly [
		"english_translated",
		"idol_promotional_video",
		"non_english_translated",
		"raw"
	];
	readonly pictures: readonly [
		"graphics",
		"photos"
	];
	readonly software: readonly [
		"applications",
		"games"
	];
};
export declare enum DataTypes {
	List = "list",
	Details = "details"
}
export declare enum ElementPropertyTypes {
	TextContent = "textContent",
	Href = "href",
	GetAttribute = "getAttribute"
}
export declare enum FileEntityType {
	File = "file",
	Folder = "folder"
}
export declare enum Filters {
	/**
	 * All torrents.
	 */
	NoFilter = 0,
	/**
	 * entries (remake) are torrents that match any of the following:
	 *  -> Reencode of original release.
	 *  -> Remux of another uploader's original release for hardsubbing and/or fixing purposes.
	 *  -> Reupload of original release using non-original file names.
	 *  -> Reupload of original release with missing and/or unrelated additional files.
	 */
	NoRemakes = 1,
	/**
	 * Torrents uploaded by trusted users.
	 */
	TrustedOnly = 2
}
export declare enum JobStatus {
	Reserved = "reserved",
	Listening = "listening",
	Dead = "dead"
}
export declare enum RunTimes {
	Puppeteer = "puppeteer",
	Cheerio = "cheerio"
}
export type BrowserInstance<RunTime extends RunTimes> = RunTime extends RunTimes.Puppeteer ? Browser : never;
export type ClientOptions<RunTime extends RunTimes> = {
	session?: SessionManager;
	/**
	 * Total number of pages to be processed in parallel
	 *
	 * @default 1
	*/
	concurrentJobs?: number;
	/**
	 * This limits the time for the next job request, I don't recommend decreasing this to less than 3000 ms
	  *
	  * @default 3000
	*/
	timeout?: number;
	runTime?: RunTime;
	/**
	 * Shows the browser and the actions being taken to perform webscraping
	 *
	 * @default false
	 */
	showNavigator?: RunTime extends RunTimes.Puppeteer ? boolean : never;
};
export type ConditionalField<T, K extends keyof T, Condition> = Condition extends true | string ? Pick<T, K> : OptionalField<T, K>;
export type DetailsEntity = {
	type: DataTypes.Details;
	description: string;
	submitter: Submitter;
	information: string;
	files: (FileEntity | FolderEntity)[];
	comments: Comment$1[];
};
export type DetailsOptions = {
	/**
	 * @default 'markdown'
	 * @type {?(boolean | 'markdown' | 'html' | 'text')}
	 */
	description?: boolean | "markdown" | "html" | "text";
	submitter?: boolean | undefined;
	information?: boolean;
	files?: boolean;
	comments?: boolean;
};
export type ElementGetAttribute = {
	type: ElementPropertyTypes.GetAttribute;
	attributeName: string;
	element: HTMLElement;
};
export type ElementHref = {
	type: ElementPropertyTypes.Href;
	element: HTMLAnchorElement;
};
export type ElementPropertyOptions = (ElementHref | ElementTextContent | ElementGetAttribute);
export type ElementSelector = {
	row: Element;
	selector: string;
	subSelector?: string;
};
export type ElementTextContent = {
	type: ElementPropertyTypes.TextContent;
	element: HTMLElement;
};
export type ExporterProps<AdditionalDetails extends (DetailsOptions | boolean), RunTime extends RunTimes> = {
	scraper: Scraper<AdditionalDetails, RunTime>;
	search: {
		content: string;
		filter?: FilterParams;
	};
	data: ListData<AdditionalDetails>;
};
export type FileEntity = {
	type: FileEntityType.File;
	/**
	 * The name of the file.
	 */
	fileName: string;
	/**
	 * The size of the file as a human-readable string (e.g., "1 MiB").
	 */
	readableSize: string;
	/**
	 * The size of the file in bytes.
	 */
	sizeInBytes: number;
};
export type FilterKeys = keyof FilterSearch;
export type FilterParams = {
	category?: FilterSearchPaths;
	/**
	 * @default Filters.NoFilter
	 */
	filter?: Filters;
};
export type FilterSearch = typeof FilterObject;
export type FilterSearchPaths = NestedKeys<FilterSearch>;
export type FilterValues = FilterSearch[keyof FilterSearch][number];
export type FolderEntity = {
	type: FileEntityType.Folder;
	/**
	 * The name of the folder.
	 */
	name: string;
	/**
	 * The list of files contained within the folder.
	 */
	files: (FileEntity | FolderEntity)[];
};
export type JobEvents<RunTime extends RunTimes> = {
	died: [
		Omit<Job<RunTime>, "create" | "finishedTask">
	];
	started: [
		Omit<Job<RunTime>, "create" | "finishedTask">
	];
	reserved: [
		Omit<Job<RunTime>, "create" | "finishedTask">
	];
	listening: [
		Omit<Job<RunTime>, "create" | "finishedTask">
	];
};
export type JobProps<RunTime extends RunTimes> = {
	id: string;
	api: RunTimeAPI<RunTime>;
	client: Client<RunTime>;
	timeout: number;
	runTime: RunTime;
};
export type ListData<AdditionalDetails extends (DetailsOptions | boolean)> = {
	type: DataTypes.List;
	metadata: {
		hasPreviousPage: boolean;
		previousPage?: number;
		previousPageLink?: string;
		hasNextPage: boolean;
		nextPage?: number;
		nextPageLink?: string;
		current: number;
		total: number;
		timestamp: number;
		timeTaken: number;
	};
	count: number;
	torrents: (AdditionalDetails extends (DetailsOptions | boolean) ? TorrentDataWithDetails<AdditionalDetails> : TorrentData)[];
};
export type MapDetailsOptions<AdditionalDetails extends (DetailsOptions | boolean)> = {
	type: DataTypes.Details;
} & (AdditionalDetails extends true ? DetailsEntity : AdditionalDetails extends DetailsOptions ? ConditionalField<DetailsEntity, "description", AdditionalDetails["description"]> & ConditionalField<DetailsEntity, "submitter", AdditionalDetails["submitter"]> & ConditionalField<DetailsEntity, "information", AdditionalDetails["information"]> & ConditionalField<DetailsEntity, "files", AdditionalDetails["files"]> & ConditionalField<DetailsEntity, "comments", AdditionalDetails["comments"]> & ConditionalField<DetailsEntity, "description", AdditionalDetails["description"]> : undefined);
export type MethodOptions<RunTime extends RunTimes, AdditionalDetails extends (DetailsOptions | boolean)> = {
	job: Job<RunTime>;
	url: string;
	loadAdditionalInfo: AdditionalDetails;
};
export type NestedKeys<T> = T extends readonly unknown[] ? T[number] & string : T extends Record<string, unknown> ? {
	[K in keyof T]: `${K & string}` | `${K & string}.${NestedKeys<T[K]>}`;
}[keyof T] : never;
export type OptionalField<T, K extends keyof T> = {
	[P in K]?: T[P];
};
export type RunTimeAPI<RunTime extends RunTimes> = RunTime extends RunTimes.Puppeteer ? Page : AxiosInstance;
export type ScraperProps<AdditionalDetails extends (DetailsOptions | boolean)> = {
	/**
	 * How many pages will be loaded for web scraping, each page has 75 torrents
	 *
	 * @default 1
	 */
	pagesToLoad?: number;
	/**
	 *  This carries additional information such as:
	 *  description, submitter, information, files, comments
	 *
	 *  But it results in 75 requests per page, so I don't recommend using it!
	 *  @default false
	 */
	loadAdditionalInfo: AdditionalDetails | DetailsOptions;
};
export type SessionOptions = {
	/**
	 * @link https://www.npmjs.com/package/user-agents
	 */
	userAgentOptions?: Partial<UserAgent["data"]>;
	/**
	 * If not defined, it will generate a userAgent on every call (recommended)
	 */
	defaultUserAgent?: string;
};
export type Submitter = {
	name: string;
	url: string;
};
export type TorrentData = {
	id: number;
	hash: string;
	name: string;
	timestamp: number;
	size: string;
	category: string;
	links: {
		page: string;
		magnet: string;
		torrent: string;
	};
	stats: {
		seeders: number;
		leechers: number;
		downloaded: number;
	};
};
export type TorrentDataWithDetails<AdditionalDetails extends (DetailsOptions | boolean)> = {
	details: MapDetailsOptions<AdditionalDetails>;
} & TorrentData;
type Comment$1 = {
	userName: string;
	avatarURL: string;
	timestamp: number;
	publishDate: string;
	message: string;
	isUploader: boolean;
};

export {
	Comment$1 as Comment,
};

export {};
