Skip to content

Commit

Permalink
update: merge from v2.3.0
Browse files Browse the repository at this point in the history
v2.3.0 - Open Video Downloader
  • Loading branch information
jely2002 authored Aug 3, 2021
2 parents 29e1713 + 86dacaf commit 95707da
Show file tree
Hide file tree
Showing 22 changed files with 571 additions and 119 deletions.
14 changes: 14 additions & 0 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ function startCriticalHandlers(env) {
taskList.load();
}

//Send the saved download type to the renderer
win.webContents.send("videoAction", {action: "setDownloadType", type: env.settings.downloadType});

env.errorHandler = new ErrorHandler(win, queryManager, env);

if(appStarting) {
Expand All @@ -71,6 +74,16 @@ function startCriticalHandlers(env) {
taskList.restore()
});

//Send the log for a specific download to renderer
ipcMain.handle("getLog", (event, identifier) => {
return env.logger.get(identifier);
});

//Save the log when renderer asks main
ipcMain.handle("saveLog", (event, identifier) => {
return env.logger.save(identifier);
})

//Catch all console.log calls, print them to stdout and send them to the renderer devtools.
console.log = (arg) => {
process.stdout.write(arg + "\n");
Expand Down Expand Up @@ -205,6 +218,7 @@ function createWindow(env) {
}

app.on('ready', async () => {
app.setAppUserModelId("com.jelleglebbeek.youtube-dl-gui");
env = new Environment(app, analytics);
await env.initialize();
createWindow(env);
Expand Down
2 changes: 2 additions & 0 deletions modules/Environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const Bottleneck = require("bottleneck");
const Filepaths = require("./Filepaths");
const Settings = require("./persistence/Settings");
const DetectPython = require("./DetectPython");
const Logger = require("./persistence/Logger");
const fs = require("fs").promises;

class Environment {
Expand All @@ -15,6 +16,7 @@ class Environment {
this.mainAudioQuality = "best";
this.mainDownloadSubs = false;
this.doneAction = "Do nothing";
this.logger = new Logger(this);
this.paths = new Filepaths(app, this);
this.downloadLimiter = new Bottleneck({
trackDoneStatus: true,
Expand Down
77 changes: 57 additions & 20 deletions modules/Filepaths.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ class Filepaths {
break;
}
case "win32portable":
this.persistentPath = path.join(this.app.getPath('appData'), "youtube-dl-gui-portable");
this.persistentPath = path.join(process.env.PORTABLE_EXECUTABLE_DIR , "open-video-downloader");
this.unpackedPrefix = path.join(path.dirname(this.appPath), "app.asar.unpacked");
this.packedPrefix = this.appPath;
await this.createAppDataFolder();
await this.createPortableFolder();
this.ffmpeg = path.join(this.persistentPath, "ffmpeg.exe");
this.ytdl = path.join(this.persistentPath, "youtube-dl.exe");
this.icon = path.join(this.packedPrefix, "renderer/img/icon.png");
Expand Down Expand Up @@ -97,7 +97,7 @@ class Filepaths {
}

detectPlatform() {
if(this.appPath.includes("\\AppData\\Local\\Temp\\")) return "win32portable";
if(process.env.PORTABLE_EXECUTABLE_DIR != null) return "win32portable";
else if(this.appPath.includes("WindowsApps")) return "win32app"
else return process.platform;
}
Expand All @@ -112,30 +112,67 @@ class Filepaths {
}

async createAppDataFolder() {
await new Promise((resolve) => {
mkdirp(this.persistentPath).then(made => {
if (made != null) {
fs.copyFileSync(path.join(this.unpackedPrefix, "binaries/youtube-dl.exe"), path.join(this.persistentPath, "youtube-dl.exe"));
fs.copyFileSync(path.join(this.unpackedPrefix, "binaries/ffmpeg.exe"), path.join(this.persistentPath, "ffmpeg.exe"));
fs.copyFileSync(path.join(this.unpackedPrefix, "binaries/AtomicParsley.exe"), path.join(this.persistentPath, "AtomicParsley.exe"));
fs.copyFileSync(path.join(this.unpackedPrefix, "binaries/ytdlVersion"), path.join(this.persistentPath, "ytdlVersion"));
}
resolve();
})
})
const from = path.join(this.unpackedPrefix + "binaries");
const toCopy = ["youtube-dl.exe", "ffmpeg.exe", "ytdlVersion", "AtomicParsley.exe"];
await this.copyFiles(from, this.persistentPath, toCopy);
}

async createPortableFolder() {
try {
await fs.promises.access(process.env.PORTABLE_EXECUTABLE_DIR, fs.constants.W_OK);
if(await this.migrateExistingAppDataFolder()) return;
const from = path.join(this.unpackedPrefix + "binaries");
const toCopy = ["youtube-dl.exe", "ffmpeg.exe", "ytdlVersion", "AtomicParsley.exe"];
await this.copyFiles(from, this.persistentPath, toCopy);
} catch (e) {
setTimeout(() => console.error(e), 5000);
this.persistentPath = path.join(this.app.getPath("appData"), "open-video-downloader");
await this.createAppDataFolder();
}
}

async migrateExistingAppDataFolder() {
const from = path.join(this.app.getPath("appData"), "youtube-dl-gui-portable");
try {
await fs.promises.access(from, fs.constants.W_OK);
const toCopy = ["youtube-dl.exe", "ffmpeg.exe", "ytdlVersion", "userSettings", "taskList"];
await this.copyFiles(from, this.persistentPath, toCopy);
try {
await fs.promises.rmdir(from, {recursive: true});
} catch (e) {
console.error(e);
}
return true;
} catch (e) {
return false;
}
}

async createHomeFolder() {
const from = path.join(this.unpackedPrefix + "binaries");
const toCopy = ["youtube-dl-unix", "ffmpeg-linux", "ytdlVersion"];
await this.copyFiles(from, this.persistentPath, toCopy);
}

async copyFiles(from, to, files) {
await new Promise((resolve) => {
mkdirp(this.persistentPath).then(made => {
mkdirp(to).then(made => {
if (made != null) {
fs.copyFileSync(path.join(this.unpackedPrefix, "binaries/youtube-dl-unix"), path.join(this.persistentPath, "youtube-dl-unix"));
fs.copyFileSync(path.join(this.unpackedPrefix, "binaries/ffmpeg-linux"), path.join(this.persistentPath, "ffmpeg"));
fs.copyFileSync(path.join(this.unpackedPrefix, "binaries/ytdlVersion"), path.join(this.persistentPath, "ytdlVersion"));
for (const file of files) {
this.copyFile(from, to, file);
}
}
resolve();
})
})
});
});
}

copyFile(from, to, filename) {
try {
fs.copyFileSync(path.join(from, filename), path.join(to, filename));
} catch (e) {
console.error("Could not copy " + filename + " to " + to + ".");
}
}
}

Expand Down
1 change: 1 addition & 0 deletions modules/QueryManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ class QueryManager {
this.managedVideos = this.managedVideos.filter(item => item.identifier !== video.identifier);
this.playlistMetadata = this.playlistMetadata.filter(item => item.video_url !== video.url && item.playlist_url !== video.url);
this.window.webContents.send("videoAction", { action: "remove", identifier: video.identifier })
this.environment.logger.clear(video.identifier);
}

onError(identifier) {
Expand Down
19 changes: 17 additions & 2 deletions modules/download/DownloadQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,15 @@ class DownloadQuery extends Query {
let args = [];
let output = path.join(this.environment.settings.downloadPath, Utils.resolvePlaylistPlaceholders(this.environment.settings.nameFormat, this.playlistMeta));
if(this.video.audioOnly) {
let numeralAudioQuality = (this.video.audioQuality === "best") ? "0" : "9";
let audioQuality = this.video.audioQuality;
if(audioQuality === "best") {
audioQuality = "0";
} else if(audioQuality === "worst") {
audioQuality = "9";
}
const audioOutputFormat = this.environment.settings.audioOutputFormat;
args = [
'--extract-audio', '--audio-quality', numeralAudioQuality,
'--extract-audio', '--audio-quality', audioQuality,
'--ffmpeg-location', this.environment.paths.ffmpeg,
'--no-mtime',
'-o', output,
Expand Down Expand Up @@ -101,6 +106,16 @@ class DownloadQuery extends Query {
const perLine = liveData.split("\n");
for(const line of perLine) {
this.video.setFilename(line);
if(line.lastIndexOf("[download]") !== line.indexOf("[download]")) {
const splitLines = line.split("[");
for(const splitLine of splitLines) {
if(splitLine.trim() !== "") {
this.environment.logger.log(this.video.identifier, "[" + splitLine.trim());
}
}
} else {
this.environment.logger.log(this.video.identifier, line);
}
}
if (!liveData.includes("[download]")) return;
if (!initialReset) {
Expand Down
2 changes: 1 addition & 1 deletion modules/exceptions/ErrorHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ErrorHandler {
console.error("An error has occurred but no error message was given.")
return false;
}
if(stderr.includes("WARNING")) {
if(stderr.trim().startsWith("WARNING:")) {
console.warn(stderr);
return;
}
Expand Down
7 changes: 6 additions & 1 deletion modules/exceptions/errorDefinitions.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@
"Unsupported URL"
]
},
{
"code": "URL not found",
"description": "This is an incorrect or non-existing URL.",
"trigger": "[Errno 11001]"
},
{
"code": "Private or non-existent playlist",
"description": "This playlist does not exist or is&nbsp;<span onclick=\"$('#authModal').modal('show');\" class=\"openAuth\">private</span>.",
Expand Down Expand Up @@ -195,7 +200,7 @@
},
{
"code": "Binaries missing/corrupted",
"description": "Please restart the app, or disable antivirus.",
"description": "Please restart the app and disable antivirus.",
"trigger": [
"Command failed with ENOENT: resources\\app.asar.unpacked\\binaries\\youtube-dl.exe",
"Command failed with ENOENT: binaries/youtube-dl.exe",
Expand Down
3 changes: 1 addition & 2 deletions modules/info/InfoQueryList.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class InfoQueryList {
}

async start() {
let result = await new Promise(((resolve) => {
return await new Promise(((resolve) => {
let totalMetadata = [];
let playlistUrls = Utils.extractPlaylistUrls(this.query);
for (const videoData of playlistUrls[1]) {
Expand Down Expand Up @@ -43,7 +43,6 @@ class InfoQueryList {
});
}
}));
return result;
}

createVideo(data, url) {
Expand Down
62 changes: 62 additions & 0 deletions modules/persistence/Logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
const {dialog} = require("electron");
const path = require("path");
const fs = require("fs");

class Logger {
constructor(environment) {
this.environment = environment;
this.logs = {};
}

log(identifier, line) {
if(line == null || line === "") return;
let trimmedLine;
if(line === "done") {
trimmedLine = "Download finished";
} else if(line === "killed") {
trimmedLine = "Download stopped";
} else {
trimmedLine = line.replace(/[\n\r]/g, "");
}
if(identifier in this.logs) {
this.logs[identifier].push(trimmedLine);
} else {
this.logs[identifier] = [trimmedLine];
}
}

get(identifier) {
return this.logs[identifier];
}

clear(identifier) {
delete this.logs[identifier];
}

async save(identifier) {
const logLines = this.logs[identifier];
let log = "";
for(const line of logLines) {
log += line + "\n";
}
const date = new Date().toLocaleString()
.replace(", ", "-")
.replace(/\//g, "-")
.replace(/:/g, "-")
let result = await dialog.showSaveDialog(this.environment.win, {
defaultPath: path.join(this.environment.settings.downloadPath, "ytdl-log-" + date.slice(0, date.length - 6)),
buttonLabel: "Save metadata",
filters: [
{ name: "txt", extensions: ["txt"] },
{ name: "All Files", extensions: ["*"] },
],
properties: ["createDirectory"]
});
if(!result.canceled) {
fs.promises.writeFile(result.filePath, log).then(() => console.log("Download log saved."));
}
}

}

module.exports = Logger;
Loading

0 comments on commit 95707da

Please sign in to comment.