Skip to content

Commit

Permalink
feat: show progress while updating/installing dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
jely2002 committed Oct 27, 2021
1 parent bc8b23e commit d4b62e9
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 40 deletions.
42 changes: 26 additions & 16 deletions modules/BinaryUpdater.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ const axios = require("axios");
const fs = require("fs");
const Sentry = require("@sentry/node");
const util = require('util');
const Utils = require('./Utils');
const exec = util.promisify(require('child_process').exec);

class BinaryUpdater {

constructor(paths, win) {
this.paths = paths;
this.win = win;
this.action = "Installing";
}

//Checks for an update and download it if there is.
Expand All @@ -28,15 +30,16 @@ class BinaryUpdater {
} else if(localVersion == null) {
transaction.setTag("download", "corrupted");
console.log("Downloading missing yt-dlp binary.");
this.win.webContents.send("binaryLock", {lock: true, placeholder: `Installing yt-dlp version: ${remoteVersion}...`})
this.win.webContents.send("binaryLock", {lock: true, placeholder: `Installing yt-dlp version: ${remoteVersion}. Preparing...`})
await this.downloadUpdate(remoteUrl, remoteVersion);
} else if(remoteVersion == null) {
transaction.setTag("download", "down");
console.log("Unable to check for new updates, GitHub may be down.");
} else {
console.log(`New version ${remoteVersion} found. Updating...`);
transaction.setTag("download", "update");
this.win.webContents.send("binaryLock", {lock: true, placeholder: `Updating yt-dlp to version: ${remoteVersion}...`})
this.action = "Updating to";
this.win.webContents.send("binaryLock", {lock: true, placeholder: `Updating yt-dlp to version: ${remoteVersion}. Preparing...`})
await this.downloadUpdate(remoteUrl, remoteVersion);
}
span.finish();
Expand Down Expand Up @@ -110,21 +113,28 @@ class BinaryUpdater {
//Downloads the file at the given url and saves it to the ytdl path.
async downloadUpdate(remoteUrl, remoteVersion) {
const writer = fs.createWriteStream(this.paths.ytdl);
return await axios.get(remoteUrl, {responseType: 'stream'}).then(response => {
return new Promise((resolve, reject) => {
response.data.pipe(writer);
let error = null;
writer.on('error', err => {
error = err;
reject(err);
});
writer.on('close', async () => {
if (!error) {
await this.writeVersionInfo(remoteVersion);
resolve(true);
}
});
const { data, headers } = await axios.get(remoteUrl, {responseType: 'stream'});
const totalLength = +headers['content-length'];
const total = Utils.convertBytes(totalLength);
let received = 0;
return await new Promise((resolve, reject) => {
let error = null;
data.on('data', (chunk) => {
received += chunk.length;
const percentage = ((received / totalLength) * 100).toFixed(0) + '%';
this.win.webContents.send("binaryLock", {lock: true, placeholder: `${this.action} yt-dlp ${remoteVersion} - ${percentage} of ${total}`})
});
writer.on('error', err => {
error = err;
reject(err);
});
writer.on('close', async () => {
if (!error) {
await this.writeVersionInfo(remoteVersion);
resolve(true);
}
});
data.pipe(writer);
});
}

Expand Down
55 changes: 35 additions & 20 deletions modules/FfmpegUpdater.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ const util = require('util');
const exec = util.promisify(require('child_process').exec);
const os = require("os");
const AdmZip = require("adm-zip");
const Utils = require('./Utils');

class FfmpegUpdater {

constructor(paths, win) {
this.paths = paths;
this.win = win;
this.action = "Installing";
}

//Checks for an update and download it if there is.
Expand All @@ -31,19 +33,22 @@ class FfmpegUpdater {
} else if(localVersion == null) {
transaction.setTag("download", "corrupted");
console.log("Downloading missing ffmpeg binary.");
this.win.webContents.send("binaryLock", {lock: true, placeholder: `Installing ffmpeg version: ${remoteVersion}...`})
await this.downloadUpdate(remoteFfmpegUrl, "ffmpeg" + this.getFileExtension());
await this.downloadUpdate(remoteFfprobeUrl, "ffprobe" + this.getFileExtension());
this.win.webContents.send("binaryLock", {lock: true, placeholder: `Installing ffmpeg version: ${remoteVersion}. Preparing...`})
await this.downloadUpdate(remoteFfmpegUrl, remoteVersion, "ffmpeg" + this.getFileExtension());
this.win.webContents.send("binaryLock", {lock: true, placeholder: `Installing ffprobe version: ${remoteVersion}. Preparing...`})
await this.downloadUpdate(remoteFfprobeUrl, remoteVersion, "ffprobe" + this.getFileExtension());
await this.writeVersionInfo(remoteVersion);
} else if(remoteVersion == null) {
transaction.setTag("download", "down");
console.log("Unable to check for new updates, ffbinaries.com may be down.");
} else {
console.log(`New version ${remoteVersion} found. Updating...`);
transaction.setTag("download", "update");
this.win.webContents.send("binaryLock", {lock: true, placeholder: `Updating ffmpeg to version: ${remoteVersion}...`})
await this.downloadUpdate(remoteFfmpegUrl, "ffmpeg" + this.getFileExtension());
await this.downloadUpdate(remoteFfprobeUrl, "ffprobe" + this.getFileExtension());
this.action = "Updating to";
this.win.webContents.send("binaryLock", {lock: true, placeholder: `Updating ffmpeg to version: ${remoteVersion}. Preparing...`})
await this.downloadUpdate(remoteFfmpegUrl, remoteVersion, "ffmpeg" + this.getFileExtension());
this.win.webContents.send("binaryLock", {lock: true, placeholder: `Updating ffprobe to version: ${remoteVersion}. Preparing...`})
await this.downloadUpdate(remoteFfprobeUrl, remoteVersion, "ffprobe" + this.getFileExtension());
await this.writeVersionInfo(remoteVersion);
}
span.finish();
Expand Down Expand Up @@ -106,27 +111,37 @@ class FfmpegUpdater {
}

//Downloads the file at the given url and saves it to the ffmpeg path.
async downloadUpdate(url, filename) {
async downloadUpdate(url, version, filename) {
const downloadPath = path.join(this.paths.ffmpeg, "downloads");
if (!fs.existsSync(downloadPath)) {
fs.mkdirSync(downloadPath);
}
const writer = fs.createWriteStream(path.join(downloadPath, filename));
await axios.get(url, {responseType: 'stream'}).then(response => {
return new Promise((resolve, reject) => {
response.data.pipe(writer);
let error = null;
writer.on('error', err => {
error = err;
reject(err);
});
writer.on('close', async () => {
if (!error) {
resolve(true);
}
});

const { data, headers } = await axios.get(url, {responseType: 'stream'});
const totalLength = +headers['content-length'];
const total = Utils.convertBytes(totalLength);
const artifact = filename.replace(".exe", "");
let received = 0;
await new Promise((resolve, reject) => {
let error = null;
data.on('data', (chunk) => {
received += chunk.length;
const percentage = ((received / totalLength) * 100).toFixed(0) + '%';
this.win.webContents.send("binaryLock", {lock: true, placeholder: `${this.action} ${artifact} ${version} - ${percentage} of ${total}`})
});
writer.on('error', err => {
error = err;
reject(err);
});
writer.on('close', async () => {
if (!error) {
resolve(true);
}
});
data.pipe(writer);
});
this.win.webContents.send("binaryLock", {lock: true, placeholder: `${this.action} ${artifact} ${version} - Extracting binaries...`})
const zipFile = new AdmZip(path.join(downloadPath, filename), {});
zipFile.extractEntryTo(filename, this.paths.ffmpeg, false, true, false, filename);
fs.rmdirSync(path.join(this.paths.ffmpeg, "downloads"), { recursive: true, force: true });
Expand Down
4 changes: 2 additions & 2 deletions tests/BinaryUpdater.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ describe("downloadUpdate", () => {
const mockReadable = new PassThrough();
const mockWriteable = new PassThrough();
jest.spyOn(fs, 'createWriteStream').mockReturnValueOnce(mockWriteable);
jest.spyOn(axios, 'get').mockResolvedValue({ data: mockReadable });
jest.spyOn(axios, 'get').mockResolvedValue({ data: mockReadable, headers: { "content-length": 1200 } });
setTimeout(() => {
mockWriteable.emit('error', "Test error");
}, 100);
Expand All @@ -150,7 +150,7 @@ describe("downloadUpdate", () => {
const mockReadable = new PassThrough();
const mockWriteable = new PassThrough();
jest.spyOn(fs, 'createWriteStream').mockReturnValueOnce(mockWriteable);
jest.spyOn(axios, 'get').mockResolvedValue({ data: mockReadable });
jest.spyOn(axios, 'get').mockResolvedValue({ data: mockReadable, headers: { "content-length": 1200 } });
setTimeout(() => {
mockWriteable.emit('close');
}, 100);
Expand Down
4 changes: 2 additions & 2 deletions tests/FfmpegUpdater.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ describe('checkUpdate', () => {
jest.spyOn(instance, 'getRemoteVersion').mockResolvedValue(["link", "v2.0.0"]);
return instance.checkUpdate().then(() => {
expect(downloadUpdateSpy).toBeCalledTimes(2);
expect(instance.win.webContents.send).toBeCalledTimes(1);
expect(instance.win.webContents.send).toBeCalledTimes(2);
});
});
it('downloads the latest remote version when local version is different', () => {
Expand All @@ -117,7 +117,7 @@ describe('checkUpdate', () => {
jest.spyOn(instance, 'getRemoteVersion').mockResolvedValue({ remoteUrl: "link", remoteVersion: "2021.10.10" });
return instance.checkUpdate().then(() => {
expect(downloadUpdateSpy).toBeCalledTimes(2);
expect(instance.win.webContents.send).toBeCalledTimes(1);
expect(instance.win.webContents.send).toBeCalledTimes(2);
});
});
});

0 comments on commit d4b62e9

Please sign in to comment.