From 3a86e54a8fbdb612a1088bce461090e3f36dd63c Mon Sep 17 00:00:00 2001 From: aandrew-me Date: Wed, 17 Jun 2026 19:43:45 +0300 Subject: [PATCH] Add system proxy support --- main.js | 72 ++++++++++++++++++++++++++++++++++++++----------- src/playlist.js | 14 +++++++--- src/renderer.js | 22 +++++++++++++-- 3 files changed, 87 insertions(+), 21 deletions(-) diff --git a/main.js b/main.js index 5e3f538..d9569d2 100644 --- a/main.js +++ b/main.js @@ -7,6 +7,7 @@ const { Tray, Menu, clipboard, + session, } = require("electron"); const {autoUpdater} = require("electron-updater"); const fs = require("fs").promises; @@ -220,7 +221,7 @@ function createTray() { "did-finish-load", () => { appState.mainWindow.webContents.send("link", text); - } + }, ); } }, @@ -322,7 +323,7 @@ function registerIpcHandlers() { if (!appState.mainWindow) return; const {canceled, filePaths} = await dialog.showOpenDialog( appState.mainWindow, - {properties: ["openDirectory"]} + {properties: ["openDirectory"]}, ); if (!canceled && filePaths.length > 0) { appState.mainWindow.webContents.send("downloadPath", filePaths); @@ -333,12 +334,12 @@ function registerIpcHandlers() { if (!appState.secondaryWindow) return; const {canceled, filePaths} = await dialog.showOpenDialog( appState.secondaryWindow, - {properties: ["openDirectory"]} + {properties: ["openDirectory"]}, ); if (!canceled && filePaths.length > 0) { appState.secondaryWindow.webContents.send( "downloadPath", - filePaths + filePaths, ); } }); @@ -347,7 +348,7 @@ function registerIpcHandlers() { if (!appState.mainWindow) return; const {canceled, filePaths} = await dialog.showOpenDialog( appState.mainWindow, - {properties: ["openDirectory"]} + {properties: ["openDirectory"]}, ); if (!canceled && filePaths.length > 0) { appState.mainWindow.webContents.send("directory-path", filePaths); @@ -358,7 +359,7 @@ function registerIpcHandlers() { if (!appState.secondaryWindow) return; const {canceled, filePaths} = await dialog.showOpenDialog( appState.secondaryWindow, - {properties: ["openFile"]} + {properties: ["openFile"]}, ); if (!canceled && filePaths.length > 0) { appState.secondaryWindow.webContents.send("configPath", filePaths); @@ -397,7 +398,7 @@ function registerIpcHandlers() { const localeFile = path.join( __dirname, "translations", - `${locale}.json` + `${locale}.json`, ); const fallbackData = JSON.parse(readFileSync(fallbackFile, "utf8")); @@ -417,26 +418,65 @@ function registerIpcHandlers() { }); ipcMain.handle("get-download-history", () => - appState.downloadHistory.getHistory() + appState.downloadHistory.getHistory(), ); ipcMain.handle("add-to-history", (_, info) => - appState.downloadHistory.addDownload(info) + appState.downloadHistory.addDownload(info), ); ipcMain.handle("get-download-stats", () => - appState.downloadHistory.getStats() + appState.downloadHistory.getStats(), ); ipcMain.handle("delete-history-item", (_, id) => - appState.downloadHistory.removeHistoryItem(id) + appState.downloadHistory.removeHistoryItem(id), ); ipcMain.handle("clear-all-history", async () => { await appState.downloadHistory.clearHistory(); return true; }); ipcMain.handle("export-history-json", () => - appState.downloadHistory.exportAsJSON() + appState.downloadHistory.exportAsJSON(), ); ipcMain.handle("export-history-csv", () => - appState.downloadHistory.exportAsCSV() + appState.downloadHistory.exportAsCSV(), + ); + + ipcMain.handle( + "get-system-proxy", + async (_event, targetUrl = "https://youtube.com") => { + try { + const proxyInfo = + await session.defaultSession.resolveProxy(targetUrl); + + const rule = String(proxyInfo) + .split(";") + .map((s) => s.trim()) + .find((s) => s && s.toUpperCase() !== "DIRECT"); + + if (!rule) { + return null; + } + + const [type, hostPort] = rule.split(/\s+/, 2); + + if (!type || !hostPort) { + return null; + } + + const protocol = { + PROXY: "http://", + HTTP: "http://", + HTTPS: "https://", + SOCKS: "socks5://", + SOCKS5: "socks5://", + SOCKS4: "socks4://", + }[type.toUpperCase()]; + + return protocol ? `${protocol}${hostPort}` : null; + } catch (error) { + console.error("Failed to get system proxy:", error); + return null; + } + }, ); } @@ -453,7 +493,7 @@ function registerAutoUpdaterEvents() { }; const {response} = await dialog.showMessageBox( appState.mainWindow, - dialogOpts + dialogOpts, ); if (response === 0) { autoUpdater.downloadUpdate(); @@ -470,7 +510,7 @@ function registerAutoUpdaterEvents() { }; const {response} = await dialog.showMessageBox( appState.mainWindow, - dialogOpts + dialogOpts, ); if (response === 0) { autoUpdater.quitAndInstall(true, true); @@ -508,7 +548,7 @@ async function loadConfiguration() { } catch (error) { console.log( "Could not load config file, using defaults.", - error.message + error.message, ); appState.config = { bounds: {width: 1024, height: 768}, diff --git a/src/playlist.js b/src/playlist.js index b5464d5..e241c10 100644 --- a/src/playlist.js +++ b/src/playlist.js @@ -213,7 +213,7 @@ const playlistDownloader = { }); }, - startDownload(type) { + async startDownload(type) { try { this.state.url = this.validateUrl(this.state.url); } catch (_) { @@ -222,7 +222,7 @@ const playlistDownloader = { return; } - this.updateDynamicConfig(); + await this.updateDynamicConfig(); this.hideOptions(); const controller = new AbortController(); @@ -525,7 +525,7 @@ const playlistDownloader = { window.scrollTo(0, document.body.scrollHeight); }, - updateDynamicConfig() { + async updateDynamicConfig() { // Naming formats from localStorage this.config.foldernameFormat = localStorage.getItem("foldernameFormat") || "%(playlist_title)s"; @@ -535,6 +535,14 @@ const playlistDownloader = { // Proxy, cookies, config file this.config.proxy = localStorage.getItem("proxy") || ""; + + if (!this.config.proxy) { + const proxy = await ipcRenderer.invoke("get-system-proxy"); + console.log("Using system proxy: " + proxy); + + this.config.proxy = proxy; + } + this.config.cookie.browser = localStorage.getItem("browser") || ""; this.config.cookie.arg = this.config.cookie.browser ? "--cookies-from-browser" diff --git a/src/renderer.js b/src/renderer.js index 1b59791..f040d22 100644 --- a/src/renderer.js +++ b/src/renderer.js @@ -161,6 +161,7 @@ class YtDownloaderApp { console.log("ffmpeg path:", this.state.ffmpegPath); console.log("JS runtime path:", this.state.jsRuntimePath); + // TODO: See if it can be removed this._loadSettings(); this._addEventListeners(); @@ -643,7 +644,7 @@ class YtDownloaderApp { /** * Loads various settings from localStorage into the application state. */ - _loadSettings() { + async _loadSettings(url) { const prefs = this.state.preferences; prefs.videoQuality = Number( @@ -665,6 +666,23 @@ class YtDownloaderApp { ) === "true"; prefs.proxy = localStorage.getItem(CONSTANTS.LOCAL_STORAGE_KEYS.PROXY) || ""; + + if (!prefs.proxy) { + try { + const systemProxy = await ipcRenderer.invoke( + "get-system-proxy", + url, + ); + if (systemProxy) { + prefs.proxy = systemProxy; + + console.log("Using system proxy:", systemProxy); + } + } catch (err) { + console.error("Failed to get system proxy:", err); + } + } + prefs.browserForCookies = localStorage.getItem( CONSTANTS.LOCAL_STORAGE_KEYS.BROWSER_COOKIES, @@ -864,7 +882,7 @@ class YtDownloaderApp { return; } - this._loadSettings(); + await this._loadSettings(safeUrl); this._defaultVideoToggle(); this._resetUIForNewLink();