mirror of
https://github.com/anidl/multi-downloader-nx.git
synced 2026-03-11 17:45:30 +00:00
Test + Style
This commit is contained in:
parent
255574df1b
commit
2c07f51f54
14 changed files with 1560 additions and 1494 deletions
2
.eslintignore
Normal file
2
.eslintignore
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
lib
|
||||
/videos/*.ts
|
||||
23
.github/workflows/eslint.yml
vendored
23
.github/workflows/eslint.yml
vendored
|
|
@ -1,23 +0,0 @@
|
|||
name: eslint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
- run: npm i
|
||||
- run: npx eslint .
|
||||
33
.github/workflows/test.yml
vendored
Normal file
33
.github/workflows/test.yml
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
name: eslint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
eslint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js 14
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14
|
||||
cache: 'npm'
|
||||
- run: npm i
|
||||
- run: npx eslint .
|
||||
test:
|
||||
needs: eslint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js 14
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14
|
||||
cache: 'npm'
|
||||
- run: npm i
|
||||
- run: npm run test
|
||||
|
||||
39
@types/episode.d.ts
vendored
39
@types/episode.d.ts
vendored
|
|
@ -59,20 +59,20 @@ export interface Value {
|
|||
}
|
||||
|
||||
export enum Label {
|
||||
Rating = "Rating",
|
||||
RatingSystem = "Rating System",
|
||||
ReleaseDate = "Release Date",
|
||||
Synopsis = "Synopsis",
|
||||
SynopsisType = "Synopsis Type",
|
||||
Rating = 'Rating',
|
||||
RatingSystem = 'Rating System',
|
||||
ReleaseDate = 'Release Date',
|
||||
Synopsis = 'Synopsis',
|
||||
SynopsisType = 'Synopsis Type',
|
||||
}
|
||||
|
||||
export enum MetaType {
|
||||
Rating = "rating",
|
||||
RatingSystemType = "RatingSystemType",
|
||||
ReleaseDate = "release-date",
|
||||
Synopsis = "synopsis",
|
||||
Synopsistype = "synopsistype",
|
||||
VideoRatingType = "VideoRatingType",
|
||||
Rating = 'rating',
|
||||
RatingSystemType = 'RatingSystemType',
|
||||
ReleaseDate = 'release-date',
|
||||
Synopsis = 'synopsis',
|
||||
Synopsistype = 'synopsistype',
|
||||
VideoRatingType = 'VideoRatingType',
|
||||
}
|
||||
|
||||
export interface HistoricalSelections {
|
||||
|
|
@ -87,8 +87,8 @@ export interface EpisodeDataIDS {
|
|||
}
|
||||
|
||||
export enum TitleElement {
|
||||
Empty = "",
|
||||
English = "English",
|
||||
Empty = '',
|
||||
English = 'English',
|
||||
}
|
||||
|
||||
export interface Media {
|
||||
|
|
@ -194,8 +194,7 @@ export interface AvailIDS {
|
|||
externalAlphaId: string;
|
||||
}
|
||||
|
||||
export interface Next {
|
||||
}
|
||||
export type Next = Record<string, unknown>
|
||||
|
||||
export interface LanguageClass {
|
||||
code: string;
|
||||
|
|
@ -299,7 +298,7 @@ export interface CatalogParent {
|
|||
}
|
||||
|
||||
export enum Source {
|
||||
Dbb = "dbb",
|
||||
Dbb = 'dbb',
|
||||
}
|
||||
|
||||
export interface MetaItems {
|
||||
|
|
@ -313,10 +312,10 @@ export interface Filters {
|
|||
}
|
||||
|
||||
export interface Items {
|
||||
"release-date": AnimationProductionStudio;
|
||||
'release-date': AnimationProductionStudio;
|
||||
rating: AnimationProductionStudio;
|
||||
synopsis: AnimationProductionStudio;
|
||||
"animation-production-studio": AnimationProductionStudio;
|
||||
'animation-production-studio': AnimationProductionStudio;
|
||||
}
|
||||
|
||||
export interface AnimationProductionStudio {
|
||||
|
|
@ -366,8 +365,8 @@ export interface PreviousSeasonEpisode {
|
|||
}
|
||||
|
||||
export enum Type {
|
||||
Episode = "episode",
|
||||
Ova = "ova",
|
||||
Episode = 'episode',
|
||||
Ova = 'ova',
|
||||
}
|
||||
|
||||
export interface Quality {
|
||||
|
|
|
|||
2
@types/hls-download.d.ts
vendored
2
@types/hls-download.d.ts
vendored
|
|
@ -2,7 +2,7 @@ declare module 'hls-download' {
|
|||
export default class hlsDownload {
|
||||
constructor(options: {
|
||||
m3u8json: {
|
||||
segments: {}[],
|
||||
segments: Record<string, unknown>[],
|
||||
mediaSequence?: number,
|
||||
},
|
||||
output?: string,
|
||||
|
|
|
|||
23
@types/items.d.ts
vendored
23
@types/items.d.ts
vendored
|
|
@ -39,8 +39,8 @@ export interface Item {
|
|||
}
|
||||
|
||||
export enum ContentType {
|
||||
Episode = "episode",
|
||||
Ova = "ova",
|
||||
Episode = 'episode',
|
||||
Ova = 'ova',
|
||||
}
|
||||
|
||||
export interface IDs {
|
||||
|
|
@ -110,19 +110,18 @@ export interface MostRecentAvodIDS {
|
|||
}
|
||||
|
||||
export enum Purchase {
|
||||
AVOD = "A-VOD",
|
||||
Dfov = "DFOV",
|
||||
Est = "EST",
|
||||
Svod = "SVOD",
|
||||
AVOD = 'A-VOD',
|
||||
Dfov = 'DFOV',
|
||||
Est = 'EST',
|
||||
Svod = 'SVOD',
|
||||
}
|
||||
|
||||
export enum Version {
|
||||
Simulcast = "Simulcast",
|
||||
Uncut = "Uncut",
|
||||
Simulcast = 'Simulcast',
|
||||
Uncut = 'Uncut',
|
||||
}
|
||||
|
||||
export interface MostRecentSvodJpnUs {
|
||||
}
|
||||
export type MostRecentSvodJpnUs = Record<string, any>
|
||||
|
||||
export interface QualityClass {
|
||||
quality: QualityQuality;
|
||||
|
|
@ -130,8 +129,8 @@ export interface QualityClass {
|
|||
}
|
||||
|
||||
export enum QualityQuality {
|
||||
HD = "HD",
|
||||
SD = "SD",
|
||||
HD = 'HD',
|
||||
SD = 'SD',
|
||||
}
|
||||
|
||||
export interface TitleImages {
|
||||
|
|
|
|||
16
@types/m3u8-parsed.d.ts
vendored
16
@types/m3u8-parsed.d.ts
vendored
|
|
@ -32,17 +32,17 @@ declare module 'm3u8-parsed' {
|
|||
uri: string,
|
||||
timeline: number,
|
||||
attributes: {
|
||||
"CLOSED-CAPTIONS": string,
|
||||
"AUDIO": string,
|
||||
"FRAME-RATE": number,
|
||||
"RESOLUTION": {
|
||||
'CLOSED-CAPTIONS': string,
|
||||
'AUDIO': string,
|
||||
'FRAME-RATE': number,
|
||||
'RESOLUTION': {
|
||||
width: number,
|
||||
height: number
|
||||
},
|
||||
"CODECS": string,
|
||||
"AVERAGE-BANDWIDTH": string,
|
||||
"BANDWIDTH": number
|
||||
'CODECS': string,
|
||||
'AVERAGE-BANDWIDTH': string,
|
||||
'BANDWIDTH': number
|
||||
}
|
||||
}[],
|
||||
}
|
||||
};
|
||||
}
|
||||
113
modules/build.ts
113
modules/build.ts
|
|
@ -5,69 +5,70 @@ import fs from 'fs-extra';
|
|||
import pkg from '../package.json';
|
||||
import modulesCleanup from 'removeNPMAbsolutePaths';
|
||||
import { exec } from 'pkg';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
const buildsDir = './_builds';
|
||||
const nodeVer = 'node14-';
|
||||
|
||||
// main
|
||||
(async function(){
|
||||
const buildStr = `${pkg.name}-${pkg.version}`;
|
||||
const acceptableBuilds = ['win64','linux64','macos64'];
|
||||
const buildType = process.argv[2];
|
||||
if(!acceptableBuilds.includes(buildType)){
|
||||
console.error('[ERROR] unknown build type!');
|
||||
process.exit(1);
|
||||
}
|
||||
await modulesCleanup('.');
|
||||
if(!fs.existsSync(buildsDir)){
|
||||
fs.mkdirSync(buildsDir);
|
||||
}
|
||||
const buildFull = `${buildStr}-${buildType}`;
|
||||
const buildDir = `${buildsDir}/${buildFull}`;
|
||||
if(fs.existsSync(buildDir)){
|
||||
fs.removeSync(buildDir);
|
||||
}
|
||||
fs.mkdirSync(buildDir);
|
||||
const buildConfig = [
|
||||
pkg.main,
|
||||
'--target', nodeVer + getTarget(buildType),
|
||||
'--output', `${buildDir}/${pkg.short_name}`,
|
||||
];
|
||||
console.log(`[Build] Build configuration: ${buildFull}`);
|
||||
try {
|
||||
await exec(buildConfig);
|
||||
}
|
||||
catch(e){
|
||||
console.log(e);
|
||||
process.exit(1);
|
||||
}
|
||||
fs.mkdirSync(`${buildDir}/bin`);
|
||||
fs.mkdirSync(`${buildDir}/config`);
|
||||
fs.mkdirSync(`${buildDir}/videos`);
|
||||
fs.copySync('./bin/', `${buildDir}/bin/`);
|
||||
fs.copySync('./config/bin-path.yml', `${buildDir}/config/bin-path.yml`);
|
||||
fs.copySync('./config/cli-defaults.yml', `${buildDir}/config/cli-defaults.yml`);
|
||||
fs.copySync('./config/dir-path.yml', `${buildDir}/config/dir-path.yml`);
|
||||
fs.copySync('./modules/cmd-here.bat', `${buildDir}/cmd-here.bat`);
|
||||
fs.copySync('./modules/NotoSans-Regular.ttf', `${buildDir}/NotoSans-Regular.ttf`);
|
||||
fs.copySync('./package.json', `${buildDir}/package.json`)
|
||||
fs.copySync('./docs/', `${buildDir}/docs/`);
|
||||
fs.copySync('./LICENSE.md', `${buildDir}/docs/LICENSE.md`);
|
||||
if(fs.existsSync(`${buildsDir}/${buildFull}.7z`)){
|
||||
fs.removeSync(`${buildsDir}/${buildFull}.7z`);
|
||||
}
|
||||
require('child_process').execSync(`7z a -t7z "${buildsDir}/${buildFull}.7z" "${buildDir}"`,{stdio:[0,1,2]});
|
||||
const buildStr = `${pkg.name}-${pkg.version}`;
|
||||
const acceptableBuilds = ['win64','linux64','macos64'];
|
||||
const buildType = process.argv[2];
|
||||
if(!acceptableBuilds.includes(buildType)){
|
||||
console.error('[ERROR] unknown build type!');
|
||||
process.exit(1);
|
||||
}
|
||||
await modulesCleanup('.');
|
||||
if(!fs.existsSync(buildsDir)){
|
||||
fs.mkdirSync(buildsDir);
|
||||
}
|
||||
const buildFull = `${buildStr}-${buildType}`;
|
||||
const buildDir = `${buildsDir}/${buildFull}`;
|
||||
if(fs.existsSync(buildDir)){
|
||||
fs.removeSync(buildDir);
|
||||
}
|
||||
fs.mkdirSync(buildDir);
|
||||
const buildConfig = [
|
||||
pkg.main,
|
||||
'--target', nodeVer + getTarget(buildType),
|
||||
'--output', `${buildDir}/${pkg.short_name}`,
|
||||
];
|
||||
console.log(`[Build] Build configuration: ${buildFull}`);
|
||||
try {
|
||||
await exec(buildConfig);
|
||||
}
|
||||
catch(e){
|
||||
console.log(e);
|
||||
process.exit(1);
|
||||
}
|
||||
fs.mkdirSync(`${buildDir}/bin`);
|
||||
fs.mkdirSync(`${buildDir}/config`);
|
||||
fs.mkdirSync(`${buildDir}/videos`);
|
||||
fs.copySync('./bin/', `${buildDir}/bin/`);
|
||||
fs.copySync('./config/bin-path.yml', `${buildDir}/config/bin-path.yml`);
|
||||
fs.copySync('./config/cli-defaults.yml', `${buildDir}/config/cli-defaults.yml`);
|
||||
fs.copySync('./config/dir-path.yml', `${buildDir}/config/dir-path.yml`);
|
||||
fs.copySync('./modules/cmd-here.bat', `${buildDir}/cmd-here.bat`);
|
||||
fs.copySync('./modules/NotoSans-Regular.ttf', `${buildDir}/NotoSans-Regular.ttf`);
|
||||
fs.copySync('./package.json', `${buildDir}/package.json`);
|
||||
fs.copySync('./docs/', `${buildDir}/docs/`);
|
||||
fs.copySync('./LICENSE.md', `${buildDir}/docs/LICENSE.md`);
|
||||
if(fs.existsSync(`${buildsDir}/${buildFull}.7z`)){
|
||||
fs.removeSync(`${buildsDir}/${buildFull}.7z`);
|
||||
}
|
||||
execSync(`7z a -t7z "${buildsDir}/${buildFull}.7z" "${buildDir}"`,{stdio:[0,1,2]});
|
||||
}());
|
||||
|
||||
function getTarget(bt: string) : string {
|
||||
switch(bt){
|
||||
case 'win64':
|
||||
return 'windows-x64';
|
||||
case 'linux64':
|
||||
return 'linux-x64';
|
||||
case 'macos64':
|
||||
return 'macos-x64';
|
||||
default:
|
||||
return 'windows-x64';
|
||||
}
|
||||
switch(bt){
|
||||
case 'win64':
|
||||
return 'windows-x64';
|
||||
case 'linux64':
|
||||
return 'linux-x64';
|
||||
case 'macos64':
|
||||
return 'macos-x64';
|
||||
default:
|
||||
return 'windows-x64';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import yargs from 'yargs';
|
||||
|
||||
const availableFilenameVars = [
|
||||
'title',
|
||||
'episode',
|
||||
'showTitle',
|
||||
'season',
|
||||
'width',
|
||||
'height'
|
||||
'title',
|
||||
'episode',
|
||||
'showTitle',
|
||||
'season',
|
||||
'width',
|
||||
'height'
|
||||
];
|
||||
|
||||
export type possibleDubs = (
|
||||
|
|
@ -22,241 +22,241 @@ const dubLang: possibleDubs = ['enUS', 'esLA', 'ptBR', 'zhMN', 'jaJP'];
|
|||
const appArgv = (cfg: {
|
||||
[key: string]: unknown
|
||||
}) => {
|
||||
// init
|
||||
const parseDefault = <T = unknown>(key: string, _default: T) : T=> {
|
||||
if (Object.prototype.hasOwnProperty.call(cfg, key)) {
|
||||
return cfg[key] as T;
|
||||
} else
|
||||
return _default;
|
||||
};
|
||||
const argv = yargs.parserConfiguration({
|
||||
'duplicate-arguments-array': true,
|
||||
'camel-case-expansion': false
|
||||
// init
|
||||
const parseDefault = <T = unknown>(key: string, _default: T) : T=> {
|
||||
if (Object.prototype.hasOwnProperty.call(cfg, key)) {
|
||||
return cfg[key] as T;
|
||||
} else
|
||||
return _default;
|
||||
};
|
||||
const argv = yargs.parserConfiguration({
|
||||
'duplicate-arguments-array': true,
|
||||
'camel-case-expansion': false
|
||||
})
|
||||
// main
|
||||
.wrap(Math.min(120)) // yargs.terminalWidth()
|
||||
.help(false).version(false)
|
||||
.usage('Usage: $0 [options]')
|
||||
// auth
|
||||
.option('auth', {
|
||||
group: 'Authentication:',
|
||||
describe: 'Enter authentication mode',
|
||||
type: 'boolean',
|
||||
})
|
||||
// main
|
||||
.wrap(Math.min(120)) // yargs.terminalWidth()
|
||||
.help(false).version(false)
|
||||
.usage('Usage: $0 [options]')
|
||||
// auth
|
||||
.option('auth', {
|
||||
group: 'Authentication:',
|
||||
describe: 'Enter authentication mode',
|
||||
type: 'boolean',
|
||||
})
|
||||
// search
|
||||
.option('search', {
|
||||
alias: 'f',
|
||||
group: 'Search:',
|
||||
describe: 'Search show ids',
|
||||
type: 'string',
|
||||
})
|
||||
// select show and eps
|
||||
.option('s', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Sets the show id',
|
||||
type: 'number',
|
||||
})
|
||||
.option('e', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Select episode ids (comma-separated, hyphen-sequence)',
|
||||
type: 'string',
|
||||
})
|
||||
.option('all', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Used to download all episodes from the show',
|
||||
type: 'boolean',
|
||||
default: parseDefault<boolean>('all', false)
|
||||
})
|
||||
.option('partsize', {
|
||||
group: 'Downloading:',
|
||||
describe: 'The amount of parts that should be downloaded in paralell',
|
||||
type: 'number',
|
||||
default: parseDefault<number>('partsize', 10)
|
||||
})
|
||||
// quality
|
||||
.option('q', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Select video layer (0 is max)',
|
||||
choices: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
||||
default: parseDefault<number>('videoLayer', 7),
|
||||
type: 'number',
|
||||
})
|
||||
// alt listing
|
||||
.option('alt', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Alternative episode listing (if available)',
|
||||
default: parseDefault<boolean>('altList', false),
|
||||
type: 'boolean',
|
||||
})
|
||||
// switch to subs
|
||||
.option('dub', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Download non-Japanese Dub (English Dub mode by default)',
|
||||
choices: dubLang,
|
||||
default: parseDefault<possibleDubs>('dub', ['enUS']),
|
||||
type: 'array',
|
||||
})
|
||||
.option('subLang', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Set the subtitle language (English is default and fallback)',
|
||||
default: parseDefault<possibleSubs>('subLang', ['enUS']),
|
||||
choices: subLang,
|
||||
type: 'array'
|
||||
})
|
||||
.option('fontSize', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Used to set the fontsize of the subtitles',
|
||||
default: parseDefault<number>('fontSize', 55),
|
||||
type: 'number'
|
||||
})
|
||||
.option('allSubs', {
|
||||
group: 'Downloading:',
|
||||
describe: 'If set to true, all available subs will get downloaded',
|
||||
default: false,
|
||||
type: 'boolean'
|
||||
})
|
||||
.option('allDubs', {
|
||||
group: 'Downloading:',
|
||||
describe: 'If set to true, all available dubs will get downloaded',
|
||||
default: false,
|
||||
type: 'boolean'
|
||||
})
|
||||
// simulcast
|
||||
.option('simul', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Force downloading simulcast ver. instead of uncut ver. (if uncut ver. available)',
|
||||
default: parseDefault<boolean>('forceSimul', false),
|
||||
type: 'boolean',
|
||||
})
|
||||
// server number
|
||||
.option('x', {
|
||||
alias: 'server',
|
||||
group: 'Downloading:',
|
||||
describe: 'Select server',
|
||||
choices: [1, 2, 3, 4],
|
||||
default: parseDefault<number>('nServer', 1),
|
||||
type: 'number',
|
||||
})
|
||||
// skip
|
||||
.option('noaudio', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Skip downloading audio',
|
||||
type: 'boolean'
|
||||
})
|
||||
.option('novids', {
|
||||
group: 'Downloading:',
|
||||
alias: 'skipdl',
|
||||
describe: 'Skip downloading video',
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('nosubs', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Skip downloading subtitles for English Dub (if available)',
|
||||
type: 'boolean',
|
||||
default: false
|
||||
})
|
||||
// proxy
|
||||
.option('proxy', {
|
||||
group: 'Proxy:',
|
||||
describe: 'Set http(s)/socks proxy WHATWG url',
|
||||
default: parseDefault<boolean>('proxy', false),
|
||||
hidden: true,
|
||||
})
|
||||
.option('proxy-auth', {
|
||||
group: 'Proxy:',
|
||||
describe: 'Colon-separated username and password for proxy',
|
||||
default: parseDefault<string|boolean>('proxy_auth', false),
|
||||
hidden: true,
|
||||
})
|
||||
.option('ssp', {
|
||||
group: 'Proxy:',
|
||||
describe: 'Don\'t use proxy for stream and subtitles downloading',
|
||||
default: parseDefault<boolean>('proxy_ssp', false),
|
||||
hidden: true,
|
||||
type: 'boolean',
|
||||
})
|
||||
// muxing
|
||||
.option('skipmux', {
|
||||
group: 'Muxing:',
|
||||
describe: 'Skip muxing video and subtitles',
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('mp4', {
|
||||
group: 'Muxing:',
|
||||
describe: 'Mux into mp4',
|
||||
default: parseDefault<boolean>('mp4mux', false),
|
||||
type: 'boolean'
|
||||
})
|
||||
// filenaming
|
||||
.option('fileName', {
|
||||
group: 'Filename Template:',
|
||||
describe: `Set the filename template. Use \${variable_name} to insert variables.\nYou may use ${availableFilenameVars
|
||||
.map(a => `'${a}'`).join(', ')} as variables.`,
|
||||
type: 'string',
|
||||
default: parseDefault<string>('fileName', '[Funimation] ${showTitle} - ${episode} [${height}p]')
|
||||
})
|
||||
.option('numbers', {
|
||||
group: 'Filename Template:',
|
||||
describe: `Set how long a number in the title should be at least.\n${[[3, 5, '005'], [2, 1, '01'], [1, 20, '20']]
|
||||
.map(val => `Set in config: ${val[0]}; Episode number: ${val[1]}; Output: ${val[2]}`).join('\n')}`,
|
||||
type: 'number',
|
||||
default: parseDefault<number>('numbers', 2)
|
||||
})
|
||||
// util
|
||||
.option('nocleanup', {
|
||||
group: 'Utilities:',
|
||||
describe: 'Dont\'t delete the input files after muxing',
|
||||
default: parseDefault<boolean>('noCleanUp', false),
|
||||
type: 'boolean'
|
||||
})
|
||||
.option('timeout', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Set the timeout of all download reqests. Set in millisecods',
|
||||
type: 'number',
|
||||
default: parseDefault('timeout', 60 * 1000)
|
||||
})
|
||||
.option('debug', {
|
||||
group: 'Utilities:',
|
||||
describe: 'Used to enter debug mode. Please use this flag when opening an issue to get more information'
|
||||
// search
|
||||
.option('search', {
|
||||
alias: 'f',
|
||||
group: 'Search:',
|
||||
describe: 'Search show ids',
|
||||
type: 'string',
|
||||
})
|
||||
// select show and eps
|
||||
.option('s', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Sets the show id',
|
||||
type: 'number',
|
||||
})
|
||||
.option('e', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Select episode ids (comma-separated, hyphen-sequence)',
|
||||
type: 'string',
|
||||
})
|
||||
.option('all', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Used to download all episodes from the show',
|
||||
type: 'boolean',
|
||||
default: parseDefault<boolean>('all', false)
|
||||
})
|
||||
.option('partsize', {
|
||||
group: 'Downloading:',
|
||||
describe: 'The amount of parts that should be downloaded in paralell',
|
||||
type: 'number',
|
||||
default: parseDefault<number>('partsize', 10)
|
||||
})
|
||||
// quality
|
||||
.option('q', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Select video layer (0 is max)',
|
||||
choices: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
||||
default: parseDefault<number>('videoLayer', 7),
|
||||
type: 'number',
|
||||
})
|
||||
// alt listing
|
||||
.option('alt', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Alternative episode listing (if available)',
|
||||
default: parseDefault<boolean>('altList', false),
|
||||
type: 'boolean',
|
||||
})
|
||||
// switch to subs
|
||||
.option('dub', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Download non-Japanese Dub (English Dub mode by default)',
|
||||
choices: dubLang,
|
||||
default: parseDefault<possibleDubs>('dub', ['enUS']),
|
||||
type: 'array',
|
||||
})
|
||||
.option('subLang', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Set the subtitle language (English is default and fallback)',
|
||||
default: parseDefault<possibleSubs>('subLang', ['enUS']),
|
||||
choices: subLang,
|
||||
type: 'array'
|
||||
})
|
||||
.option('fontSize', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Used to set the fontsize of the subtitles',
|
||||
default: parseDefault<number>('fontSize', 55),
|
||||
type: 'number'
|
||||
})
|
||||
.option('allSubs', {
|
||||
group: 'Downloading:',
|
||||
describe: 'If set to true, all available subs will get downloaded',
|
||||
default: false,
|
||||
type: 'boolean'
|
||||
})
|
||||
.option('allDubs', {
|
||||
group: 'Downloading:',
|
||||
describe: 'If set to true, all available dubs will get downloaded',
|
||||
default: false,
|
||||
type: 'boolean'
|
||||
})
|
||||
// simulcast
|
||||
.option('simul', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Force downloading simulcast ver. instead of uncut ver. (if uncut ver. available)',
|
||||
default: parseDefault<boolean>('forceSimul', false),
|
||||
type: 'boolean',
|
||||
})
|
||||
// server number
|
||||
.option('x', {
|
||||
alias: 'server',
|
||||
group: 'Downloading:',
|
||||
describe: 'Select server',
|
||||
choices: [1, 2, 3, 4],
|
||||
default: parseDefault<number>('nServer', 1),
|
||||
type: 'number',
|
||||
})
|
||||
// skip
|
||||
.option('noaudio', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Skip downloading audio',
|
||||
type: 'boolean'
|
||||
})
|
||||
.option('novids', {
|
||||
group: 'Downloading:',
|
||||
alias: 'skipdl',
|
||||
describe: 'Skip downloading video',
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('nosubs', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Skip downloading subtitles for English Dub (if available)',
|
||||
type: 'boolean',
|
||||
default: false
|
||||
})
|
||||
// proxy
|
||||
.option('proxy', {
|
||||
group: 'Proxy:',
|
||||
describe: 'Set http(s)/socks proxy WHATWG url',
|
||||
default: parseDefault<boolean>('proxy', false),
|
||||
hidden: true,
|
||||
})
|
||||
.option('proxy-auth', {
|
||||
group: 'Proxy:',
|
||||
describe: 'Colon-separated username and password for proxy',
|
||||
default: parseDefault<string|boolean>('proxy_auth', false),
|
||||
hidden: true,
|
||||
})
|
||||
.option('ssp', {
|
||||
group: 'Proxy:',
|
||||
describe: 'Don\'t use proxy for stream and subtitles downloading',
|
||||
default: parseDefault<boolean>('proxy_ssp', false),
|
||||
hidden: true,
|
||||
type: 'boolean',
|
||||
})
|
||||
// muxing
|
||||
.option('skipmux', {
|
||||
group: 'Muxing:',
|
||||
describe: 'Skip muxing video and subtitles',
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('mp4', {
|
||||
group: 'Muxing:',
|
||||
describe: 'Mux into mp4',
|
||||
default: parseDefault<boolean>('mp4mux', false),
|
||||
type: 'boolean'
|
||||
})
|
||||
// filenaming
|
||||
.option('fileName', {
|
||||
group: 'Filename Template:',
|
||||
describe: `Set the filename template. Use \${variable_name} to insert variables.\nYou may use ${availableFilenameVars
|
||||
.map(a => `'${a}'`).join(', ')} as variables.`,
|
||||
type: 'string',
|
||||
default: parseDefault<string>('fileName', '[Funimation] ${showTitle} - ${episode} [${height}p]')
|
||||
})
|
||||
.option('numbers', {
|
||||
group: 'Filename Template:',
|
||||
describe: `Set how long a number in the title should be at least.\n${[[3, 5, '005'], [2, 1, '01'], [1, 20, '20']]
|
||||
.map(val => `Set in config: ${val[0]}; Episode number: ${val[1]}; Output: ${val[2]}`).join('\n')}`,
|
||||
type: 'number',
|
||||
default: parseDefault<number>('numbers', 2)
|
||||
})
|
||||
// util
|
||||
.option('nocleanup', {
|
||||
group: 'Utilities:',
|
||||
describe: 'Dont\'t delete the input files after muxing',
|
||||
default: parseDefault<boolean>('noCleanUp', false),
|
||||
type: 'boolean'
|
||||
})
|
||||
.option('timeout', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Set the timeout of all download reqests. Set in millisecods',
|
||||
type: 'number',
|
||||
default: parseDefault('timeout', 60 * 1000)
|
||||
})
|
||||
.option('debug', {
|
||||
group: 'Utilities:',
|
||||
describe: 'Used to enter debug mode. Please use this flag when opening an issue to get more information'
|
||||
+ '\n!Be careful! - Your token might be exposed so make sure to delete it!',
|
||||
type: 'boolean',
|
||||
default: false
|
||||
})
|
||||
// help
|
||||
.option('help', {
|
||||
alias: 'h',
|
||||
group: 'Help:',
|
||||
describe: 'Show this help',
|
||||
type: 'boolean'
|
||||
})
|
||||
// usage
|
||||
.example([
|
||||
['$0 --search "My Hero"', 'search "My Hero" in title'],
|
||||
['$0 -s 124389 -e 1,2,3', 'download episodes 1-3 from show with id 124389'],
|
||||
['$0 -s 124389 -e 1-3,2-7,s1-2', 'download episodes 1-7 and "S"-episodes 1-2 from show with id 124389'],
|
||||
])
|
||||
type: 'boolean',
|
||||
default: false
|
||||
})
|
||||
// help
|
||||
.option('help', {
|
||||
alias: 'h',
|
||||
group: 'Help:',
|
||||
describe: 'Show this help',
|
||||
type: 'boolean'
|
||||
})
|
||||
// usage
|
||||
.example([
|
||||
['$0 --search "My Hero"', 'search "My Hero" in title'],
|
||||
['$0 -s 124389 -e 1,2,3', 'download episodes 1-3 from show with id 124389'],
|
||||
['$0 -s 124389 -e 1-3,2-7,s1-2', 'download episodes 1-7 and "S"-episodes 1-2 from show with id 124389'],
|
||||
])
|
||||
|
||||
// --
|
||||
.parseSync();
|
||||
// --
|
||||
.parseSync();
|
||||
// Resolve unwanted arrays
|
||||
if (argv.allDubs)
|
||||
argv.dub = dubLang;
|
||||
if (argv.allSubs)
|
||||
argv.subLang = subLang;
|
||||
for (let key in argv) {
|
||||
if (argv[key] instanceof Array && !(key === 'subLang' || key === 'dub')) {
|
||||
argv[key] = (argv[key] as Array<unknown>).pop();
|
||||
}
|
||||
if (argv.allDubs)
|
||||
argv.dub = dubLang;
|
||||
if (argv.allSubs)
|
||||
argv.subLang = subLang;
|
||||
for (const key in argv) {
|
||||
if (argv[key] instanceof Array && !(key === 'subLang' || key === 'dub')) {
|
||||
argv[key] = (argv[key] as Array<unknown>).pop();
|
||||
}
|
||||
return argv;
|
||||
}
|
||||
return argv;
|
||||
};
|
||||
|
||||
const showHelp = yargs.showHelp;
|
||||
|
||||
export {
|
||||
appArgv,
|
||||
showHelp,
|
||||
availableFilenameVars,
|
||||
dubLang,
|
||||
subLang
|
||||
appArgv,
|
||||
showHelp,
|
||||
availableFilenameVars,
|
||||
dubLang,
|
||||
subLang
|
||||
};
|
||||
|
|
|
|||
|
|
@ -185,16 +185,16 @@ class Merger {
|
|||
MKVmerge: undefined|string|false,
|
||||
FFmpeg: undefined|string|false
|
||||
} = {
|
||||
MKVmerge: bin.mkvmerge,
|
||||
FFmpeg: bin.ffmpeg,
|
||||
MKVmerge: bin.mkvmerge,
|
||||
FFmpeg: bin.ffmpeg,
|
||||
};
|
||||
if( !useMP4format && !merger.MKVmerge ){
|
||||
console.log('[WARN] MKVMerge not found, skip using this...');
|
||||
merger.MKVmerge = false;
|
||||
console.log('[WARN] MKVMerge not found, skip using this...');
|
||||
merger.MKVmerge = false;
|
||||
}
|
||||
if( !merger.MKVmerge && !merger.FFmpeg || useMP4format && !merger.FFmpeg ){
|
||||
console.log('[WARN] FFmpeg not found, skip using this...');
|
||||
merger.FFmpeg = false;
|
||||
console.log('[WARN] FFmpeg not found, skip using this...');
|
||||
merger.FFmpeg = false;
|
||||
}
|
||||
return merger;
|
||||
|
||||
|
|
|
|||
953
package-lock.json
generated
953
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "funimation-downloader-nx",
|
||||
"short_name": "funi",
|
||||
"version": "4.12.5",
|
||||
"version": "5.0.0",
|
||||
"description": "Download videos from Funimation via cli.",
|
||||
"keywords": [
|
||||
"download",
|
||||
|
|
@ -57,6 +57,8 @@
|
|||
"build-macos64": "cd lib && node modules/build macos64",
|
||||
"eslint": "eslint *.js modules",
|
||||
"eslint-fix": "eslint *.js modules --fix",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
"pretest": "npm run tsc",
|
||||
"test": "cd lib && node modules/build win64 && node modules/build linux64 && node modules/build macos64"
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
32
tsc.ts
32
tsc.ts
|
|
@ -1,7 +1,7 @@
|
|||
import { exec } from "child_process";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { removeSync, copyFileSync } from "fs-extra";
|
||||
import { exec } from 'child_process';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { removeSync, copyFileSync } from 'fs-extra';
|
||||
|
||||
const ignore = [
|
||||
'.git',
|
||||
|
|
@ -13,29 +13,29 @@ const ignore = [
|
|||
(async () => {
|
||||
removeSync('lib');
|
||||
const tsc = exec('npx tsc');
|
||||
tsc.stdout?.on("data", console.log);
|
||||
tsc.stderr?.on("data", console.log);
|
||||
tsc.stdout?.on('data', console.log);
|
||||
tsc.stderr?.on('data', console.log);
|
||||
|
||||
tsc.on("close", () => {
|
||||
tsc.on('close', () => {
|
||||
const files = readDir(__dirname);
|
||||
const filtered = files.filter(a => {
|
||||
if (a.stats.isFile()) {
|
||||
return a.path.split('.').pop() !== 'ts';
|
||||
} else {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
})
|
||||
});
|
||||
filtered.forEach(item => {
|
||||
const itemPath = path.join(__dirname, 'lib', item.path.replace(__dirname, ''));
|
||||
if (item.stats.isDirectory()) {
|
||||
if (!fs.existsSync(itemPath))
|
||||
fs.mkdirSync(itemPath)
|
||||
fs.mkdirSync(itemPath);
|
||||
} else {
|
||||
copyFileSync(item.path, itemPath)
|
||||
copyFileSync(item.path, itemPath);
|
||||
}
|
||||
})
|
||||
})
|
||||
})()
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
||||
const readDir = (dir: string) : {
|
||||
path: string,
|
||||
|
|
@ -56,8 +56,8 @@ const readDir = (dir: string) : {
|
|||
stats
|
||||
});
|
||||
if (stats.isDirectory()) {
|
||||
items.push(...readDir(itemPath))
|
||||
items.push(...readDir(itemPath));
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
};
|
||||
Loading…
Reference in a new issue