cartoon-cli
Version:
Cartoon CLI for getting json info of episodes and downloading cartoons
263 lines (240 loc) • 7.98 kB
JavaScript
const readline = require('readline-sync');
var nconf = require('nconf');
nconf.env().file({file:`${__dirname.replace("\\bin","\\settings.json")}`})
const fs = require("fs")
const axios = require("axios").default
const {getVideoApi,getSlug,getPage,getMainApi}=require("./services")
const yargs = require('yargs').options({
"download":{
alias:"d",
description:"if true downloads mp4 of the episode if false puts url of the mp4 in json file",
type:"boolean"
},
"specify":{
type:"string"
}
})
const argv = yargs.argv
const GivenTitle = argv._
const _cliProgress = require('cli-progress');
var ChosenTitle = ""
var MaxEpisodes = 1;
var Slug = ""
var Path = nconf.get("path")
const invalid_answer = ()=>{
const ans = readline.question("invalid answer, try again. [y,n] : ")
if(ans!="y"&&ans!="n"){
invalid_answer()
}
return ans
}
const dealWithNoValue = (val)=>{
if(val!=null&&val!=""){
return val
}else{
no_value()
}
}
const no_value = async () =>{
const val = readline.question("--specify needs a value (ex. D:/desktop/cartoons) : ")
if(val==""||val==null){
const new_val = dealWithNoValue(val)
return new_val
}
return val
}
const cli_init =async ()=>{
if (argv.path!=null) {
console.log(`default path changed from \x1b[33m${Path}\x1b[0m to \x1b[32m${argv.path}\x1b[0m`)
if (!fs.existsSync(Path)) {
fs.mkdirSync(Path,{recursive:true})
}
Path = argv.path
nconf.set("path",argv.path)
nconf.save((err)=>{
if (err) {
console.error(err.message);
return;
}
})
if (argv._.length==0) return
}
if(argv.specify!=null)
{
let specify = argv.specify
if(specify===""){
specify = await no_value()
}
if(!fs.existsSync(specify))
{
const ans = readline.question(`directory ${specify} doesn't exists, do you want to create it?[y,n] : `)
let answer = ans
if(ans!="y"&&ans!="n"){
answer = invalid_answer()
}
if(answer=="y"){
fs.mkdirSync(specify,{recursive:true})
}else{
console.log("Using default directory ",Path)
startDisplayOptions()
}
console.log("made directory ",specify)
}
Path = specify
}
if(argv.download!=null){
nconf.set("download",argv.download)
nconf.save((err)=>{
if (err) {
console.error(err.message);
return;
}
})
argv.download
?
console.log("\x1b[35m episodes will be downloaded \x1b[0m")
:
console.log("\x1b[35m info of episodes will be written in json file \x1b[0m")
if (argv._.length==0) return
}
startDisplayOptions()
}
const startDisplayOptions = async ()=>{
if(GivenTitle.length==0)
{
const show_name= readline.question("Enter Cartoon Name : ")
const formated = show_name.replace(" ","+").toLowerCase()
const arr = await getSlug(formated)
displayOptions(arr)
}
else
{
getWithYargs()
}
}
const getWithYargs = async (specify)=>{
let show_name=""
GivenTitle.map(child=>{
show_name+=(child+"+")
})
const arr = await getSlug(show_name.toLowerCase())
displayOptions(arr,specify)
}
const displayOptions = async (arr,specify)=>{
const index = readline.question("Choose Index : ")
if (!isNaN(index)==false||index==="") {
console.log("invalid value, try again")
displayOptions(arr,specify)
return
}
if (index>arr.length-1) {
console.log(`index ${index} is too high!`)
displayOptions(arr,specify)
return
}
if(index<0){
console.log(`index ${index} is too low!`)
displayOptions(arr,specify)
return
}
const splat = arr[index].url.split("/")
ChosenTitle = arr[index].title
Slug = splat[splat.length-2]
const Download = nconf.get("download")
MaxEpisodes = await getMaxEp()
if(specify){
const path=readline.question("Enter file path (file must be .json) : ")
Path=path
}
const range = readline.question("Enter Episode Range (ex. 4,6) : ")
if(range!=null&&range!=="")
{
const str_arr = range.replace(" ","").split(",")
const ep_range= [parseInt(str_arr[0]),parseInt(str_arr[1])]
console.log("Starting To Fetch Every Episode... \n")
Download?downloadEpisodes(ep_range):fetchAllTheEpisodes(ep_range)
}
else
{
console.log("Starting To Fetch Every Episode... \n")
Download?downloadEpisodes([1,MaxEpisodes]):fetchAllTheEpisodes([1,MaxEpisodes])
}
}
const arr = []
const fetchAllTheEpisodes=async (Ep_range)=>
{
const ep=Ep_range[0]
const max = Ep_range[1]
setTimeout(async()=>
{
ep<=max&&console.log(`Fetching Episode ${ep}...`)
const episode_obj= await fetchEpisode(MaxEpisodes-ep+1)
arr.push(episode_obj)
console.log('\x1b[32m%s\x1b[0m',`Episode ${ep} Fetched \n`)
if(ep===max){
if (!fs.existsSync(`${Path}/${ChosenTitle}`)) {
fs.mkdirSync(`${Path}/${ChosenTitle}`,{recursive:true})
}
fs.writeFileSync(`${Path}/${ChosenTitle}/${ChosenTitle.replace(" ","-")}.json`,JSON.stringify(arr,null,2),{flag:"w+"},(err)=>{err&&console.log(err);return})
console.log("Done!")
return;
}
if(ep<=max)
{
fetchAllTheEpisodes([ep+1,max])
}
}
,2500
)
}
const getMaxEp = async ()=>{
const html = await getPage(Slug,1)
const {max} = await getMainApi(html)
console.log(`Episode Range [1-${max}]`)
return max
}
const fetchEpisode=async (ep)=>{
const html = await getPage(Slug,ep)
const {semi} = await getMainApi(html)
const {video,quality} = await getVideoApi(semi)
return {episode:MaxEpisodes-ep+1,url:video,quality:quality}
}
const downloadEpisodes=async (Ep_range)=>
{
const ep=Ep_range[0]
const max = Ep_range[1]
ep<=max&&console.log(`Fetching Episode ${ep}...`)
const {url}= await fetchEpisode(MaxEpisodes-ep+1)
if (!fs.existsSync(`${Path}/${ChosenTitle}`)) {
fs.mkdirSync(`${Path}/${ChosenTitle}`,{recursive:true})
}
const file = fs.createWriteStream(`${Path}/${ChosenTitle}/${ChosenTitle}_EP${ep<10?" 0"+ep:" "+ep}.mp4`)
let receivedBytes = 0
const progressBar = new _cliProgress.SingleBar({
format: '{bar} {percentage}% | ETA: {eta}s'
}, _cliProgress.Presets.shades_classic);
const stream = await axios.get(url,{responseType:"stream"})
const totalBytes = stream.headers['content-length'];
progressBar.start(totalBytes, 0);
stream.data.on('data', (chunk) => {
receivedBytes += chunk.length;
progressBar.update(receivedBytes);
})
.pipe(file)
.on("finish",()=>{
progressBar.stop()
console.log('\x1b[32m%s\x1b[0m',`Episode ${ep} Fetched \n`)
if(ep===max){
console.log("Done!")
return;
}
if(ep<=max)
{
const next_ep = Ep_range[0]+1
const ep_range = [next_ep,max]
downloadEpisodes(ep_range)
}
})
}
cli_init()