fast-dirpy 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,12 +25,19 @@ A simple library/CLI to download youtube(etc.) videos.
25
25
  - [Hanime1.me](https://hanime1.me/)
26
26
  - [wow.xxx](https://www.wow.xxx/)
27
27
  - [xhamster](https://xhamster.com/) (m3u8, retry if error)
28
- - [rule34.xyz](https://rule34.xyz/) (anime style)
29
- </details>
28
+ - [rule34.xyz](https://rule34.xyz/) (2d/3d videos)
30
29
 
31
- And `.m3u8` videos.
30
+ > [!WARNING]
31
+ > MissAV has a cloudflare challenge page which can't be bypassed using puppeteer/playwright, so you need to download the html page manually
32
+ > (no js and css needed, only html), then pass the local file path to extract m3u8 source.
33
+ > `fast-dirpy download --json '[{"url": "missav:/home/xxx/Downloads/xxx.html", "path": "./msav-test.mp4"}]'`
34
+ >
35
+ > And this method is unstable, sometimes you'll get http 429.
32
36
 
33
- You can use this [userscript](https://greasyfork.org/zh-CN/scripts/449581-m3u8%E8%A7%86%E9%A2%91%E4%BE%A6%E6%B5%8B%E4%B8%8B%E8%BD%BD%E5%99%A8-%E8%87%AA%E5%8A%A8%E5%97%85%E6%8E%A2) to extract `.m3u8` sources from websites.
37
+ - [missav](https://missav.ws/)
38
+ </details>
39
+
40
+ And `.m3u8` videos.
34
41
 
35
42
  ## Installation
36
43
 
package/dist/cli.mjs CHANGED
@@ -1 +1 @@
1
- import{C as e,D as t,O as n,_ as r,a as i,b as a,c as o,d as s,g as c,h as l,i as u,l as d,m as f,n as p,o as m,p as h,r as g,t as _,u as v,v as y,w as b}from"./judgeUrl-f5ejW-iH.mjs";import{bold as x,dim as S}from"ansis";import{cac as C}from"cac";import w from"restore-cursor";import T from"fs/promises";const E=C(`fast-dirpy`),{version:D}=t;E.command(`get <url>`,`get video direct link.`).option(`--proxyHost, -H <proxyHost>`,`Proxy host.`).option(`--proxyPort, -P <proxyPort>`,`Proxy port.`).option(`--config, -c <path>`,`Specify an external config file.`).option(`--silent`,`Suppress non-error logs`).option(`--chromePath`,`Path to your Google Chrome browser`).action(async(t,n)=>{let r=_(t),{proxyHost:i,proxyPort:a,config:o,silent:s,chromePath:l}=n,d=i?{proxy:{host:i,port:a}}:void 0,h=l?{puppeteer:{executablePath:l}}:void 0;if(b(!!s),e.info(`fast-dirpy ${S(`v${D}`)} : ${x(`Direct Link Getter`)}.`),r===p.AnimeIdHentai){e.info(`Matched link source: Animeidhentai.`);let n=await y({url:t,cwd:o},{...d,...h});console.log(n)}else if(r===p.KoreanPM){e.info(`Matched link source: KoreanPM.`);let n=await v({url:t,cwd:o},d);console.log(n)}else if(r===p.Wowxxx){e.info(`Matched link source: Wowxxx.`);let n=await m({url:t,cwd:o},d);console.log(n)}else if(r===p.XHamster){e.info(`Matched link source: XHamster.`);let n=await u({url:t,cwd:o},d);console.log(n)}else if(r===p.Bilibili){if(e.info(`Matched link source: Bilibili.`),!t.includes(`bilibili.com`)){e.error(`Please provide a valid Bilibili URL.`);return}let n=c(t);console.log(n)}else if(r===p.Dirpy){e.info(`Matched link source: Dirpy.`);let n=await f({url:t,cwd:o},d);console.log(n)}else e.error(`Your link is not supported!`)}),E.command(`download`,`download a video.`).option(`--json, -j <json>`,`JSON download params.`).option(`--jsonFile, -F <jsonFile>`,`Path to a JSON file containing download params.`).option(`--proxyHost, -H <proxyHost>`,`Proxy host.`).option(`--proxyPort, -P <proxyPort>`,`Proxy port.`).option(`--config, -c <path>`,`Specify an external config file.`).option(`--silent`,`Suppress non-error logs`).option(`--chromePath`,`Path to your Google Chrome browser`).action(async t=>{let{json:n,jsonFile:c}=t;if(!n&&!c){e.error(`No JSON params provided.`);return}let u=await(async(e,t)=>{if(e)return JSON.parse(e);if(t){let e=await T.readFile(t,`utf-8`);return JSON.parse(e)}})(n,c);if(Array.isArray(u)||(u=[u]),u.length<1){e.error(`No params provided.`);return}let{proxyHost:f,proxyPort:m,config:v,silent:y,chromePath:C}=t,w=f?{proxy:{host:f,port:m}}:void 0,E=C?{puppeteer:{executablePath:C}}:void 0;b(!!y),e.info(`fast-dirpy ${S(`v${D}`)} : ${x(`Video Downloader`)}.`);for(let e of u)e.urlType=_(e.url),e.cwd=v;let O=u.filter(e=>e.urlType===p.Bilibili),k=u.filter(e=>e.urlType===p.AnimeIdHentai),A=u.filter(e=>e.urlType===p.KoreanPM),j=u.filter(e=>e.urlType===p.Hanime),M=u.filter(e=>e.urlType===p.Wowxxx),N=u.filter(e=>e.urlType===p.XHamster),P=u.filter(e=>e.urlType===p.Dirpy),F=u.filter(e=>e.urlType===p.MP4),I=u.filter(e=>e.urlType===p.M3U8);O.length>0&&await l(O),k.length>0&&await r(k,{...w,...E}),A.length>0&&await d(A,{...w,...E}),j.length>0&&await s(j,{...w,...E}),M.length>0&&await i(M,{...w,...E}),N.length>0&&await g(N,{...w,...E}),P.length>0&&await h(P,{...w,...E}),F.length>0&&await a(F,{...w,...E}),I.length>0&&await o(I,{...w,...E})}),E.help(),E.version(n),E.parse(),w();export{};
1
+ import{A as e,E as t,S as n,T as r,_ as i,a,b as o,d as s,f as c,g as l,h as u,i as d,k as f,n as p,o as m,p as h,r as g,s as _,t as v,u as y,v as b,y as x}from"./judgeUrl-NeoaY5pF.mjs";import S from"node:fs/promises";import{bold as C,dim as w}from"ansis";import{cac as T}from"cac";import E from"restore-cursor";const D=T(`fast-dirpy`),{version:O}=f;D.command(`get <url>`,`get video direct link.`).option(`--proxyHost, -H <proxyHost>`,`Proxy host.`).option(`--proxyPort, -P <proxyPort>`,`Proxy port.`).option(`--config, -c <path>`,`Specify an external config file.`).option(`--silent`,`Suppress non-error logs`).option(`--chromePath`,`Path to your Google Chrome browser`).action(async(e,n)=>{let i=v(e),{proxyHost:a,proxyPort:s,config:u,silent:f,chromePath:h}=n,g=a?{proxy:{host:a,port:s}}:void 0,_=h?{puppeteer:{executablePath:h}}:void 0;if(t(!!f),r.info(`fast-dirpy ${w(`v${O}`)} : ${C(`Direct Link Getter`)}.`),i===p.AnimeIdHentai){r.info(`Matched link source: Animeidhentai.`);let t=await o({url:e,cwd:u},{...g,..._});console.log(t)}else if(i===p.KoreanPM){r.info(`Matched link source: KoreanPM.`);let t=await c({url:e,cwd:u},g);console.log(t)}else if(i===p.Wowxxx){r.info(`Matched link source: Wowxxx.`);let t=await m({url:e,cwd:u},g);console.log(t)}else if(i===p.XHamster){r.info(`Matched link source: XHamster.`);let t=await d({url:e,cwd:u},g);console.log(t)}else if(i===p.Bilibili){if(r.info(`Matched link source: Bilibili.`),!e.includes(`bilibili.com`)){r.error(`Please provide a valid Bilibili URL.`);return}let t=b(e);console.log(t)}else if(i===p.Dirpy){r.info(`Matched link source: Dirpy.`);let t=await l({url:e,cwd:u},g);console.log(t)}else r.error(`Your link is not supported!`)}),D.command(`download`,`download a video.`).option(`--json, -j <json>`,`JSON download params.`).option(`--jsonFile, -F <jsonFile>`,`Path to a JSON file containing download params.`).option(`--proxyHost, -H <proxyHost>`,`Proxy host.`).option(`--proxyPort, -P <proxyPort>`,`Proxy port.`).option(`--config, -c <path>`,`Specify an external config file.`).option(`--silent`,`Suppress non-error logs`).option(`--chromePath`,`Path to your Google Chrome browser`).action(async e=>{let{json:o,jsonFile:c}=e;if(!o&&!c){r.error(`No JSON params provided.`);return}let l=await(async(e,t)=>{if(e)return JSON.parse(e);if(t){let e=await S.readFile(t,`utf-8`);return JSON.parse(e)}})(o,c);if(Array.isArray(l)||(l=[l]),l.length<1){r.error(`No params provided.`);return}let{proxyHost:d,proxyPort:f,config:m,silent:b,chromePath:T}=e,E=d?{proxy:{host:d,port:f}}:void 0,D=T?{puppeteer:{executablePath:T}}:void 0;t(!!b),r.info(`fast-dirpy ${w(`v${O}`)} : ${C(`Video Downloader`)}.`);for(let e of l)e.urlType=v(e.url),e.cwd=m;let k=l.filter(e=>e.urlType===p.Bilibili),A=l.filter(e=>e.urlType===p.AnimeIdHentai),j=l.filter(e=>e.urlType===p.KoreanPM),M=l.filter(e=>e.urlType===p.Hanime),N=l.filter(e=>e.urlType===p.Wowxxx),P=l.filter(e=>e.urlType===p.XHamster),F=l.filter(e=>e.urlType===p.Dirpy),I=l.filter(e=>e.urlType===p.MP4),L=l.filter(e=>e.urlType===p.M3U8),R=l.filter(e=>e.urlType===p.MissAV);k.length>0&&await i(k),A.length>0&&await x(A,{...E,...D}),j.length>0&&await s(j,{...E,...D}),M.length>0&&await h(M,{...E,...D}),N.length>0&&await a(N,{...E,...D}),P.length>0&&await g(P,{...E,...D}),R.length>0&&await _(R,{...E}),F.length>0&&await u(F,{...E,...D}),I.length>0&&await n(I,{...E,...D}),L.length>0&&await y(L,{...E,...D})}),D.help(),D.version(e),D.parse(),E();export{};
@@ -13,8 +13,9 @@ interface Options {
13
13
  };
14
14
  }
15
15
  interface DirectLinkParams {
16
- url: string;
16
+ url?: string;
17
17
  cwd?: string;
18
+ missavHtmlPage?: string;
18
19
  }
19
20
  interface DownloadParams {
20
21
  url: string;
@@ -34,9 +35,11 @@ declare enum UrlType {
34
35
  M3U8 = 3,
35
36
  KoreanPM = 4,
36
37
  Hanime = 5,
37
- Wowxxx = 6,
38
- XHamster = 7,
39
- MP4 = 8
38
+ MissAV = 6,
39
+ NJavTV = 7,
40
+ Wowxxx = 8,
41
+ XHamster = 9,
42
+ MP4 = 10
40
43
  }
41
44
  //#endregion
42
45
  //#region src/config.d.ts
package/dist/config.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { t as defineConfig } from "./config-pHnrv5F6.mjs";
1
+ import { t as defineConfig } from "./config-Cce0JT9r.mjs";
2
2
  export { defineConfig };
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as Options, i as M3U8Params, n as DirectLinkParams, o as UrlType, r as DownloadParams, t as defineConfig } from "./config-pHnrv5F6.mjs";
1
+ import { a as Options, i as M3U8Params, n as DirectLinkParams, o as UrlType, r as DownloadParams, t as defineConfig } from "./config-Cce0JT9r.mjs";
2
2
 
3
3
  //#region src/constants.d.ts
4
4
  declare const DEFAULT_OPTIONS: Options;
@@ -57,6 +57,14 @@ declare function remoteM3U8ToMP4(params: M3U8Params, options?: Partial<Options>,
57
57
  */
58
58
  declare function remoteM3U8ToMP4Parallel(paramsList: M3U8Params[], options?: Partial<Options>, maxConcurrent?: number, onProgress?: (progress: ParallelM3U8Progress) => void, onDownloadProgress?: (identifier: string, progress: M3U8DownloadProgress) => void): Promise<void[]>;
59
59
  //#endregion
60
+ //#region src/core/missav.d.ts
61
+ declare function getMissavLink(params: DirectLinkParams, options?: Partial<Options>): Promise<string | null>;
62
+ declare function downloadMissav(params: DownloadParams | DownloadParams[], options?: Partial<Options>): Promise<void>;
63
+ //#endregion
64
+ //#region src/core/rule34xyz.d.ts
65
+ declare function getRule34XyzVideoLink(params: DirectLinkParams, options?: Partial<Options>): Promise<string>;
66
+ declare function downloadRule34XyzVideo(params: DownloadParams | DownloadParams[], options?: Partial<Options>): Promise<void>;
67
+ //#endregion
60
68
  //#region src/core/wowxxx.d.ts
61
69
  declare function getWowxxxLink(params: DirectLinkParams, options?: Partial<Options>): Promise<Record<string, any>[]>;
62
70
  declare function downloadWowxxx(params: DownloadParams | DownloadParams[], options?: Partial<Options>): Promise<void>;
@@ -65,10 +73,6 @@ declare function downloadWowxxx(params: DownloadParams | DownloadParams[], optio
65
73
  declare function getXHamsterLink(params: DirectLinkParams, options?: Partial<Options>): Promise<string>;
66
74
  declare function downloadXHamster(params: DownloadParams | DownloadParams[], options?: Partial<Options>): Promise<void>;
67
75
  //#endregion
68
- //#region src/core/rule34xyz.d.ts
69
- declare function getRule34XyzVideoLink(params: DirectLinkParams, options?: Partial<Options>): Promise<string>;
70
- declare function downloadRule34XyzVideo(params: DownloadParams | DownloadParams[], options?: Partial<Options>): Promise<void>;
71
- //#endregion
72
76
  //#region src/utils/downloader.d.ts
73
77
  declare function downloadVideo(params: DownloadParams, options?: Partial<Options>): Promise<void>;
74
78
  interface ParallelDownloadProgress {
@@ -94,4 +98,4 @@ declare function downloadVideosParallel(paramsList: DownloadParams[], options?:
94
98
  declare function fastLink(params: DirectLinkParams, options?: Partial<Options>): Promise<string | Record<string, any>[]>;
95
99
  declare function fastDownload(params: DownloadParams | DownloadParams[], options?: Partial<Options>): Promise<void>;
96
100
  //#endregion
97
- export { DEFAULT_OPTIONS, DirectLinkParams, DownloadParams, M3U8DownloadProgress, M3U8Params, Options, ParallelDownloadProgress, ParallelM3U8Progress, UrlType, __dirname, defineConfig, downloadAnimeIdHentai, downloadBilibili, downloadDirpy, downloadHanime, downloadKoreanPm, downloadRule34XyzVideo, downloadVideo, downloadVideosParallel, downloadWowxxx, downloadXHamster, fastDownload, fastLink, getAnimeIdHentaiLink, getBilibiliLink, getDirpyLink, getHanimeLink, getKoreanPmLink, getRule34XyzVideoLink, getWowxxxLink, getXHamsterLink, remoteM3U8ToMP4, remoteM3U8ToMP4Parallel };
101
+ export { DEFAULT_OPTIONS, DirectLinkParams, DownloadParams, M3U8DownloadProgress, M3U8Params, Options, ParallelDownloadProgress, ParallelM3U8Progress, UrlType, __dirname, defineConfig, downloadAnimeIdHentai, downloadBilibili, downloadDirpy, downloadHanime, downloadKoreanPm, downloadMissav, downloadRule34XyzVideo, downloadVideo, downloadVideosParallel, downloadWowxxx, downloadXHamster, fastDownload, fastLink, getAnimeIdHentaiLink, getBilibiliLink, getDirpyLink, getHanimeLink, getKoreanPmLink, getMissavLink, getRule34XyzVideoLink, getWowxxxLink, getXHamsterLink, remoteM3U8ToMP4, remoteM3U8ToMP4Parallel };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{C as e,D as t,E as n,S as r,T as i,_ as a,a as o,b as s,c,d as l,f as u,g as d,h as f,i as p,l as m,m as h,n as g,o as _,p as v,r as y,s as b,t as x,u as S,v as C,x as w,y as T}from"./judgeUrl-f5ejW-iH.mjs";import{defineConfig as E}from"./config.mjs";import{bold as D,dim as O}from"ansis";import k from"axios";import{load as A}from"cheerio";async function j(e,t=i){let{url:n,cwd:a}=e,{proxy:o,timeout:s}=await r(t,a),c=o?.host===``?void 0:o,{data:l}=await k.get(n,{headers:{"User-Agent":w(),Referer:`https://rule34.xyz`},proxy:c,timeout:s}),u=A(l),d=``,f=u(`source[type="video/mp4"]`).attr();return f&&(d=`https://rule34.xyz${f.src.replace(`mov480`,`mov`)}`),d}async function M(e,t=i){Array.isArray(e)||(e=[e]);let n=[];for(let r of e){let e=await j({url:r.url,cwd:r.cwd},t);n.push({...r,url:e})}await s(n)}const{version:N}=t;async function P(t,n=i){let{url:r,cwd:a}=t,{proxy:o,puppeteer:s}=n,c=o||{},l=s||{},f=x(r);return e.info(`fast-dirpy ${O(`v${N}`)} : ${D(`Direct Link Getter`)}.`),f===g.Bilibili?(e.info(`Matched link source: Bilibili.`),r.includes(`bilibili.com`)?await d({url:r,cwd:a}):(e.error(`Please provide a valid Bilibili URL.`),``)):f===g.AnimeIdHentai?(e.info(`Matched link source: Animeidhentai.`),await C({url:r,cwd:a},{...c,...l})):f===g.KoreanPM?(e.info(`Matched link source: KoreanPM.`),await S({url:r,cwd:a},c)):f===g.Hanime?(e.info(`Matched link source: Hanime.`),await u({url:r,cwd:a},c)):f===g.Wowxxx?(e.info(`Matched link source: Wowxxx.`),await _({url:r,cwd:a},c)):f===g.XHamster?(e.info(`Matched link source: XHamster.`),await p({url:r,cwd:a},c)):f===g.Dirpy?(e.info(`Matched link source: Dirpy.`),await h({url:r,cwd:a},c)):(e.error(`Your link is not supported!`),``)}async function F(t,n=i){if(Array.isArray(t)||(t=[t]),t.length<1){e.error(`No valid params provided.`);return}let{proxy:r,puppeteer:u}=n,d=r||{},p=u||{};for(let e of t)e.urlType=x(e.url);e.info(`fast-dirpy ${O(`v${N}`)} : ${D(`Video Downloader`)}.`);let h=t.filter(e=>e.urlType===g.Bilibili),_=t.filter(e=>e.urlType===g.AnimeIdHentai),b=t.filter(e=>e.urlType===g.KoreanPM),S=t.filter(e=>e.urlType===g.Hanime),C=t.filter(e=>e.urlType===g.Wowxxx),w=t.filter(e=>e.urlType===g.XHamster),T=t.filter(e=>e.urlType===g.Dirpy),E=t.filter(e=>e.urlType===g.MP4),k=t.filter(e=>e.urlType===g.M3U8);h.length>0&&await f(h),_.length>0&&await a(_,{...d,...p}),b.length>0&&await m(b,{...d,...p}),S.length>0&&await l(S,{...d,...p}),C.length>0&&await o(C,{...d,...p}),w.length>0&&await y(w,{...d,...p}),T.length>0&&await v(T,{...d,...p}),E.length>0&&await s(E,{...d,...p}),k.length>0&&await c(k,{...d,...p})}export{i as DEFAULT_OPTIONS,g as UrlType,n as __dirname,E as defineConfig,a as downloadAnimeIdHentai,f as downloadBilibili,v as downloadDirpy,l as downloadHanime,m as downloadKoreanPm,M as downloadRule34XyzVideo,T as downloadVideo,s as downloadVideosParallel,o as downloadWowxxx,y as downloadXHamster,F as fastDownload,P as fastLink,C as getAnimeIdHentaiLink,d as getBilibiliLink,h as getDirpyLink,u as getHanimeLink,S as getKoreanPmLink,j as getRule34XyzVideoLink,_ as getWowxxxLink,p as getXHamsterLink,b as remoteM3U8ToMP4,c as remoteM3U8ToMP4Parallel};
1
+ import{C as e,D as t,O as n,S as r,T as i,_ as a,a as o,b as s,c,d as l,f as u,g as d,h as f,i as p,k as m,l as h,m as g,n as _,o as v,p as y,r as b,s as x,t as S,u as C,v as w,w as T,x as E,y as D}from"./judgeUrl-NeoaY5pF.mjs";import{defineConfig as O}from"./config.mjs";import{bold as k,dim as A}from"ansis";import j from"axios";import{load as M}from"cheerio";async function N(n,r=t){let{url:i,cwd:a}=n,{proxy:o,timeout:s}=await T(r,a),c=o?.host===``?void 0:o,{data:l}=await j.get(i,{headers:{"User-Agent":e(),Referer:`https://rule34.xyz`},proxy:c,timeout:s}),u=M(l),d=``,f=u(`source[type="video/mp4"]`).attr();return f&&(d=`https://rule34.xyz${f.src.replace(`mov480`,`mov`)}`),d}async function P(e,n=t){Array.isArray(e)||(e=[e]);let i=[];for(let t of e){let e=await N({url:t.url,cwd:t.cwd},n);i.push({...t,url:e})}await r(i)}const{version:F}=m;async function I(e,n=t){let{url:r,cwd:a}=e,{proxy:o,puppeteer:c}=n,l=o||{},f=c||{},m=S(r);return i.info(`fast-dirpy ${A(`v${F}`)} : ${k(`Direct Link Getter`)}.`),m===_.Bilibili?(i.info(`Matched link source: Bilibili.`),r.includes(`bilibili.com`)?await w({url:r,cwd:a}):(i.error(`Please provide a valid Bilibili URL.`),``)):m===_.AnimeIdHentai?(i.info(`Matched link source: Animeidhentai.`),await s({url:r,cwd:a},{...l,...f})):m===_.KoreanPM?(i.info(`Matched link source: KoreanPM.`),await u({url:r,cwd:a},l)):m===_.Hanime?(i.info(`Matched link source: Hanime.`),await g({url:r,cwd:a},l)):m===_.Wowxxx?(i.info(`Matched link source: Wowxxx.`),await v({url:r,cwd:a},l)):m===_.XHamster?(i.info(`Matched link source: XHamster.`),await p({url:r,cwd:a},l)):m===_.Dirpy?(i.info(`Matched link source: Dirpy.`),await d({url:r,cwd:a},l)):(i.error(`Your link is not supported!`),``)}async function L(e,n=t){if(Array.isArray(e)||(e=[e]),e.length<1){i.error(`No valid params provided.`);return}let{proxy:s,puppeteer:c}=n,u=s||{},d=c||{};for(let t of e)t.urlType=S(t.url);i.info(`fast-dirpy ${A(`v${F}`)} : ${k(`Video Downloader`)}.`);let p=e.filter(e=>e.urlType===_.Bilibili),m=e.filter(e=>e.urlType===_.AnimeIdHentai),h=e.filter(e=>e.urlType===_.KoreanPM),g=e.filter(e=>e.urlType===_.Hanime),v=e.filter(e=>e.urlType===_.Wowxxx),w=e.filter(e=>e.urlType===_.XHamster),T=e.filter(e=>e.urlType===_.Dirpy),E=e.filter(e=>e.urlType===_.MP4),O=e.filter(e=>e.urlType===_.M3U8),j=e.filter(e=>e.urlType===_.MissAV);p.length>0&&await a(p),m.length>0&&await D(m,{...u,...d}),h.length>0&&await l(h,{...u,...d}),g.length>0&&await y(g,{...u,...d}),v.length>0&&await o(v,{...u,...d}),w.length>0&&await b(w,{...u,...d}),j.length>0&&await x(j,{...u}),T.length>0&&await f(T,{...u,...d}),E.length>0&&await r(E,{...u,...d}),O.length>0&&await C(O,{...u,...d})}export{t as DEFAULT_OPTIONS,_ as UrlType,n as __dirname,O as defineConfig,D as downloadAnimeIdHentai,a as downloadBilibili,f as downloadDirpy,y as downloadHanime,l as downloadKoreanPm,x as downloadMissav,P as downloadRule34XyzVideo,E as downloadVideo,r as downloadVideosParallel,o as downloadWowxxx,b as downloadXHamster,L as fastDownload,I as fastLink,s as getAnimeIdHentaiLink,w as getBilibiliLink,d as getDirpyLink,g as getHanimeLink,u as getKoreanPmLink,c as getMissavLink,N as getRule34XyzVideoLink,v as getWowxxxLink,p as getXHamsterLink,h as remoteM3U8ToMP4,C as remoteM3U8ToMP4Parallel};
@@ -0,0 +1 @@
1
+ import{readFile as e}from"node:fs/promises";import t from"axios";import{load as n}from"cheerio";import r from"node:path";import{fileURLToPath as i}from"node:url";import{createConfigLoader as a}from"unconfig";import o from"node:process";import{consola as s}from"consola";import c,{createWriteStream as l}from"node:fs";import u from"puppeteer-core";import d from"m3u8stream";var f=Object.create,p=Object.defineProperty,m=Object.getOwnPropertyDescriptor,h=Object.getOwnPropertyNames,g=Object.getPrototypeOf,_=Object.prototype.hasOwnProperty,v=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),y=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=h(t),a=0,o=i.length,s;a<o;a++)s=i[a],!_.call(e,s)&&s!==n&&p(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=m(t,s))||r.enumerable});return e},ee=(e,t,n)=>(n=e==null?{}:f(g(e)),y(t||!e||!e.__esModule?p(n,`default`,{value:e,enumerable:!0}):n,e)),b=`1.0.1`,x={name:`fast-dirpy`,type:`module`,version:b,description:`A simple library/CLI to download video from several websites.`,author:`Vincent-the-gamer`,license:`MIT`,homepage:`https://github.com/Vincent-the-gamer/fast-dirpy#readme`,repository:{type:`git`,url:`git+https://github.com/Vincent-the-gamer/fast-dirpy.git`},bugs:{url:`https://github.com/Vincent-the-gamer/fast-dirpy/issues`},sideEffects:!1,main:`dist/index.mjs`,module:`dist/index.mjs`,types:`dist/index.d.mts`,typesVersions:{"*":{".":[`./dist/index.d.mts`,`./dist/cli.d.mts`]}},bin:{"fast-dirpy":`bin/fast-dirpy.js`},files:[`dist`],scripts:{tsx:`tsx`,build:`tsdown`,test:`vitest`,dep:`taze major -I`,"lint:fix":`eslint . --fix`,login:`pnpm login --registry https://registry.npmjs.com`},publishConfig:{registry:`https://registry.npmjs.com`,access:`public`},dependencies:{ansis:`^4.2.0`,axios:`^1.14.0`,cac:`^7.0.0`,cheerio:`^1.2.0`,consola:`^3.4.2`,m3u8stream:`^0.8.6`,"puppeteer-core":`^24.40.0`,"restore-cursor":`^5.1.0`,unconfig:`^7.5.0`},devDependencies:{"@antfu/eslint-config":`^8.0.0`,"@types/node":`^25.5.2`,deepmerge:`^4.3.1`,eslint:`^10.2.0`,taze:`^19.11.0`,tsdown:`^0.21.7`,tsx:`^4.21.0`,typescript:`^6.0.2`,vitest:`^4.1.2`}};const S={timeout:2e4},C=i(import.meta.url),w=r.dirname(C);var T=v(((e,t)=>{var n=function(e){return r(e)&&!i(e)};function r(e){return!!e&&typeof e==`object`}function i(e){var t=Object.prototype.toString.call(e);return t===`[object RegExp]`||t===`[object Date]`||o(e)}var a=typeof Symbol==`function`&&Symbol.for?Symbol.for(`react.element`):60103;function o(e){return e.$$typeof===a}function s(e){return Array.isArray(e)?[]:{}}function c(e,t){return t.clone!==!1&&t.isMergeableObject(e)?g(s(e),e,t):e}function l(e,t,n){return e.concat(t).map(function(e){return c(e,n)})}function u(e,t){if(!t.customMerge)return g;var n=t.customMerge(e);return typeof n==`function`?n:g}function d(e){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter(function(t){return Object.propertyIsEnumerable.call(e,t)}):[]}function f(e){return Object.keys(e).concat(d(e))}function p(e,t){try{return t in e}catch{return!1}}function m(e,t){return p(e,t)&&!(Object.hasOwnProperty.call(e,t)&&Object.propertyIsEnumerable.call(e,t))}function h(e,t,n){var r={};return n.isMergeableObject(e)&&f(e).forEach(function(t){r[t]=c(e[t],n)}),f(t).forEach(function(i){m(e,i)||(p(e,i)&&n.isMergeableObject(t[i])?r[i]=u(i,n)(e[i],t[i],n):r[i]=c(t[i],n))}),r}function g(e,t,r){r||={},r.arrayMerge=r.arrayMerge||l,r.isMergeableObject=r.isMergeableObject||n,r.cloneUnlessOtherwiseSpecified=c;var i=Array.isArray(t);return i===Array.isArray(e)?i?r.arrayMerge(e,t,r):h(e,t,r):c(t,r)}g.all=function(e,t){if(!Array.isArray(e))throw Error(`first argument should be an array`);return e.reduce(function(e,n){return g(e,n,t)},{})},t.exports=g}));const E=s.withTag(`fast-dirpy`);function te(e){`CONSOLA_LEVEL`in o.env||(E.level=e?0:3)}var D=ee(T(),1);async function O(e,t){let n=S,{config:r,sources:i}=await a({sources:[{files:[`fast-dirpy.config`],extensions:[`ts`,`mts`,`cts`,`js`,`mjs`,`cjs`,`json`]}],cwd:t||process.cwd(),merge:!1}).load();return i.length?(E.info(`Config file found: ${i[0]}`),(0,D.default)((0,D.default)(n,r),e)):(0,D.default)(n,e)}function k(e){return e[Math.floor(Math.random()*e.length)]}const A=[`Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10`,`Mozilla/5.0 (Windows NT 6.1; rv,2.0.1) Gecko/20100101 Firefox/4.0.1`,`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36`,`Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36`,`Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.11 (KHTML, like Gecko) Ubuntu/11.10 Chromium/27.0.1453.93 Chrome/27.0.1453.93 Safari/537.36`];function j(){return k(A)}function M(e){return`[${e.url.split(`/`).pop()||`unknown`}]`}async function N(e,n=S){let{path:r,url:i}=e,a=M(e),{proxy:o,timeout:s}=await O(n),l=o?.host===``?void 0:o;if(i===``)return Promise.reject(Error(`Extract direct link failed!`));let u=c.createWriteStream(r||`./download.mp4`);return(await t({url:i,headers:{"User-Agent":j(),...n.headers},method:`GET`,responseType:`stream`,proxy:l,timeout:s,onDownloadProgress:e=>{let{loaded:t,total:n,progress:r}=e,i=`[${a??``}] loaded:${t} total: ${n} progress: ${(r*100).toFixed(2)}%`;E.info(i)}})).data.pipe(u),new Promise((e,t)=>{u.on(`finish`,e),u.on(`error`,t)})}async function P(e,t=S,n=5,r){let i=[],a=new Set,o=0,s=0,c=e.length;E.info(`Starting parallel downloads: ${c} videos, max concurrent: ${n}`);for(let[l,u]of e.entries()){let e=M(u),d=N(u,t).then(t=>(o++,a.delete(d),E.info(`${l+1}/${c} ${e} Download completed`),r?.({total:c,completed:o,failed:s,currentParams:u,identifier:e,status:`success`}),t)).catch(t=>{s++,a.delete(d);let n=t instanceof Error?t.message:String(t);return E.error(`${e} Download failed: ${n}`),r?.({total:c,completed:o,failed:s,currentParams:u,identifier:e,status:`failed`,error:t}),Promise.resolve()});i.push(d),a.add(d),a.size>=n&&await Promise.race(a)}let l=await Promise.allSettled(i);return E.info(`Parallel downloads finished. Success: ${o}, Failed: ${s}, Total: ${c}`),l.filter(e=>e.status===`fulfilled`).map(e=>e.value)}async function F(e){return await u.launch(e)}async function ne(e,r=S){let{url:i,cwd:a}=e,{proxy:o,timeout:s}=await O(r,a),c=o?.host===``?void 0:o,{data:l}=await t.get(i,{headers:{"User-Agent":j()},proxy:c,timeout:s}),u=n(l),d=``,f=u(`div.embed.rad2 > iframe`).attr();return f&&(d=f.src),d}async function I(e,t=S){let{url:n,cwd:r}=e,{proxy:i,puppeteer:a}=await O(t,r),o=i?.host===``?void 0:i,s=await ne({url:n},{proxy:o}),{executablePath:c,headless:l}=a,u=await F({executablePath:c,headless:l,args:[`--proxy-server=http://${o?.host}:${i?.port}`]}),d=j(),f=await u.newPage();await f.setUserAgent(d),await f.goto(s),await f.waitForSelector(`div.play.p-pulse`),await f.click(`div.play.p-pulse`),await f.waitForSelector(`div.frame > iframe`);let p=await f.$eval(`div.frame > iframe`,e=>e.src),m=await u.newPage();await m.goto(`${p}`),await m.waitForSelector(`video.jw-video.jw-reset`);let h=await m.$eval(`video.jw-video.jw-reset`,e=>e.src);return await u.close(),h}async function re(e,t=S){Array.isArray(e)||(e=[e]);let n=[];for(let r of e){let{url:e,cwd:i}=r,a=await I({url:e,cwd:i},t);n.push({...r,url:a})}n.length>0&&await P(n)}async function L(e,t=S){let{url:n,cwd:r}=e,{proxy:i,puppeteer:a}=await O(t,r),o=i?.host===``?void 0:i,{executablePath:s,headless:c}=a,l=await F({executablePath:s,headless:c,args:[`--proxy-server=http://${o?.host}:${i?.port}`,`--disable-features=IsolateOrigins,site-per-process`,`--disable-site-isolation-trials`,`--disable-web-security`,`--disable-setuid-sandbox`,`--no-sandbox`,`--disable-gpu`,`--disable-dev-shm-usage`,`--disable-accelerated-2d-canvas`,`--no-first-run`,`--no-zygote`,`--window-size=1920,1080`],slowMo:10}),u=await l.newPage(),d=j();await u.setUserAgent(d);try{await u.goto(`https://snapany.com/zh/bilibili`),await u.waitForNetworkIdle();let e=`input[name='link']`;await u.waitForSelector(e),await u.type(e,n,{delay:10});let t=`button[type='submit']`;return await u.waitForSelector(t),await u.click(t),await u.waitForSelector(`div[data-testid="flowbite-card"]`),(await u.$$eval(`div[data-testid="flowbite-card"]`,e=>e.map(e=>{let t=e.querySelector(`a[href*=".mp4"]`)?.getAttribute(`href`)||``;return t=t.replace(/&amp;/g,`&`),{videoUrl:t}}))).filter(e=>e.videoUrl)[0]?.videoUrl}catch(e){E.error(`Error during scraping: ${e}`)}finally{E.info(`Closing browser`),await l.close()}}async function R(e){Array.isArray(e)||(e=[e]);let t=[];for(let n of e){let e=await L({url:n.url,cwd:n.cwd});t.push({...n,url:e})}await P(t)}async function z(e,r=S){let{url:i,cwd:a}=e,{proxy:o,timeout:s}=await O(r,a),c=o?.host===``?void 0:o,{data:l}=await t.get(`https://dirpy.com/studio`,{params:{url:i},headers:{"User-Agent":j(),Referer:`https://dirpy.com/studio?url=${i}`},proxy:c,timeout:s}),u=n(l),d=``,f=u(`#media-source`).attr();return f&&(d=f.src),d}async function B(e,t=S){Array.isArray(e)||(e=[e]);let n=[];for(let r of e){let e=await z({url:r.url,cwd:r.cwd},t);n.push({...r,url:e})}n.length>0&&await P(n)}function V(e,t){return Number(e.size)-Number(t.size)}async function H(e,r=S){let{url:i,cwd:a}=e,{proxy:o,timeout:s}=await O(r,a),c=o?.host===``?void 0:o,{data:l}=await t.get(i,{headers:{"User-Agent":j(),Referer:`https://hanime1.me/`},proxy:c,timeout:s}),u=n(l)(`source[type="video/mp4"]`);return Object.values(u).map(e=>e.attribs).filter(e=>e!=null).sort(V)}async function U(e,t=S){Array.isArray(e)||(e=[e]);let n=[];for(let r of e){let{url:e,cwd:i}=r,a=await H({url:e,cwd:i},t);a.length>0&&E.success(`Successfully get video sources, size ${a.at(-1).size} to be downloaded.`),n.push({...r,url:a.at(-1).src})}n.length>0&&await P(n)}async function W(e,r=S){let{url:i,cwd:a}=e,{proxy:o,timeout:s}=await O(r,a),c=o?.host===``?void 0:o,{data:l}=await t.get(i,{headers:{"User-Agent":j()},proxy:c,timeout:s}),u=n(l),d=``,f=u(`meta[itemprop="contentURL"]`).attr();return f&&(d=f.content),d}async function G(e,t=S){Array.isArray(e)||(e=[e]);let n=[];for(let r of e){let{url:e,cwd:i}=r,a=await W({url:e,cwd:i},t);n.push({...r,url:a})}n.length>0&&await P(n)}function K(e){return`[${e.url?.split(`/`).pop()||`unknown`}]`}async function q(e,t=S,n){let{url:i,cwd:a,path:o}=e,{proxy:s,timeout:c}=await O(t,a);if(!i)return Promise.reject(Error(`M3U8 URL is required!`));let u=K(e),f=o??r.resolve(w,`../m3u8-download.mp4`);return E.info(`${u} Starting M3U8 download from: ${i}`),E.info(`${u} Output path: ${f}`),new Promise((e,r)=>{try{let a=d(i,{requestOptions:{headers:t.headers,timeout:c,...s?.host?{proxy:`http://${s.host}:${s.port}`}:{}}}),o=l(f);a.on(`progress`,(e,t,r)=>{let i=r/1024/1024,a=t>0?e.num/t*100:0,o={segment:e,totalSegments:t,downloaded:r,downloadedMB:i,percent:a};E.info(`${u} Segment: ${e.num}/${t}, Downloaded: ${i.toFixed(2)}MB (${a.toFixed(2)}%)`),n?.(o)}),a.on(`error`,e=>{E.error(`${u} M3U8 stream error: ${e.message}`),o.end(),r(e)}),a.pipe(o),o.on(`finish`,()=>{E.info(`${u} M3U8 download completed successfully`),e()}),o.on(`error`,e=>{E.error(`${u} File write error: ${e.message}`),r(e)})}catch(e){let t=e instanceof Error?e.message:String(e);E.error(`${u} Failed to initialize M3U8 download: ${t}`),r(e)}})}async function J(e,t=S,n=3,r,i){let a=[],o=new Set,s=0,c=0,l=e.length;E.info(`Starting parallel M3U8 downloads: ${l} videos, max concurrent: ${n}`);for(let[u,d]of e.entries()){let e=K(d),f=q(d,t,t=>{i?.(e,t),r?.({total:l,completed:s,failed:c,currentParams:d,identifier:e,status:`downloading`,downloadProgress:t})}).then(t=>(s++,o.delete(f),E.info(`${u+1}/${l} ${e} M3U8 download completed`),r?.({total:l,completed:s,failed:c,currentParams:d,identifier:e,status:`success`}),t)).catch(t=>{c++,o.delete(f);let n=t instanceof Error?t.message:String(t);return E.error(`${e} M3U8 download failed: ${n}`),r?.({total:l,completed:s,failed:c,currentParams:d,identifier:e,status:`failed`,error:t}),Promise.resolve()});a.push(f),o.add(f),o.size>=n&&await Promise.race(o)}let u=await Promise.allSettled(a);return E.info(`Parallel M3U8 downloads finished. Success: ${s}, Failed: ${c}, Total: ${l}`),u.filter(e=>e.status===`fulfilled`).map(e=>e.value)}async function Y(e){let t=e.match(/m3u8\|([a-f0-9|]+)\|com\|surrit\|https\|video/);return t?t[1].split(`|`).reverse().join(`-`):(E.error(`Failed to extract UUID from HTML.`),null)}async function X(e,n=S){let{cwd:r,missavHtmlPage:i}=e,{proxy:a,timeout:o}=await O(n,r);if(!i)return E.error(`missavHtmlPage is required for getMissavLink.`),null;let s=await Y(i),c=`https://surrit.com/${s}/playlist.m3u8`,{data:l}=await t.get(c,{headers:{"User-Agent":j(),Referer:n.headers?.Referer||`https://missav.ws/`},proxy:a,timeout:o});return`https://surrit.com/${s}/${l.match(/(?:\d+p|\d+x\d+)\/video\.m3u8/g).at(-1)}`}async function ie(t,n=S){Array.isArray(t)||(t=[t]);let r=[];for(let i of t){let{cwd:t,url:a}=i;if(!a||!a.includes(`missav:`)){E.warn(`Invalid missavHtmlPath: ${a}`);continue}let o=await X({missavHtmlPage:await e(a.replace(`missav:`,``).trim(),`utf-8`),cwd:t},n);r.push({...i,url:o})}await J(r,{...n,headers:{Referer:n.headers?.Referer||`https://missav.ws/`}})}function ae(e,t){let n=e.label.slice(0,e.label.length-1),r=t.label.slice(0,t.label.length-1);return Number(n)-Number(r)}async function Z(e,r=S){let{url:i,cwd:a}=e,{proxy:o,timeout:s}=await O(r,a),c=o?.host===``?void 0:o,{data:l}=await t.get(i,{headers:{"User-Agent":j(),Referer:`https://www.wow.xxx/`},proxy:c,timeout:s}),u=n(l)(`source[type="video/mp4"]`);return Object.values(u).map(e=>e.attribs).filter(e=>e!=null).sort(ae)}async function oe(e,t=S){Array.isArray(e)||(e=[e]);let n=[];for(let r of e){let{url:e,cwd:i}=r,a=await Z({url:e,cwd:i},t);a.length>0&&E.success(`Successfully get video sources, size ${a.at(-1).size} to be downloaded.`),n.push({...r,url:a.at(-1).src})}await P(n)}async function Q(e,r=S){let{url:i,cwd:a}=e,{proxy:o,timeout:s}=await O(r,a),c=o?.host===``?void 0:o,{data:l}=await t.get(i,{headers:{"User-Agent":j(),Referer:`https://xhamster.com`},proxy:c,timeout:s}),u=n(l),d=``,f=u(`head link[rel="preload"][crossorigin="true"][as="fetch"]`).attr();return f&&(d=f.href),d}async function se(e,t=S){Array.isArray(e)||(e=[e]);let n=[];for(let r of e){let{url:e,cwd:i}=r,a=await Q({url:e,cwd:i},t);if(!a)return Promise.reject(Error(`Failed to fetch XHamster video link`));a=a.includes(`1080p`)?a.replace(`_TPL_`,`1080p`):a.includes(`720p`)?a.replace(`_TPL_`,`720p`):a.includes(`480p`)?a.replace(`_TPL_`,`480p`):a.includes(`240p`)?a.replace(`_TPL_`,`240p`):a.replace(`_TPL_`,`144p`),n.push({...r,url:a})}await P(n)}let $=function(e){return e[e.Bilibili=0]=`Bilibili`,e[e.AnimeIdHentai=1]=`AnimeIdHentai`,e[e.Dirpy=2]=`Dirpy`,e[e.M3U8=3]=`M3U8`,e[e.KoreanPM=4]=`KoreanPM`,e[e.Hanime=5]=`Hanime`,e[e.MissAV=6]=`MissAV`,e[e.NJavTV=7]=`NJavTV`,e[e.Wowxxx=8]=`Wowxxx`,e[e.XHamster=9]=`XHamster`,e[e.MP4=10]=`MP4`,e}({});function ce(e){return e.includes(`bilibili`)||/BV[a-zA-Z0-9]+/.test(e)?$.Bilibili:e.includes(`animeidhentai`)?$.AnimeIdHentai:e.includes(`koreanpornmovie`)?$.KoreanPM:e.startsWith(`missav:`)?$.MissAV:e.includes(`hanime1.me`)?$.Hanime:e.includes(`wow.xxx`)?$.Wowxxx:e.includes(`xhamster.com`)?$.XHamster:e.endsWith(`.m3u8`)||e.includes(`.m3u8`)&&!e.endsWith(`.mp4`)?$.M3U8:e.endsWith(`.mp4`)||e.includes(`.mp4`)&&!e.endsWith(`.m3u8`)?$.MP4:$.Dirpy}export{b as A,j as C,S as D,te as E,w as O,P as S,E as T,R as _,oe as a,I as b,X as c,G as d,W as f,z as g,B as h,Q as i,x as k,q as l,H as m,$ as n,Z as o,U as p,se as r,ie as s,ce as t,J as u,L as v,O as w,N as x,re as y};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fast-dirpy",
3
3
  "type": "module",
4
- "version": "1.0.0",
4
+ "version": "1.0.1",
5
5
  "description": "A simple library/CLI to download video from several websites.",
6
6
  "author": "Vincent-the-gamer",
7
7
  "license": "MIT",
@@ -37,25 +37,25 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "ansis": "^4.2.0",
40
- "axios": "^1.13.6",
40
+ "axios": "^1.14.0",
41
41
  "cac": "^7.0.0",
42
42
  "cheerio": "^1.2.0",
43
43
  "consola": "^3.4.2",
44
44
  "m3u8stream": "^0.8.6",
45
- "puppeteer-core": "^24.38.0",
45
+ "puppeteer-core": "^24.40.0",
46
46
  "restore-cursor": "^5.1.0",
47
47
  "unconfig": "^7.5.0"
48
48
  },
49
49
  "devDependencies": {
50
- "@antfu/eslint-config": "^7.7.0",
51
- "@types/node": "^25.3.5",
50
+ "@antfu/eslint-config": "^8.0.0",
51
+ "@types/node": "^25.5.2",
52
52
  "deepmerge": "^4.3.1",
53
- "eslint": "^10.0.3",
54
- "taze": "^19.10.0",
55
- "tsdown": "^0.21.0",
53
+ "eslint": "^10.2.0",
54
+ "taze": "^19.11.0",
55
+ "tsdown": "^0.21.7",
56
56
  "tsx": "^4.21.0",
57
- "typescript": "^5.9.3",
58
- "vitest": "^4.0.18"
57
+ "typescript": "^6.0.2",
58
+ "vitest": "^4.1.2"
59
59
  },
60
60
  "scripts": {
61
61
  "tsx": "tsx",
@@ -1 +0,0 @@
1
- import e from"axios";import{load as t}from"cheerio";import n from"node:path";import{fileURLToPath as r}from"node:url";import{createConfigLoader as i}from"unconfig";import a from"node:process";import{consola as o}from"consola";import s,{createWriteStream as c}from"node:fs";import l from"puppeteer-core";import u from"m3u8stream";var d=Object.create,f=Object.defineProperty,p=Object.getOwnPropertyDescriptor,m=Object.getOwnPropertyNames,h=Object.getPrototypeOf,g=Object.prototype.hasOwnProperty,_=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),v=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=m(t),a=0,o=i.length,s;a<o;a++)s=i[a],!g.call(e,s)&&s!==n&&f(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=p(t,s))||r.enumerable});return e},ee=(e,t,n)=>(n=e==null?{}:d(h(e)),v(t||!e||!e.__esModule?f(n,`default`,{value:e,enumerable:!0}):n,e)),y=`1.0.0`,b={name:`fast-dirpy`,type:`module`,version:y,description:`A simple library/CLI to download video from several websites.`,author:`Vincent-the-gamer`,license:`MIT`,homepage:`https://github.com/Vincent-the-gamer/fast-dirpy#readme`,repository:{type:`git`,url:`git+https://github.com/Vincent-the-gamer/fast-dirpy.git`},bugs:{url:`https://github.com/Vincent-the-gamer/fast-dirpy/issues`},sideEffects:!1,main:`dist/index.mjs`,module:`dist/index.mjs`,types:`dist/index.d.mts`,typesVersions:{"*":{".":[`./dist/index.d.mts`,`./dist/cli.d.mts`]}},bin:{"fast-dirpy":`bin/fast-dirpy.js`},files:[`dist`],scripts:{tsx:`tsx`,build:`tsdown`,test:`vitest`,dep:`taze major -I`,"lint:fix":`eslint . --fix`,login:`pnpm login --registry https://registry.npmjs.com`},publishConfig:{registry:`https://registry.npmjs.com`,access:`public`},dependencies:{ansis:`^4.2.0`,axios:`^1.13.6`,cac:`^7.0.0`,cheerio:`^1.2.0`,consola:`^3.4.2`,m3u8stream:`^0.8.6`,"puppeteer-core":`^24.38.0`,"restore-cursor":`^5.1.0`,unconfig:`^7.5.0`},devDependencies:{"@antfu/eslint-config":`^7.7.0`,"@types/node":`^25.3.5`,deepmerge:`^4.3.1`,eslint:`^10.0.3`,taze:`^19.10.0`,tsdown:`^0.21.0`,tsx:`^4.21.0`,typescript:`^5.9.3`,vitest:`^4.0.18`}};const x={timeout:2e4},S=r(import.meta.url),C=n.dirname(S);var w=_(((e,t)=>{var n=function(e){return r(e)&&!i(e)};function r(e){return!!e&&typeof e==`object`}function i(e){var t=Object.prototype.toString.call(e);return t===`[object RegExp]`||t===`[object Date]`||o(e)}var a=typeof Symbol==`function`&&Symbol.for?Symbol.for(`react.element`):60103;function o(e){return e.$$typeof===a}function s(e){return Array.isArray(e)?[]:{}}function c(e,t){return t.clone!==!1&&t.isMergeableObject(e)?g(s(e),e,t):e}function l(e,t,n){return e.concat(t).map(function(e){return c(e,n)})}function u(e,t){if(!t.customMerge)return g;var n=t.customMerge(e);return typeof n==`function`?n:g}function d(e){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter(function(t){return Object.propertyIsEnumerable.call(e,t)}):[]}function f(e){return Object.keys(e).concat(d(e))}function p(e,t){try{return t in e}catch{return!1}}function m(e,t){return p(e,t)&&!(Object.hasOwnProperty.call(e,t)&&Object.propertyIsEnumerable.call(e,t))}function h(e,t,n){var r={};return n.isMergeableObject(e)&&f(e).forEach(function(t){r[t]=c(e[t],n)}),f(t).forEach(function(i){m(e,i)||(p(e,i)&&n.isMergeableObject(t[i])?r[i]=u(i,n)(e[i],t[i],n):r[i]=c(t[i],n))}),r}function g(e,t,r){r||={},r.arrayMerge=r.arrayMerge||l,r.isMergeableObject=r.isMergeableObject||n,r.cloneUnlessOtherwiseSpecified=c;var i=Array.isArray(t);return i===Array.isArray(e)?i?r.arrayMerge(e,t,r):h(e,t,r):c(t,r)}g.all=function(e,t){if(!Array.isArray(e))throw Error(`first argument should be an array`);return e.reduce(function(e,n){return g(e,n,t)},{})},t.exports=g}));const T=o.withTag(`fast-dirpy`);function E(e){`CONSOLA_LEVEL`in a.env||(T.level=e?0:3)}var D=ee(w(),1);async function O(e,t){let n=x,{config:r,sources:a}=await i({sources:[{files:[`fast-dirpy.config`],extensions:[`ts`,`mts`,`cts`,`js`,`mjs`,`cjs`,`json`]}],cwd:t||process.cwd(),merge:!1}).load();return a.length?(T.info(`Config file found: ${a[0]}`),(0,D.default)((0,D.default)(n,r),e)):(0,D.default)(n,e)}function k(e){return e[Math.floor(Math.random()*e.length)]}const A=[`Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10`,`Mozilla/5.0 (Windows NT 6.1; rv,2.0.1) Gecko/20100101 Firefox/4.0.1`,`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36`,`Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36`,`Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.11 (KHTML, like Gecko) Ubuntu/11.10 Chromium/27.0.1453.93 Chrome/27.0.1453.93 Safari/537.36`];function j(){return k(A)}const M=e=>`[${e.url.split(`/`).pop()||`unknown`}]`;async function N(t,n=x){let{path:r,url:i}=t,a=M(t),{proxy:o,timeout:c}=await O(n),l=o?.host===``?void 0:o;if(i===``)return Promise.reject(Error(`Extract direct link failed!`));let u=s.createWriteStream(r||`./download.mp4`);return(await e({url:i,headers:{"User-Agent":j(),...n.headers},method:`GET`,responseType:`stream`,proxy:l,timeout:c,onDownloadProgress:e=>{let{loaded:t,total:n,progress:r}=e,i=`[${a??``}] loaded:${t} total: ${n} progress: ${(r*100).toFixed(2)}%`;T.info(i)}})).data.pipe(u),new Promise((e,t)=>{u.on(`finish`,e),u.on(`error`,t)})}async function P(e,t=x,n=5,r){let i=[],a=new Set,o=0,s=0,c=e.length;T.info(`Starting parallel downloads: ${c} videos, max concurrent: ${n}`);for(let[l,u]of e.entries()){let e=M(u),d=N(u,t).then(t=>(o++,a.delete(d),T.info(`${l+1}/${c} ${e} Download completed`),r?.({total:c,completed:o,failed:s,currentParams:u,identifier:e,status:`success`}),t)).catch(t=>{s++,a.delete(d);let n=t instanceof Error?t.message:String(t);return T.error(`${e} Download failed: ${n}`),r?.({total:c,completed:o,failed:s,currentParams:u,identifier:e,status:`failed`,error:t}),Promise.resolve()});i.push(d),a.add(d),a.size>=n&&await Promise.race(a)}let l=await Promise.allSettled(i);return T.info(`Parallel downloads finished. Success: ${o}, Failed: ${s}, Total: ${c}`),l.filter(e=>e.status===`fulfilled`).map(e=>e.value)}async function F(e){return await l.launch(e)}async function te(n,r=x){let{url:i,cwd:a}=n,{proxy:o,timeout:s}=await O(r,a),c=o?.host===``?void 0:o,{data:l}=await e.get(i,{headers:{"User-Agent":j()},proxy:c,timeout:s}),u=t(l),d=``,f=u(`div.embed.rad2 > iframe`).attr();return f&&(d=f.src),d}async function I(e,t=x){let{url:n,cwd:r}=e,{proxy:i,puppeteer:a}=await O(t,r),o=i?.host===``?void 0:i,s=await te({url:n},{proxy:o}),{executablePath:c,headless:l}=a,u=await F({executablePath:c,headless:l,args:[`--proxy-server=http://${o?.host}:${i?.port}`]}),d=j(),f=await u.newPage();await f.setUserAgent(d),await f.goto(s),await f.waitForSelector(`div.play.p-pulse`),await f.click(`div.play.p-pulse`),await f.waitForSelector(`div.frame > iframe`);let p=await f.$eval(`div.frame > iframe`,e=>e.src),m=await u.newPage();await m.goto(`${p}`),await m.waitForSelector(`video.jw-video.jw-reset`);let h=await m.$eval(`video.jw-video.jw-reset`,e=>e.src);return await u.close(),h}async function L(e,t=x){Array.isArray(e)||(e=[e]);let n=[];for(let r of e){let{url:e,cwd:i}=r,a=await I({url:e,cwd:i},t);n.push({...r,url:a})}n.length>0&&await P(n)}async function R(e,t=x){let{url:n,cwd:r}=e,{proxy:i,puppeteer:a}=await O(t,r),o=i?.host===``?void 0:i,{executablePath:s,headless:c}=a,l=await F({executablePath:s,headless:c,args:[`--proxy-server=http://${o?.host}:${i?.port}`,`--disable-features=IsolateOrigins,site-per-process`,`--disable-site-isolation-trials`,`--disable-web-security`,`--disable-setuid-sandbox`,`--no-sandbox`,`--disable-gpu`,`--disable-dev-shm-usage`,`--disable-accelerated-2d-canvas`,`--no-first-run`,`--no-zygote`,`--window-size=1920,1080`],slowMo:10}),u=await l.newPage(),d=j();await u.setUserAgent(d);try{await u.goto(`https://snapany.com/zh/bilibili`),await u.waitForNetworkIdle();let e=`input[name='link']`;await u.waitForSelector(e),await u.type(e,n,{delay:10});let t=`button[type='submit']`;return await u.waitForSelector(t),await u.click(t),await u.waitForSelector(`div[data-testid="flowbite-card"]`),(await u.$$eval(`div[data-testid="flowbite-card"]`,e=>e.map(e=>{let t=e.querySelector(`a[href*=".mp4"]`)?.getAttribute(`href`)||``;return t=t.replace(/&amp;/g,`&`),{videoUrl:t}}))).filter(e=>e.videoUrl)[0]?.videoUrl}catch(e){T.error(`Error during scraping: ${e}`)}finally{T.info(`Closing browser`),await l.close()}}async function z(e){Array.isArray(e)||(e=[e]);let t=[];for(let n of e){let e=await R({url:n.url,cwd:n.cwd});t.push({...n,url:e})}await P(t)}async function B(n,r=x){let{url:i,cwd:a}=n,{proxy:o,timeout:s}=await O(r,a),c=o?.host===``?void 0:o,{data:l}=await e.get(`https://dirpy.com/studio`,{params:{url:i},headers:{"User-Agent":j(),Referer:`https://dirpy.com/studio?url=${i}`},proxy:c,timeout:s}),u=t(l),d=``,f=u(`#media-source`).attr();return f&&(d=f.src),d}async function V(e,t=x){Array.isArray(e)||(e=[e]);let n=[];for(let r of e){let e=await B({url:r.url,cwd:r.cwd},t);n.push({...r,url:e})}n.length>0&&await P(n)}function H(e,t){return Number(e.size)-Number(t.size)}async function U(n,r=x){let{url:i,cwd:a}=n,{proxy:o,timeout:s}=await O(r,a),c=o?.host===``?void 0:o,{data:l}=await e.get(i,{headers:{"User-Agent":j(),Referer:`https://hanime1.me/`},proxy:c,timeout:s}),u=t(l)(`source[type="video/mp4"]`);return Object.values(u).map(e=>e.attribs).filter(e=>e!=null).sort(H)}async function W(e,t=x){Array.isArray(e)||(e=[e]);let n=[];for(let r of e){let{url:e,cwd:i}=r,a=await U({url:e,cwd:i},t);a.length>0&&T.success(`Successfully get video sources, size ${a.at(-1).size} to be downloaded.`),n.push({...r,url:a.at(-1).src})}n.length>0&&await P(n)}async function G(n,r=x){let{url:i,cwd:a}=n,{proxy:o,timeout:s}=await O(r,a),c=o?.host===``?void 0:o,{data:l}=await e.get(i,{headers:{"User-Agent":j()},proxy:c,timeout:s}),u=t(l),d=``,f=u(`meta[itemprop="contentURL"]`).attr();return f&&(d=f.content),d}async function K(e,t=x){Array.isArray(e)||(e=[e]);let n=[];for(let r of e){let{url:e,cwd:i}=r,a=await G({url:e,cwd:i},t);n.push({...r,url:a})}n.length>0&&await P(n)}const q=e=>`[${e.url?.split(`/`).pop()||`unknown`}]`;async function J(e,t=x,r){let{url:i,cwd:a,path:o}=e,{proxy:s,timeout:l}=await O(t,a);if(!i)return Promise.reject(Error(`M3U8 URL is required!`));let d=q(e),f=o??n.resolve(C,`../m3u8-download.mp4`);return T.info(`${d} Starting M3U8 download from: ${i}`),T.info(`${d} Output path: ${f}`),new Promise((e,n)=>{try{let a=u(i,{requestOptions:{headers:t.headers,timeout:l,...s?.host?{proxy:`http://${s.host}:${s.port}`}:{}}}),o=c(f);a.on(`progress`,(e,t,n)=>{let i=n/1024/1024,a=t>0?e.num/t*100:0,o={segment:e,totalSegments:t,downloaded:n,downloadedMB:i,percent:a};T.info(`${d} Segment: ${e.num}/${t}, Downloaded: ${i.toFixed(2)}MB (${a.toFixed(2)}%)`),r?.(o)}),a.on(`error`,e=>{T.error(`${d} M3U8 stream error: ${e.message}`),o.end(),n(e)}),a.pipe(o),o.on(`finish`,()=>{T.info(`${d} M3U8 download completed successfully`),e()}),o.on(`error`,e=>{T.error(`${d} File write error: ${e.message}`),n(e)})}catch(e){let t=e instanceof Error?e.message:String(e);T.error(`${d} Failed to initialize M3U8 download: ${t}`),n(e)}})}async function Y(e,t=x,n=3,r,i){let a=[],o=new Set,s=0,c=0,l=e.length;T.info(`Starting parallel M3U8 downloads: ${l} videos, max concurrent: ${n}`);for(let[u,d]of e.entries()){let e=q(d),f=J(d,t,t=>{i?.(e,t),r?.({total:l,completed:s,failed:c,currentParams:d,identifier:e,status:`downloading`,downloadProgress:t})}).then(t=>(s++,o.delete(f),T.info(`${u+1}/${l} ${e} M3U8 download completed`),r?.({total:l,completed:s,failed:c,currentParams:d,identifier:e,status:`success`}),t)).catch(t=>{c++,o.delete(f);let n=t instanceof Error?t.message:String(t);return T.error(`${e} M3U8 download failed: ${n}`),r?.({total:l,completed:s,failed:c,currentParams:d,identifier:e,status:`failed`,error:t}),Promise.resolve()});a.push(f),o.add(f),o.size>=n&&await Promise.race(o)}let u=await Promise.allSettled(a);return T.info(`Parallel M3U8 downloads finished. Success: ${s}, Failed: ${c}, Total: ${l}`),u.filter(e=>e.status===`fulfilled`).map(e=>e.value)}function X(e,t){let n=e.label.slice(0,e.label.length-1),r=t.label.slice(0,t.label.length-1);return Number(n)-Number(r)}async function Z(n,r=x){let{url:i,cwd:a}=n,{proxy:o,timeout:s}=await O(r,a),c=o?.host===``?void 0:o,{data:l}=await e.get(i,{headers:{"User-Agent":j(),Referer:`https://www.wow.xxx/`},proxy:c,timeout:s}),u=t(l)(`source[type="video/mp4"]`);return Object.values(u).map(e=>e.attribs).filter(e=>e!=null).sort(X)}async function ne(e,t=x){Array.isArray(e)||(e=[e]);let n=[];for(let r of e){let{url:e,cwd:i}=r,a=await Z({url:e,cwd:i},t);a.length>0&&T.success(`Successfully get video sources, size ${a.at(-1).size} to be downloaded.`),n.push({...r,url:a.at(-1).src})}await P(n)}async function Q(n,r=x){let{url:i,cwd:a}=n,{proxy:o,timeout:s}=await O(r,a),c=o?.host===``?void 0:o,{data:l}=await e.get(i,{headers:{"User-Agent":j(),Referer:`https://xhamster.com`},proxy:c,timeout:s}),u=t(l),d=``,f=u(`head link[rel="preload"][crossorigin="true"][as="fetch"]`).attr();return f&&(d=f.href),d}async function re(e,t=x){Array.isArray(e)||(e=[e]);let n=[];for(let r of e){let{url:e,cwd:i}=r,a=await Q({url:e,cwd:i},t);if(!a)return Promise.reject(Error(`Failed to fetch XHamster video link`));a=a.includes(`1080p`)?a.replace(`_TPL_`,`1080p`):a.includes(`720p`)?a.replace(`_TPL_`,`720p`):a.includes(`480p`)?a.replace(`_TPL_`,`480p`):a.includes(`240p`)?a.replace(`_TPL_`,`240p`):a.replace(`_TPL_`,`144p`),n.push({...r,url:a})}await P(n)}let $=function(e){return e[e.Bilibili=0]=`Bilibili`,e[e.AnimeIdHentai=1]=`AnimeIdHentai`,e[e.Dirpy=2]=`Dirpy`,e[e.M3U8=3]=`M3U8`,e[e.KoreanPM=4]=`KoreanPM`,e[e.Hanime=5]=`Hanime`,e[e.Wowxxx=6]=`Wowxxx`,e[e.XHamster=7]=`XHamster`,e[e.MP4=8]=`MP4`,e}({});function ie(e){return e.includes(`bilibili`)||/BV[a-zA-Z0-9]+/.test(e)?$.Bilibili:e.includes(`animeidhentai`)?$.AnimeIdHentai:e.includes(`koreanpornmovie`)?$.KoreanPM:e.includes(`missav`)?$.MissAV:e.includes(`hanime1.me`)?$.Hanime:e.includes(`wow.xxx`)?$.Wowxxx:e.includes(`xhamster.com`)?$.XHamster:e.endsWith(`.m3u8`)||e.includes(`.m3u8`)&&!e.endsWith(`.mp4`)?$.M3U8:e.endsWith(`.mp4`)||e.includes(`.mp4`)&&!e.endsWith(`.m3u8`)?$.MP4:$.Dirpy}export{T as C,b as D,C as E,y as O,O as S,x as T,L as _,ne as a,P as b,Y as c,W as d,U as f,R as g,z as h,Q as i,K as l,B as m,$ as n,Z as o,V as p,re as r,J as s,ie as t,G as u,I as v,E as w,j as x,N as y};