|
#!/usr/bin/env node |
|
|
|
// Requires |
|
const { execSync } = require('child_process'), |
|
{ get } = require('https'), |
|
{ writeFile, unlink } = require('fs').promises, |
|
{ resolve } = require('path'); |
|
|
|
// Constants |
|
const EMBY_GITHUB_URL = `https://api.github.com/repos/MediaBrowser/Emby.Releases/releases`, |
|
TEMP_DIR = `/tmp/`; |
|
|
|
/** |
|
* Program entry point. |
|
*/ |
|
(function main() { |
|
expectRoot(); |
|
|
|
// Detect arguments |
|
const beta = process.argv.indexOf('beta') >= 0; |
|
const force = process.argv.indexOf('force') >= 0; |
|
const help = process.argv.indexOf('help') >= 0 || |
|
process.argv.indexOf('-h') >= 0 || |
|
process.argv.indexOf('--help') >= 0; |
|
|
|
// Display help message. |
|
if (help) { |
|
console.log(`usage: emby-install.js [beta] [force] [help|--help|-h] |
|
beta: Install the beta version instead of the Release. |
|
force: Install the latest version even if the same version is installed. |
|
help: Display this message.`); |
|
process.exit(0); |
|
} |
|
|
|
processUpdate(beta, force) |
|
.catch(err => console.log(err)); |
|
})(); |
|
|
|
/** |
|
* Validate if the current user is root |
|
* If the user isn't root, terminate the process. |
|
*/ |
|
function expectRoot() { |
|
// Need to run script as root |
|
const username = require('os').userInfo().username; |
|
if (username != 'root') { |
|
console.log('This script need to be ran as root.'); |
|
process.exit(1); |
|
} |
|
} |
|
|
|
/** |
|
* The update process |
|
* @param {boolean} beta Install the beta version instead of the official release. |
|
* @param {boolean} force Install the application even if the version is the same. |
|
*/ |
|
async function processUpdate(beta, force) { |
|
try { |
|
const systemVersion = getInstalledVersion(); |
|
const asset = await getDownloadAsset(beta); |
|
|
|
// Only download & install if installation is forced or the online version is different from the currently installed version. |
|
if (force || systemVersion === null || !systemVersion.includes(asset.version)) { |
|
// Download the installer file. |
|
const path = resolve(TEMP_DIR, asset.name); |
|
await downloadFile(asset.browser_download_url, path); |
|
|
|
// Stop the emby server before install. |
|
if (systemVersion !== null) { |
|
execSync('systemctl stop emby-server'); |
|
} |
|
|
|
// Exec dpkg to install deb. |
|
execSync(`dpkg -i ${path}`); |
|
|
|
// Remove file downloaded. |
|
await unlink(path); |
|
|
|
// Restart the server. |
|
execSync('systemctl start emby-server'); |
|
console.log(execSync('systemctl status emby-server').toString()); |
|
} else { |
|
console.log('Already up to date.') |
|
} |
|
} catch(e) { |
|
console.log(e.message); |
|
process.exit(1); |
|
} |
|
} |
|
|
|
/** |
|
* Query the system for the version of Emby installed. |
|
* @returns {string|null} The currently installed version, or null if none. |
|
*/ |
|
function getInstalledVersion() { |
|
const query = execSync(`dpkg-query -s emby-server`); |
|
return /Version: ?([a-z0-9\.]*)/.exec(query)[1] || null; |
|
} |
|
|
|
/** |
|
* Get the Github asset to download |
|
* @param {boolean} beta True if we're looking for a beta, otherwise false. |
|
* @returns {Promise<object>} A promise to return the asset to download, otherwise catch with error. |
|
*/ |
|
async function getDownloadAsset(beta) { |
|
const raw = await httpRequest(EMBY_GITHUB_URL); |
|
|
|
let versions; |
|
try { versions = JSON.parse(raw.toString()); } |
|
catch (e) { throw new Error('Invalid version format.'); } |
|
|
|
return findValidVersionAsset(versions, beta); |
|
} |
|
|
|
/** |
|
* Find a suitable asset version to install. |
|
* @param {object} versions The release version object from github. |
|
* @param {boolean} beta True if we're looking for a beta, otherwise false. |
|
* @returns {object} The asset to be downloaded from a valid release. |
|
*/ |
|
function findValidVersionAsset(versions, beta) { |
|
for (let v of versions) { |
|
// Continue if we're looking for a beta but the current version isn't one, |
|
// or if we aren't looking for a beta and the current version is one. |
|
const isBeta = v.name.includes('beta'); |
|
if ((beta && !isBeta) || (!beta && isBeta)) |
|
continue; |
|
|
|
// Find which asset is a deb file for x86_64 (amd64). |
|
let debAsset = null; |
|
for (let a of v.assets) { |
|
if (/^emby-server-deb(.*)amd64.deb$/.test(a.name)) { |
|
debAsset = a; |
|
debAsset.version = v.tag_name; |
|
break; |
|
} |
|
} |
|
|
|
// If asset is valid finish. |
|
if (debAsset !== null) { |
|
return debAsset; |
|
} |
|
} |
|
} |
|
|
|
/** |
|
* Download a file to the disk. |
|
* @param {string} url The URL of the file to download. |
|
* @param {string} filename The path where the file will be created. |
|
*/ |
|
async function downloadFile(url, filename) { |
|
console.log(`Downloading installer to ${filename}`); |
|
const data = await httpRequest(url); |
|
try { await writeFile(filename, data); } |
|
catch (e) { throw new Error(`Failed to write installer to file: ${e.message}`); } |
|
} |
|
|
|
/** |
|
* Makes a HTTP call to a specified URL. |
|
* @param {string} url The URL to query |
|
* @returns {Promise<Buffer>} The server response. |
|
*/ |
|
function httpRequest(url) { |
|
return new Promise((resolve, reject) => { |
|
get(url, { |
|
headers: { |
|
'User-Agent': 'NODE HTTPS' |
|
} |
|
}, (res) => { |
|
console.log(`Request to ${url}: ${res.statusCode}`); |
|
|
|
//res.on('data', data => { console.log(data.toString()) }); |
|
if ([200, 202].includes(res.statusCode)) { |
|
const bufs = []; |
|
let downloaded = 0; |
|
|
|
res.on('data', data => { |
|
downloaded += data.length; |
|
let progress = Math.round((downloaded / parseInt(res.headers['content-length'], 10) * 100) * 100) / 100; |
|
process.stdout.write(`Download progress: ${progress}%${" ".repeat(10)}\r`); |
|
|
|
bufs.push(data); |
|
}); |
|
|
|
res.on('end', () => { |
|
process.stdout.write('\n'); |
|
return resolve(Buffer.concat(bufs)); |
|
}) |
|
} |
|
|
|
// Redirect, redo the request on the redirected URL. |
|
else if ([301, 302].includes(res.statusCode)) |
|
return resolve(httpRequest(res.headers.location)); |
|
|
|
// Incorrect status code. |
|
else |
|
return reject(new Error(`Bad response from server: ${res.statusCode}`)); |
|
}).on('error', err => { |
|
// An error occured when opening the HTTP request. |
|
return reject(new Error(`Request failed: ${err.message}`)); |
|
}); |
|
}); |
|
} |
Hi where i need to put the file and how i can execute it? Do you have an example
I'm using emby into a debian machine
Thanks