rtlmost-downloader
Advanced tools
Comparing version 1.2.1 to 1.3.0
#!/usr/bin/env node | ||
process.title = 'rtlmost-downloader (@a-sync)'; | ||
process.title = 'github.com/a-sync/rtlmost-downloader'; | ||
const {setup, parser, downloader} = require('../index.js'); | ||
const ora = require('ora'); | ||
const {setup, parser, downloader} = require('..'); | ||
if (process.argv.length > 2) { | ||
setup.parseCmdArgs() | ||
.then(download) | ||
.catch(err => { | ||
console.error(err.message); | ||
}); | ||
setup.parseCmdArgs().then(download).catch(() => {}); | ||
} else { | ||
setup.showPrompts() | ||
.then(download) | ||
.catch(err => { | ||
console.error(err.message); | ||
}); | ||
setup.showPrompts().then(download).catch(() => {}); | ||
} | ||
function download(params) { | ||
return parser.load(params.url).then( | ||
videoUrls => { | ||
if (Array.isArray(videoUrls) && videoUrls.length > 0) { | ||
const targetUrl = findGoodTarget(videoUrls); | ||
async function download(params) { | ||
const videoUrls = await parser.load(params.url); | ||
// Debug: console.debug(JSON.stringify(videoUrls, null, 2)); | ||
if (targetUrl || process.argv.length > 2) { | ||
downloader.download(targetUrl, params.file); | ||
} else { | ||
return setup.showMediaSelector(videoUrls, 0).then( | ||
selected => { | ||
downloader.download(selected.media, params.file); | ||
} | ||
); | ||
} | ||
if (Array.isArray(videoUrls) && videoUrls.length > 0) { | ||
const targetUrls = await checkSources(videoUrls); | ||
// Debug: console.debug(JSON.stringify(targetUrls, null, 2)); | ||
if (process.argv.length > 2 || targetUrls.length > 0) { | ||
if (targetUrls.length === 0) { | ||
throw new Error('Nem található letölthető url.'); | ||
} | ||
return downloader.download(targetUrls.pop(), params.file); | ||
} | ||
).catch(err => { | ||
console.error(err.message); | ||
}); | ||
const selected = await setup.showMediaSelector(videoUrls, 0); | ||
return downloader.download(selected.media, params.file); | ||
} | ||
} | ||
function findGoodTarget(videoUrls) { | ||
return videoUrls | ||
async function checkSources(videoUrls) { | ||
const spinner = ora('Url-ek ellenőrzése...').start(); | ||
const urls = []; | ||
const targetUrl = videoUrls | ||
.filter(url => { | ||
@@ -50,3 +46,30 @@ return (url.indexOf('_drmnp.ism/') === -1); | ||
}); | ||
if (targetUrl) { | ||
const targetCheck = await downloader.check(targetUrl); | ||
if (targetCheck.meta) { | ||
urls.push(targetUrl); | ||
} | ||
if (targetUrl.indexOf('.fr/v1/resource/s/') !== -1) { | ||
const urlId = targetUrl.split('.fr/v1/resource/s/')[1].split('_unpnp.ism/')[0]; | ||
const videoId = urlId.split('/').pop(); | ||
const hdUrl = 'https://rtlhu.vod.6cloud.fr/' + urlId + '_unpnp.ism/' + videoId + '_.m3u8'; | ||
const hdCheck = await downloader.check(hdUrl); | ||
if (hdCheck.meta) { | ||
urls.push(hdUrl); | ||
} | ||
} | ||
} | ||
if (urls.length === 0) { | ||
spinner.fail('Nem található letölthető url.'); | ||
} else { | ||
spinner.succeed(urls.length + ' db letölthető url.'); | ||
} | ||
return urls; | ||
} | ||
// TODO: try to download all other URLs if no good target can be found, or the first try fails | ||
@@ -0,0 +0,0 @@ 'use strict'; |
@@ -6,4 +6,6 @@ 'use strict'; | ||
const ffmpegBin = require('ffmpeg-static'); | ||
const ffprobeBin = require('ffprobe-static'); | ||
ffmpeg.setFfmpegPath(ffmpegBin.path); | ||
ffmpeg.setFfprobePath(ffprobeBin.path); | ||
@@ -14,49 +16,62 @@ const loadingText = 'Videó letöltése... '; | ||
function download(url, file) { | ||
let spinner = ora({color: 'blue'}); | ||
const procSpinner = ora({spinner: 'bouncingBar'}); | ||
return new Promise((resolve, reject) => { | ||
let spinner = ora({color: 'blue'}); | ||
const procSpinner = ora({spinner: 'bouncingBar'}); | ||
try { | ||
let videoLength; | ||
ffmpeg(url) | ||
.videoCodec('copy') | ||
.audioCodec('copy') | ||
.format('mp4') | ||
/* | ||
.addOption([ | ||
'-c copy', | ||
'-bsf:a aac_adtstoasc' | ||
]) | ||
*/ | ||
.on('start', () => { | ||
// Debug: console.log('Start command:', cmd); | ||
spinner.start('Videó ellenőrzése...'); | ||
}) | ||
.on('codecData', data => { | ||
// Debug: console.log('Codec data:', data); | ||
videoLength = parseTimeStamp(data.duration); | ||
spinner.info('V/A: ' + data.video.split(' ')[0] + '/' + data.audio.split(' ')[0] + ' ' + data.duration.split('.')[0]); | ||
spinner = null; | ||
procSpinner.start(loadingText + ' 00:00:00 (0%)'); | ||
}) | ||
.on('progress', data => { | ||
// Debug: console.log('Progress:', data); | ||
const mark = parseTimeStamp(data.timemark); | ||
const percent = (videoLength > 0 && mark > 0) ? Math.floor(mark / videoLength * 100) : 0; | ||
procSpinner.text = loadingText + data.timemark.split('.')[0] + ' (' + String(percent) + '%)'; | ||
}) | ||
.on('error', err => { | ||
console.error(loadingFailedText, err.message); | ||
if (spinner) { | ||
spinner.fail(loadingFailedText); | ||
} else { | ||
procSpinner.fail(loadingFailedText); | ||
} | ||
}) | ||
.on('end', () => { | ||
procSpinner.succeed(); | ||
}) | ||
.save(file); | ||
} catch (err) { | ||
console.error(loadingFailedText, err.message); | ||
} | ||
try { | ||
let videoLength; | ||
ffmpeg(url) | ||
.videoCodec('copy') | ||
.audioCodec('copy') | ||
.format('mp4') | ||
/* .addOption([ | ||
// ,'-c copy' | ||
// ,'-bsf:a aac_adtstoasc' | ||
]) */ | ||
.on('start', () => { | ||
// Debug: console.log('Start command:', cmd); | ||
spinner.start('Videó ellenőrzése...'); | ||
}) | ||
.on('codecData', data => { | ||
// Debug: console.log('Codec data:', data); | ||
videoLength = parseTimeStamp(data.duration); | ||
spinner.info('Videó: ' + | ||
data.video_details[2].split(' ')[0] + ' ' + | ||
data.video_details[3] + ' ' + | ||
data.video.split(' ')[0]); | ||
spinner.info('Audió: ' + | ||
data.audio_details[1] + ' ' + | ||
data.audio_details[2] + ' ' + | ||
data.audio.split(' ')[0]); | ||
spinner.info('Hossz: ' + | ||
data.duration.split('.')[0]); | ||
spinner = null; | ||
procSpinner.start(loadingText + '00:00:00 (0%)'); | ||
}) | ||
.on('progress', data => { | ||
// Debug: console.log('Progress:', data); | ||
const mark = parseTimeStamp(data.timemark); | ||
const percent = (videoLength > 0 && mark > 0) ? Math.floor(mark / videoLength * 100) : 0; | ||
procSpinner.text = loadingText + data.timemark.split('.')[0] + ' (' + String(percent) + '%)'; | ||
}) | ||
.on('error', err => { | ||
// Debug: console.error(loadingFailedText, err.message); | ||
if (spinner) { | ||
spinner.fail(loadingFailedText); | ||
} else { | ||
procSpinner.fail(loadingFailedText); | ||
} | ||
return reject(new Error(err)); | ||
}) | ||
.on('end', () => { | ||
procSpinner.succeed(); | ||
return resolve(); | ||
}) | ||
.save(file); | ||
} catch (err) { | ||
// Debug: console.error(loadingFailedText, err.message); | ||
return reject(new Error(err)); | ||
} | ||
}); | ||
} | ||
@@ -66,2 +81,13 @@ | ||
function check(url) { | ||
return new Promise(resolve => { | ||
ffmpeg | ||
.ffprobe(url, (err, meta) => { | ||
return resolve({err, meta}); | ||
}); | ||
}); | ||
} | ||
module.exports.check = check; | ||
function parseTimeStamp(str) { | ||
@@ -68,0 +94,0 @@ let re = 0; |
@@ -24,25 +24,25 @@ 'use strict'; | ||
}) | ||
/* | ||
.on('downloadProgress', data => { | ||
// Debug: console.log('downloadProgress', data); | ||
spinner.text = loadingText + '(' + Math.floor(data.percent * 100) + '%)'; | ||
}) | ||
*/ | ||
.then(res => { | ||
/* | ||
.on('downloadProgress', data => { | ||
// Debug: console.log('downloadProgress', data); | ||
spinner.text = loadingText + '(' + Math.floor(data.percent * 100) + '%)'; | ||
}) | ||
*/ | ||
.then(res => { | ||
// Debug: console.log('got:res.body.length', res.body.length); | ||
data = res.body || ''; | ||
return parse(); | ||
}) | ||
.then(re => { | ||
if (Array.isArray(re) && re.length > 0) { | ||
spinner.succeed(); | ||
} else { | ||
spinner.fail(parsingFailedText); | ||
} | ||
return re; | ||
}) | ||
.catch(err => { | ||
console.error(err.message); | ||
spinner.fail(loadingFailedText); | ||
}); | ||
data = res.body || ''; | ||
return parse(); | ||
}) | ||
.then(re => { | ||
if (Array.isArray(re) && re.length > 0) { | ||
spinner.succeed(); | ||
} else { | ||
spinner.fail(parsingFailedText); | ||
} | ||
return re; | ||
}) | ||
.catch(err => { | ||
// Debug: console.error(err.message); | ||
spinner.fail(loadingFailedText); | ||
}); | ||
} | ||
@@ -49,0 +49,0 @@ |
@@ -42,33 +42,32 @@ 'use strict'; | ||
]) | ||
.then(params1 => { | ||
const defaultFileName = parseFileNameFromRtlMostUrl(params1.url) || String(dateObj.getTime()); | ||
/* Ne kérdezzen rá a fájlnévre, csak ha muszáj: | ||
if (defaultFileName) { | ||
return {url: params1.url, file: defaultFileName + '.mp4'}; | ||
} | ||
*/ | ||
.then(params1 => { | ||
const defaultFileName = parseFileNameFromRtlMostUrl(params1.url) || String(dateObj.getTime()); | ||
/* Ne kérdezzen rá a fájlnévre, csak ha muszáj: | ||
if (defaultFileName) { | ||
return {url: params1.url, file: defaultFileName + '.mp4'}; | ||
} | ||
*/ | ||
return inquirer.prompt([{ | ||
name: 'file', | ||
message: 'Fájl név:', | ||
default: defaultFileName, | ||
validate: val => { | ||
if (val.slice(-1) === path.sep) { | ||
return true; | ||
} | ||
return inquirer.prompt([{ | ||
name: 'file', | ||
message: 'Fájl név:', | ||
default: defaultFileName, | ||
validate: val => { | ||
if (val.slice(-1) === path.sep) { | ||
return true; | ||
return isValidFileName(val); | ||
}, | ||
filter: val => { | ||
return createProperFileName(val, defaultFileName); | ||
} | ||
return isValidFileName(val); | ||
}, | ||
filter: val => { | ||
return createProperFileName(val, defaultFileName); | ||
} | ||
}]) | ||
.then(params2 => { | ||
return {url: params1.url, file: params2.file}; | ||
}]) | ||
.then(params2 => { | ||
return {url: params1.url, file: params2.file}; | ||
}); | ||
}) | ||
.catch(err => { | ||
// Debug: console.error(err.message); | ||
throw new Error('Hiba az adatok bekérésénél!'); | ||
}); | ||
}) | ||
.catch(err => { | ||
console.error(err.message); | ||
throw new Error('Hiba az adatok bekérésénél!'); | ||
}); | ||
} | ||
@@ -100,6 +99,6 @@ | ||
}]) | ||
.catch(err => { | ||
console.error(err.message); | ||
throw new Error('Hiba az adatok bekérésénél!'); | ||
}); | ||
.catch(err => { | ||
// Debug: console.error(err.message); | ||
throw new Error('Hiba az adatok bekérésénél!'); | ||
}); | ||
} | ||
@@ -125,3 +124,3 @@ | ||
str = path.basename(str); | ||
return /^(?!\.)(?!com[0-9]$)(?!con$)(?!lpt[0-9]$)(?!nul$)(?!prn$)[^|*?\\:<>/$"]*[^.|*?\\:<>/$"]+$/.test(str); | ||
return /^(?!\.)(?!com\d$)(?!con$)(?!lpt\d$)(?!nul$)(?!prn$)[^|*?\\:<>/$"]*[^.|*?\\:<>/$"]+$/.test(str); | ||
} | ||
@@ -128,0 +127,0 @@ |
{ | ||
"name": "rtlmost-downloader", | ||
"version": "1.2.1", | ||
"version": "1.3.0", | ||
"description": "A videók letöltését teszi lehetővé a megújult rtlmost.hu oldalról, regisztráció és bejelentkezés nélkül.", | ||
@@ -22,7 +22,8 @@ "main": "index.js", | ||
"ffmpeg-static": "^2.3.0", | ||
"ffprobe-static": "^3.0.0", | ||
"fluent-ffmpeg": "^2.1.2", | ||
"got": "^8.3.2", | ||
"inquirer": "^6.0.0", | ||
"got": "^9.2.2", | ||
"inquirer": "^6.2.0", | ||
"minimist": "^1.2.0", | ||
"ora": "^2.1.0" | ||
"ora": "^3.0.0" | ||
}, | ||
@@ -29,0 +30,0 @@ "bin": { |
# rtlmost-downloader [![npm (scoped)](https://img.shields.io/npm/v/rtlmost-downloader.svg)](https://www.npmjs.com/package/rtlmost-downloader) | ||
A videók letöltését teszi lehetővé a megújult rtlmost.hu oldalról, regisztráció és bejelentkezés nélkül. | ||
![rtlmost-downloader](https://user-images.githubusercontent.com/14183614/35911255-97e75de8-0bf9-11e8-8e73-9eb749521979.gif) | ||
![rtlmost-downloader](https://user-images.githubusercontent.com/14183614/46839788-eb01a000-cdbf-11e8-834b-649eff7da58d.gif) | ||
@@ -5,0 +5,0 @@ ## Indítás parancssori dialógussal |
Sorry, the diff of this file is not supported yet
15193
323
7
+ Addedffprobe-static@^3.0.0
+ Added@sindresorhus/is@0.14.0(transitive)
+ Added@szmarczak/http-timer@1.1.2(transitive)
+ Addedcacheable-request@6.1.0(transitive)
+ Addedcli-spinners@2.9.2(transitive)
+ Addedclone-response@1.0.3(transitive)
+ Addeddefer-to-connect@1.1.3(transitive)
+ Addedend-of-stream@1.4.4(transitive)
+ Addedffprobe-static@3.1.0(transitive)
+ Addedget-stream@4.1.05.2.0(transitive)
+ Addedgot@9.6.0(transitive)
+ Addedhttp-cache-semantics@4.1.1(transitive)
+ Addedkeyv@3.1.0(transitive)
+ Addedlowercase-keys@2.0.0(transitive)
+ Addednormalize-url@4.5.1(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedora@3.4.0(transitive)
+ Addedp-cancelable@1.1.0(transitive)
+ Addedpump@3.0.2(transitive)
+ Addedto-readable-stream@1.0.0(transitive)
+ Addedwrappy@1.0.2(transitive)
- Removed@sindresorhus/is@0.7.0(transitive)
- Removedcacheable-request@2.1.4(transitive)
- Removedcli-spinners@1.3.1(transitive)
- Removedclone-response@1.0.2(transitive)
- Removedcore-util-is@1.0.3(transitive)
- Removeddecode-uri-component@0.2.2(transitive)
- Removedfrom2@2.3.0(transitive)
- Removedget-stream@3.0.0(transitive)
- Removedgot@8.3.2(transitive)
- Removedhas-symbol-support-x@1.4.2(transitive)
- Removedhas-to-string-tag-x@1.4.1(transitive)
- Removedhttp-cache-semantics@3.8.1(transitive)
- Removedinherits@2.0.4(transitive)
- Removedinto-stream@3.1.0(transitive)
- Removedis-object@1.0.2(transitive)
- Removedis-plain-obj@1.1.0(transitive)
- Removedis-retry-allowed@1.2.0(transitive)
- Removedisarray@1.0.0(transitive)
- Removedisurl@1.0.0(transitive)
- Removedkeyv@3.0.0(transitive)
- Removedlowercase-keys@1.0.0(transitive)
- Removednormalize-url@2.0.1(transitive)
- Removedobject-assign@4.1.1(transitive)
- Removedora@2.1.0(transitive)
- Removedp-cancelable@0.4.1(transitive)
- Removedp-finally@1.0.0(transitive)
- Removedp-is-promise@1.1.0(transitive)
- Removedp-timeout@2.0.1(transitive)
- Removedpify@3.0.0(transitive)
- Removedprocess-nextick-args@2.0.1(transitive)
- Removedquery-string@5.1.1(transitive)
- Removedreadable-stream@2.3.8(transitive)
- Removedsafe-buffer@5.1.25.2.1(transitive)
- Removedsort-keys@2.0.0(transitive)
- Removedstrict-uri-encode@1.1.0(transitive)
- Removedstring_decoder@1.1.1(transitive)
- Removedtimed-out@4.0.1(transitive)
- Removedurl-to-options@1.0.1(transitive)
- Removedutil-deprecate@1.0.2(transitive)
Updatedgot@^9.2.2
Updatedinquirer@^6.2.0
Updatedora@^3.0.0