diff --git a/main.js b/main.js index 95d62bd..8b27dc0 100644 --- a/main.js +++ b/main.js @@ -74,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"); diff --git a/modules/Environment.js b/modules/Environment.js index a51dfd8..1d36fc9 100644 --- a/modules/Environment.js +++ b/modules/Environment.js @@ -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 { @@ -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, diff --git a/modules/QueryManager.js b/modules/QueryManager.js index 46ce662..9130b43 100644 --- a/modules/QueryManager.js +++ b/modules/QueryManager.js @@ -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) { diff --git a/modules/download/DownloadQuery.js b/modules/download/DownloadQuery.js index 4df0352..5ebc6fe 100644 --- a/modules/download/DownloadQuery.js +++ b/modules/download/DownloadQuery.js @@ -106,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) { diff --git a/modules/info/InfoQueryList.js b/modules/info/InfoQueryList.js index e8ed63c..c3a48f4 100644 --- a/modules/info/InfoQueryList.js +++ b/modules/info/InfoQueryList.js @@ -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]) { @@ -43,7 +43,6 @@ class InfoQueryList { }); } })); - return result; } createVideo(data, url) { diff --git a/modules/persistence/Logger.js b/modules/persistence/Logger.js new file mode 100644 index 0000000..b34c5cd --- /dev/null +++ b/modules/persistence/Logger.js @@ -0,0 +1,63 @@ +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(", ", "-") + .replaceAll("/", "-") + .replaceAll(":", "-") + .replace(/:.. /," "); + let result = await dialog.showSaveDialog(this.environment.win, { + defaultPath: path.join(this.environment.settings.downloadPath, "ytdl-log-" + date), + 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; diff --git a/modules/types/Query.js b/modules/types/Query.js index 7ebdf10..8f7bf1d 100644 --- a/modules/types/Query.js +++ b/modules/types/Query.js @@ -104,6 +104,7 @@ class Query { resolve("done"); }); this.process.stderr.on("data", (data) => { + cb(data.toString()); if(this.environment.errorHandler.checkError(data.toString(), this.identifier)) { cb("killed"); resolve("killed"); diff --git a/preload.js b/preload.js index 817974d..13ce1ba 100644 --- a/preload.js +++ b/preload.js @@ -40,7 +40,9 @@ contextBridge.exposeInMainWorld( "getDoneActions", "setDoneAction", "getSubtitles", - "getSelectedSubtitles" + "getSelectedSubtitles", + "getLog", + "saveLog" ]; if (validChannels.includes(channel)) { return await ipcRenderer.invoke(channel, data); diff --git a/renderer/renderer.css b/renderer/renderer.css index 13e253a..6078437 100644 --- a/renderer/renderer.css +++ b/renderer/renderer.css @@ -500,6 +500,27 @@ option.audio { } } +/* LOG MODAL */ +#logModal { + padding: 0 5rem; +} + +#logModal .modal-dialog { + max-width: 1200px; + margin: 1.75rem auto !important; +} + +#logModal .log { + overflow-y: auto; + max-height: 550px; + border-color: var(--tertiary-bg-color); + background-color: var(--secondary-bg-color); +} + +#logModal .log p { + margin-bottom: 0.5rem; +} + /* INFO MODAL */ #info-description { resize: none; diff --git a/renderer/renderer.html b/renderer/renderer.html index 807dad8..0877c65 100644 --- a/renderer/renderer.html +++ b/renderer/renderer.html @@ -222,6 +222,27 @@ + +