@ -11,6 +11,7 @@ var archiver = require('archiver');
var unzipper = require ( 'unzipper' ) ;
var mergeFiles = require ( 'merge-files' ) ;
const low = require ( 'lowdb' )
var ProgressBar = require ( 'progress' ) ;
var md5 = require ( 'md5' ) ;
const NodeID3 = require ( 'node-id3' )
const downloader = require ( 'youtube-dl/lib/downloader' )
@ -61,12 +62,23 @@ var archivePath = path.join(__dirname, 'appdata', 'archives');
// other needed values
var options = null ; // encryption options
var url _domain = null ;
var updaterStatus = null ;
// check if debug mode
let debugMode = process . env . YTDL _MODE === 'debug' ;
if ( debugMode ) console . log ( 'YTDL-Material in debug mode!' ) ;
// check if just updated
const just _restarted = fs . existsSync ( 'restart.json' ) ;
if ( just _restarted ) {
updaterStatus = {
updating : false ,
details : 'Update complete! You are now on ' + CONSTS [ 'CURRENT_VERSION' ]
}
fs . unlinkSync ( 'restart.json' ) ;
}
// updates & starts youtubedl
startYoutubeDL ( ) ;
@ -153,42 +165,63 @@ async function restartServer() {
fs . writeFileSync ( 'restart.json' , 'internal use only' ) ;
}
async function updateServer ( ) {
const new _version _available = await isNewVersionAvailable ( ) ;
if ( ! new _version _available ) {
console . log ( 'ERROR: Failed to update - no update is available.' ) ;
return false ;
async function updateServer ( tag ) {
// no tag provided means update to the latest version
if ( ! tag ) {
const new _version _available = await isNewVersionAvailable ( ) ;
if ( ! new _version _available ) {
console . log ( 'ERROR: Failed to update - no update is available.' ) ;
return false ;
}
}
return new Promise ( async resolve => {
// backup current dir
updaterStatus = {
updating : true ,
'details' : 'Backing up key server files...'
}
let backup _succeeded = await backupServerLite ( ) ;
if ( ! backup _succeeded ) {
resolve ( false ) ;
return false ;
}
updaterStatus = {
updating : true ,
'details' : 'Downloading requested release...'
}
// grab new package.json and public folder
await downloadUpdateFiles ( ) ;
// await downloadReleaseFiles(tag);
updaterStatus = {
updating : true ,
'details' : 'Installing new dependencies...'
}
// run npm install
await installDependencies ( ) ;
updaterStatus = {
updating : true ,
'details' : 'Update complete! Restarting server...'
}
restartServer ( ) ;
} , err => {
updaterStatus = {
updating : false ,
error : true ,
'details' : 'Update failed. Check error logs for more info.'
}
} ) ;
}
async function downloadUpdateFiles ( ) {
let tag = await getLatestVersion ( ) ;
async function download ReleaseFiles( tag ) {
tag = tag ? tag : await getLatestVersion ( ) ;
return new Promise ( async resolve => {
console . log ( 'Downloading new files...' )
var options = {
owner : 'tzahi12345' ,
repo : 'YoutubeDL-Material' ,
branch : tag
} ;
// downloads the latest release zip file
await download Latest Release( tag ) ;
await downloadReleaseZip ( tag ) ;
// deletes contents of public dir
fs . removeSync ( path . join ( _ _dirname , 'public' ) ) ;
@ -199,7 +232,7 @@ async function downloadUpdateFiles() {
console . log ( ` Installing update ${ tag } ... ` )
// downloads new package.json and adds new public dir files from the downloaded zip
fs . createReadStream ( path . join ( _ _dirname , 'youtubedl-material-latest-release.zip' ) ) . pipe ( unzipper . Parse ( ) )
fs . createReadStream ( path . join ( _ _dirname , ` youtubedl-material-latest-release- ${ tag } .zip ` ) ) . pipe ( unzipper . Parse ( ) )
. on ( 'entry' , function ( entry ) {
var fileName = entry . path ;
var type = entry . type ; // 'Directory' or 'File'
@ -229,17 +262,46 @@ async function downloadUpdateFiles() {
} ) ;
}
async function downloadLatestRelease ( tag ) {
// helper function to download file using fetch
async function fetchFile ( url , path , file _label ) {
var len = null ;
const res = await fetch ( url ) ;
len = parseInt ( res . headers . get ( "Content-Length" ) , 10 ) ;
var bar = new ProgressBar ( ` Downloading ${ file _label } [:bar] :percent :etas ` , {
complete : '=' ,
incomplete : ' ' ,
width : 20 ,
total : len
} ) ;
const fileStream = fs . createWriteStream ( path ) ;
await new Promise ( ( resolve , reject ) => {
res . body . pipe ( fileStream ) ;
res . body . on ( "error" , ( err ) => {
reject ( err ) ;
} ) ;
res . body . on ( 'data' , function ( chunk ) {
bar . tick ( chunk . length ) ;
} ) ;
fileStream . on ( "finish" , function ( ) {
resolve ( ) ;
} ) ;
} ) ;
}
async function downloadReleaseZip ( tag ) {
console . log ( 'downloading' ) ;
return new Promise ( async resolve => {
// get name of latest zip file, which depends on the version
const latest _release _link = 'https://github.com/Tzahi12345/YoutubeDL-Material/releases/latest/download/' ;
// get name of zip file, which depends on the version
const latest _release _link = ` https://github.com/Tzahi12345/YoutubeDL-Material/releases/download/ ${ tag } / ` ;
const tag _without _v = tag . substring ( 1 , tag . length ) ;
const zip _file _name = ` youtubedl-material- ${ tag _without _v } .zip `
const latest _zip _link = latest _release _link + zip _file _name ;
let output _path = path . join ( _ _dirname , ` youtubedl-material-latest-release.zip ` ) ;
let output _path = path . join ( _ _dirname , ` youtubedl-material- release-${ tag } .zip` ) ;
// download zip from release
await fetchFile ( latest _zip _link , output _path ) ;
await fetchFile ( latest _zip _link , output _path , 'update ' + tag );
resolve ( true ) ;
} ) ;
@ -254,21 +316,6 @@ async function installDependencies() {
}
// helper function to download file using fetch
const fetchFile = ( async ( url , path ) => {
const res = await fetch ( url ) ;
const fileStream = fs . createWriteStream ( path ) ;
await new Promise ( ( resolve , reject ) => {
res . body . pipe ( fileStream ) ;
res . body . on ( "error" , ( err ) => {
reject ( err ) ;
} ) ;
fileStream . on ( "finish" , function ( ) {
resolve ( ) ;
} ) ;
} ) ;
} ) ;
async function backupServerLite ( ) {
return new Promise ( async resolve => {
let output _path = ` backup- ${ Date . now ( ) } .zip ` ;
@ -1695,6 +1742,32 @@ app.post('/api/downloadArchive', async (req, res) => {
} ) ;
// Updater API calls
app . get ( '/api/updaterStatus' , async ( req , res ) => {
let status = updaterStatus ;
if ( status ) {
res . send ( updaterStatus ) ;
} else {
res . sendStatus ( 404 ) ;
}
} ) ;
app . post ( '/api/updateServer' , async ( req , res ) => {
let tag = req . body . tag ;
updateServer ( tag ) ;
res . send ( {
success : true
} ) ;
} ) ;
// Pin API calls
app . post ( '/api/isPinSet' , async ( req , res ) => {
let stored _pin = db . get ( 'pin_md5' ) . value ( ) ;
let is _set = false ;