yts-commandline
Version:
CLI (command line interface) client for YTS
266 lines (240 loc) • 7.72 kB
JavaScript
const program = require('commander')
const opn = require('open')
const Table = require('cli-table3')
const Ora = require('ora')
const querystring = require('querystring');
const colors = require('colors');
const isOnline = require('is-online');
const {
movies,
getMovie,
getSuggestions,
magnetURI
} = require('./index.js')
const {
getTorrentLinks,
getTorrentHash,
availableQualities,
mapTable
} = require('./utils.js')
// Ora default spinner
const spinner = new Ora({
text: 'Loading '
})
// Init commander program
program
.version('1.3.0')
.name('yts')
.usage("[command] [option]")
.description('YTS Movies CLI Client')
// Default table style
let tableConfig = {
head: ['ID', 'Rating', 'Title', 'Available In'],
colWidths: [7, 8, 35, 25],
wordWrap: true,
style: {
'padding-left': 1
}
}
let tableConfigForM = {
colWidths: [15, 45],
compact: true,
wordWrap: true,
style: {
'padding-left': 1
}
}
/**
* listMovies
* @param query String
* @return Promise
*/
const listMovies = async (query, options) => {
spinner.start();
if (!await isOnline()) {
spinner.fail(' Sorry I can\'t work offline. Please enable network connectivity.');
process.exit();
}
try {
let queryObj = {};
if (query) {
queryObj.query_term = query;
}
if (options.quality) {
switch (options.quality) {
case 'HD':
queryObj.quality = '720p';
break;
case 'FHD':
queryObj.quality = '1080p';
break;
case '4K':
queryObj.quality = '2160p';
break;
case '3D':
queryObj.quality = '3D';
break;
default:
spinner.fail(" Invalid quality value.");
process.exit();
//break;
}
}
if (options.genre) {
queryObj.genre = options.genre;
}
if (options.sort) {
queryObj.sort_by = options.sort;
}
if (options.order) {
queryObj.order_by = options.order;
}
if (options.minrating) {
queryObj.minimum_rating = options.minrating;
}
if (process.stdout.columns < 100) {
tableConfig.colWidths = [7, 8, process.stdout.columns - 31, 11];
} else if (process.stdout.columns > 100) {
tableConfig.colWidths = [7, 8, 60, 25];
}
const table = new Table(tableConfig);
const qs = querystring.stringify(queryObj);
const data = await movies(qs);
if (!data) {
spinner.fail(' No movie found.')
process.exit()
}
if (data.length > 1) {
await data.map(movie => movie.torrents ? table.push(mapTable(movie)) : null);
} else {
table.push(mapTable(data))
}
return spinner.succeed('Done!\n' + table.toString());
} catch (error) {
spinner.fail(' Something went wrong, please check your network connection and try again.\n If problem persists, please contact author.');
}
}
/**
* movieAction
* @param id Number
* @return Promise
*/
const movieAction = async (id, options) => {
spinner.start()
if (!await isOnline()) {
spinner.fail(' Sorry I can\'t work offline. Please enable network connectivity.');
process.exit();
}
try {
if (id.toString().match('^[0-9]*$') == null) {
spinner.fail(' ID can be numeric value only.');
process.exit();
}
if (id) {
let data = await getMovie(id);
if (data.id == 0) {
spinner.fail(' No movie found, please verify that correct ID was passed.');
process.exit();
}
const {
torrents
} = data;
if (options.open) {
await opn(data.url, {
wait: true
});
spinner.succeed('Done');
process.exit()
}
if (options.trailer) {
await opn(`https://youtu.be/${data.yt_trailer_code}`, {
wait: true
});
spinner.succeed('Done');
process.exit()
}
if (options.imdb) {
await opn(`http://imdb.com/title/${data.imdb_code}`, {
wait: true
});
spinner.succeed('Done');
process.exit()
}
if (options.suggest) {
if (process.stdout.columns < 100) {
tableConfig.colWidths = [7, 8, process.stdout.columns - 31, 11];
} else if (process.stdout.columns > 100) {
tableConfig.colWidths = [7, 8, 60, 25];
}
let table = new Table(tableConfig);
data = await getSuggestions(id);
if (data.length > 1) {
await data.map(movie => movie.torrents ? table.push(mapTable(movie)) : null);
} else {
table.push(mapTable(data))
}
return spinner.succeed('Done!\n' + table.toString());
} else if (options.download) {
if (typeof options.download != "string") {
spinner.info("Using default quality - 1080p");
options.download = "1080p";
}
const hash = getTorrentHash(options.download, torrents);
if (hash.length === 0) {
spinner.fail('Could not generate a magnet link with that quality')
process.exit(1);
}
const hashLink = magnetURI(hash, data.title_long)
console.info("Magnet Link:")
console.info(hashLink)
await opn(hashLink, {
wait: true
});
spinner.succeed('Done');
process.exit()
} else {
tableConfigForM.colWidths = [13, process.stdout.columns - 16 > 65 ? 65 : process.stdout.columns - 16];
let table = new Table(tableConfigForM);
table.push([colors.red('Title'), data.title_long]);
table.push([colors.red('Rating'), data.rating]);
table.push([colors.red('Genre'), data.genres.join(', ')]);
data.cast ? table.push([colors.red('Cast'), data.cast.map(c => c.name).join(', ')]) : null;
table.push([colors.red('Description'), data.description_full]);
data.torrents ? table.push([colors.red('Available In'), data.torrents.map(t => (t.quality + ' ' + t.type).padEnd(13) + ' | ' + t.size.padEnd(10) + ' | Seeds - ' + t.seeds).join('\n')]) : null;
return spinner.succeed('Done!\n' + table.toString());
}
}
} catch (error) {
spinner.fail(' Something went wrong, please check your network connection and try again.\n If problem persists, please contact author.');
// console.error(error);
}
}
program
.command('search [query] [option]')
.usage("[query] [option]")
.option('-q, --quality <quality>', 'find using below supported qualities\n(HD, FHD, 4K, 3D)')
.option('-g, --genre <genre>', 'find using genre, see https://www.imdb.com/feature/genre')
.option('-s, --sort <sorting>', 'sorts the results by choosen value,\n(title, year, rating, peers, seeds, download_count, like_count, date_added)')
.option('-o, --order <order>', 'orders the results by either ascending or descending order\n(desc, asc)')
.option('-m, --minrating <rating>', 'filter movies by a given minimum IMDb rating\n(integer between 0 - 9)')
.description('search movies')
.alias('s')
.action((id, arg, options) => listMovies(id, options))
program
.command('movie <id>')
.usage('<id> [option]')
.option('-d, --download [quality]', 'download torrent')
.option('-o, --open', 'view on YTS')
.option('-t, --trailer', 'open trailer')
.option('-i, --imdb', 'view movie on IMDB')
.option('-s, --suggest', 'suggest 4 related movies')
.description('fetch movie and perform operations like download, view trailer etc, \nuse search command to get id')
.alias('m')
.action((id, options) => movieAction(id, options))
// Assert that a VALID command is provided
if (!process.argv.slice(2).length) {
program.outputHelp();
process.exit();
}
program.parse(process.argv)