fast-dirpy 0.2.0 → 0.2.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
@@ -16,8 +16,22 @@ 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>NSFW</summary>
21
+
22
+ * [Animehentai](https://animeidhentai.com/)
23
+ * [Koreanpornmovies](https://koreanpornmovie.com/)
24
+ * [XVideos](https://www.xvideos.com/)
25
+ * [Missav](https://missav.ws/) (m3u8)
26
+ </details>
27
+
28
+
19
29
  And `.m3u8` videos(using `ffmpeg`).
20
30
 
31
+ > [!IMPORTANT]
32
+ > From v0.2.1, .m3u8 downloader is no longer using ffmpeg.
33
+ > And it doesn't provide proxy settings, so, you need to use `export https_proxy=http://ip:port` to set proxy manually in terminal.
34
+
21
35
  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.
22
36
 
23
37
  ## Installation
package/bin/fast-dirpy.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fast-dirpy",
3
3
  "type": "module",
4
- "version": "0.2.0",
4
+ "version": "0.2.1",
5
5
  "description": "A simple library/CLI to download video from several websites.",
6
6
  "author": "Vincent-the-gamer",
7
7
  "license": "MIT",
@@ -31,14 +31,6 @@
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
- },
42
34
  "publishConfig": {
43
35
  "registry": "https://registry.npmjs.com",
44
36
  "access": "public"
@@ -49,19 +41,28 @@
49
41
  "cac": "^6.7.14",
50
42
  "cheerio": "^1.1.2",
51
43
  "consola": "^3.4.2",
52
- "puppeteer-core": "^24.22.3",
44
+ "m3u8stream": "^0.8.6",
45
+ "puppeteer-core": "^24.23.0",
53
46
  "restore-cursor": "^5.1.0",
54
47
  "unconfig": "^7.3.3"
55
48
  },
56
49
  "devDependencies": {
57
50
  "@antfu/eslint-config": "^5.4.1",
58
- "@types/node": "^22.18.7",
51
+ "@types/node": "^24.7.0",
59
52
  "deepmerge": "^4.3.1",
60
- "eslint": "^9.36.0",
53
+ "eslint": "^9.37.0",
61
54
  "taze": "^19.7.0",
62
- "tsdown": "^0.15.5",
55
+ "tsdown": "^0.15.6",
63
56
  "tsx": "^4.20.6",
64
- "typescript": "^5.9.2",
57
+ "typescript": "^5.9.3",
65
58
  "vitest": "^3.2.4"
59
+ },
60
+ "scripts": {
61
+ "tsx": "tsx",
62
+ "build": "tsdown",
63
+ "test": "vitest",
64
+ "dep": "taze major -I",
65
+ "lint:fix": "eslint . --fix",
66
+ "login": "pnpm login --registry https://registry.npmjs.com"
66
67
  }
67
- }
68
+ }
package/dist/cli.d.ts DELETED
@@ -1 +0,0 @@
1
- export { };
package/dist/cli.js DELETED
@@ -1 +0,0 @@
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{};
@@ -1,35 +0,0 @@
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 };
@@ -1 +0,0 @@
1
- function e(e){return e}export{e as defineConfig};
package/dist/config.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import { defineConfig } from "./config-BbJq3Qd3.js";
2
- export { defineConfig };
package/dist/config.js DELETED
@@ -1 +0,0 @@
1
- import{defineConfig as e}from"./config-ld9QlYHr.js";export{e as defineConfig};
package/dist/index.d.ts DELETED
@@ -1,29 +0,0 @@
1
- import { DirectLinkParams, DownloadParams, Options, UrlType, defineConfig } from "./config-BbJq3Qd3.js";
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
8
- declare function getBilibiliLink(link: string): string;
9
- declare function downloadBilibili(params: DownloadParams): Promise<void>;
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 DELETED
@@ -1 +0,0 @@
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};
@@ -1 +0,0 @@
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};