2023-08-21 11:46:48 -05:00
const ytdl = require ( 'ytdl-core' ) ,
fs = require ( 'fs' ) ,
path = require ( 'path' ) ,
express = require ( 'express' ) ,
2023-10-18 20:04:42 -05:00
ffmpeg = require ( 'ffmpeg' ) ,
2023-08-24 08:48:41 -05:00
bodyParser = require ( 'body-parser' )
2023-05-05 11:15:22 -05:00
const PORT = process . env . PORT || 8080
const app = express ( )
2023-10-20 18:03:54 -05:00
if ( fs . existsSync ( path . join ( _ _dirname , 'cached' ) ) ) {
2023-10-23 23:31:23 -05:00
fs . rmSync ( path . join ( _ _dirname , 'cached' ) , { recursive : true , force : true } )
2023-10-20 18:03:54 -05:00
}
2023-10-23 10:57:35 -05:00
function formatBytes ( bytes , decimals = 2 ) {
if ( ! + bytes ) return '0 Bytes'
const k = 1024
const dm = decimals < 0 ? 0 : decimals
const sizes = [ 'Bytes' , 'KiB' , 'MiB' , 'GiB' , 'TiB' , 'PiB' , 'EiB' , 'ZiB' , 'YiB' ]
const i = Math . floor ( Math . log ( bytes ) / Math . log ( k ) )
return ` ${ parseFloat ( ( bytes / Math . pow ( k , i ) ) . toFixed ( dm ) ) } ${ sizes [ i ] } `
}
2023-10-20 18:03:54 -05:00
fs . mkdirSync ( path . join ( _ _dirname , 'cached' ) )
2023-10-23 22:39:30 -05:00
const cacheDuration = 30 || process . env . CACHEDUR
2023-05-05 11:15:22 -05:00
2023-08-24 11:00:33 -05:00
process . on ( 'uncaughtException' , ( err , origin ) => {
fs . writeSync (
process . stderr . fd ,
` Caught exception: ${ err } \n ` +
` Exception origin: ${ origin } ` ,
) ;
} ) ;
2023-08-23 11:35:10 -05:00
2023-08-24 11:00:33 -05:00
app . use ( bodyParser . urlencoded ( { extended : false } ) )
2023-08-23 11:35:10 -05:00
2023-10-20 18:03:54 -05:00
app . get ( "/getLink" , async ( req , res ) => {
2023-05-08 12:52:41 -05:00
const filename = req . query . filename
const url = req . query . url
2023-05-10 12:36:26 -05:00
const format = req . query . format
2023-05-05 11:15:22 -05:00
const quality = req . query . quality
2023-10-23 23:31:23 -05:00
const redir = req . query . redirect
2023-05-10 12:36:26 -05:00
2023-08-28 08:33:16 -05:00
if ( ! ytdl . validateURL ( url ) ) {
2023-10-20 18:03:54 -05:00
res . header ( "Content-Type" , "text/html" )
res . write ( ` <link rel="stylesheet" href="/style.css"> ` )
res . write ( ` <p>Invalid URL! Check the url for any errors! <br> ${ url } </p> ` )
2023-08-24 11:00:33 -05:00
return
}
2023-10-25 12:32:46 -05:00
if ( [ "mp4" , "webm" ] . includes ( format ) ) {
var ytvid = ytdl ( url , { 'quality' : quality , 'format' : format } )
var debounce = false
ytvid . on ( "progress" , ( chunk , cd , td ) => {
if ( ! debounce ) {
res . setHeader ( 'Content-Disposition' , ` attachment; filename=" ${ filename } . ${ format } "; ` ) ;
res . setHeader ( "Content-Length" , td )
ytvid . pipe ( res )
// console.log(td)
debounce = true
}
} )
} else {
if ( redir != "redirect" ) {
res . setHeader ( "Content-Type" , "text/html" ) ;
2023-08-24 11:00:33 -05:00
2023-10-25 12:32:46 -05:00
res . write ( ` <link rel="stylesheet" href="/style.css"> ` )
}
2023-10-23 23:31:23 -05:00
2023-10-25 12:32:46 -05:00
// String(Math.floor(Math.random() * 100000)) +
var ytpath = path . join ( _ _dirname , 'cached/' + ytdl . getVideoID ( url ) + '.mp4' )
2023-08-23 11:35:10 -05:00
2023-10-25 12:32:46 -05:00
var vidinfo = await ytdl . getBasicInfo ( url )
2023-10-18 20:04:42 -05:00
2023-10-25 12:32:46 -05:00
if ( redir != "redirect" ) {
res . write ( ` <p>Starting download...</p> ` )
}
var lastp = 0
var ytvid = ytdl ( url , { 'quality' : quality , 'format' : 'mp4' } )
2023-10-18 20:04:42 -05:00
2023-10-25 12:32:46 -05:00
if ( redir != "redirect" ) {
ytvid . on ( "progress" , ( data , ctotal , etotal ) => {
var integer = 1
var percent = ( Math . ceil ( ctotal / etotal * 100 ) )
if ( percent % integer == 0 && lastp != percent ) {
res . write ( ` <p class="percent" id="percent ${ percent } ">Downloading... ${ percent } % ( ${ formatBytes ( ctotal ) } )</p> ` )
res . write ( `
2023-10-20 18:03:54 -05:00
< style >
# percent$ { lastp } {
display : none ;
2023-10-18 20:04:42 -05:00
}
2023-10-20 18:03:54 -05:00
< / s t y l e >
` )
2023-10-25 12:32:46 -05:00
lastp = percent
}
} )
}
ytvid . pipe ( fs . createWriteStream ( ytpath ) )
. on ( "close" , ( ) => {
if ( redir != "redirect" ) {
res . write ( "<p>Downloaded!</p>" )
}
var proc = new ffmpeg ( ytpath )
// res.write(`<p>Converting... (May take a while, <a href="https://github.com/Violets-puragtory/NoJS-YTConverter"> doesn't support progress updates yet</a>)</p>`)
var endpath = ( 'cached/' + ytdl . getVideoID ( url ) + String ( Math . floor ( Math . random ( ) * 100000 ) ) + "Converted." + format )
if ( redir != "redirect" ) {
res . write ( ` <p>Starting Video Conversion... Conversion may be slow depending on instance.</p> ` )
} else {
console . log ( redir )
}
proc . then ( function ( video ) {
video
. setVideoDuration ( vidinfo . videoDetails . lengthSeconds )
. setVideoFormat ( format )
. save ( endpath , ( error , file ) => {
if ( redir != "redirect" ) {
res . write ( ` <p>Converted! (<a href="https://github.com/damianociarla/node-ffmpeg/issues/33">Why doesn't conversion support %s?</a>)</p> ` )
res . write ( `
2023-10-23 10:57:35 -05:00
< style >
. cv {
display : none ;
}
< / s t y l e >
` )
2023-10-25 12:32:46 -05:00
res . write ( ` <p><a href="/download?path= ${ path . basename ( file ) } &filename= ${ filename } . ${ format } " target="_blank">Link to video download!</a> (Link is deleted after ${ cacheDuration } minutes!)</p> ` )
if ( redir == "redirectjs" ) {
res . write ( `
2023-10-23 23:31:23 -05:00
< script >
window . location = "/download?path=${path.basename(file)}&filename=${filename}.${format}"
< / s c r i p t >
` )
2023-10-25 12:32:46 -05:00
}
} else {
res . redirect ( ` /download?path= ${ path . basename ( file ) } &filename= ${ filename } . ${ format } ` )
2023-10-23 23:31:23 -05:00
}
2023-10-25 12:32:46 -05:00
setTimeout ( ( ) => {
if ( fs . existsSync ( ytpath ) ) {
fs . unlinkSync ( ytpath )
}
if ( fs . existsSync ( file ) ) {
fs . unlinkSync ( file )
}
} , 60 * 1000 )
} )
} )
var count = 0
var integer = 1
var lastc = 0
var percent = 0
async function update ( ) {
if ( fs . existsSync ( endpath ) ) {
var ffile = await fs . readFileSync ( endpath )
var yt = await fs . readFileSync ( ytpath )
percent = ( Math . round ( ffile . length / yt . length * ( 100 / integer ) ) ) * integer
// console.log(ffile.length)
// if (ffile.length != lastc) {
res . write ( ` <p class="cv" id="convert ${ count } ">Converting... ( ${ formatBytes ( ffile . length ) } )</p> ` )
res . write ( `
2023-10-20 18:03:54 -05:00
< style >
2023-10-23 10:57:35 -05:00
# convert$ { count - 1 } {
2023-10-20 18:03:54 -05:00
display : none ;
}
< / s t y l e >
` )
2023-10-25 12:32:46 -05:00
lastc = percent
count += 1
// }
}
if ( percent < 100 && redir != "redirect" ) {
setTimeout ( ( ) => {
update ( )
} , 2000 ) ;
}
2023-10-23 23:31:23 -05:00
}
2023-10-25 12:32:46 -05:00
update ( )
} )
}
2023-10-20 18:03:54 -05:00
} ) ;
2023-08-21 11:46:48 -05:00
2023-10-20 18:03:54 -05:00
app . get ( '/download' , ( req , res ) => {
var file = req . query . path
var filename = req . query . filename
var dest = path . join ( _ _dirname , 'cached/' , file )
2023-05-05 11:15:22 -05:00
2023-10-20 18:03:54 -05:00
if ( fs . existsSync ( dest ) ) {
2023-10-25 12:32:46 -05:00
res . setHeader ( 'Content-Disposition' , ` attachment; filename=" ${ filename } " ` ) ;
res . setHeader ( 'Content-Length' , fs . readFileSync ( dest ) . length )
2023-10-20 18:03:54 -05:00
fs . createReadStream ( dest ) . pipe ( res )
} else {
res . header ( "Content-Type" , "text/html" )
res . write ( ` <link rel="stylesheet" href="/style.css"> ` )
2023-10-23 23:31:23 -05:00
res . write ( ` <p>Uh oh! It seems that video couldn't be found... Maybe the URL expired? Or, the link was invalid. <br>If you believe this was a mistake, please put a issue on <a href="https://github.com/Violets-puragtory/NoJS-YTConverter/">Github</a></p> ` , ( ) => {
2023-10-20 18:03:54 -05:00
res . end ( )
} )
}
} )
2023-05-05 11:15:22 -05:00
app . use ( express . static ( path . join ( _ _dirname , 'static' ) ) )
2023-05-10 12:36:26 -05:00
app . listen ( PORT , function ( ) {
2023-05-05 11:15:22 -05:00
console . log ( "Hosted on port " + PORT )
} )