Files
alexis/lib/phantomloader.js
2023-08-01 12:47:58 +02:00

177 lines
5.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict'
const os = require('os')
const url = require('url')
const path = require('path')
const cp = require('child_process')
const fs = require('fs-extra')
const request = require('request')
const extractZip = require('extract-zip')
const PHANTOM_VERSION = '2.1.1'
const DEFAULT_CDN = 'https://github.com/Medium/phantomjs/releases/download/v2.1.1'
const ARM_URL = 'https://github.com/fg2it/phantomjs-on-raspberry/raw/master/rpi-1-2-3/wheezy-jessie/v2.1.1/phantomjs'
const PLATFORM = os.platform()
const ARCH = os.arch()
const getDownloadUrl = () => {
let downloadUrl = DEFAULT_CDN + '/phantomjs-' + PHANTOM_VERSION + '-'
if (PLATFORM === 'linux' && ARCH === 'x64') {
downloadUrl += 'linux-x86_64.tar.bz2'
} else if (PLATFORM === 'linux' && ARCH == 'ia32') {
downloadUrl += 'linux-i686.tar.bz2'
} else if (PLATFORM === 'linux' && ARCH.search('arm') !== -1) {
downloadUrl = ARM_URL
} else if (PLATFORM === 'darwin') {
downloadUrl += 'macosx.zip'
} else if (PLATFORM === 'win32') {
downloadUrl += 'windows.zip'
} else {
return null
}
return downloadUrl
}
const downloadPhantomjs = (logger, downloadUrl, data_dir) => {
return new Promise((resolve, reject) => {
const file_name = downloadUrl.split('/').pop()
const downloaded_file = path.join(data_dir, file_name)
// actually downloads the file
const startDownload = (url, dest, cb) => {
const file = fs.createWriteStream(dest)
// download file
request(url)
.pipe(file)
.on('error', cb)
file.on('close', () => {
// close file & invoke callback
file.close()
cb()
})
}
startDownload(downloadUrl, downloaded_file, err => {
if (err) return reject(err)
resolve(downloaded_file)
})
})
}
const extractDownload = (logger, filePath) => {
return new Promise((resolve, reject) => {
var extractedPath = filePath + '-extract-' + Date.now()
var options = {cwd: extractedPath}
fs.mkdirsSync(extractedPath, '0777')
// Make double sure we have 0777 permissions; some operating systems
// default umask does not allow write by default.
fs.chmodSync(extractedPath, '0777')
if (filePath.substr(-4) === '.zip') {
logger.log('PHANTOMJS','Extracting zip contents')
extractZip(path.resolve(filePath), {dir: extractedPath}, err => {
if (err) {
reject(err)
} else {
resolve(extractedPath)
}
})
} else {
logger.log('PHANTOMJS', 'Extracting tar contents (via spawned process)')
cp.execFile('tar', ['jxf', path.resolve(filePath)], options, err => {
if (err) {
reject(err)
} else {
resolve(extractedPath)
}
})
}
})
}
const copyIntoPlace = (logger, extractedPath, archiveFile, targetPath) => {
return new Promise((resolve, reject) => {
logger.log('PHANTOMJS', `Removing ${archiveFile}`)
fs.removeSync(archiveFile)
const folders = fs.readdirSync(extractedPath)
const bin_dir = path.join(extractedPath, folders[0], 'bin')
const files = fs.readdirSync(path.join(extractedPath, folders[0], 'bin'))
let moved = false
for (let i = 0; i < files.length; i++) {
let file = path.join(bin_dir, files[i])
let filename = files[i]
let target = targetPath + path.sep + filename
logger.log('PHANTOMJS', `Copying extracted binary ${file} -> ${target}`)
fs.moveSync(file, target)
logger.log('PHANTOMJS', `Removing temporary download folder ${extractedPath}`)
fs.removeSync(extractedPath)
moved = target
}
if (moved !== false) {
resolve(moved)
} else {
reject()
}
})
}
const download = async (logger, phantom_bin, data_dir) => {
const download_url = getDownloadUrl()
let downloaded_file = ''
let extracted_folder = ''
let moved_file = ''
// error out if we couldn't find a suitable platform/arch combination
if (download_url === null) {
logger.log('ERROR',
`Unexpected platform or architecture: ${PLATFORM} / ${ARCH}\n` +
'It seems there is no binary available for your platform/architecture\n' +
`Try to install PhantomJS on your own & copy/link the executable to "${data_dir}"`)
return false
}
logger.log('PHANTOMJS', `Downloading from "${download_url}" to "${data_dir}/"`)
// download phantomjs
try {
downloaded_file = await downloadPhantomjs(logger, download_url, data_dir)
logger.log('PHANTOMJS', 'Download finished')
} catch (e) {
logger.log('ERROR', 'Error downloading PhantomJS - ' + e)
return false
}
// extract phantomjs (if needed)
// if it´s ARM, we´re done now
if (ARCH.search('arm') !== -1) return true
logger.log('PHANTOMJS', `Extracting PhantomJS binary: ${downloaded_file}`)
try {
extracted_folder = await extractDownload(logger, downloaded_file)
} catch (e) {
logger.log('ERROR', 'Error extracting PhantomJS - ' + e)
return false
}
logger.log('PHANTOMJS', 'Successfully extracted archive: "${extracted_folder}"')
// move Phantom executable
logger.log('PHANTOMJS', 'Moving executable to top level')
try {
moved_file = await copyIntoPlace(logger, extracted_folder, downloaded_file, data_dir)
} catch (e) {
logger.log('PHANTOMJS', 'Could not find extracted file')
return false
}
// make phantomjs executable
try {
fs.chmodSync(moved_file, '755')
} catch (e) {
logger.log('PHANTOMJS', 'Possible error with rights of downloaded Phantom binary')
}
return true
}
module.exports = (logger) => {
return {
download: download.bind(this, logger)
}
}