diff --git a/assets/jsons/translations/de.json b/assets/jsons/translations/de.json index d3f1c4dcd..50be05d4d 100644 --- a/assets/jsons/translations/de.json +++ b/assets/jsons/translations/de.json @@ -279,6 +279,13 @@ "error-notification": { "message": "Ein Fehler ist aufgetreten, die Einstellungen für symbolische Links können nicht geändert werden." } + }, + "use-system-proxy": { + "title": "System-Proxy verwenden", + "description": "BSManager wird Netzwerkrequests über Ihren Systemproxy durchführen.", + "error-notification": { + "message": "Es ist ein Fehler aufgetreten, die Systemproxyeinstellungen können nicht geändert werden." + } } } } diff --git a/assets/jsons/translations/en.json b/assets/jsons/translations/en.json index 0380cc7be..063a5f0ea 100644 --- a/assets/jsons/translations/en.json +++ b/assets/jsons/translations/en.json @@ -265,7 +265,7 @@ "confirm-btn": "Yes I'm sure" }, "error-notification": { - "message": "An error occured, unable to disable hardware acceleration." + "message": "An error occurred, unable to disable hardware acceleration." } }, "use-symlinks": { @@ -277,7 +277,14 @@ "confirm-btn": "Yes I'm sure" }, "error-notification": { - "message": "An error occured, unable to change symlinks settings." + "message": "An error occurred, unable to change symlinks settings." + } + }, + "use-system-proxy": { + "title": "Use system proxy", + "description": "BSManager will make network requests through your system proxy.", + "error-notification": { + "message": "An error occurred, unable to change system proxy settings." } } } @@ -1045,7 +1052,7 @@ }, "no-models": "No models found.", "no-internet": "No internet connection.", - "error-occured": "An error occurred, try again later." + "error-occurred": "An error occurred, try again later." } }, "notifications": { diff --git a/assets/jsons/translations/es.json b/assets/jsons/translations/es.json index c78d2959f..af62103fa 100644 --- a/assets/jsons/translations/es.json +++ b/assets/jsons/translations/es.json @@ -279,6 +279,13 @@ "error-notification": { "message": "Ocurrió un error, no se pueden cambiar los ajustes de los enlaces simbólicos." } + }, + "use-system-proxy": { + "title": "Usar proxy del sistema", + "description": "BSManager realizará solicitudes de red a través de su proxy del sistema.", + "error-notification": { + "message": "Ocurrió un error, no se pueden cambiar los ajustes del proxy del sistema." + } } } } diff --git a/assets/jsons/translations/fr.json b/assets/jsons/translations/fr.json index 02852a847..ff2a856ca 100644 --- a/assets/jsons/translations/fr.json +++ b/assets/jsons/translations/fr.json @@ -279,6 +279,13 @@ "error-notification": { "message": "Une erreur s'est produite, impossible de changer les paramètres des liens symboliques." } + }, + "use-system-proxy": { + "title": "Utiliser le proxy du système", + "description": "BSManager effectuera des requêtes réseau via votre proxy système.", + "error-notification": { + "message": "Une erreur est survenue, impossible de modifier les paramètres du proxy système." + } } } } diff --git a/assets/jsons/translations/ja.json b/assets/jsons/translations/ja.json index d87c5772f..1e4220ade 100644 --- a/assets/jsons/translations/ja.json +++ b/assets/jsons/translations/ja.json @@ -279,6 +279,13 @@ "error-notification": { "message": "エラーが発生しました。シンボリックリンク設定を変更できません。" } + }, + "use-system-proxy": { + "title": "システムプロキシを使用", + "description": "BSManagerはシステムプロキシを通じてネットワークリクエストを行います。", + "error-notification": { + "message": "エラーが発生しました。システムプロキシ設定を変更できません。" + } } } } diff --git a/assets/jsons/translations/ko.json b/assets/jsons/translations/ko.json index 99b3d2b99..abc2ab9a4 100644 --- a/assets/jsons/translations/ko.json +++ b/assets/jsons/translations/ko.json @@ -279,6 +279,13 @@ "error-notification": { "message": "오류가 발생했습니다. 심볼릭 링크 설정을 변경할 수 없습니다." } + }, + "use-system-proxy": { + "title": "시스템 프록시 사용", + "description": "BSManager는 시스템 프록시를 통해 네트워크 요청을 수행합니다.", + "error-notification": { + "message": "오류가 발생했습니다. 시스템 프록시 설정을 변경할 수 없습니다." + } } } } diff --git a/assets/jsons/translations/ru.json b/assets/jsons/translations/ru.json index ab6a38959..ed64c100f 100644 --- a/assets/jsons/translations/ru.json +++ b/assets/jsons/translations/ru.json @@ -279,6 +279,13 @@ "error-notification": { "message": "Произошла ошибка, невозможно изменить настройки символических ссылок." } + }, + "use-system-proxy": { + "title": "Использовать системный прокси", + "description": "BSManager будет делать сетевые запросы через ваш системный прокси.", + "error-notification": { + "message": "Произошла ошибка, не удалось изменить настройки системного прокси." + } } } } diff --git a/assets/jsons/translations/zh-tw.json b/assets/jsons/translations/zh-tw.json index c2881a3d3..1c838f97b 100644 --- a/assets/jsons/translations/zh-tw.json +++ b/assets/jsons/translations/zh-tw.json @@ -279,6 +279,13 @@ "error-notification": { "message": "發生錯誤,無法更改符號鏈接設置。" } + }, + "use-system-proxy": { + "title": "使用系統代理", + "description": "BSManager將通過您的系統代理發送網絡請求。", + "error-notification": { + "message": "發生錯誤,無法更改系統代理設置。" + } } } } diff --git a/assets/jsons/translations/zh.json b/assets/jsons/translations/zh.json index f75a37153..00d6edf81 100644 --- a/assets/jsons/translations/zh.json +++ b/assets/jsons/translations/zh.json @@ -279,6 +279,13 @@ "error-notification": { "message": "发生错误,无法更改符号链接设置。" } + }, + "use-system-proxy": { + "title": "使用系统代理", + "description": "BSMansger将通过系统代理发起网络请求。", + "error-notification": { + "message": "发生错误,无法启用系统代理。" + } } } } diff --git a/package-lock.json b/package-lock.json index dd60eacf3..3738ce5dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "format-duration": "^3.0.2", "framer-motion": "^11.2.6", "fs-extra": "^11.2.0", + "global-agent": "^3.0.0", "got": "^14.4.4", "history": "^5.3.0", "is-elevated": "^4.0.0", @@ -74,6 +75,7 @@ "@types/color": "^3.0.3", "@types/crypto-js": "^4.2.1", "@types/dateformat": "^5.0.0", + "@types/global-agent": "^2.1.3", "@types/got": "^9.6.12", "@types/jest": "^29.5.11", "@types/node": "22.8.6", @@ -6158,6 +6160,13 @@ "@types/node": "*" } }, + "node_modules/@types/global-agent": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@types/global-agent/-/global-agent-2.1.3.tgz", + "integrity": "sha512-rGtZZcgZcKWuKNTkGBGsqyOQ7Nn2MjXh4+xeZbf+5b5KMUx8H1rTqLRackxos7pUlreszbYjQcop5JvqCnZlLw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/got": { "version": "9.6.12", "resolved": "https://registry.npmjs.org/@types/got/-/got-9.6.12.tgz", diff --git a/package.json b/package.json index 2a7df7b05..35b8da3db 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "@types/color": "^3.0.3", "@types/crypto-js": "^4.2.1", "@types/dateformat": "^5.0.0", + "@types/global-agent": "^2.1.3", "@types/got": "^9.6.12", "@types/jest": "^29.5.11", "@types/node": "22.8.6", @@ -170,6 +171,7 @@ "format-duration": "^3.0.2", "framer-motion": "^11.2.6", "fs-extra": "^11.2.0", + "global-agent": "^3.0.0", "got": "^14.4.4", "history": "^5.3.0", "is-elevated": "^4.0.0", diff --git a/src/main/helpers/proxy.helpers.ts b/src/main/helpers/proxy.helpers.ts new file mode 100644 index 000000000..71f9a3669 --- /dev/null +++ b/src/main/helpers/proxy.helpers.ts @@ -0,0 +1,81 @@ +import log from 'electron-log'; +import { RegDwordValue, RegSzValue } from "regedit-rs" +import { execOnOs } from "../helpers/env.helpers"; +import { bootstrap } from 'global-agent'; +import { StaticConfigurationService } from "../services/static-configuration.service"; + +const staticConfig = StaticConfigurationService.getInstance(); + +const { list } = (execOnOs({ win32: () => require("regedit-rs") }, true) ?? {}) as typeof import("regedit-rs"); + +async function isProxyEnabled(): Promise{ + const res = await list("HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"); + const key = res["HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"]; + if(!key.exists){ throw new Error("Key \"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\" not exist"); } + const registryValue = key.values.ProxyEnable as RegDwordValue; + if(!registryValue){ throw new Error("Value \"ProxyEnable\" not exist"); } + return (1 === registryValue.value); +} + +async function getProxyServer(): Promise{ + const res = await list("HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"); + const key = res["HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"]; + if(!key.exists){ throw new Error("Key \"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\" not exist"); } + const registryValue = key.values.ProxyServer as RegSzValue; + if(!registryValue){ throw new Error("Value \"ProxyServer\" not exist"); } + return registryValue.value; +} + +async function getProxyOverride(): Promise{ + const res = await list("HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"); + const key = res["HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"]; + if(!key.exists){ throw new Error("Key \"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\" not exist"); } + const registryValue = key.values.ProxyOverride as RegSzValue; + if(!registryValue){ throw new Error("Value \"ProxyOverride\" not exist"); } + return registryValue.value; +} + +async function enableWindowsProxy(enable: boolean): Promise { + if (!(await isProxyEnabled().catch(err => log.error(err)))) { + log.info("enableWindowsProxy: System proxy not detected"); + return; + } + + let { GLOBAL_AGENT: globalProxyAgent } = global as any; + if (!globalProxyAgent) { // If this is undefined, call bootstrap to set it up + if (!bootstrap()) { + log.error("enableWindowsProxy: Could not setup proxy stuff"); + return; + } + globalProxyAgent = (global as any).GLOBAL_AGENT; + } + + if (enable) { + const httpProxyUrl = `http://${await getProxyServer().catch(err => log.error(err))}` + globalProxyAgent.HTTP_PROXY = httpProxyUrl; + globalProxyAgent.HTTPS_PROXY = httpProxyUrl; + globalProxyAgent.NO_PROXY = `${await getProxyOverride().catch(err => log.error(err))}`; + + log.info(`enableWindowsProxy: Using system proxy: ${httpProxyUrl}`); + } else { + delete globalProxyAgent.HTTP_PROXY; + delete globalProxyAgent.HTTPS_PROXY; + delete globalProxyAgent.NO_PROXY; + + log.info("enableWindowsProxy: proxy disabled"); + } +} + +export function configureProxy() { + if (process.platform === "win32") { + enableWindowsProxy(staticConfig.get("use-system-proxy")); + + staticConfig.$watch("use-system-proxy").subscribe((useSystemProxy) => { + enableWindowsProxy(useSystemProxy); + + log.info(`configureProxy: UseSystemProxy is set to ${useSystemProxy}`); + }); + } else { + log.info("configureProxy: Unsupported platform"); + } +} diff --git a/src/main/main.ts b/src/main/main.ts index 6d6fbf805..0c8ab1c8b 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -25,6 +25,7 @@ import { FileAssociationService } from "./services/file-association.service"; import { SongDetailsCacheService } from "./services/additional-content/maps/song-details-cache.service"; import { readdirSync, statSync, unlinkSync } from "fs-extra"; import { StaticConfigurationService } from "./services/static-configuration.service"; +import { configureProxy } from './helpers/proxy.helpers'; const isDebug = process.env.NODE_ENV === "development" || process.env.DEBUG_PROD === "true"; const staticConfig = StaticConfigurationService.getInstance(); @@ -46,6 +47,7 @@ staticConfig.take("disable-hadware-acceleration", disabled => { } }); +configureProxy(); if (process.env.NODE_ENV === "production") { const sourceMapSupport = require("source-map-support"); diff --git a/src/main/services/static-configuration.service.ts b/src/main/services/static-configuration.service.ts index 1748b42d3..0a90c6072 100644 --- a/src/main/services/static-configuration.service.ts +++ b/src/main/services/static-configuration.service.ts @@ -88,6 +88,7 @@ export interface StaticConfigKeyValues { "song-details-cache-etag": string; "disable-hadware-acceleration": boolean; "use-symlinks": boolean; + "use-system-proxy": boolean; // Linux Specific static configs "proton-folder": string; diff --git a/src/renderer/pages/settings-page.component.tsx b/src/renderer/pages/settings-page.component.tsx index 991c4ece4..19530fb44 100644 --- a/src/renderer/pages/settings-page.component.tsx +++ b/src/renderer/pages/settings-page.component.tsx @@ -541,10 +541,12 @@ function AdvancedSettings() { const [hardwareAccelerationEnabled, setHardwareAccelerationEnabled] = useState(true); const [useSymlink, setUseSymlink] = useState(false); + const [useSystemProxy, setUseSystemProxy] = useState(false); useEffect(() => { staticConfig.get("disable-hadware-acceleration").then(disabled =>setHardwareAccelerationEnabled(() => disabled !== true)); staticConfig.get("use-symlinks").then(useSymlinks => setUseSymlink(() => useSymlinks)); + staticConfig.get("use-system-proxy").then(useSystemProxy => setUseSystemProxy(() => useSystemProxy)); }, []); const onChangeHardwareAcceleration = async (newHardwareAccelerationEnabled: boolean) => { @@ -609,6 +611,22 @@ function AdvancedSettings() { setUseSymlink(() => newUseSymlink); } + const onChangeUseSystemProxy = async (newUseSystemProxy: boolean) => { + + if (window.electron.platform !== "win32" || newUseSystemProxy === useSystemProxy) { + return; + } + + const { error } = await tryit(() => staticConfig.set("use-system-proxy", newUseSystemProxy)); + + if(error){ + notification.notifyError({ title: "notifications.types.error", desc: "pages.settings.advanced.use-system-proxy.error-notification.message" }); + return; + } + + setUseSystemProxy(() => newUseSystemProxy); + } + const advancedItems: Item[] = [{ checked: hardwareAccelerationEnabled, text: t.text("pages.settings.advanced.hardware-acceleration.title"), @@ -622,6 +640,12 @@ function AdvancedSettings() { desc: t.text("pages.settings.advanced.use-symlinks.description"), onChange: onChangeUseSymlinks }); + advancedItems.push({ + checked: useSystemProxy, + text: t.text("pages.settings.advanced.use-system-proxy.title"), + desc: t.text("pages.settings.advanced.use-system-proxy.description"), + onChange: onChangeUseSystemProxy + }); } return