fast-dirpy 0.1.8 → 0.2.0

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
@@ -16,11 +16,9 @@ A simple library/CLI to download youtube(etc.) videos.
16
16
  - [YouTube](https://www.youtube.com/)
17
17
  - [Bilibili](https://www.bilibili.com/)
18
18
 
19
- <details>
20
- <summary>「Mystic」Websites</summary>
19
+ And `.m3u8` videos(using `ffmpeg`).
21
20
 
22
- - Animeidhentai (Google Chrome required)
23
- </details>
21
+ 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.
24
22
 
25
23
  ## Installation
26
24
 
@@ -37,6 +35,10 @@ deno add jsr:@vince-g/fast-dirpy
37
35
  npm i fast-dirpy -g
38
36
  ```
39
37
 
38
+ ### Additional: download `ffmpeg`
39
+
40
+ https://www.ffmpeg.org/download.html
41
+
40
42
  ## Usage
41
43
 
42
44
  ### Config file
@@ -60,8 +62,12 @@ export default defineConfig({
60
62
  // Path to Chrome. Please notice that you must give the inner unix executable file path in macOS.
61
63
  // /Applications/Google Chrome.app will not work.
62
64
  executablePath: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
63
- headless: false
64
- }
65
+ headless: true
66
+ },
67
+ // binary file path of ffmpeg
68
+ // in Windows, use: "xx/ffmpeg.exe"
69
+ // if no ffmpeg path given, it will rely on your env variable.
70
+ ffmpeg: "./ffmpeg"
65
71
  }
66
72
  ```
67
73
 
@@ -95,7 +101,8 @@ fast-dirpy get https\://www.youtube.com/watch\?v\=6c28qWDMPBA
95
101
  #### Download Video
96
102
 
97
103
  > [!IMPORTANT]
98
- > Some website listed in [Supported Websites](#supported-websites) requires Google Chrome installed for Puppeteer use. You have to use a config file or give parameter of puppeteer executable path.
104
+ > 1. Some website listed in [Supported Websites](#supported-websites) requires Google Chrome installed for Puppeteer use. You have to use a config file or give parameter of puppeteer executable path.
105
+ > 2. `.m3u8` source is handled by `ffmpeg`.
99
106
 
100
107
  ```shell
101
108
  # get video direct link
@@ -110,7 +117,10 @@ fast-dirpy get https\://www.youtube.com/watch\?v\=6c28qWDMPBA
110
117
  fast-dirpy download https\://www.youtube.com/watch\?v\=6c28qWDMPBA -p ./test.mp4 -H 127.0.0.1 -P 7890
111
118
 
112
119
  # Bilibili source doesn't need any proxy, so it's disabled by default.
113
- fast-dirpy download https://www.bilibili.com/video/BV1TSPeeGE35 -p ./test.mp4
120
+ fast-dirpy download https\://www.bilibili.com/video/BV1TSPeeGE35 -p ./test.mp4
121
+
122
+ # m3u8 sources
123
+ fast-dirpy download https\://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8 -p ./test.mp4
114
124
  ```
115
125
 
116
126
  if you have set your proxy config in `fast-dirpy.config.ts`, you can omit proxy parameters:
@@ -131,7 +141,7 @@ fast-dirpy --help
131
141
  > If a website is listed in [Supported Websites](#supported-websites), then `getXXXLink` is to get direct link and `downloadXXX` is to download video.
132
142
 
133
143
  ```ts
134
- import { downloadDirpy, getBilibiliLink, getDirpyLink } from 'fast-dirpy'
144
+ import { downloadDirpy, getBilibiliLink, getDirpyLink, remoteM3U8ToMP4 } from 'fast-dirpy'
135
145
 
136
146
  // get direct link
137
147
  const link = await getDirpyLink(
@@ -166,6 +176,20 @@ await downloadBilibili({
166
176
  url: '<url>',
167
177
  path: './myvideo.mp4'
168
178
  })
179
+
180
+ // download `.m3u8` video
181
+ await remoteM3U8ToMP4({
182
+ input: 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8',
183
+ output: './test.mp4',
184
+ })
185
+ ```
186
+
187
+ ## Test
188
+
189
+ To run single test case in Vitest, using:
190
+
191
+ ```shell
192
+ pnpm run test src/test/xxx.test.ts:<line_number>
169
193
  ```
170
194
 
171
195
  ## License
package/bin/fast-dirpy.js CHANGED
File without changes
package/dist/cli.d.ts CHANGED
@@ -1,2 +1 @@
1
-
2
- export { }
1
+ export { };
package/dist/cli.js CHANGED
@@ -1 +1 @@
1
- import{a as e,b as y,c as g,d as x,e as b,f as P,g as w,h as k}from"./chunk-RM2BKSBF.js";import{c as m}from"./chunk-HD53P4DN.js";m();import{bold as v,dim as H}from"ansis";import{cac as C}from"cac";import I from"restore-cursor";var h={name:"fast-dirpy",type:"module",version:"0.1.8",description:"A simple library/CLI to download video using dirpy.com",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.js",module:"dist/index.js",types:"dist/index.d.ts",typesVersions:{"*":{".":["./dist/index.d.ts","./dist/cli.d.ts"]}},bin:{"fast-dirpy":"bin/fast-dirpy.js"},files:["dist"],scripts:{tsx:"tsx",build:"tsup",test:"vitest",dep:"taze major","lint:fix":"eslint . --fix",login:"pnpm login --registry https://registry.npmjs.com"},publishConfig:{registry:"https://registry.npmjs.com",access:"public"},dependencies:{ansis:"^3.17.0",axios:"^1.8.4",cac:"^6.7.14",consola:"^3.4.2",jsdom:"^26.1.0","puppeteer-core":"^24.7.1","restore-cursor":"^5.1.0",unconfig:"^7.3.2"},devDependencies:{"@antfu/eslint-config":"^4.12.0","@types/node":"^22.14.1",deepmerge:"^4.3.1",eslint:"^9.25.1",taze:"^19.0.4",tsup:"^8.4.0",tsx:"^4.19.3",typescript:"^5.8.3",vitest:"^3.1.2"}};m();function u(i){let r=/BV[a-zA-Z0-9]+/;return i.includes("bilibili")||r.test(i)?0:i.includes("animeidhentai")?2:1}var a=C("fast-dirpy"),{version:A}=h;a.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(i,r)=>{let o=u(i),{proxyHost:s,proxyPort:f,config:n,silent:d,chromePath:l}=r,p=s?{proxy:{host:s,port:f}}:void 0,c=l?{puppeteer:{executablePath:l}}:void 0;if(y(!!d),e.info(`fast-dirpy ${H(`v${A}`)} : ${v("Direct Link Getter")}.`),o===0){if(e.info("Matched link source: Bilibili."),!i.includes("bilibili.com")){e.error("Please provide a valid Bilibili URL.");return}let t=await b(i);console.log(t)}else if(o===1){e.info("Matched link source: Dirpy.");let t=await w({url:i,cwd:n},p);console.log(t)}else if(o===2){e.info("Matched link source: Animeidhentai.");let t=await g({url:i,cwd:n},{...p,...c});console.log(t)}else e.error("Your link is not supported!")});a.command("download <url>","download a video.").option("--path, -p <path>","Download destination path + filename. e.g. /xxx/example.mp4.").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(i,r)=>{let o=u(i),{proxyHost:s,proxyPort:f,path:n,config:d,silent:l,chromePath:p}=r,c=s?{proxy:{host:s,port:f}}:void 0,t=p?{puppeteer:{executablePath:p}}:void 0;y(!!l),e.info(`fast-dirpy ${H(`v${A}`)} : ${v("Video Downloader")}.`),o===0?(e.info("Matched link source: Bilibili."),await P({url:i,path:n})):o===1?(e.info("Matched link source: Dirpy."),k({url:i,path:n||"./dirpy.mp4",cwd:d},c)):o===2?(e.info("Matched link source: AnimeIdHentai."),await x({url:i,path:n||"./animeidhentai.mp4",cwd:d},{...c,...t})):e.error("Your link is not supported!")});a.help();a.version(h.version);a.parse();I();
1
+ import{DEFAULT_OPTIONS as e,UrlType as t,downloadAnimeIdHentai as n,downloadBilibili as r,downloadDirpy as i,downloadVideo as a,getAnimeIdHentaiLink as o,getBilibiliLink as s,getDirpyLink as c,logger as l,remoteM3U8ToMP4 as u,resolveConfig as d,setSilent as f,useRandomUserAgent as p}from"./types-D0MVglb-.js";import{bold as m,dim as h}from"ansis";import{cac as g}from"cac";import _ from"restore-cursor";import v from"axios";import{load as y}from"cheerio";var b={name:`fast-dirpy`,type:`module`,version:`0.2.0`,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.js`,module:`dist/index.js`,types:`dist/index.d.ts`,typesVersions:{"*":{".":[`./dist/index.d.ts`,`./dist/cli.d.ts`]}},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.12.2`,cac:`^6.7.14`,cheerio:`^1.1.2`,consola:`^3.4.2`,"puppeteer-core":`^24.22.3`,"restore-cursor":`^5.1.0`,unconfig:`^7.3.3`},devDependencies:{"@antfu/eslint-config":`^5.4.1`,"@types/node":`^22.18.7`,deepmerge:`^4.3.1`,eslint:`^9.36.0`,taze:`^19.7.0`,tsdown:`^0.15.5`,tsx:`^4.20.6`,typescript:`^5.9.2`,vitest:`^3.2.4`}};function x(e){return e.includes(`bilibili`)||/BV[a-zA-Z0-9]+/.test(e)?t.Bilibili:e.includes(`animeidhentai`)?t.AnimeIdHentai:e.includes(`koreanpornmovie`)?t.KoreanPM:e.endsWith(`.m3u8`)?t.M3U8:t.Dirpy}async function S(t,n=e){let{url:r,cwd:i}=t,{proxy:a,timeout:o}=await d(n,i),s=a?.host===``?void 0:a,{data:c}=await v.get(r,{headers:{"User-Agent":p()},proxy:s,timeout:o}),l=y(c),u=``,f=l(`meta[itemprop="contentURL"]`).attr();return f&&(u=f.content),u}async function C(t,n=e){let{path:r,url:i,cwd:o}=t,s=await S({url:i},n);await a({url:s,path:r,cwd:o},n)}const w=g(`fast-dirpy`),{version:T}=b;w.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 r=x(e),{proxyHost:i,proxyPort:a,config:u,silent:d,chromePath:p}=n,g=i?{proxy:{host:i,port:a}}:void 0,_=p?{puppeteer:{executablePath:p}}:void 0;if(f(!!d),l.info(`fast-dirpy ${h(`v${T}`)} : ${m(`Direct Link Getter`)}.`),r===t.Bilibili){if(l.info(`Matched link source: Bilibili.`),!e.includes(`bilibili.com`)){l.error(`Please provide a valid Bilibili URL.`);return}let t=await s(e);console.log(t)}else if(r===t.Dirpy){l.info(`Matched link source: Dirpy.`);let t=await c({url:e,cwd:u},g);console.log(t)}else if(r===t.AnimeIdHentai){l.info(`Matched link source: Animeidhentai.`);let t=await o({url:e,cwd:u},{...g,..._});console.log(t)}else if(r===t.KoreanPM){l.info(`Matched link source: KoreanPM.`);let t=await S({url:e,cwd:u},g);console.log(t)}else l.error(`Your link is not supported!`)}),w.command(`download <url>`,`download a video.`).option(`--path, -p <path>`,`Download destination path + filename. e.g. /xxx/example.mp4.`).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,a)=>{let o=x(e),{proxyHost:s,proxyPort:c,path:d,config:p,silent:g,chromePath:_}=a,v=s?{proxy:{host:s,port:c}}:void 0,y=_?{puppeteer:{executablePath:_}}:void 0;f(!!g),l.info(`fast-dirpy ${h(`v${T}`)} : ${m(`Video Downloader`)}.`),o===t.Bilibili?(l.info(`Matched link source: Bilibili.`),await r({url:e,path:d})):o===t.Dirpy?(l.info(`Matched link source: Dirpy.`),i({url:e,path:d||`./dirpy.mp4`,cwd:p},v)):o===t.AnimeIdHentai?(l.info(`Matched link source: AnimeIdHentai.`),await n({url:e,path:d||`./animeidhentai.mp4`,cwd:p},{...v,...y})):o===t.KoreanPM?(l.info(`Matched link source: KoreanPM.`),await C({url:e,path:d||`./korean-pm.mp4`,cwd:p},v)):o===t.M3U8?(l.info(`Matched link source: m3u8.`),await u({input:e,output:d||`./m3u8-download.mp4`,cwd:p})):l.error(`Your link is not supported!`)}),w.help(),w.version(b.version),w.parse(),_();export{};
@@ -0,0 +1,35 @@
1
+ //#region src/types/index.d.ts
2
+ interface Options {
3
+ proxy?: {
4
+ protocol?: string;
5
+ host: string;
6
+ port: number;
7
+ };
8
+ timeout?: number;
9
+ puppeteer?: {
10
+ executablePath: string;
11
+ headless?: boolean;
12
+ };
13
+ ffmpeg?: string;
14
+ }
15
+ interface DirectLinkParams {
16
+ url: string;
17
+ cwd?: string;
18
+ }
19
+ interface DownloadParams {
20
+ url: string;
21
+ path: string;
22
+ cwd?: string;
23
+ }
24
+ declare enum UrlType {
25
+ Bilibili = 0,
26
+ AnimeIdHentai = 1,
27
+ Dirpy = 2,
28
+ M3U8 = 3,
29
+ KoreanPM = 4,
30
+ }
31
+ //#endregion
32
+ //#region src/config.d.ts
33
+ declare function defineConfig(options: Options): Options;
34
+ //#endregion
35
+ export { DirectLinkParams, DownloadParams, Options, UrlType, defineConfig };
@@ -0,0 +1 @@
1
+ function e(e){return e}export{e as defineConfig};
package/dist/config.d.ts CHANGED
@@ -1 +1,2 @@
1
- export { d as defineConfig } from './config-0EeRO6Y-.js';
1
+ import { defineConfig } from "./config-BbJq3Qd3.js";
2
+ export { defineConfig };
package/dist/config.js CHANGED
@@ -1 +1 @@
1
- import{a}from"./chunk-OYM7YQEE.js";import"./chunk-HD53P4DN.js";export{a as defineConfig};
1
+ import{defineConfig as e}from"./config-ld9QlYHr.js";export{e as defineConfig};
package/dist/index.d.ts CHANGED
@@ -1,15 +1,29 @@
1
- import { D as DirectLinkParams, a as DirpyOptions, b as DownloadParams } from './config-0EeRO6Y-.js';
2
- export { U as UrlType, d as defineConfig } from './config-0EeRO6Y-.js';
3
-
4
- declare function getAnimeIdHentaiLink(params: DirectLinkParams, options?: Partial<DirpyOptions>): Promise<string>;
5
- declare function downloadAnimeIdHentai(params: DownloadParams, options?: Partial<DirpyOptions>): Promise<void>;
1
+ import { DirectLinkParams, DownloadParams, Options, UrlType, defineConfig } from "./config-BbJq3Qd3.js";
6
2
 
3
+ //#region src/core/animeidhentai.d.ts
4
+ declare function getAnimeIdHentaiLink(params: DirectLinkParams, options?: Partial<Options>): Promise<string>;
5
+ declare function downloadAnimeIdHentai(params: DownloadParams, options?: Partial<Options>): Promise<void>;
6
+ //#endregion
7
+ //#region src/core/bilibili.d.ts
7
8
  declare function getBilibiliLink(link: string): string;
8
9
  declare function downloadBilibili(params: DownloadParams): Promise<void>;
9
-
10
- declare function getDirpyLink(params: DirectLinkParams, options?: Partial<DirpyOptions>): Promise<string>;
11
- declare function downloadDirpy(params: DownloadParams, options?: Partial<DirpyOptions>): Promise<void>;
12
-
13
- declare function downloadVideo(params: DownloadParams, options?: Partial<DirpyOptions>): Promise<void>;
14
-
15
- export { DirectLinkParams, DirpyOptions, DownloadParams, downloadAnimeIdHentai, downloadBilibili, downloadDirpy, downloadVideo, getAnimeIdHentaiLink, getBilibiliLink, getDirpyLink };
10
+ //#endregion
11
+ //#region src/core/dirpy.d.ts
12
+ declare function getDirpyLink(params: DirectLinkParams, options?: Partial<Options>): Promise<string>;
13
+ declare function downloadDirpy(params: DownloadParams, options?: Partial<Options>): Promise<void>;
14
+ //#endregion
15
+ //#region src/core/m3u8.d.ts
16
+ interface M3U8ParserParams {
17
+ input: string;
18
+ output: string;
19
+ cwd?: string;
20
+ }
21
+ /**
22
+ * Get remote m3u8 stream, then use ffmpeg to parse it to mp4.
23
+ */
24
+ declare function remoteM3U8ToMP4(params: M3U8ParserParams, options?: Partial<Options>): Promise<void>;
25
+ //#endregion
26
+ //#region src/core/index.d.ts
27
+ declare function downloadVideo(params: DownloadParams, options?: Partial<Options>): Promise<void>;
28
+ //#endregion
29
+ export { DirectLinkParams, DownloadParams, Options, UrlType, defineConfig, downloadAnimeIdHentai, downloadBilibili, downloadDirpy, downloadVideo, getAnimeIdHentaiLink, getBilibiliLink, getDirpyLink, remoteM3U8ToMP4 };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{c as r,d as e,e as f,f as m,g as p,h as t,i as x,j as a}from"./chunk-RM2BKSBF.js";import{a as b}from"./chunk-OYM7YQEE.js";import{c as o}from"./chunk-HD53P4DN.js";o();export{a as UrlType,b as defineConfig,e as downloadAnimeIdHentai,m as downloadBilibili,t as downloadDirpy,x as downloadVideo,r as getAnimeIdHentaiLink,f as getBilibiliLink,p as getDirpyLink};
1
+ import{UrlType as e,downloadAnimeIdHentai as t,downloadBilibili as n,downloadDirpy as r,downloadVideo as i,getAnimeIdHentaiLink as a,getBilibiliLink as o,getDirpyLink as s,remoteM3U8ToMP4 as c}from"./types-D0MVglb-.js";import{defineConfig as l}from"./config-ld9QlYHr.js";export{e as UrlType,l as defineConfig,t as downloadAnimeIdHentai,n as downloadBilibili,r as downloadDirpy,i as downloadVideo,a as getAnimeIdHentaiLink,o as getBilibiliLink,s as getDirpyLink,c as remoteM3U8ToMP4};
@@ -0,0 +1 @@
1
+ import e from"node:fs";import t from"axios";import{createConfigLoader as n}from"unconfig";import r from"node:process";import{consola as i}from"consola";import{load as a}from"cheerio";import o from"puppeteer-core";import{spawn as s}from"node:child_process";var c=Object.create,l=Object.defineProperty,u=Object.getOwnPropertyDescriptor,d=Object.getOwnPropertyNames,f=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty,m=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),h=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=d(t),a=0,o=i.length,s;a<o;a++)s=i[a],!p.call(e,s)&&s!==n&&l(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=u(t,s))||r.enumerable});return e},g=(e,t,n)=>(n=e==null?{}:c(f(e)),h(t||!e||!e.__esModule?l(n,`default`,{value:e,enumerable:!0}):n,e));const _={timeout:2e4};var v=m(((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 y=i.withTag(`fast-dirpy`);function b(e){`CONSOLA_LEVEL`in r.env||(y.level=e?0:3)}var x=g(v(),1);async function S(e,t){let r=_,{config:i,sources:a}=await n({sources:[{files:[`fast-dirpy.config`],extensions:[`ts`,`mts`,`cts`,`js`,`mjs`,`cjs`,`json`]}],cwd:t||process.cwd(),merge:!1}).load();return a.length?(y.info(`Config file found: ${a[0]}`),(0,x.default)((0,x.default)(r,i),e)):(0,x.default)(r,e)}function C(e){let t=Math.floor(Math.random()*e.length);return e[t]}const w=[`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 T(){return C(w)}async function E(e){return await o.launch(e)}async function D(e,n=_){let{url:r,cwd:i}=e,{proxy:o,timeout:s}=await S(n,i),c=o?.host===``?void 0:o,{data:l}=await t.get(r,{headers:{"User-Agent":T()},proxy:c,timeout:s}),u=a(l),d=``,f=u(`div.embed.rad2 > iframe`).attr();return f&&(d=f.src),d}async function O(e,t=_){let{url:n,cwd:r}=e,{proxy:i,puppeteer:a}=await S(t,r),o=i?.host===``?void 0:i,s=await D({url:n},{proxy:o}),{executablePath:c,headless:l}=a,u=await E({executablePath:c,headless:l,args:[`--proxy-server=http://${o?.host}:${i?.port}`]}),d=T(),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 k(e,t=_){let{path:n,url:r,cwd:i}=e,a=await O({url:r},t);await F({url:a,path:n,cwd:i},t)}function A(e){let t=e.match(/BV[a-zA-Z0-9]+/);return t?`https://bilibili-real-url.deno.dev/${t[0]}.mp4`:``}async function j(e){let{path:t,url:n}=e,r=A(n);r===``?console.error(`Extract direct link failed!`):await F({url:r,path:t||`./download.mp4`})}async function M(e,n=_){let{url:r,cwd:i}=e,{proxy:o,timeout:s}=await S(n,i),c=o?.host===``?void 0:o,{data:l}=await t.get(`https://dirpy.com/studio`,{params:{url:r},headers:{"User-Agent":T(),Referer:`https://dirpy.com/studio?url=${r}`},proxy:c,timeout:s}),u=a(l),d=``,f=u(`#media-source`).attr();return f&&(d=f.src),d}async function N(e,t=_){let{path:n,url:r,cwd:i}=e,a=await M({url:r},t);await F({url:a,path:n,cwd:i},t)}async function P(e,t=_){let{cwd:n,input:r,output:i}=e,{ffmpeg:a,proxy:o}=await S(t,n),c=o?.host===``?void 0:o,l=s(a||`ffmpeg`,[`-http_proxy`,`${c?.protocol}://${c?.host}:${c?.port}`,`-i`,r,`-bsf:a`,`aac_adtstoasc`,`-vcodec`,`copy`,`-acodec`,`copy`,`-crf`,`50`,i],{stdio:`inherit`,shell:process.platform===`win32`});l.stdout?.on(`data`,e=>{y.info(e)}),l.stderr?.on(`data`,e=>{y.error(`FFmpeg stderr: ${e.toString()}`),process.exit(1)}),l.stdin?.on(`error`,e=>{y.error(e),process.exit(1)}),l.on(`close`,()=>{process.exit(0)})}async function F(n,r=_){let{path:i,url:a}=n,{proxy:o,timeout:s}=await S(r),c=o?.host===``?void 0:o;if(a===``)return Promise.reject(`Extract direct link failed!`);let l=e.createWriteStream(i);return(await t({url:a,headers:{"User-Agent":T()},method:`GET`,responseType:`stream`,proxy:c,timeout:s,onDownloadProgress:e=>{let{loaded:t,total:n,progress:r}=e,i=`loaded:${t} total: ${n} progress: ${(r*100).toFixed(2)}%`;y.info(i)}})).data.pipe(l),new Promise((e,t)=>{l.on(`finish`,e),l.on(`error`,t)})}let I=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}({});export{_ as DEFAULT_OPTIONS,I as UrlType,k as downloadAnimeIdHentai,j as downloadBilibili,N as downloadDirpy,F as downloadVideo,O as getAnimeIdHentaiLink,A as getBilibiliLink,M as getDirpyLink,y as logger,P as remoteM3U8ToMP4,S as resolveConfig,b as setSilent,T as useRandomUserAgent};
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "fast-dirpy",
3
3
  "type": "module",
4
- "version": "0.1.8",
5
- "description": "A simple library/CLI to download video using dirpy.com",
4
+ "version": "0.2.0",
5
+ "description": "A simple library/CLI to download video from several websites.",
6
6
  "author": "Vincent-the-gamer",
7
7
  "license": "MIT",
8
8
  "homepage": "https://github.com/Vincent-the-gamer/fast-dirpy#readme",
@@ -31,37 +31,37 @@
31
31
  "files": [
32
32
  "dist"
33
33
  ],
34
+ "scripts": {
35
+ "tsx": "tsx",
36
+ "build": "tsdown",
37
+ "test": "vitest",
38
+ "dep": "taze major -I",
39
+ "lint:fix": "eslint . --fix",
40
+ "login": "pnpm login --registry https://registry.npmjs.com"
41
+ },
34
42
  "publishConfig": {
35
43
  "registry": "https://registry.npmjs.com",
36
44
  "access": "public"
37
45
  },
38
46
  "dependencies": {
39
- "ansis": "^3.17.0",
40
- "axios": "^1.8.4",
47
+ "ansis": "^4.2.0",
48
+ "axios": "^1.12.2",
41
49
  "cac": "^6.7.14",
50
+ "cheerio": "^1.1.2",
42
51
  "consola": "^3.4.2",
43
- "jsdom": "^26.1.0",
44
- "puppeteer-core": "^24.7.1",
52
+ "puppeteer-core": "^24.22.3",
45
53
  "restore-cursor": "^5.1.0",
46
- "unconfig": "^7.3.2"
54
+ "unconfig": "^7.3.3"
47
55
  },
48
56
  "devDependencies": {
49
- "@antfu/eslint-config": "^4.12.0",
50
- "@types/node": "^22.14.1",
57
+ "@antfu/eslint-config": "^5.4.1",
58
+ "@types/node": "^22.18.7",
51
59
  "deepmerge": "^4.3.1",
52
- "eslint": "^9.25.1",
53
- "taze": "^19.0.4",
54
- "tsup": "^8.4.0",
55
- "tsx": "^4.19.3",
56
- "typescript": "^5.8.3",
57
- "vitest": "^3.1.2"
58
- },
59
- "scripts": {
60
- "tsx": "tsx",
61
- "build": "tsup",
62
- "test": "vitest",
63
- "dep": "taze major",
64
- "lint:fix": "eslint . --fix",
65
- "login": "pnpm login --registry https://registry.npmjs.com"
60
+ "eslint": "^9.36.0",
61
+ "taze": "^19.7.0",
62
+ "tsdown": "^0.15.5",
63
+ "tsx": "^4.20.6",
64
+ "typescript": "^5.9.2",
65
+ "vitest": "^3.2.4"
66
66
  }
67
- }
67
+ }
@@ -1 +0,0 @@
1
- var n=Object.create;var i=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var c=Object.getPrototypeOf,f=Object.prototype.hasOwnProperty;var l=(t,e)=>()=>(t&&(e=t(t=0)),e);var d=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var s=(t,e,o,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let m of p(e))!f.call(t,m)&&m!==o&&i(t,m,{get:()=>e[m],enumerable:!(r=a(e,m))||r.enumerable});return t};var g=(t,e,o)=>(o=t!=null?n(c(t)):{},s(e||!t||!t.__esModule?i(o,"default",{value:t,enumerable:!0}):o,t));var _=l(()=>{"use strict"});export{d as a,g as b,_ as c};
@@ -1 +0,0 @@
1
- import{c as i}from"./chunk-HD53P4DN.js";i();function o(p){return p}export{o as a};
@@ -1 +0,0 @@
1
- import{a as T,b as C,c as i}from"./chunk-HD53P4DN.js";var E=T((Pr,L)=>{"use strict";i();var F=function(e){return N(e)&&!U(e)};function N(r){return!!r&&typeof r=="object"}function U(r){var e=Object.prototype.toString.call(r);return e==="[object RegExp]"||e==="[object Date]"||z(r)}var V=typeof Symbol=="function"&&Symbol.for,W=V?Symbol.for("react.element"):60103;function z(r){return r.$$typeof===W}function K(r){return Array.isArray(r)?[]:{}}function x(r,e){return e.clone!==!1&&e.isMergeableObject(r)?b(K(r),r,e):r}function B(r,e,t){return r.concat(e).map(function(n){return x(n,t)})}function G(r,e){if(!e.customMerge)return b;var t=e.customMerge(r);return typeof t=="function"?t:b}function H(r){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(r).filter(function(e){return Object.propertyIsEnumerable.call(r,e)}):[]}function v(r){return Object.keys(r).concat(H(r))}function S(r,e){try{return e in r}catch{return!1}}function Y(r,e){return S(r,e)&&!(Object.hasOwnProperty.call(r,e)&&Object.propertyIsEnumerable.call(r,e))}function X(r,e,t){var n={};return t.isMergeableObject(r)&&v(r).forEach(function(o){n[o]=x(r[o],t)}),v(e).forEach(function(o){Y(r,o)||(S(r,o)&&t.isMergeableObject(e[o])?n[o]=G(o,t)(r[o],e[o],t):n[o]=x(e[o],t))}),n}function b(r,e,t){t=t||{},t.arrayMerge=t.arrayMerge||B,t.isMergeableObject=t.isMergeableObject||F,t.cloneUnlessOtherwiseSpecified=x;var n=Array.isArray(e),o=Array.isArray(r),a=n===o;return a?n?t.arrayMerge(r,e,t):X(r,e,t):x(e,t)}b.all=function(e,t){if(!Array.isArray(e))throw new Error("first argument should be an array");return e.reduce(function(n,o){return b(n,o,t)},{})};var J=b;L.exports=J});i();import R from"node:process";import{consola as $}from"consola";var P=$.withTag("fast-dirpy");function yr(r){"CONSOLA_LEVEL"in R.env||(P.level=r?0:3)}i();import sr from"axios";import cr from"jsdom";i();var l={timeout:2e4};i();var D=C(E(),1);import{createConfigLoader as q}from"unconfig";async function y(r,e){let t=l,n=q({sources:[{files:["fast-dirpy.config"],extensions:["ts","mts","cts","js","mjs","cjs","json"]}],cwd:e||process.cwd(),merge:!1}),{config:o,sources:a}=await n.load();return a.length?(P.info(`Config file found: ${a[0]}`),(0,D.default)((0,D.default)(t,o),r)):(0,D.default)(t,r)}i();import Z from"puppeteer-core";async function I(r){return await Z.launch(r)}i();i();function _(r){let e=Math.floor(Math.random()*r.length);return r[e]}var Q=["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 w(){return _(Q)}i();import ir from"node:fs";import ar from"axios";i();function rr(r){let e=r.match(/BV[a-zA-Z0-9]+/);return e?`https://bilibili-real-url.deno.dev/${e[0]}.mp4`:""}async function Rr(r){let{path:e,url:t}=r,n=rr(t);n!==""?await O({url:n,path:e||"./download.mp4"}):console.error("Extract direct link failed!")}i();import er from"axios";import tr from"jsdom";var{JSDOM:or}=tr;async function nr(r,e=l){let{url:t,cwd:n}=r,{proxy:o,timeout:a}=await y(e,n),u=o?.host!==""?o:void 0,{data:f}=await er.get("https://dirpy.com/studio",{params:{url:t},headers:{"User-Agent":w(),Referer:`https://dirpy.com/studio?url=${t}`},proxy:u,timeout:a}),{window:g}=new or(f),c="",s=g.document.getElementById("media-source");return s&&(c=s.src),c}async function Br(r,e=l){let{path:t,url:n,cwd:o}=r,a=await nr({url:n},e);await O({url:a,path:t,cwd:o},e)}async function O(r,e=l){let{path:t,url:n}=r,{proxy:o,timeout:a}=await y(e),u=o?.host!==""?o:void 0;if(n==="")return Promise.reject("Extract direct link failed!");let f=ir.createWriteStream(t);return(await ar({url:n,headers:{"User-Agent":w()},method:"GET",responseType:"stream",proxy:u,timeout:a,onDownloadProgress:c=>{let{loaded:s,total:h,progress:d}=c,A=`loaded:${s} total: ${h} progress: ${(d*100).toFixed(2)}%`;P.info(A)}})).data.pipe(f),new Promise((c,s)=>{f.on("finish",c),f.on("error",s)})}var{JSDOM:pr}=cr;async function mr(r,e=l){let{url:t,cwd:n}=r,{proxy:o,timeout:a}=await y(e,n),u=o?.host!==""?o:void 0,{data:f}=await sr.get(t,{headers:{"User-Agent":w()},proxy:u,timeout:a}),{window:g}=new pr(f),c="",s=g.document.querySelector("div.embed.rad2 > iframe");return s&&(c=s.src),c}async function lr(r,e=l){let{url:t,cwd:n}=r,{proxy:o,puppeteer:a}=await y(e,n),u=o?.host!==""?o:void 0,f=await mr({url:t},{proxy:u}),{executablePath:g,headless:c}=a,s=await I({executablePath:g,headless:c,args:[`--proxy-server=http://${u?.host}:${o?.port}`]}),h=w(),d=await s.newPage();await d.setUserAgent(h),await d.goto(f),await d.waitForSelector("div.play.p-pulse"),await d.click("div.play.p-pulse"),await d.waitForSelector("div.frame > iframe");let A=await d.$eval("div.frame > iframe",M=>M.src),j=await s.newPage();await j.goto(`${A}`),await j.waitForSelector("video.jw-video.jw-reset");let k=await j.$eval("video.jw-video.jw-reset",M=>M.src);return await s.close(),k}async function fe(r,e=l){let{path:t,url:n,cwd:o}=r,a=await lr({url:n},e);await O({url:a,path:t,cwd:o},e)}i();var fr=(o=>(o[o.Bilibili=0]="Bilibili",o[o.Dirpy=1]="Dirpy",o[o.AnimeIdHentai=2]="AnimeIdHentai",o[o.Others=3]="Others",o))(fr||{});export{P as a,yr as b,lr as c,fe as d,rr as e,Rr as f,nr as g,Br as h,O as i,fr as j};
@@ -1,31 +0,0 @@
1
- interface DirpyOptions {
2
- proxy?: {
3
- protocol?: string;
4
- host: string;
5
- port: number;
6
- };
7
- timeout?: number;
8
- puppeteer?: {
9
- executablePath: string;
10
- headless?: boolean;
11
- };
12
- }
13
- interface DirectLinkParams {
14
- url: string;
15
- cwd?: string;
16
- }
17
- interface DownloadParams {
18
- url: string;
19
- path: string;
20
- cwd?: string;
21
- }
22
- declare enum UrlType {
23
- Bilibili = 0,
24
- Dirpy = 1,
25
- AnimeIdHentai = 2,
26
- Others = 3
27
- }
28
-
29
- declare function defineConfig(options: DirpyOptions): DirpyOptions;
30
-
31
- export { type DirectLinkParams as D, UrlType as U, type DirpyOptions as a, type DownloadParams as b, defineConfig as d };