{"version":3,"sources":["../src/index.ts","../src/sources/video/hanime.ts","../src/sources/video/hentai-haven.ts","../src/utils/get-number-from-string.ts","../src/utils/rot13.ts","../src/sources/video/hentai-stream.ts","../src/utils/normalize.ts","../src/utils/remove-number-from-string.ts","../src/sources/gallery/r34.ts","../src/utils/Dimension.ts"],"sourcesContent":["export * from \"./sources\";\nexport * from \"./utils\";\n","import { load } from \"cheerio\";\nimport type { PaginatedResult } from \"../../types\";\n\nexport const HANIME_BASE_URL = \"https://hanime.tv\";\nexport const HANIME_SEARCH_URL = \"https://search.htv-services.com\";\nexport const HANIME_SIGNATURE_GENERATOR = () =>\n\tArray.from({ length: 32 }, () => Math.floor(Math.random() * 16).toString(16)).join(\"\");\n\nexport const HAnime = class {\n\tpublic BASE_URL = HANIME_BASE_URL;\n\tpublic SEARCH_URL = HANIME_BASE_URL;\n\tpublic generateSignature = HANIME_SIGNATURE_GENERATOR;\n\n\t/**\n\t * Creates a new instance of the HAnime client.\n\t *\n\t * @param {HAnimeOptions} [options] - Configuration options for the HAnime client.\n\t * @param {string} [options.baseUrl] - Custom base URL for the HAnime website.\n\t * @param {string} [options.searchUrl] - Custom search API URL.\n\t * @param {function(): string} [options.signatureGenerator] - Custom function to generate request signatures.\n\t */\n\tconstructor(options?: HAnimeOptions) {\n\t\tthis.BASE_URL = options?.baseUrl || HANIME_BASE_URL;\n\t\tthis.SEARCH_URL = options?.searchUrl || HANIME_SEARCH_URL;\n\t\tthis.generateSignature = options?.signatureGenerator || HANIME_SIGNATURE_GENERATOR;\n\t}\n\n\t/**\n\t * Searches for videos on Hanime.tv based on the provided query.\n\t *\n\t * @param {string} query - The search query string.\n\t * @param {number} [page=1] - The page number to retrieve (default is 1).\n\t * @param {number} [perPage=10] - The number of results per page (default is 10).\n\t * @returns {Promise<PaginatedResult<HAnimeSearchResult>>} A promise that resolves to a paginated result of search results.\n\t */\n\tpublic search = async (\n\t\tquery: string,\n\t\tpage = 1,\n\t\tperPage = 10,\n\t): Promise<PaginatedResult<HAnimeSearchResult>> => {\n\t\tif (!query) {\n\t\t\tthrow new Error(\"Search query cannot be empty\");\n\t\t}\n\n\t\tlet validPage = page;\n\t\tif (validPage < 1) {\n\t\t\tvalidPage = 1;\n\t\t}\n\n\t\tlet validPerPage = perPage;\n\t\tif (validPerPage < 1) {\n\t\t\tvalidPerPage = 10;\n\t\t}\n\n\t\ttry {\n\t\t\tconst response = await fetch(this.SEARCH_URL, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tblacklist: [],\n\t\t\t\t\tbrands: [],\n\t\t\t\t\torder_by: \"created_at_unix\",\n\t\t\t\t\tpage: validPage - 1,\n\t\t\t\t\ttags: [],\n\t\t\t\t\tsearch_text: query.trim(),\n\t\t\t\t\ttags_mode: \"AND\",\n\t\t\t\t}),\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(`Search request failed with status: ${response.status}`);\n\t\t\t}\n\n\t\t\tconst data = (await response.json()) as {\n\t\t\t\tpage: number;\n\t\t\t\tnbPages: number;\n\t\t\t\tnbHits: number;\n\t\t\t\thitsPerPage: number;\n\t\t\t\thits: HAnimeRawSearchResult[];\n\t\t\t};\n\n\t\t\tif (!data.hits) {\n\t\t\t\treturn {\n\t\t\t\t\tresults: [],\n\t\t\t\t\ttotal: 0,\n\t\t\t\t\tpage,\n\t\t\t\t\tpages: 0,\n\t\t\t\t\thasNextPage: false,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tlet allResults: HAnimeSearchResult[] = [];\n\t\t\ttry {\n\t\t\t\tallResults = data.hits.map((result) => this.mapToSearchResult(result));\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Failed to parse search results:\", error);\n\t\t\t\tthrow new Error(\"Failed to parse search results\");\n\t\t\t}\n\n\t\t\tconst totalResults = data.nbHits || 0;\n\t\t\tconst totalPages = Math.max(1, Math.ceil(totalResults / validPerPage));\n\n\t\t\tconst finalPage = Math.min(Math.max(1, validPage), totalPages);\n\n\t\t\tconst startIndex = (finalPage - 1) * validPerPage;\n\t\t\tconst endIndex = Math.min(startIndex + validPerPage, allResults.length);\n\t\t\tconst results = allResults.slice(startIndex, endIndex);\n\n\t\t\treturn {\n\t\t\t\tresults,\n\t\t\t\ttotal: totalResults,\n\t\t\t\tpage: finalPage,\n\t\t\t\tpages: totalPages,\n\t\t\t\tprevious: finalPage > 1 ? finalPage - 1 : undefined,\n\t\t\t\tnext: finalPage < totalPages ? finalPage + 1 : undefined,\n\t\t\t\thasNextPage: finalPage < totalPages,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Search error:\", error);\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to search HAnime: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t};\n\n\t/**\n\t * Retrieves detailed information about a specific video by its slug.\n\t *\n\t * @param {string} slug - The unique slug identifier for the video.\n\t * @returns {Promise<HAnimeVideoInfo>} A promise that resolves to detailed information about the video.\n\t */\n\tpublic getInfo = async (slug: string): Promise<HAnimeVideoInfo> => {\n\t\tconst path = `/videos/hentai/${slug}`;\n\t\tconst url = `${this.BASE_URL}${path}`;\n\n\t\tconst response = await fetch(url);\n\t\tconst html = await response.text();\n\n\t\tconst $ = load(html);\n\n\t\tconst script = $('script:contains(\"window.__NUXT__\")');\n\t\tconst scriptHtml = script.html();\n\t\tconst json = JSON.parse(\n\t\t\tscriptHtml?.replace(\"window.__NUXT__=\", \"\").replaceAll(\";\", \"\") || \"{}\",\n\t\t) as HanimeResponse;\n\n\t\tconst videoData = json.state.data.video;\n\n\t\treturn {\n\t\t\ttitle: json.state.data.video.hentai_franchise.name,\n\t\t\tslug: json.state.data.video.hentai_franchise.slug,\n\t\t\tid: videoData.hentai_video.id,\n\t\t\tdescription: videoData.hentai_video.description,\n\t\t\tviews: videoData.hentai_video.views,\n\t\t\tinterests: videoData.hentai_video.interests,\n\t\t\tposterUrl: videoData.hentai_video.poster_url,\n\t\t\tcoverUrl: videoData.hentai_video.cover_url,\n\t\t\tbrand: {\n\t\t\t\tname: videoData.hentai_video.brand,\n\t\t\t\tid: videoData.hentai_video.brand_id,\n\t\t\t},\n\t\t\tdurationMs: videoData.hentai_video.duration_in_ms,\n\t\t\tisCensored: videoData.hentai_video.is_censored,\n\t\t\tlikes: videoData.hentai_video.likes,\n\t\t\trating: videoData.hentai_video.rating,\n\t\t\tdislikes: videoData.hentai_video.dislikes,\n\t\t\tdownloads: videoData.hentai_video.downloads,\n\t\t\trankMonthly: videoData.hentai_video.monthly_rank,\n\t\t\ttags: videoData.hentai_tags,\n\t\t\tcreatedAt: videoData.hentai_video.created_at,\n\t\t\treleasedAt: videoData.hentai_video.released_at,\n\t\t\tepisodes: {\n\t\t\t\tnext: this.mapToEpisode(videoData.next_hentai_video),\n\t\t\t\tall: json.state.data.video.hentai_franchise_hentai_videos.map(this.mapToEpisode),\n\t\t\t\trandom: this.mapToEpisode(videoData.next_random_hentai_video),\n\t\t\t},\n\t\t};\n\t};\n\n\t/**\n\t * Retrieves stream information for a specific video episode by its slug.\n\t *\n\t * @param {string} slug - The unique slug identifier for the video episode.\n\t * @returns {Promise<HAnimeStream[]>} A promise that resolves to an array of available video streams.\n\t */\n\tpublic getEpisode = async (slug: string): Promise<HAnimeStream[]> => {\n\t\tconst apiUrl = `${this.BASE_URL}/rapi/v7/videos_manifests/${slug}`;\n\t\tconst signature = this.generateSignature();\n\n\t\tconst response = await fetch(apiUrl, {\n\t\t\theaders: {\n\t\t\t\t\"x-signature\": signature,\n\t\t\t\t\"x-time\": Math.floor(Date.now() / 1000).toString(),\n\t\t\t\t\"x-signature-version\": \"web2\",\n\t\t\t},\n\t\t});\n\n\t\tconst json = (await response.json()) as { videos_manifest: VideosManifest };\n\n\t\tconst data = json.videos_manifest;\n\t\tconst videos = data.servers.flatMap((server) => server.streams);\n\n\t\tconst streams = videos\n\t\t\t.map((video) => ({\n\t\t\t\tid: video.id,\n\t\t\t\tserverId: video.server_id,\n\t\t\t\tkind: video.kind,\n\t\t\t\textension: video.extension,\n\t\t\t\tmimeType: video.mime_type,\n\t\t\t\twidth: video.width,\n\t\t\t\theight: video.height,\n\t\t\t\tdurationInMs: video.duration_in_ms,\n\t\t\t\tfilesizeMbs: video.filesize_mbs,\n\t\t\t\tfilename: video.filename,\n\t\t\t\turl: video.url,\n\t\t\t}))\n\t\t\t.filter((video) => video.url && video.url !== \"\" && video.kind !== \"premium_alert\");\n\n\t\treturn streams;\n\t};\n\n\tpublic mapToSearchResult = (raw: HAnimeRawSearchResult): HAnimeSearchResult => {\n\t\treturn {\n\t\t\tid: raw.id,\n\t\t\tname: raw.name,\n\t\t\ttitles: raw.titles,\n\t\t\tslug: raw.slug,\n\t\t\tdescription: raw.description,\n\t\t\tviews: raw.views,\n\t\t\tinterests: raw.interests,\n\t\t\tbannerImage: raw.poster_url,\n\t\t\tcoverImage: raw.cover_url,\n\t\t\tbrand: {\n\t\t\t\tname: raw.brand,\n\t\t\t\tid: raw.brand_id,\n\t\t\t},\n\t\t\tdurationMs: raw.duration_in_ms,\n\t\t\tisCensored: raw.is_censored,\n\t\t\tlikes: raw.likes,\n\t\t\trating: raw.rating,\n\t\t\tdislikes: raw.dislikes,\n\t\t\tdownloads: raw.downloads,\n\t\t\trankMonthly: raw.monthly_rank,\n\t\t\ttags:\n\t\t\t\ttypeof raw.tags === \"object\" && Array.isArray(raw.tags) ? raw.tags : JSON.parse(raw.tags),\n\t\t\tcreatedAt: raw.created_at,\n\t\t\treleasedAt: raw.released_at,\n\t\t};\n\t};\n\n\tpublic mapToEpisode = (raw: {\n\t\tid: number;\n\t\tname: string;\n\t\tslug: string;\n\t\tcreated_at: string;\n\t\treleased_at: string;\n\t\tviews: number;\n\t\tinterests: number;\n\t\tposter_url: string;\n\t\tcover_url: string;\n\t\tis_hard_subtitled: boolean;\n\t\tbrand: string;\n\t\tduration_in_ms: number;\n\t\tis_censored: boolean;\n\t\trating: number;\n\t\tlikes: number;\n\t\tdislikes: number;\n\t\tdownloads: number;\n\t\tmonthly_rank: number;\n\t\tbrand_id: string;\n\t\tis_banned_in: string;\n\t\tpreview_url: null;\n\t\tprimary_color: null;\n\t\tcreated_at_unix: number;\n\t\treleased_at_unix: number;\n\t}) => {\n\t\treturn {\n\t\t\tid: raw.id,\n\t\t\tname: raw.name,\n\t\t\tslug: raw.slug,\n\t\t\tviews: raw.views,\n\t\t\tinterests: raw.interests,\n\t\t\tthumbnailUrl: raw.poster_url,\n\t\t\tcoverUrl: raw.cover_url,\n\t\t\tisHardSubtitled: raw.is_hard_subtitled,\n\t\t\tbrand: {\n\t\t\t\tname: raw.brand,\n\t\t\t\tid: raw.brand_id,\n\t\t\t},\n\t\t\tdurationMs: raw.duration_in_ms,\n\t\t\tisCensored: raw.is_censored,\n\t\t\tlikes: raw.likes,\n\t\t\trating: raw.rating,\n\t\t\tdislikes: raw.dislikes,\n\t\t\tdownloads: raw.downloads,\n\t\t\trankMonthly: raw.monthly_rank,\n\t\t\tbrandId: raw.brand_id,\n\t\t\tisBannedIn: raw.is_banned_in,\n\t\t\tpreviewUrl: raw.preview_url,\n\t\t\tcolor: raw.primary_color,\n\t\t\tcreatedAt: raw.created_at_unix,\n\t\t\treleasedAt: raw.released_at_unix,\n\t\t};\n\t};\n};\n\nexport interface HAnimeOptions {\n\tbaseUrl?: string;\n\tsearchUrl?: string;\n\tsignatureGenerator?: () => string;\n}\n\nexport interface HAnimeVideoInfo {\n\ttitle: string;\n\tslug: string;\n\tid: number;\n\tdescription?: string;\n\tviews: number;\n\tinterests: number;\n\tposterUrl: string;\n\tcoverUrl: string;\n\tbrand: {\n\t\tname: string;\n\t\tid: string | number;\n\t};\n\tdurationMs: number;\n\tisCensored: boolean;\n\tlikes: number;\n\trating: number;\n\tdislikes: number;\n\tdownloads: number;\n\trankMonthly: number;\n\ttags: HentaiTag[];\n\tcreatedAt: string;\n\treleasedAt: string;\n\tepisodes: {\n\t\tnext: HentaiVideoEpisode;\n\t\tall: HentaiVideoEpisode[];\n\t\trandom: HentaiVideoEpisode;\n\t};\n}\n\nexport interface HentaiVideoEpisode {\n\tid: number;\n\tname: string;\n\tslug: string;\n\tviews: number;\n\tinterests: number;\n\tthumbnailUrl: string;\n\tcoverUrl: string;\n\tisHardSubtitled: boolean;\n\tbrand: {\n\t\tname: string;\n\t\tid: string;\n\t};\n\tdurationMs: number;\n\tisCensored: boolean;\n\tlikes: number;\n\trating: number;\n\tdislikes: number;\n\tdownloads: number;\n\trankMonthly: number;\n\tbrandId: string;\n\tisBannedIn: string;\n\tpreviewUrl: null;\n\tcolor: null;\n\tcreatedAt: number;\n\treleasedAt: number;\n}\n\nexport interface HAnimeStream {\n\tid: number;\n\tserverId: number;\n\tkind: string;\n\textension: string;\n\tmimeType: string;\n\twidth: number;\n\theight: string | number;\n\tdurationInMs: number;\n\tfilesizeMbs: number;\n\tfilename: string;\n\turl: string;\n}\n\nexport interface HanimeResponse {\n\tlayout: string;\n\tdata: unknown[];\n\terror: null;\n\tserverRendered: boolean;\n\tstate: State;\n\tvideos_manifest?: VideosManifest;\n\tpr?: boolean;\n}\n\nexport interface State {\n\tscrollY: number;\n\tversion: number;\n\tis_new_version: boolean;\n\tr: null;\n\tcountry_code: null;\n\tpage_name: string;\n\tuser_agent: string;\n\tip: null;\n\treferrer: null;\n\tgeo: null;\n\tis_dev: boolean;\n\tis_wasm_supported: boolean;\n\tis_mounted: boolean;\n\tis_loading: boolean;\n\tis_searching: boolean;\n\tbrowser_width: number;\n\tbrowser_height: number;\n\tsystem_msg: string;\n\tdata: Data;\n\tauth_claim: null;\n\tsession_token: string;\n\tsession_token_expire_time_unix: number;\n\tenv: Env;\n\tuser: null;\n\tuser_setting: null;\n\tplaylists: null;\n\tshuffle: boolean;\n\taccount_dialog: AccountDialog;\n\tcontact_us_dialog: ContactUsDialog;\n\tgeneral_confirmation_dialog: GeneralConfirmationDialog;\n\tsnackbar: Snackbar;\n\tsearch: Search;\n}\n\nexport interface Data {\n\tvideo: Video;\n}\n\nexport interface Video {\n\tplayer_base_url: string;\n\thentai_video: HentaiVideo;\n\thentai_tags: HentaiTag[];\n\thentai_franchise: HentaiFranchise;\n\thentai_franchise_hentai_videos: HentaiVideo[];\n\thentai_video_storyboards: HentaiVideoStoryboard[];\n\tbrand: Brand;\n\twatch_later_playlist_hentai_videos: null;\n\tlike_dislike_playlist_hentai_videos: null;\n\tplaylist_hentai_videos: null;\n\tsimilar_playlists_data: null;\n\tnext_hentai_video: HentaiVideo;\n\tnext_random_hentai_video: HentaiVideo;\n\tvideos_manifest?: VideosManifest;\n\tuser_license: null;\n\tbs: Bs;\n\tap: number;\n\tpre: string;\n\tencrypted_user_license: null;\n\thost: string;\n}\n\nexport interface HentaiVideo {\n\tid: number;\n\tis_visible: boolean;\n\tname: string;\n\tslug: string;\n\tcreated_at: string;\n\treleased_at: string;\n\tdescription?: string;\n\tviews: number;\n\tinterests: number;\n\tposter_url: string;\n\tcover_url: string;\n\tis_hard_subtitled: boolean;\n\tbrand: string;\n\tduration_in_ms: number;\n\tis_censored: boolean;\n\trating: number;\n\tlikes: number;\n\tdislikes: number;\n\tdownloads: number;\n\tmonthly_rank: number;\n\tbrand_id: string;\n\tis_banned_in: string;\n\tpreview_url: null;\n\tprimary_color: null;\n\tcreated_at_unix: number;\n\treleased_at_unix: number;\n\thentai_tags?: HentaiTag[];\n\ttitles?: unknown[];\n}\n\nexport interface HentaiTag {\n\tid: number;\n\ttext: string;\n\tcount?: number;\n\tdescription?: string;\n\twide_image_url?: string;\n\ttall_image_url?: string;\n}\n\nexport interface HentaiFranchise {\n\tid: number;\n\tname: string;\n\tslug: string;\n\ttitle: string;\n}\n\nexport interface HentaiVideoStoryboard {\n\tid: number;\n\tnum_total_storyboards: number;\n\tsequence: number;\n\turl: string;\n\tframe_width: number;\n\tframe_height: number;\n\tnum_total_frames: number;\n\tnum_horizontal_frames: number;\n\tnum_vertical_frames: number;\n}\n\nexport interface Brand {\n\tid: number;\n\ttitle: string;\n\tslug: string;\n\twebsite_url: null;\n\tlogo_url: null;\n\temail: null;\n\tcount: number;\n}\n\nexport interface VideosManifest {\n\tservers: Server[];\n}\n\nexport interface Server {\n\tid: number;\n\tname: string;\n\tslug: string;\n\tna_rating: number;\n\teu_rating: number;\n\tasia_rating: number;\n\tsequence: number;\n\tis_permanent: boolean;\n\tstreams: Stream[];\n}\n\nexport interface Stream {\n\tid: number;\n\tserver_id: number;\n\tslug: string;\n\tkind: string;\n\textension: string;\n\tmime_type: string;\n\twidth: number;\n\theight: string;\n\tduration_in_ms: number;\n\tfilesize_mbs: number;\n\tfilename: string;\n\turl: string;\n\tis_guest_allowed: boolean;\n\tis_member_allowed: boolean;\n\tis_premium_allowed: boolean;\n\tis_downloadable: boolean;\n\tcompatibility: string;\n\thv_id: number;\n\tserver_sequence: number;\n\tvideo_stream_group_id: string;\n\textra2: null;\n}\n\nexport interface Bs {\n\tntv_1: Ntv1;\n\tntv_2: Ntv2;\n\tfooter_0: Footer0;\n\tnative_1: Native1;\n\tnative_0: Native0;\n\tntv_0: Ntv0;\n}\n\nexport interface Ntv1 {\n\tdesktop: DesktopAd;\n}\n\nexport interface Ntv2 {\n\tdesktop: DesktopAd;\n}\n\nexport interface Footer0 {\n\tmobile: MobileAd;\n\tdesktop: DesktopAd;\n}\n\nexport interface Native1 {\n\tmobile: NativeAd;\n}\n\nexport interface Native0 {\n\tmobile: NativeAd;\n}\n\nexport interface Ntv0 {\n\tdesktop: DesktopAd;\n}\n\nexport interface DesktopAd {\n\tid: number;\n\tad_id: string;\n\tad_type: string;\n\tplacement: string;\n\timage_url: null;\n\tiframe_url: string;\n\tclick_url: null | string;\n\twidth: number;\n\theight: number;\n\tpage: string;\n\tform_factor: string;\n\tvideo_url: null;\n\timpressions: number;\n\tclicks: number;\n\tseconds: number;\n\tplacement_x: null;\n}\n\nexport interface MobileAd {\n\tid: number;\n\tad_id: string;\n\tad_type: string;\n\tplacement: string;\n\timage_url: null;\n\tiframe_url: string;\n\tclick_url: null;\n\twidth: number;\n\theight: number;\n\tpage: string;\n\tform_factor: string;\n\tvideo_url: null;\n\timpressions: number;\n\tclicks: number;\n\tseconds: number;\n\tplacement_x: null;\n}\n\nexport interface NativeAd {\n\tid: number;\n\tad_id: string;\n\tad_type: string;\n\tplacement: string;\n\timage_url: string;\n\tiframe_url: null;\n\tclick_url: string;\n\twidth: number;\n\theight: number;\n\tpage: string;\n\tform_factor: string;\n\tvideo_url: null;\n\timpressions: number;\n\tclicks: number;\n\tseconds: number;\n\tplacement_x: string;\n}\n\nexport interface Env {\n\tvhtv_version: number;\n\tpremium_coin_cost: number;\n\tmobile_apps: MobileApps;\n}\n\nexport interface MobileApps {\n\tcode_name: string;\n\t_build_number: number;\n\t_semver: string;\n\t_md5: string;\n\t_url: string;\n}\n\nexport interface AccountDialog {\n\tis_visible: boolean;\n\tactive_tab_id: string;\n\ttabs: Tab[];\n}\n\nexport interface Tab {\n\tid: string;\n\ticon: string;\n\ttitle: string;\n}\n\nexport interface ContactUsDialog {\n\tis_visible: boolean;\n\tis_video_report: boolean;\n\tsubject: string;\n\temail: string;\n\tmessage: string;\n\tis_sent: boolean;\n}\n\nexport interface GeneralConfirmationDialog {\n\tis_visible: boolean;\n\tis_persistent: boolean;\n\tis_mini_close_button_visible: boolean;\n\tis_cancel_button_visible: boolean;\n\tcancel_button_text: string;\n\ttitle: string;\n\tbody: string;\n\tconfirm_button_text: string;\n\tconfirmation_callback: null;\n}\n\nexport interface Snackbar {\n\ttimeout: number;\n\tcontext: string;\n\tmode: string;\n\ty: string;\n\tx: string;\n\tis_visible: boolean;\n\ttext: string;\n}\n\nexport interface Search {\n\tcache_sorting_config: unknown[];\n\tcache_tags_filter: null;\n\tcache_active_brands: null;\n\tcache_blacklisted_tags_filter: null;\n\tsearch_text: string;\n\tsearch_response_payload: null;\n\ttotal_search_results_count: number;\n\torder_by: string;\n\tordering: string;\n\ttags_match: string;\n\tpage_size: number;\n\toffset: number;\n\tpage: number;\n\tnumber_of_pages: number;\n\ttags: unknown[];\n\tactive_tags_count: number;\n\tbrands: unknown[];\n\tactive_brands_count: number;\n\tblacklisted_tags: unknown[];\n\tactive_blacklisted_tags_count: number;\n\tis_using_preferences: boolean;\n}\n\nexport interface HAnimeSearchResult {\n\tid: number;\n\tname: string;\n\ttitles: string[];\n\tslug: string;\n\tdescription: string;\n\tviews: number;\n\tinterests: number;\n\tbannerImage: string;\n\tcoverImage: string;\n\tbrand: {\n\t\tname: string;\n\t\tid: number;\n\t};\n\tdurationMs: number;\n\tisCensored: boolean;\n\tlikes: number;\n\trating: number;\n\tdislikes: number;\n\tdownloads: number;\n\trankMonthly: number;\n\ttags: string[];\n\tcreatedAt: number;\n\treleasedAt: number;\n}\n\nexport interface HAnimeRawSearchResult {\n\tid: number;\n\tname: string;\n\ttitles: string[];\n\tslug: string;\n\tdescription: string;\n\tviews: number;\n\tinterests: number;\n\tposter_url: string;\n\tcover_url: string;\n\tbrand: string;\n\tbrand_id: number;\n\tduration_in_ms: number;\n\tis_censored: boolean;\n\tlikes: number;\n\trating: number;\n\tdislikes: number;\n\tdownloads: number;\n\tmonthly_rank: number;\n\ttags: string[] | string;\n\tcreated_at: number;\n\treleased_at: number;\n}\n","import { load } from \"cheerio\";\nimport { parse } from \"date-fns\";\nimport { getNumberFromString } from \"../../utils/get-number-from-string\";\nimport { rot13Cipher } from \"../../utils/rot13\";\n\n/**\n * Base URL for the Hentai Haven website.\n */\nexport const HENTAI_HAVEN_URL = \"http://hentaihaven.xxx\";\n\n/**\n * Client for interacting with the Hentai Haven website.\n */\nexport const HentaiHaven = class {\n\t/**\n\t * Base URL for API requests.\n\t */\n\tpublic BASE_URL = HENTAI_HAVEN_URL;\n\n\t/**\n\t * Creates a new instance of the HentaiHaven client.\n\t *\n\t * @param {HentaiHavenOptions} options - Configuration options for the HentaiHaven client.\n\t * @param {string} [options.baseUrl] - Custom base URL for the HentaiHaven website.\n\t */\n\tconstructor(options?: HentaiHavenOptions) {\n\t\tthis.BASE_URL = options?.baseUrl || HENTAI_HAVEN_URL;\n\t}\n\n\t/**\n\t * Searches for hentai videos on Hentai Haven based on the provided query.\n\t *\n\t * @param {string} query - The search query string.\n\t * @returns {Promise<HHSearchResult[]>} A promise that resolves to an array of search results.\n\t * @throws {TypeError} If the query is empty or not a string.\n\t */\n\tpublic search = async (query: string) => {\n\t\tif (!query || typeof query !== \"string\") {\n\t\t\tthrow new TypeError(\"Invalid query in search.\");\n\t\t}\n\n\t\tconst url = `${this.BASE_URL}/?s=${query}&post_type=wp-manga`;\n\n\t\tconst response = await fetch(url);\n\t\tconst data = await response.text();\n\n\t\tconst $ = load(data);\n\t\tconst results: HHSearchResult[] = [];\n\n\t\t$(\".c-tabs-item__content\").each((_i, el) => {\n\t\t\tconst cover = $(el).find(\".c-image-hover img\").attr(\"src\") || \"\";\n\t\t\tconst id = $(el).find(\".c-image-hover a\").attr(\"href\")?.split(\"/\")[4] || \"\";\n\t\t\tconst title = $(el).find(\".post-title h3\").text().trim();\n\t\t\tconst alternative = $(el).find(\".tab-summary .mg_alternative .summary-content\").text().trim();\n\t\t\tconst author = $(el).find(\".tab-summary .mg_author .summary-content\").text().trim();\n\t\t\tconst released = Number(\n\t\t\t\t$(el).find(\".tab-summary .mg_release .summary-content\").text().trim(),\n\t\t\t);\n\t\t\tconst totalEpisodes =\n\t\t\t\tgetNumberFromString($(el).find(\".tab-meta .latest-chap .chapter\").text().trim()) || 0;\n\t\t\tconst dateString = $(el).find(\".tab-meta .post-on\").text().trim();\n\t\t\tconst parsedDate = parse(dateString, \"MMM dd, yyyy\", new Date());\n\n\t\t\tconst rating = Number($(el).find(\".tab-meta .rating .total_votes\").text().trim());\n\n\t\t\tconst genres: HHGenre[] = [];\n\n\t\t\t$(\".tab-summary .mg_genres .summary-content a\").each((_, element) => {\n\t\t\t\tgenres.push({\n\t\t\t\t\tid: $(element).attr(\"href\")?.split(\"/\")[4] || \"\",\n\t\t\t\t\turl: $(element).attr(\"href\") || \"\",\n\t\t\t\t\tname: $(element).text().trim().replaceAll(\",\", \"\"),\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tresults.push({\n\t\t\t\tid,\n\t\t\t\ttitle,\n\t\t\t\tcover: cover.replaceAll(\" \", \"%20\"),\n\t\t\t\trating,\n\t\t\t\treleased,\n\t\t\t\tgenres,\n\t\t\t\ttotalEpisodes,\n\t\t\t\tdate: {\n\t\t\t\t\tunparsed: dateString,\n\t\t\t\t\tparsed: parsedDate,\n\t\t\t\t},\n\t\t\t\talternative,\n\t\t\t\tauthor,\n\t\t\t});\n\t\t});\n\n\t\treturn results;\n\t};\n\n\t/**\n\t * Retrieves detailed information about a hentai series by its ID.\n\t *\n\t * @param {string} id - The unique identifier of the hentai series.\n\t * @param {HHEpisodesSort} [episodeSort=\"ASC\"] - The sort order for episodes (ascending or descending).\n\t * @returns {Promise<HHHentaiInfo>} A promise that resolves to detailed information about the hentai series.\n\t * @throws {Error} If the ID is not provided or if there's an error fetching the data.\n\t */\n\tpublic getInfo = async (id: string, episodeSort: HHEpisodesSort = \"ASC\") => {\n\t\tif (!id) {\n\t\t\tthrow new Error(\"Id is required\");\n\t\t}\n\n\t\tconst url = `${this.BASE_URL}/watch/${id}`;\n\n\t\tconst response = await fetch(url);\n\t\tconst data = await response.text();\n\n\t\tif (data === \"\" || !data) {\n\t\t\tthrow new Error(\"Error fetching data\");\n\t\t}\n\n\t\tconst $ = load(data);\n\n\t\tif ($(\"body\").text().includes(\"webpage has been blocked\")) {\n\t\t\tthrow new Error(`The webpage is blocked. Consider using a CORS proxy. GET ${url}`);\n\t\t}\n\n\t\tconst title = $(\".post-title h1\").text().trim();\n\t\tconst cover = $(\".summary_image img\").attr(\"src\") || \"\";\n\t\tconst ratingCount = Number($('span[property=\"ratingCount\"]').text().trim());\n\t\tconst views = getNumberFromString(\n\t\t\t$(\".post-content_item:nth-child(4) .summary-content\").text(),\n\t\t) as number;\n\t\tconst released = Number($(\".post-status .summary-content a\").text().trim());\n\t\tconst summary = $(\".description-summary p\").text().trim();\n\n\t\tconst genres: HHGenre[] = [];\n\t\tconst episodes: HHHentaiEpisode[] = [];\n\n\t\t$(\".genres-content a\").each((_i, el) => {\n\t\t\tgenres.push({\n\t\t\t\tid: $(el).attr(\"href\")?.split(\"/\")[4] || \"\",\n\t\t\t\turl: $(el).attr(\"href\") || \"\",\n\t\t\t\tname: $(el).text().trim(),\n\t\t\t});\n\t\t});\n\n\t\tconst episodesLength = $(\"li.wp-manga-chapter\").length;\n\n\t\t$(\"li.wp-manga-chapter\").each((i, el) => {\n\t\t\tconst thumbnail = $(el).find(\"img\").attr(\"src\");\n\t\t\tconst id = `${$(el).find(\"a\").attr(\"href\")?.split(\"/\")[4]}/${\n\t\t\t\t$(el).find(\"a\").attr(\"href\")?.split(\"/\")[5]\n\t\t\t}`;\n\t\t\tconst title = $(el).find(\"a\").text().trim();\n\t\t\tconst number = episodesLength - i;\n\t\t\tconst released = $(el).find(\".chapter-release-date\").text().trim();\n\t\t\tconst releasedUTC = parse(released, \"MMMM dd, yyyy\", new Date());\n\n\t\t\tepisodes.push({\n\t\t\t\t// Episode id spoofing cause the API doesn't return the episode id, it returns a path.\n\t\t\t\tid: btoa(id),\n\t\t\t\ttitle,\n\t\t\t\tthumbnail,\n\t\t\t\tnumber,\n\t\t\t\treleasedUTC,\n\t\t\t\treleasedRelative: released,\n\t\t\t});\n\t\t});\n\n\t\tthis.sortEpisodes(episodes, episodeSort);\n\n\t\treturn {\n\t\t\tid,\n\t\t\ttitle,\n\t\t\tcover: cover ? cover.replaceAll(\" \", \"%20\") : \"\",\n\t\t\tsummary,\n\t\t\tviews,\n\t\t\tratingCount,\n\t\t\treleased,\n\t\t\tgenres,\n\t\t\ttotalEpisodes: episodesLength,\n\t\t\tepisodes,\n\t\t} as HHHentaiInfo;\n\t};\n\n\t/**\n\t * Retrieves streaming sources for a specific episode by its ID.\n\t *\n\t * @param {string} id - The encoded episode ID.\n\t * @returns {Promise<HHHentaiSources>} A promise that resolves to the streaming sources for the episode.\n\t * @throws {TypeError} If the ID is invalid or not provided.\n\t * @throws {Error} If the episode ID is not properly encoded.\n\t */\n\tpublic getEpisode = async (id: string) => {\n\t\tif (!id || typeof id !== \"string\") {\n\t\t\tthrow new TypeError(\"Invalid identifier\");\n\t\t}\n\n\t\tif (id?.includes(\"episode-\")) {\n\t\t\tthrow new Error(\"The Episode ID must be encoded.\");\n\t\t}\n\n\t\tconst pageUrl = `${this.BASE_URL}/watch/${atob(id)}`;\n\n\t\tconst pageResponse = await fetch(pageUrl);\n\t\tconst pageHtml = await pageResponse.text();\n\n\t\tconst $page = load(pageHtml);\n\t\tconst iframeSrc = $page(\".player_logic_item > iframe\").attr(\"src\");\n\n\t\tconst iframeResponse = await fetch(iframeSrc || \"\");\n\t\tconst iframeHtml = await iframeResponse.text();\n\n\t\tconst $iframe = load(iframeHtml);\n\t\tconst secureToken = $iframe('meta[name=\"x-secure-token\"]')\n\t\t\t.attr(\"content\")\n\t\t\t?.replace(\"sha512-\", \"\");\n\n\t\tconst rotatedSha = rot13Cipher(secureToken || \"\");\n\t\tconst firstDecode = atob(rotatedSha);\n\t\tconst secondRotate = rot13Cipher(firstDecode);\n\t\tconst secondDecode = atob(secondRotate);\n\t\tconst thirdRotate = rot13Cipher(secondDecode);\n\n\t\tconst decryptedData = JSON.parse(atob(thirdRotate)) as {\n\t\t\ten: string;\n\t\t\tiv: string;\n\t\t\turi: string;\n\t\t};\n\n\t\tconst formData = new FormData();\n\t\tformData.append(\"action\", \"zarat_get_data_player_ajax\");\n\t\tformData.append(\"a\", decryptedData.en);\n\t\tformData.append(\"b\", decryptedData.iv);\n\n\t\tconst apiUrl = `${\n\t\t\tdecryptedData.uri || \"https://hentaihaven.xxx/wp-content/plugins/player-logic/\"\n\t\t}api.php`;\n\t\tconst apiResponse = (await (\n\t\t\tawait fetch(apiUrl, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: formData,\n\t\t\t\tmode: \"cors\",\n\t\t\t\tcache: \"default\",\n\t\t\t})\n\t\t).json()) as {\n\t\t\tstatus: boolean;\n\t\t\tdata: {\n\t\t\t\timage: string | null;\n\t\t\t\tsources: HHHentaiSource[];\n\t\t\t};\n\t\t\tauthorization: {\n\t\t\t\ttoken: string;\n\t\t\t\texpiration: number;\n\t\t\t\tip: string;\n\t\t\t};\n\t\t};\n\n\t\tconst sources = apiResponse.data.sources;\n\t\tconst thumbnail = apiResponse.data.image;\n\n\t\treturn {\n\t\t\tsources,\n\t\t\tthumbnail,\n\t\t} as HHHentaiSources;\n\t};\n\n\t/**\n\t * Sorts an array of episodes based on the specified sort order.\n\t *\n\t * @param {HHHentaiEpisode[]} episodes - The array of episodes to sort.\n\t * @param {HHEpisodesSort} sortOrder - The sort order to apply (\"ASC\" for ascending, \"DESC\" for descending).\n\t */\n\tpublic sortEpisodes(episodes: HHHentaiEpisode[], sortOrder: HHEpisodesSort) {\n\t\tepisodes.sort((a, b) => {\n\t\t\tif (sortOrder === \"ASC\") {\n\t\t\t\treturn a.number - b.number;\n\t\t\t}\n\t\t\treturn b.number - a.number;\n\t\t});\n\t}\n};\n\n/**\n * Configuration options for the HentaiHaven client.\n */\ninterface HentaiHavenOptions {\n\t/**\n\t * Custom base URL for the HentaiHaven website.\n\t */\n\tbaseUrl?: string;\n}\n\n/**\n * Sort order for episodes.\n */\nexport type HHEpisodesSort = \"ASC\" | \"DESC\";\n\n/**\n * Represents a genre in Hentai Haven.\n */\nexport interface HHGenre {\n\t/**\n\t * Unique identifier for the genre.\n\t */\n\tid: string;\n\t/**\n\t * URL to the genre page.\n\t */\n\turl: string;\n\t/**\n\t * Name of the genre.\n\t */\n\tname: string;\n}\n\n/**\n * Represents an episode of a hentai series.\n */\nexport interface HHHentaiEpisode {\n\t/**\n\t * Unique identifier for the episode.\n\t */\n\tid: string;\n\t/**\n\t * Title of the episode.\n\t */\n\ttitle: string;\n\t/**\n\t * URL to the episode thumbnail image.\n\t */\n\tthumbnail?: string;\n\t/**\n\t * Episode number.\n\t */\n\tnumber: number;\n\t/**\n\t * Release date in UTC.\n\t */\n\treleasedUTC: Date;\n\t/**\n\t * Relative time since release (e.g., \"2 days ago\").\n\t */\n\treleasedRelative: string;\n}\n\n/**\n * Detailed information about a hentai series.\n */\nexport interface HHHentaiInfo {\n\t/**\n\t * Unique identifier for the series.\n\t */\n\tid: string;\n\t/**\n\t * Title of the series.\n\t */\n\ttitle: string;\n\t/**\n\t * URL to the cover image.\n\t */\n\tcover: string;\n\t/**\n\t * Plot summary or description.\n\t */\n\tsummary: string;\n\t/**\n\t * Number of views.\n\t */\n\tviews: number;\n\t/**\n\t * Number of ratings received.\n\t */\n\tratingCount: number;\n\t/**\n\t * Year of release.\n\t */\n\treleased: number;\n\t/**\n\t * List of genres associated with the series.\n\t */\n\tgenres: HHGenre[];\n\t/**\n\t * Total number of episodes in the series.\n\t */\n\ttotalEpisodes: number;\n\t/**\n\t * List of episodes in the series.\n\t */\n\tepisodes: HHHentaiEpisode[];\n}\n\n/**\n * Represents a video source for streaming.\n */\nexport interface HHHentaiSource {\n\t/**\n\t * Label for the video quality or source.\n\t */\n\tlabel: string;\n\t/**\n\t * URL to the video source.\n\t */\n\tsrc: string;\n\t/**\n\t * MIME type of the video.\n\t */\n\ttype: string;\n}\n\n/**\n * Collection of video sources for a hentai episode.\n */\nexport interface HHHentaiSources {\n\t/**\n\t * List of available video sources.\n\t */\n\tsources: HHHentaiSource[];\n\t/**\n\t * URL to the video thumbnail.\n\t */\n\tthumbnail?: string;\n}\n\n/**\n * Represents a search result from Hentai Haven.\n */\nexport interface HHSearchResult {\n\t/**\n\t * Unique identifier for the series.\n\t */\n\tid: string;\n\t/**\n\t * Title of the series.\n\t */\n\ttitle: string;\n\t/**\n\t * URL to the cover image.\n\t */\n\tcover: string;\n\t/**\n\t * Average rating of the series.\n\t */\n\trating: number;\n\t/**\n\t * Year of release.\n\t */\n\treleased: number;\n\t/**\n\t * List of genres associated with the series.\n\t */\n\tgenres: HHGenre[];\n\t/**\n\t * Total number of episodes in the series.\n\t */\n\ttotalEpisodes: number;\n\t/**\n\t * Date information.\n\t */\n\tdate: {\n\t\t/**\n\t\t * Unparsed date string.\n\t\t */\n\t\tunparsed: string;\n\t\t/**\n\t\t * Parsed Date object.\n\t\t */\n\t\tparsed: Date;\n\t};\n\t/**\n\t * Alternative titles.\n\t */\n\talternative: string;\n\t/**\n\t * Author or creator of the series.\n\t */\n\tauthor: string;\n}\n","/**\n * Extracts the first number from a string.\n *\n * @param {string} str - The input string to extract a number from.\n * @returns {number | null} The first number found in the string, or null if no numbers are found.\n * @throws {TypeError} If the input is not a string.\n *\n * @example\n * // Returns 123\n * getNumberFromString(\"abc123def456\");\n *\n * @example\n * // Returns null\n * getNumberFromString(\"no numbers here\");\n */\nexport function getNumberFromString(str: string): number | null {\n\tif (typeof str !== \"string\") {\n\t\tthrow new TypeError(\"Input must be a string\");\n\t}\n\n\tif (str.trim() === \"\") {\n\t\treturn null;\n\t}\n\n\tconst numbers = str.match(/\\d+/g);\n\treturn numbers ? Number(numbers[0]) : null;\n}\n","/**\n * Applies the ROT13 cipher to a string, shifting each letter 13 positions in the alphabet.\n * Non-alphabetic characters remain unchanged.\n *\n * @param {string} str - The input string to be encoded or decoded with ROT13.\n * @returns {string} The ROT13 transformed string.\n * @throws {TypeError} If the input is not a string.\n *\n * @example\n * // Returns \"uryyb\"\n * rot13Cipher(\"hello\");\n *\n * @example\n * // Returns \"hello\"\n * rot13Cipher(\"uryyb\");\n *\n * @example\n * // Returns \"Uryyb, Jbeyq! 123\"\n * rot13Cipher(\"Hello, World! 123\");\n */\nexport const rot13Cipher = (str: string): string => {\n\tif (typeof str !== \"string\") {\n\t\tthrow new TypeError(\"Input must be a string\");\n\t}\n\n\tif (str.length === 0) {\n\t\treturn \"\";\n\t}\n\n\treturn str.replace(/[a-zA-Z]/g, (c) => {\n\t\tconst charCode = c.charCodeAt(0);\n\t\tconst isUpperCase = charCode >= 65 && charCode <= 90;\n\t\tconst shiftedCharCode = isUpperCase\n\t\t\t? ((charCode - 65 + 13) % 26) + 65\n\t\t\t: ((charCode - 97 + 13) % 26) + 97;\n\t\treturn String.fromCharCode(shiftedCharCode);\n\t});\n};\n","import { load } from \"cheerio\";\nimport { parseDate } from \"chrono-node\";\nimport { getNumberFromString } from \"../../utils/get-number-from-string\";\nimport { normalize } from \"../../utils/normalize\";\nimport { removeNumberFromString } from \"../../utils/remove-number-from-string\";\n\nexport const HENTAI_STREAM_BASE_URL = \"https://tube.hentaistream.com\";\n\n/**\n * HentaiStream class for interacting with the HentaiStream API\n */\nexport const HentaiStream = class {\n\tpublic BASE_URL = HENTAI_STREAM_BASE_URL;\n\n\t/**\n\t * Creates a new HentaiStream instance\n\t * @param options - Configuration options\n\t */\n\tconstructor(options?: HentaiStreamOptions) {\n\t\tthis.BASE_URL = options?.baseUrl || HENTAI_STREAM_BASE_URL;\n\t}\n\n\t/**\n\t * Search for anime on HentaiStream\n\t * @param query - The search query\n\t * @returns Promise resolving to an array of search results\n\t * @throws {TypeError} If query is invalid\n\t */\n\tpublic search = async (query: string): Promise<HStreamResult[]> => {\n\t\tif (!query || typeof query !== \"string\") {\n\t\t\tthrow new TypeError(\"Invalid Query\");\n\t\t}\n\n\t\tconst url = `${this.BASE_URL}/?s=${encodeURIComponent(query)}`;\n\n\t\tconst response = await fetch(url);\n\t\tconst data = await response.text();\n\n\t\tconst $ = load(data);\n\n\t\tconst results: HStreamResult[] = [];\n\n\t\t$(\".content .post\").each((_i, e) => {\n\t\t\tconst $e = $(e);\n\n\t\t\tconst id = ($e.find(\"div.postimg a\").attr(\"href\") || \"\").split(\"/\").pop() || \"\";\n\t\t\tconst title = $e.find(\"p.posttitle ins\").text().trim() || \"\";\n\t\t\tconst image = $e.find(\"div.postimg img\").attr(\"src\");\n\t\t\tconst views =\n\t\t\t\tNumber.parseInt($e.find(\".view\").text().trim().split(\" \")[0].replaceAll(\",\", \"\")) || 0;\n\t\t\tconst releaseDate = parseDate($e.find(\".dtcreated\").text().trim().split(\"Added: \")[1].trim());\n\n\t\t\tresults.push({\n\t\t\t\tid,\n\t\t\t\timage,\n\t\t\t\ttitle,\n\t\t\t\tviews,\n\t\t\t\treleaseDate,\n\t\t\t});\n\t\t});\n\n\t\treturn results;\n\t};\n\n\t/**\n\t * Get information about a specific episode\n\t * @param id - The episode ID\n\t * @returns Promise resolving to episode information\n\t * @throws {TypeError} If ID is invalid\n\t */\n\tpublic getInfoEpisode = async (id: string): Promise<HStreamEpisodeInfo> => {\n\t\tif (!id || typeof id !== \"string\") {\n\t\t\tthrow new TypeError(\"Invalid ID.\");\n\t\t}\n\n\t\tconst url = `${this.BASE_URL}/${id}`;\n\n\t\tconst response = await fetch(url);\n\t\tconst data = await response.text();\n\n\t\tconst $ = load(data);\n\n\t\tconst title = $(\".videotitle\").text().trim().replaceAll(\"¤\", \"\").trim();\n\t\tconst releasedDate = parseDate(\n\t\t\t$(\".threebox p:nth-child(1)\").text().trim().split(\"Added: \")[1].split(\" @\")[0].trim(),\n\t\t);\n\t\tconst views = Number.parseInt(\n\t\t\t$(\".threebox p:nth-child(2)\").text().trim().split(\"Views: \")[1].replaceAll(\",\", \"\"),\n\t\t);\n\t\tconst genres = $('div.videotags:contains(\"Genre(s)\") a')\n\t\t\t.map((_i, e) => $(e).text().trim())\n\t\t\t.get();\n\n\t\treturn {\n\t\t\ttitle,\n\t\t\treleasedDate,\n\t\t\tviews,\n\t\t\tgenres,\n\t\t};\n\t};\n\n\t/**\n\t * Get detailed information about an anime series\n\t * @param id - The anime ID or title\n\t * @returns Promise resolving to anime information or null if not found\n\t * @throws {TypeError} If ID is invalid\n\t */\n\tpublic getInfo = async (id: string): Promise<HStreamAnimeInfo | null> => {\n\t\tif (!id || typeof id !== \"string\") {\n\t\t\tthrow new TypeError(\"Invalid ID.\");\n\t\t}\n\n\t\tconst normalizedId = normalize(id);\n\n\t\tconst searchData = await this.search(normalizedId);\n\n\t\tconst matchingResults = searchData.filter((result) => {\n\t\t\tconst normalizedTitle = normalize(result.title || \"\");\n\t\t\treturn normalizedTitle.includes(normalizedId);\n\t\t});\n\n\t\tif (matchingResults.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst firstResult = matchingResults[0];\n\n\t\tconst episodes = await Promise.all(\n\t\t\tmatchingResults.map(async (result) => {\n\t\t\t\tconst episodeInfo = await this.getInfoEpisode(result.id);\n\t\t\t\tconst episodeNumber = getNumberFromString(result.title || \"\");\n\n\t\t\t\treturn {\n\t\t\t\t\t...result,\n\t\t\t\t\t...episodeInfo,\n\t\t\t\t\tepisodeNumber,\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\n\t\tepisodes.sort((a, b) => {\n\t\t\tconst aNum = a.episodeNumber || 0;\n\t\t\tconst bNum = b.episodeNumber || 0;\n\t\t\treturn aNum - bNum;\n\t\t});\n\n\t\tconst averageViews = Math.ceil(\n\t\t\tepisodes.reduce((sum, episode) => sum + (episode.views || 0), 0) / episodes.length,\n\t\t);\n\t\tconst genres = new Set(episodes.flatMap((episode) => episode.genres || []));\n\n\t\treturn {\n\t\t\ttitle: (normalizedId.charAt(0).toUpperCase() + normalizedId.slice(1)).trim(),\n\t\t\timage: firstResult.image,\n\t\t\tgenres: [...genres.values()],\n\t\t\tviews: averageViews,\n\t\t\tepisodes: episodes.map((ep) => ({\n\t\t\t\tid: btoa(ep.id),\n\t\t\t\tnumber: ep.episodeNumber,\n\t\t\t\tviews: ep.views,\n\t\t\t\treleasedDate: ep.releaseDate,\n\t\t\t\ttitle: ep.title,\n\t\t\t\timage: ep.image,\n\t\t\t})),\n\t\t\treleasedDate: episodes[0].releaseDate,\n\t\t};\n\t};\n\n\t/**\n\t * Get streaming information for a specific episode\n\t * @param id - The encoded episode ID\n\t * @returns Promise resolving to episode streaming information\n\t * @throws {TypeError} If ID is invalid\n\t * @throws {Error} If streams cannot be fetched\n\t */\n\tpublic getEpisode = async (id: string): Promise<HStreamEpisodeStream> => {\n\t\tif (!id || typeof id !== \"string\") {\n\t\t\tthrow new TypeError(\"Invalid ID.\");\n\t\t}\n\n\t\tconst url = `${this.BASE_URL}/${atob(id)}`;\n\n\t\tconst response = await fetch(url);\n\t\tconst data = await response.text();\n\n\t\tconst $ = load(data);\n\n\t\tconst frameUrl = $(\"iframe\").attr(\"src\");\n\n\t\tconst title = $(\".videotitle\").text().trim().replaceAll(\"¤\", \"\").trim();\n\t\tconst releasedDate = parseDate(\n\t\t\t$(\".threebox p:nth-child(1)\").text().trim().split(\"Added: \")[1].split(\" @\")[0].trim(),\n\t\t);\n\t\tconst views = Number.parseInt(\n\t\t\t$(\".threebox p:nth-child(2)\").text().trim().split(\"Views: \")[1].replaceAll(\",\", \"\"),\n\t\t);\n\n\t\tif (!frameUrl) {\n\t\t\tthrow new Error(\"Failed to fetch streams\");\n\t\t}\n\n\t\tconst res = await fetch(frameUrl);\n\t\tconst frameData = await res.text();\n\n\t\tconst $$ = load(frameData);\n\n\t\tconst $video = $$(\"video\");\n\n\t\tconst source = $video.find(\"source\").attr(\"src\");\n\n\t\treturn {\n\t\t\ttitle,\n\t\t\treleasedDate,\n\t\t\tviews,\n\t\t\tsource,\n\t\t};\n\t};\n};\n\n/**\n * Configuration options for HentaiStream\n */\nexport interface HentaiStreamOptions {\n\tbaseUrl?: string;\n}\n\n/**\n * Search result from HentaiStream\n */\nexport interface HStreamResult {\n\tid: string;\n\ttitle?: string;\n\tviews?: number;\n\timage?: string;\n\treleaseDate?: Date | null;\n}\n\n/**\n * Episode information\n */\nexport interface HStreamEpisodeInfo {\n\ttitle?: string;\n\treleasedDate?: Date | null;\n\tviews?: number;\n\tgenres?: string[];\n}\n\n/**\n * Anime series information\n */\nexport interface HStreamAnimeInfo {\n\ttitle: string;\n\timage?: string;\n\tgenres: string[];\n\tviews: number;\n\tepisodes: HStreamEpisodeListItem[];\n\treleasedDate?: Date | null;\n}\n\n/**\n * Episode list item\n */\nexport interface HStreamEpisodeListItem {\n\tid: string;\n\tnumber?: number | null;\n\tviews?: number;\n\treleasedDate?: Date | null;\n\ttitle?: string;\n\timage?: string;\n}\n\n/**\n * Episode streaming information\n */\nexport interface HStreamEpisodeStream {\n\ttitle?: string;\n\treleasedDate?: Date | null;\n\tviews?: number;\n\tsource?: string;\n}\n","/**\n * Normalizes a string by removing all symbols, special characters, and numbers,\n * then converts it to lowercase.\n *\n * @param {string} str - The input string to normalize.\n * @returns {string} The normalized string.\n * @throws {TypeError} If the input is not a string.\n *\n * @example\n * // Returns \"hello world\"\n * normalize(\"Hello World! 123\");\n *\n * @example\n * // Returns \"just text\"\n * normalize(\"Just TEXT! @#$%^&*()\");\n */\nexport function normalize(str: string): string {\n\tif (typeof str !== \"string\") {\n\t\tthrow new TypeError(\"Input must be a string\");\n\t}\n\n\tif (str.trim() === \"\") {\n\t\treturn str;\n\t}\n\n\t// Remove all symbols, special characters, and numbers\n\tconst normalized = str.replace(/[^a-zA-Z\\s]/g, \" \");\n\n\t// Convert to lowercase and remove double or more spaces\n\treturn normalized\n\t\t.toLowerCase()\n\t\t.replace(/\\s{2,}/g, \" \")\n\t\t.replaceAll(\"episode\", \"\");\n}\n","/**\n * Removes all numbers from a string.\n *\n * @param {string} str - The input string to remove numbers from.\n * @returns {string} The string with all numbers removed.\n * @throws {TypeError} If the input is not a string.\n *\n * @example\n * // Returns \"abcdef\"\n * removeNumberFromString(\"abc123def456\");\n *\n * @example\n * // Returns \"no numbers here\"\n * removeNumberFromString(\"no numbers here\");\n */\nexport function removeNumberFromString(str: string): string {\n\tif (typeof str !== \"string\") {\n\t\tthrow new TypeError(\"Input must be a string\");\n\t}\n\n\tif (str.trim() === \"\") {\n\t\treturn str;\n\t}\n\n\treturn str.replace(/\\d+/g, \"\");\n}\n","import { load } from \"cheerio\";\nimport type { PaginatedResult } from \"../../types\";\nimport { Dimension } from \"../../utils/Dimension\";\n\n/**\n * Base URL for the Rule34 website.\n */\nexport const RULE34_BASE_URL = \"https://rule34.xxx\";\n\n/**\n * API URL for Rule34 autocomplete functionality.\n */\nexport const RULE34_API_URL = \"https://ac.rule34.xxx\";\n\n/**\n * Class representing a Rule34 client for interacting with the Rule34 website.\n */\nexport const Rule34 = class {\n\t/**\n\t * Base URL for the Rule34 website.\n\t */\n\tpublic BASE_URL = RULE34_BASE_URL;\n\n\t/**\n\t * API URL for Rule34 autocomplete functionality.\n\t */\n\tpublic API_URL = RULE34_API_URL;\n\n\t/**\n\t * Creates a new instance of the Rule34 client.\n\t *\n\t * @param {R34Options} [options] - Configuration options for the Rule34 client.\n\t * @param {string} [options.baseUrl] - Custom base URL for the Rule34 website.\n\t * @param {string} [options.apiUrl] - Custom API URL for Rule34 autocomplete functionality.\n\t */\n\tconstructor(options?: R34Options) {\n\t\tthis.BASE_URL = options?.baseUrl || RULE34_BASE_URL;\n\t\tthis.API_URL = options?.apiUrl || RULE34_API_URL;\n\t}\n\n\t/**\n\t * Searches for autocomplete suggestions based on the provided query.\n\t *\n\t * @param {string} query - The search query string.\n\t * @returns {Promise<Array<{completedQuery: string, label: string, type: string}>>} A promise that resolves to an array of autocomplete suggestions.\n\t * @throws {TypeError} If the query is empty or not a string.\n\t */\n\tsearchAutocomplete = async (query: string) => {\n\t\tif (!query || typeof query !== \"string\") {\n\t\t\tthrow new TypeError(\"Query invalid\");\n\t\t}\n\n\t\tconst url = `${this.API_URL}/autocomplete.php?q=${query}`;\n\n\t\tconst response = await fetch(url);\n\t\tconst data = (await response.json()) as { label: string; value: string; type: string }[];\n\n\t\treturn data.map((item) => ({\n\t\t\tcompletedQuery: item.value,\n\t\t\tlabel: item.label,\n\t\t\ttype: item.type,\n\t\t}));\n\t};\n\n\t/**\n\t * Searches for images on Rule34 based on the provided query.\n\t *\n\t * @param {string} query - The search query string.\n\t * @param {number} [page=1] - The page number to retrieve (default is 1).\n\t * @param {number} [perPage=10] - The number of results per page (default is 10).\n\t * @returns {Promise<R34SearchResult>} A promise that resolves to a paginated result of search results.\n\t * @throws {TypeError} If the query is empty or not a string.\n\t */\n\tsearch = async (query: string, page = 1, perPage = 10) => {\n\t\tif (!query || typeof query !== \"string\") {\n\t\t\tthrow new TypeError(\"Query invalid\");\n\t\t}\n\n\t\tconst url = `${this.BASE_URL}/index.php?page=post&s=list&tags=${query}&pid=${(page - 1) * perPage}`;\n\n\t\tconst response = await fetch(url);\n\t\tconst data = await response.text();\n\n\t\tconst $ = load(data);\n\n\t\tconst results: R3SearchResult[] = [];\n\n\t\t$(\".image-list span\").each((_i, e) => {\n\t\t\tconst $e = $(e);\n\n\t\t\tconst id = $e.attr(\"id\")?.replace(\"s\", \"\") || \"\";\n\t\t\tconst image = $e.find(\"img\").attr(\"src\") || \"\";\n\t\t\tconst tags =\n\t\t\t\t$e\n\t\t\t\t\t.find(\"img\")\n\t\t\t\t\t.attr(\"alt\")\n\t\t\t\t\t?.trim()\n\t\t\t\t\t?.split(\" \")\n\t\t\t\t\t.filter((tag) => tag !== \"\") || [];\n\n\t\t\tresults.push({\n\t\t\t\tid: id,\n\t\t\t\timage: image,\n\t\t\t\ttags: tags,\n\t\t\t\ttype: \"preview\",\n\t\t\t});\n\t\t});\n\n\t\tconst pagination = $(\"#paginator .pagination\");\n\t\tconst totalPages =\n\t\t\tNumber.parseInt(pagination.find(\"a:last\").attr(\"href\")?.split(\"pid=\")[1] || \"1\", 10) /\n\t\t\t\tperPage +\n\t\t\t1;\n\t\tconst currentPage = page;\n\t\tconst nextPage = currentPage < totalPages ? currentPage + 1 : null;\n\t\tconst previousPage = currentPage > 1 ? currentPage - 1 : null;\n\t\tconst hasNextPage = nextPage !== null;\n\t\tconst next = nextPage !== null ? nextPage * perPage : 0;\n\t\tconst previous = previousPage !== null ? previousPage * perPage : 0;\n\n\t\treturn {\n\t\t\ttotal: totalPages * perPage,\n\t\t\tnext: next,\n\t\t\tprevious: previous,\n\t\t\tpages: totalPages,\n\t\t\tpage: currentPage,\n\t\t\thasNextPage,\n\t\t\tresults,\n\t\t} as R34SearchResult;\n\t};\n\n\t/**\n\t * Gets detailed information about a specific image by its ID.\n\t *\n\t * @param {string} id - The ID of the image to retrieve information for.\n\t * @returns {Promise<R34ImageInfo>} A promise that resolves to an object containing detailed information about the image.\n\t */\n\tpublic getInfo = async (id: string): Promise<R34ImageInfo> => {\n\t\tconst url = `${this.BASE_URL}/index.php?page=post&s=view&id=${id}`;\n\n\t\tconst resizeCookies = {\n\t\t\t\"resize-notification\": 1,\n\t\t\t\"resize-original\": 1,\n\t\t};\n\n\t\tconst [resizedResponse, nonResizedResponse] = await Promise.all([\n\t\t\tfetch(url),\n\t\t\tfetch(url, {\n\t\t\t\theaders: {\n\t\t\t\t\tcookie: Object.entries(resizeCookies)\n\t\t\t\t\t\t.map(([key, value]) => `${key}=${value}`)\n\t\t\t\t\t\t.join(\"; \"),\n\t\t\t\t},\n\t\t\t}),\n\t\t]);\n\n\t\tconst [resized, original] = await Promise.all([\n\t\t\tresizedResponse.text(),\n\t\t\tnonResizedResponse.text(),\n\t\t]);\n\n\t\tconst $resized = load(resized);\n\n\t\tconst resizedImageUrl = $resized(\"#image\").attr(\"src\");\n\n\t\tconst $ = load(original);\n\t\tconst fullImage = $(\"#image\").attr(\"src\");\n\t\tconst tags = $(\"#image\")\n\t\t\t.attr(\"alt\")\n\t\t\t?.trim()\n\t\t\t?.split(\" \")\n\t\t\t.filter((tag) => tag !== \"\");\n\n\t\tconst stats = $(\"#stats ul\");\n\n\t\tconst postedData = stats.find(\"li:nth-child(2)\").text().trim();\n\t\tconst createdAt = new Date(postedData.split(\"Posted: \")[1].split(\"by\")[0]).getTime();\n\t\tconst publishedBy = postedData.split(\"by\")[1].trim();\n\t\tconst size = stats.find(\"li:nth-child(3)\").text().trim().split(\"Size: \")[1];\n\t\tconst rating = stats.find(\"li:contains('Rating:')\").text().trim().split(\"Rating: \")[1];\n\t\tconst dimension = Dimension.fromString(size);\n\t\tconst comments = $(\"#comment-list div\")\n\t\t\t.map((_i, el) => {\n\t\t\t\tconst $el = $(el);\n\t\t\t\tconst id = $el.attr(\"id\")?.replace(\"c\", \"\");\n\t\t\t\tconst user = $el.find(\".col1\").text().trim().split(\"\\n\")[0];\n\t\t\t\tconst comment = $el.find(\".col2\").text().trim();\n\t\t\t\treturn {\n\t\t\t\t\tid,\n\t\t\t\t\tuser,\n\t\t\t\t\tcomment,\n\t\t\t\t};\n\t\t\t})\n\t\t\t.get()\n\t\t\t.filter(Boolean)\n\t\t\t.filter((comment) => comment.comment !== \"\");\n\n\t\treturn {\n\t\t\tid,\n\t\t\tfullImage,\n\t\t\tresizedImageUrl,\n\t\t\ttags,\n\t\t\tcreatedAt,\n\t\t\tpublishedBy,\n\t\t\trating,\n\t\t\tsizes: {\n\t\t\t\taspect: dimension?.getAspectRatio(),\n\t\t\t\twidth: dimension?.getWidthInPx(),\n\t\t\t\theight: dimension?.getHeightInPx(),\n\t\t\t\twidthRem: dimension?.getWidthInRem(),\n\t\t\t\theightRem: dimension?.getHeightInRem(),\n\t\t\t\tfullSize: dimension ? dimension.getWidthInPx() * dimension.getHeightInPx() : undefined,\n\t\t\t\tformatted: `${dimension?.getWidthInPx()}x${dimension?.getHeightInPx()}`,\n\t\t\t},\n\t\t\tcomments,\n\t\t};\n\t};\n};\n\n/**\n * Configuration options for the Rule34 client.\n */\nexport interface R34Options {\n\t/**\n\t * Custom base URL for the Rule34 website.\n\t */\n\tbaseUrl?: string;\n\n\t/**\n\t * Custom API URL for Rule34 autocomplete functionality.\n\t */\n\tapiUrl?: string;\n}\n\n/**\n * Represents a single search result from Rule34.\n */\nexport interface R3SearchResult {\n\t/**\n\t * The unique identifier of the image.\n\t */\n\tid: string;\n\n\t/**\n\t * The URL of the image.\n\t */\n\timage: string;\n\n\t/**\n\t * Array of tags associated with the image.\n\t */\n\ttags: string[];\n\n\t/**\n\t * The type of the result, always \"preview\" for search results.\n\t */\n\ttype: \"preview\";\n}\n\n/**\n * Represents a comment on a Rule34 image.\n */\nexport interface R34Comment {\n\t/**\n\t * The unique identifier of the comment.\n\t */\n\tid?: string;\n\n\t/**\n\t * The username of the commenter.\n\t */\n\tuser: string;\n\n\t/**\n\t * The content of the comment.\n\t */\n\tcomment: string;\n}\n\n/**\n * Represents size information for a Rule34 image.\n */\nexport interface R34ImageSizes {\n\t/**\n\t * The aspect ratio of the image (e.g., \"16:9\").\n\t */\n\taspect?: string;\n\n\t/**\n\t * The width of the image in pixels.\n\t */\n\twidth?: number;\n\n\t/**\n\t * The height of the image in pixels.\n\t */\n\theight?: number;\n\n\t/**\n\t * The width of the image in rem units.\n\t */\n\twidthRem?: number;\n\n\t/**\n\t * The height of the image in rem units.\n\t */\n\theightRem?: number;\n\n\t/**\n\t * The total number of pixels in the image (width × height).\n\t */\n\tfullSize?: number;\n\n\t/**\n\t * The formatted dimensions of the image (e.g., \"1920x1080\").\n\t */\n\tformatted?: string;\n}\n\n/**\n * Represents detailed information about a Rule34 image.\n */\nexport interface R34ImageInfo {\n\t/**\n\t * The unique identifier of the image.\n\t */\n\tid: string;\n\n\t/**\n\t * The URL of the full-size image.\n\t */\n\tfullImage?: string;\n\n\t/**\n\t * The URL of the resized image.\n\t */\n\tresizedImageUrl?: string;\n\n\t/**\n\t * Array of tags associated with the image.\n\t */\n\ttags?: string[];\n\n\t/**\n\t * The timestamp when the image was created/posted.\n\t */\n\tcreatedAt: number;\n\n\t/**\n\t * The username of the person who published the image.\n\t */\n\tpublishedBy: string;\n\n\t/**\n\t * The content rating of the image (e.g., \"Safe\", \"Questionable\", \"Explicit\").\n\t */\n\trating: string;\n\n\t/**\n\t * Size information about the image.\n\t */\n\tsizes: R34ImageSizes;\n\n\t/**\n\t * Array of comments on the image.\n\t */\n\tcomments: R34Comment[];\n}\n\n/**\n * Represents a paginated search result from Rule34.\n */\nexport type R34SearchResult = PaginatedResult<R3SearchResult>;\n","export class Dimension {\n\tprivate width: number;\n\tprivate height: number;\n\n\tconstructor(width: number, height: number) {\n\t\tthis.width = width;\n\t\tthis.height = height;\n\t}\n\n\tpublic getAspectRatio(): string {\n\t\tconst gcd = this.gcd(this.width, this.height);\n\t\treturn `${this.width / gcd}:${this.height / gcd}`;\n\t}\n\n\tpublic getWidthInPx(): number {\n\t\treturn this.width;\n\t}\n\n\tpublic getHeightInPx(): number {\n\t\treturn this.height;\n\t}\n\n\tpublic getWidthInRem(baseFontSize = 16): number {\n\t\treturn this.width / baseFontSize;\n\t}\n\n\tpublic getHeightInRem(baseFontSize = 16): number {\n\t\treturn this.height / baseFontSize;\n\t}\n\n\tprivate gcd(a: number, b: number): number {\n\t\tif (b === 0) {\n\t\t\treturn a;\n\t\t}\n\t\treturn this.gcd(b, a % b);\n\t}\n\n\tpublic static fromString(dimensionString: string): Dimension | null {\n\t\tconst [width, height] = dimensionString.split(\"x\").map(Number);\n\t\tif (Number.isNaN(width) || Number.isNaN(height) || width <= 0 || height <= 0) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new Dimension(width, height);\n\t}\n}\n"],"mappings":"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","names":["import_cheerio","id","title","released","import_cheerio","import_cheerio","id"]}