152 lines
3.8 KiB
TypeScript
152 lines
3.8 KiB
TypeScript
import { ERROR_CODE } from './Errors';
|
|
|
|
import { execSync } from 'child_process';
|
|
import colors from 'colors';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
function sanitizeUrls(urls: string[]) {
|
|
// eslint-disable-next-line
|
|
const rex = new RegExp(/(?:https:\/\/)?.*\/video\/[a-z0-9]{8}-(?:[a-z0-9]{4}\-){3}[a-z0-9]{12}$/, 'i');
|
|
const sanitized: string[] = [];
|
|
|
|
for (let i = 0, l = urls.length; i < l; ++i) {
|
|
let url = urls[i].split('?')[0];
|
|
|
|
if (!rex.test(url)) {
|
|
if (url !== '') {
|
|
console.warn(colors.yellow('Invalid URL at line ' + (i + 1) + ', skip..'));
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if (url.substring(0, 8) !== 'https://') {
|
|
url = 'https://' + url;
|
|
}
|
|
|
|
sanitized.push(url);
|
|
}
|
|
|
|
if (!sanitized.length) {
|
|
process.exit(ERROR_CODE.INVALID_INPUT_URLS);
|
|
}
|
|
|
|
return sanitized;
|
|
}
|
|
|
|
function sanitizeOutDirsList(dirsList: string[]) {
|
|
const sanitized: string[] = [];
|
|
|
|
dirsList.forEach(dir => {
|
|
if (dir !== '') {
|
|
sanitized.push(dir);
|
|
}
|
|
});
|
|
|
|
return sanitized;
|
|
}
|
|
|
|
function readFileToArray(path: string) {
|
|
return fs.readFileSync(path).toString('utf-8').split(/[\r\n]/);
|
|
}
|
|
|
|
export async function forEachAsync(array: any, callback: any) {
|
|
for (let i = 0, l = array.length; i < l; ++i) {
|
|
await callback(array[i], i, array);
|
|
}
|
|
}
|
|
|
|
export function parseVideoUrls(videoUrls: any) {
|
|
let input = videoUrls[0] as string;
|
|
const isPath = input.substring(input.length - 4) === '.txt';
|
|
let urls: string[];
|
|
|
|
if (isPath) {
|
|
urls = readFileToArray(input);
|
|
}
|
|
else {
|
|
urls = videoUrls as string[];
|
|
}
|
|
|
|
return sanitizeUrls(urls);
|
|
}
|
|
|
|
export function getOutputDirectoriesList(outDirArg: string) {
|
|
const isList = outDirArg.substring(outDirArg.length - 4) === '.txt';
|
|
let dirsList: string[];
|
|
|
|
if (isList) {
|
|
dirsList = sanitizeOutDirsList(readFileToArray(outDirArg));
|
|
}
|
|
else {
|
|
dirsList = [outDirArg];
|
|
}
|
|
|
|
return dirsList;
|
|
}
|
|
|
|
export function makeOutputDirectories(dirsList: string[]) {
|
|
dirsList.forEach(dir => {
|
|
if (!fs.existsSync(dir)) {
|
|
console.info(colors.yellow('Creating output directory:'));
|
|
console.info(colors.green(dir) + '\n');
|
|
|
|
try {
|
|
fs.mkdirSync(dir, { recursive: true });
|
|
}
|
|
catch (e) {
|
|
process.exit(ERROR_CODE.INVALID_OUTPUT_DIR);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
export function checkOutDirsUrlsMismatch(dirsList: string[], urlsList: string[]) {
|
|
const dirsListL = dirsList.length;
|
|
const urlsListL = urlsList.length;
|
|
|
|
// single out dir, treat this as the chosen one for all
|
|
if (dirsListL == 1) {
|
|
return;
|
|
}
|
|
else if (dirsListL != urlsListL) {
|
|
process.exit(ERROR_CODE.OUTDIRS_URLS_MISMATCH);
|
|
}
|
|
}
|
|
|
|
export function sleep(ms: number) {
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
}
|
|
|
|
export function checkRequirements() {
|
|
try {
|
|
const ffmpegVer = execSync('ffmpeg -version').toString().split('\n')[0];
|
|
console.info(colors.green(`Using ${ffmpegVer}\n`));
|
|
|
|
}
|
|
catch (e) {
|
|
process.exit(ERROR_CODE.MISSING_FFMPEG);
|
|
}
|
|
}
|
|
|
|
export function makeUniqueTitle(title: string, outDir: string, skip?: boolean, format?: string) {
|
|
let ntitle = title;
|
|
let k = 0;
|
|
|
|
while (!skip && fs.existsSync(outDir + path.sep + ntitle + '.' + format)) {
|
|
ntitle = title + ' - ' + (++k).toString();
|
|
}
|
|
|
|
return ntitle;
|
|
}
|
|
|
|
export function ffmpegTimemarkToChunk(timemark: string) {
|
|
const timeVals: string[] = timemark.split(':');
|
|
const hrs = parseInt(timeVals[0]);
|
|
const mins = parseInt(timeVals[1]);
|
|
const secs = parseInt(timeVals[2]);
|
|
const chunk = (hrs * 60) + mins + (secs / 60);
|
|
|
|
return chunk;
|
|
}
|