From 7c4f2841e108560fa3a38c229388e939bc6a82a7 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Sat, 27 Dec 2025 11:41:52 +0100
Subject: [PATCH 01/46] Fix: Security #5
---
server/controller/info.controller.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/controller/info.controller.js b/server/controller/info.controller.js
index 187d074..932621c 100644
--- a/server/controller/info.controller.js
+++ b/server/controller/info.controller.js
@@ -12,7 +12,7 @@ async function infoController(req, res){
/* Si pas d'url ou url invalide*/
- if (!url || !isValidUrl(url)) return res.status(400).send("❌ Invalid URL Or Missing");
+ if (!url || typeof url !== "string" || !isValidUrl(url)) return res.status(400).send("❌ Invalid URL Or Missing");
logger.info(`/Info Request receive by the Info Controller. URL: ${url}`);
From f31767e7e7a435a396b2f9d4e79dcb38b4fe4072 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Sat, 27 Dec 2025 12:14:21 +0100
Subject: [PATCH 02/46] Fix: Error Handling Info Controller
---
server/controller/info.controller.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/server/controller/info.controller.js b/server/controller/info.controller.js
index 932621c..906cbff 100644
--- a/server/controller/info.controller.js
+++ b/server/controller/info.controller.js
@@ -40,7 +40,8 @@ async function infoController(req, res){
} catch (err) {
- return res.status(500).send(`❌ ${err.message}`);
+ logger.error(`Info controller error: ${err && err.message ? err.message : err}`);
+ return res.status(500).send(`❌ Unable to fetch info`);
}
}
From 12ff25cc4bbd451f24d559b003c6da7d9e0ead33 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Sat, 27 Dec 2025 12:15:28 +0100
Subject: [PATCH 03/46] Fix: Error Handling Download Controller
---
server/controller/download.controller.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/controller/download.controller.js b/server/controller/download.controller.js
index 3b820ee..97c071c 100644
--- a/server/controller/download.controller.js
+++ b/server/controller/download.controller.js
@@ -25,7 +25,7 @@ async function downloadController(req, res) {
} catch (err) {
logger.error(`Server Error in /download : ${err.message}`);
- res.status(500).send(`❌ ${err.message}`);
+ res.status(500).send(`❌ Server Error`);
}
}
From ae7d33847449d6322e2f588363d9c504635f570b Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Sun, 28 Dec 2025 12:40:55 +0100
Subject: [PATCH 04/46] Add: Rate Limit to front rendering. Using Components
for reusability
---
package-lock.json | 46 +++++++++++++++++++++++++++++++++----
package.json | 1 +
server/helpers/rateLimit.js | 14 +++++++++++
server/server.js | 4 ++--
4 files changed, 59 insertions(+), 6 deletions(-)
create mode 100644 server/helpers/rateLimit.js
diff --git a/package-lock.json b/package-lock.json
index dba5193..963b2e4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,6 +14,7 @@
"electron-squirrel-startup": "^1.0.1",
"electron-updater": "^6.6.2",
"express": "^5.1.0",
+ "express-rate-limit": "^8.2.1",
"webidl-conversions": "^8.0.0",
"winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0"
@@ -547,6 +548,7 @@
"dev": true,
"license": "BSD-2-Clause",
"optional": true,
+ "peer": true,
"dependencies": {
"cross-dirname": "^0.1.0",
"debug": "^4.3.4",
@@ -568,6 +570,7 @@
"dev": true,
"license": "MIT",
"optional": true,
+ "peer": true,
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
@@ -584,6 +587,7 @@
"dev": true,
"license": "MIT",
"optional": true,
+ "peer": true,
"dependencies": {
"universalify": "^2.0.0"
},
@@ -598,6 +602,7 @@
"dev": true,
"license": "MIT",
"optional": true,
+ "peer": true,
"engines": {
"node": ">= 10.0.0"
}
@@ -1106,7 +1111,6 @@
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -2088,7 +2092,8 @@
"integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==",
"dev": true,
"license": "MIT",
- "optional": true
+ "optional": true,
+ "peer": true
},
"node_modules/cross-spawn": {
"version": "7.0.6",
@@ -2686,6 +2691,7 @@
"dev": true,
"hasInstallScript": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@electron/asar": "^3.2.1",
"debug": "^4.1.1",
@@ -2706,6 +2712,7 @@
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"graceful-fs": "^4.1.2",
"jsonfile": "^4.0.0",
@@ -2907,6 +2914,33 @@
"url": "https://opencollective.com/express"
}
},
+ "node_modules/express-rate-limit": {
+ "version": "8.2.1",
+ "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.2.1.tgz",
+ "integrity": "sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g==",
+ "license": "MIT",
+ "dependencies": {
+ "ip-address": "10.0.1"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/express-rate-limit"
+ },
+ "peerDependencies": {
+ "express": ">= 4.11"
+ }
+ },
+ "node_modules/express-rate-limit/node_modules/ip-address": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz",
+ "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
"node_modules/extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
@@ -3547,7 +3581,7 @@
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
- "devOptional": true,
+ "dev": true,
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
@@ -4654,6 +4688,7 @@
"dev": true,
"license": "MIT",
"optional": true,
+ "peer": true,
"dependencies": {
"commander": "^9.4.0"
},
@@ -4671,6 +4706,7 @@
"dev": true,
"license": "MIT",
"optional": true,
+ "peer": true,
"engines": {
"node": "^12.20.0 || >=14"
}
@@ -5511,6 +5547,7 @@
"integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"mkdirp": "^0.5.1",
"rimraf": "~2.6.2"
@@ -5574,6 +5611,7 @@
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"minimist": "^1.2.6"
},
@@ -5588,6 +5626,7 @@
"deprecated": "Rimraf versions prior to v4 are no longer supported",
"dev": true,
"license": "ISC",
+ "peer": true,
"dependencies": {
"glob": "^7.1.3"
},
@@ -5879,7 +5918,6 @@
"resolved": "https://registry.npmjs.org/winston/-/winston-3.19.0.tgz",
"integrity": "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@colors/colors": "^1.6.0",
"@dabh/diagnostics": "^2.0.8",
diff --git a/package.json b/package.json
index cdf3322..da90d5f 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"electron-squirrel-startup": "^1.0.1",
"electron-updater": "^6.6.2",
"express": "^5.1.0",
+ "express-rate-limit": "^8.2.1",
"webidl-conversions": "^8.0.0",
"winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0"
diff --git a/server/helpers/rateLimit.js b/server/helpers/rateLimit.js
new file mode 100644
index 0000000..d65336f
--- /dev/null
+++ b/server/helpers/rateLimit.js
@@ -0,0 +1,14 @@
+const RateLimit = require("express-rate-limit");
+
+
+/* Rate Limite */
+const rateLimite = RateLimit({
+ windowMs: 15 * 60, // 15 minutes
+ max: 5, // limit each IP to 100 requests per windowMs on the root path
+ message: "Too many requests, please try again later.",
+ statusCode: 429, // HTTP status code for "Too Many Requests"
+});
+
+module.exports = {
+ rateLimite
+}
\ No newline at end of file
diff --git a/server/server.js b/server/server.js
index fba428c..09c7ec7 100644
--- a/server/server.js
+++ b/server/server.js
@@ -5,7 +5,7 @@ const { logger, logSessionStart, logSessionEnd } = require("./logger");
const config = require("../config");
const { execFile } = require("child_process");
const { userYtDlp } = require("./helpers/path");
-
+const { rateLimite } = require("./helpers/rateLimit")
const app = express();
@@ -37,7 +37,7 @@ app.use(express.static(path.join(__dirname, "../public")));
app.use("/download", require("./routes/download.route"));
app.use("/info", require("./routes/info.route"));
-app.get("/", (req, res) => {
+app.get("/", rateLimite ,(req, res) => {
res.sendFile(path.join(__dirname, "../public/index.html"));
});
From 008428f10a6081a12d57e5350a0bad6df4ebffc0 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Sun, 28 Dec 2025 12:47:00 +0100
Subject: [PATCH 05/46] Fix: Remove Unsued Import in Controller
---
server/controller/download.controller.js | 1 -
server/controller/info.controller.js | 3 ---
2 files changed, 4 deletions(-)
diff --git a/server/controller/download.controller.js b/server/controller/download.controller.js
index 97c071c..597b290 100644
--- a/server/controller/download.controller.js
+++ b/server/controller/download.controller.js
@@ -1,7 +1,6 @@
const { fetchDownload } = require("../services/download.services");
const { logger } = require("../logger");
const { isValidUrl, isSafePath } = require("../helpers/validation");
-const { buildYtDlpArgs } = require("../helpers/buildArgs");
const { notifyDownloadFinished } = require("../helpers/notify");
const listeners = [];
diff --git a/server/controller/info.controller.js b/server/controller/info.controller.js
index 906cbff..949506b 100644
--- a/server/controller/info.controller.js
+++ b/server/controller/info.controller.js
@@ -1,6 +1,3 @@
-const express = require("express");
-const router = express.Router();
-
const { fetchInfo } = require("../services/info.services");
const { parseVideo, parsePlaylist } = require("../helpers/parseInfo");
const { logger } = require("../logger");
From 6c9d296fbd0b0f1fe9ed6e4dcc8df85c23372831 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Tue, 30 Dec 2025 11:38:18 +0100
Subject: [PATCH 06/46] Add: Some Variables in config.js. For Modules
---
config.js | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/config.js b/config.js
index e460608..a8362a8 100644
--- a/config.js
+++ b/config.js
@@ -7,4 +7,17 @@ module.exports = {
debugMode: true,
localMode: !app.isPackaged,
DiscordRPCID: "1410934537051181146",
+
+ // Variables Used to toggle main features
+ autoUpdate: true,
+ discordRPC: true,
+ customTopBar: true, // (Will be active on next launch)
+ autoDownloadPlaylist: true,
+ logSystem: true, // Disable = Dangerous
+ autoCheckInfo: true, // To Improve speed ? (NO)
+ outputTitleCheck: true, // For Non latin characters (Russian)
+ addThumbail: true, // The Pictures in the files (audio files)
+ addMetadata: true, // Looks Explicit
+ downloadSystem: true, // Why would you disable this ? I don't know but why not
+ notifySystem: true // Notification when download
}
\ No newline at end of file
From 43869420c0a7735a59619ecb11dff2ba1115c489 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Wed, 14 Jan 2026 10:04:38 +0100
Subject: [PATCH 07/46] Update: Update Script + Dependencies
---
package-lock.json | 1272 ++++++++++++++++++++-------------------------
package.json | 2 +-
2 files changed, 579 insertions(+), 695 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 963b2e4..e2c08aa 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -63,9 +63,9 @@
}
},
"node_modules/@electron/asar": {
- "version": "3.2.18",
- "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.18.tgz",
- "integrity": "sha512-2XyvMe3N3Nrs8cV39IKELRHTYUWFKrmqqSY1U+GMlc0jvqjIVnoxhNd2H4JolWQncbJi1DCvb5TNxZuI2fEjWg==",
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz",
+ "integrity": "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -169,88 +169,6 @@
"global-agent": "^3.0.0"
}
},
- "node_modules/@electron/node-gyp": {
- "version": "10.2.0-electron.1",
- "resolved": "git+ssh://git@github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2",
- "integrity": "sha512-4MSBTT8y07YUDqf69/vSh80Hh791epYqGtWHO3zSKhYFwQg+gx9wi1PqbqP6YqC4WMsNxZ5l9oDmnWdK5pfCKQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "env-paths": "^2.2.0",
- "exponential-backoff": "^3.1.1",
- "glob": "^8.1.0",
- "graceful-fs": "^4.2.6",
- "make-fetch-happen": "^10.2.1",
- "nopt": "^6.0.0",
- "proc-log": "^2.0.1",
- "semver": "^7.3.5",
- "tar": "^6.2.1",
- "which": "^2.0.2"
- },
- "bin": {
- "node-gyp": "bin/node-gyp.js"
- },
- "engines": {
- "node": ">=12.13.0"
- }
- },
- "node_modules/@electron/node-gyp/node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
- "node_modules/@electron/node-gyp/node_modules/glob": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
- "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^5.0.1",
- "once": "^1.3.0"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/@electron/node-gyp/node_modules/minimatch": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
- "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@electron/node-gyp/node_modules/semver": {
- "version": "7.7.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
- "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/@electron/notarize": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.5.0.tgz",
@@ -306,9 +224,9 @@
}
},
"node_modules/@electron/osx-sign": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.1.tgz",
- "integrity": "sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==",
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.3.tgz",
+ "integrity": "sha512-KZ8mhXvWv2rIEgMbWZ4y33bDHyUKMXnx4M0sTyPNK/vcB81ImdeY9Ggdqy0SWbMDgmbqyQ+phgejh6V3R2QuSg==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
@@ -379,21 +297,21 @@
}
},
"node_modules/@electron/rebuild": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.7.0.tgz",
- "integrity": "sha512-VW++CNSlZwMYP7MyXEbrKjpzEwhB5kDNbzGtiPEjwYysqyTCF+YbNJ210Dj3AjWsGSV4iEEwNkmJN9yGZmVvmw==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-4.0.1.tgz",
+ "integrity": "sha512-iMGXb6Ib7H/Q3v+BKZJoETgF9g6KMNZVbsO4b7Dmpgb5qTFqyFTzqW9F3TOSHdybv2vKYKzSS9OiZL+dcJb+1Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron/node-gyp": "git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2",
"@malept/cross-spawn-promise": "^2.0.0",
"chalk": "^4.0.0",
"debug": "^4.1.1",
"detect-libc": "^2.0.1",
- "fs-extra": "^10.0.0",
"got": "^11.7.0",
- "node-abi": "^3.45.0",
- "node-api-version": "^0.2.0",
+ "graceful-fs": "^4.2.11",
+ "node-abi": "^4.2.0",
+ "node-api-version": "^0.2.1",
+ "node-gyp": "^11.2.0",
"ora": "^5.1.0",
"read-binary-file-arch": "^1.0.6",
"semver": "^7.3.5",
@@ -404,35 +322,7 @@
"electron-rebuild": "lib/cli.js"
},
"engines": {
- "node": ">=12.13.0"
- }
- },
- "node_modules/@electron/rebuild/node_modules/fs-extra": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
- "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@electron/rebuild/node_modules/jsonfile": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
- "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
+ "node": ">=22.12.0"
}
},
"node_modules/@electron/rebuild/node_modules/semver": {
@@ -448,24 +338,14 @@
"node": ">=10"
}
},
- "node_modules/@electron/rebuild/node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
"node_modules/@electron/universal": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.1.tgz",
- "integrity": "sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.3.tgz",
+ "integrity": "sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron/asar": "^3.2.7",
+ "@electron/asar": "^3.3.1",
"@malept/cross-spawn-promise": "^2.0.0",
"debug": "^4.3.1",
"dir-compare": "^4.2.0",
@@ -607,13 +487,6 @@
"node": ">= 10.0.0"
}
},
- "node_modules/@gar/promisify": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
- "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@isaacs/balanced-match": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
@@ -740,6 +613,19 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
+ "node_modules/@isaacs/fs-minipass": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
+ "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^7.0.4"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
"node_modules/@malept/cross-spawn-promise": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz",
@@ -818,18 +704,41 @@
"node": ">= 10.0.0"
}
},
- "node_modules/@npmcli/fs": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz",
- "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==",
+ "node_modules/@npmcli/agent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-3.0.0.tgz",
+ "integrity": "sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "agent-base": "^7.1.0",
+ "http-proxy-agent": "^7.0.0",
+ "https-proxy-agent": "^7.0.1",
+ "lru-cache": "^10.0.1",
+ "socks-proxy-agent": "^8.0.3"
+ },
+ "engines": {
+ "node": "^18.17.0 || >=20.5.0"
+ }
+ },
+ "node_modules/@npmcli/agent/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@npmcli/fs": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz",
+ "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==",
"dev": true,
"license": "ISC",
"dependencies": {
- "@gar/promisify": "^1.1.3",
"semver": "^7.3.5"
},
"engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ "node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/@npmcli/fs/node_modules/semver": {
@@ -845,21 +754,6 @@
"node": ">=10"
}
},
- "node_modules/@npmcli/move-file": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz",
- "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==",
- "deprecated": "This functionality has been moved to @npmcli/fs",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "mkdirp": "^1.0.4",
- "rimraf": "^3.0.2"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@@ -907,16 +801,6 @@
"node": ">=10"
}
},
- "node_modules/@tootallnate/once": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
- "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 10"
- }
- },
"node_modules/@types/cacheable-request": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz",
@@ -975,9 +859,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "22.19.3",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.3.tgz",
- "integrity": "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==",
+ "version": "22.19.6",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.6.tgz",
+ "integrity": "sha512-qm+G8HuG6hOHQigsi7VGuLjUVu6TtBo/F05zvX04Mw2uCg9Dv0Qxy3Qw7j41SidlTcl5D/5yg0SEZqOB+EqZnQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1049,11 +933,14 @@
"license": "MIT"
},
"node_modules/abbrev": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
- "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz",
+ "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==",
"dev": true,
- "license": "ISC"
+ "license": "ISC",
+ "engines": {
+ "node": "^18.17.0 || >=20.5.0"
+ }
},
"node_modules/accepts": {
"version": "2.0.0",
@@ -1078,33 +965,6 @@
"node": ">= 14"
}
},
- "node_modules/agentkeepalive": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz",
- "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "humanize-ms": "^1.2.1"
- },
- "engines": {
- "node": ">= 8.0.0"
- }
- },
- "node_modules/aggregate-error": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
- "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "clean-stack": "^2.0.0",
- "indent-string": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -1165,52 +1025,53 @@
"license": "MIT"
},
"node_modules/app-builder-lib": {
- "version": "26.0.12",
- "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-26.0.12.tgz",
- "integrity": "sha512-+/CEPH1fVKf6HowBUs6LcAIoRcjeqgvAeoSE+cl7Y7LndyQ9ViGPYibNk7wmhMHzNgHIuIbw4nWADPO+4mjgWw==",
+ "version": "26.4.0",
+ "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-26.4.0.tgz",
+ "integrity": "sha512-Uas6hNe99KzP3xPWxh5LGlH8kWIVjZixzmMJHNB9+6hPyDpjc7NQMkVgi16rQDdpCFy22ZU5sp8ow7tvjeMgYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@develar/schema-utils": "~2.6.5",
- "@electron/asar": "3.2.18",
+ "@electron/asar": "3.4.1",
"@electron/fuses": "^1.8.0",
"@electron/notarize": "2.5.0",
- "@electron/osx-sign": "1.3.1",
- "@electron/rebuild": "3.7.0",
- "@electron/universal": "2.0.1",
+ "@electron/osx-sign": "1.3.3",
+ "@electron/rebuild": "4.0.1",
+ "@electron/universal": "2.0.3",
"@malept/flatpak-bundler": "^0.4.0",
"@types/fs-extra": "9.0.13",
"async-exit-hook": "^2.0.1",
- "builder-util": "26.0.11",
- "builder-util-runtime": "9.3.1",
+ "builder-util": "26.3.4",
+ "builder-util-runtime": "9.5.1",
"chromium-pickle-js": "^0.2.0",
- "config-file-ts": "0.2.8-rc1",
+ "ci-info": "4.3.1",
"debug": "^4.3.4",
"dotenv": "^16.4.5",
"dotenv-expand": "^11.0.6",
"ejs": "^3.1.8",
- "electron-publish": "26.0.11",
+ "electron-publish": "26.3.4",
"fs-extra": "^10.1.0",
"hosted-git-info": "^4.1.0",
- "is-ci": "^3.0.0",
"isbinaryfile": "^5.0.0",
+ "jiti": "^2.4.2",
"js-yaml": "^4.1.0",
"json5": "^2.2.3",
"lazy-val": "^1.0.5",
- "minimatch": "^10.0.0",
+ "minimatch": "^10.0.3",
"plist": "3.1.0",
"resedit": "^1.7.0",
- "semver": "^7.3.8",
+ "semver": "~7.7.3",
"tar": "^6.1.12",
"temp-file": "^3.4.0",
- "tiny-async-pool": "1.3.0"
+ "tiny-async-pool": "1.3.0",
+ "which": "^5.0.0"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
- "dmg-builder": "26.0.12",
- "electron-builder-squirrel-windows": "26.0.12"
+ "dmg-builder": "26.4.0",
+ "electron-builder-squirrel-windows": "26.4.0"
}
},
"node_modules/app-builder-lib/node_modules/fs-extra": {
@@ -1376,9 +1237,9 @@
}
},
"node_modules/body-parser": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz",
- "integrity": "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==",
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
+ "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==",
"license": "MIT",
"dependencies": {
"bytes": "^3.1.2",
@@ -1387,7 +1248,7 @@
"http-errors": "^2.0.0",
"iconv-lite": "^0.7.0",
"on-finished": "^2.4.1",
- "qs": "^6.14.0",
+ "qs": "^6.14.1",
"raw-body": "^3.0.1",
"type-is": "^2.0.1"
},
@@ -1400,9 +1261,9 @@
}
},
"node_modules/body-parser/node_modules/iconv-lite": {
- "version": "0.7.1",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz",
- "integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==",
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
+ "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
@@ -1478,23 +1339,22 @@
"license": "MIT"
},
"node_modules/builder-util": {
- "version": "26.0.11",
- "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-26.0.11.tgz",
- "integrity": "sha512-xNjXfsldUEe153h1DraD0XvDOpqGR0L5eKFkdReB7eFW5HqysDZFfly4rckda6y9dF39N3pkPlOblcfHKGw+uA==",
+ "version": "26.3.4",
+ "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-26.3.4.tgz",
+ "integrity": "sha512-aRn88mYMktHxzdqDMF6Ayj0rKoX+ZogJ75Ck7RrIqbY/ad0HBvnS2xA4uHfzrGr5D2aLL3vU6OBEH4p0KMV2XQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/debug": "^4.1.6",
"7zip-bin": "~5.2.0",
"app-builder-bin": "5.0.0-alpha.12",
- "builder-util-runtime": "9.3.1",
+ "builder-util-runtime": "9.5.1",
"chalk": "^4.1.2",
"cross-spawn": "^7.0.6",
"debug": "^4.3.4",
"fs-extra": "^10.1.0",
"http-proxy-agent": "^7.0.0",
"https-proxy-agent": "^7.0.0",
- "is-ci": "^3.0.0",
"js-yaml": "^4.1.0",
"sanitize-filename": "^1.6.3",
"source-map-support": "^0.5.19",
@@ -1504,9 +1364,9 @@
}
},
"node_modules/builder-util-runtime": {
- "version": "9.3.1",
- "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.3.1.tgz",
- "integrity": "sha512-2/egrNDDnRaxVwK3A+cJq6UOlqOdedGA7JPqCeJjN2Zjk1/QB/6QUi3b714ScIGS7HafFXTyzJEOr5b44I3kvQ==",
+ "version": "9.5.1",
+ "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.5.1.tgz",
+ "integrity": "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ==",
"license": "MIT",
"dependencies": {
"debug": "^4.3.4",
@@ -1564,33 +1424,27 @@
}
},
"node_modules/cacache": {
- "version": "16.1.3",
- "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz",
- "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==",
+ "version": "19.0.1",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz",
+ "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==",
"dev": true,
"license": "ISC",
"dependencies": {
- "@npmcli/fs": "^2.1.0",
- "@npmcli/move-file": "^2.0.0",
- "chownr": "^2.0.0",
- "fs-minipass": "^2.1.0",
- "glob": "^8.0.1",
- "infer-owner": "^1.0.4",
- "lru-cache": "^7.7.1",
- "minipass": "^3.1.6",
- "minipass-collect": "^1.0.2",
+ "@npmcli/fs": "^4.0.0",
+ "fs-minipass": "^3.0.0",
+ "glob": "^10.2.2",
+ "lru-cache": "^10.0.1",
+ "minipass": "^7.0.3",
+ "minipass-collect": "^2.0.1",
"minipass-flush": "^1.0.5",
"minipass-pipeline": "^1.2.4",
- "mkdirp": "^1.0.4",
- "p-map": "^4.0.0",
- "promise-inflight": "^1.0.1",
- "rimraf": "^3.0.2",
- "ssri": "^9.0.0",
- "tar": "^6.1.11",
- "unique-filename": "^2.0.0"
+ "p-map": "^7.0.2",
+ "ssri": "^12.0.0",
+ "tar": "^7.4.3",
+ "unique-filename": "^4.0.0"
},
"engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ "node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/cacache/node_modules/brace-expansion": {
@@ -1603,48 +1457,85 @@
"balanced-match": "^1.0.0"
}
},
+ "node_modules/cacache/node_modules/chownr": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
+ "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/cacache/node_modules/glob": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
- "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
"dev": true,
"license": "ISC",
"dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^5.0.1",
- "once": "^1.3.0"
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
},
- "engines": {
- "node": ">=12"
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/cacache/node_modules/lru-cache": {
- "version": "7.18.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
- "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
+ "license": "ISC"
},
"node_modules/cacache/node_modules/minimatch": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
- "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
- "node": ">=10"
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/cacache/node_modules/tar": {
+ "version": "7.5.2",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz",
+ "integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/fs-minipass": "^4.0.0",
+ "chownr": "^3.0.0",
+ "minipass": "^7.1.2",
+ "minizlib": "^3.1.0",
+ "yallist": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/cacache/node_modules/yallist": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
+ "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
}
},
"node_modules/cacheable-lookup": {
@@ -1739,9 +1630,9 @@
"license": "MIT"
},
"node_modules/ci-info": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
- "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz",
+ "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==",
"dev": true,
"funding": [
{
@@ -1754,16 +1645,6 @@
"node": ">=8"
}
},
- "node_modules/clean-stack": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
- "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/cli-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
@@ -1959,74 +1840,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/config-file-ts": {
- "version": "0.2.8-rc1",
- "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.8-rc1.tgz",
- "integrity": "sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "glob": "^10.3.12",
- "typescript": "^5.4.3"
- }
- },
- "node_modules/config-file-ts/node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
- "node_modules/config-file-ts/node_modules/glob": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
- "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "foreground-child": "^3.1.0",
- "jackspeak": "^3.1.2",
- "minimatch": "^9.0.4",
- "minipass": "^7.1.2",
- "package-json-from-dist": "^1.0.0",
- "path-scurry": "^1.11.1"
- },
- "bin": {
- "glob": "dist/esm/bin.mjs"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/config-file-ts/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/config-file-ts/node_modules/minipass": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
- "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
"node_modules/content-disposition": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
@@ -2110,6 +1923,29 @@
"node": ">= 8"
}
},
+ "node_modules/cross-spawn/node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/cross-spawn/node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
@@ -2292,15 +2128,14 @@
}
},
"node_modules/dmg-builder": {
- "version": "26.0.12",
- "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-26.0.12.tgz",
- "integrity": "sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==",
+ "version": "26.4.0",
+ "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-26.4.0.tgz",
+ "integrity": "sha512-ce4Ogns4VMeisIuCSK0C62umG0lFy012jd8LMZ6w/veHUeX4fqfDrGe+HTWALAEwK6JwKP+dhPvizhArSOsFbg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "app-builder-lib": "26.0.12",
- "builder-util": "26.0.11",
- "builder-util-runtime": "9.3.1",
+ "app-builder-lib": "26.4.0",
+ "builder-util": "26.3.4",
"fs-extra": "^10.1.0",
"iconv-lite": "^0.6.2",
"js-yaml": "^4.1.0"
@@ -2466,19 +2301,19 @@
}
},
"node_modules/electron-builder": {
- "version": "26.0.12",
- "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-26.0.12.tgz",
- "integrity": "sha512-cD1kz5g2sgPTMFHjLxfMjUK5JABq3//J4jPswi93tOPFz6btzXYtK5NrDt717NRbukCUDOrrvmYVOWERlqoiXA==",
+ "version": "26.4.0",
+ "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-26.4.0.tgz",
+ "integrity": "sha512-FCUqvdq2AULL+Db2SUGgjOYTbrgkPxZtCjqIZGnjH9p29pTWyesQqBIfvQBKa6ewqde87aWl49n/WyI/NyUBog==",
"dev": true,
"license": "MIT",
"dependencies": {
- "app-builder-lib": "26.0.12",
- "builder-util": "26.0.11",
- "builder-util-runtime": "9.3.1",
+ "app-builder-lib": "26.4.0",
+ "builder-util": "26.3.4",
+ "builder-util-runtime": "9.5.1",
"chalk": "^4.1.2",
- "dmg-builder": "26.0.12",
+ "ci-info": "^4.2.0",
+ "dmg-builder": "26.4.0",
"fs-extra": "^10.1.0",
- "is-ci": "^3.0.0",
"lazy-val": "^1.0.5",
"simple-update-notifier": "2.0.0",
"yargs": "^17.6.2"
@@ -2492,15 +2327,15 @@
}
},
"node_modules/electron-builder-squirrel-windows": {
- "version": "26.0.12",
- "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.0.12.tgz",
- "integrity": "sha512-kpwXM7c/ayRUbYVErQbsZ0nQZX4aLHQrPEG9C4h9vuJCXylwFH8a7Jgi2VpKIObzCXO7LKHiCw4KdioFLFOgqA==",
+ "version": "26.4.0",
+ "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.4.0.tgz",
+ "integrity": "sha512-7dvalY38xBzWNaoOJ4sqy2aGIEpl2S1gLPkkB0MHu1Hu5xKQ82il1mKSFlXs6fLpXUso/NmyjdHGlSHDRoG8/w==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
- "app-builder-lib": "26.0.12",
- "builder-util": "26.0.11",
+ "app-builder-lib": "26.4.0",
+ "builder-util": "26.3.4",
"electron-winstaller": "5.4.0"
}
},
@@ -2543,15 +2378,15 @@
}
},
"node_modules/electron-publish": {
- "version": "26.0.11",
- "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-26.0.11.tgz",
- "integrity": "sha512-a8QRH0rAPIWH9WyyS5LbNvW9Ark6qe63/LqDB7vu2JXYpi0Gma5Q60Dh4tmTqhOBQt0xsrzD8qE7C+D7j+B24A==",
+ "version": "26.3.4",
+ "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-26.3.4.tgz",
+ "integrity": "sha512-5/ouDPb73SkKuay2EXisPG60LTFTMNHWo2WLrK5GDphnWK9UC+yzYrzVeydj078Yk4WUXi0+TaaZsNd6Zt5k/A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/fs-extra": "^9.0.11",
- "builder-util": "26.0.11",
- "builder-util-runtime": "9.3.1",
+ "builder-util": "26.3.4",
+ "builder-util-runtime": "9.5.1",
"chalk": "^4.1.2",
"form-data": "^4.0.0",
"fs-extra": "^10.1.0",
@@ -2622,18 +2457,18 @@
"license": "MIT"
},
"node_modules/electron-updater": {
- "version": "6.6.2",
- "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.6.2.tgz",
- "integrity": "sha512-Cr4GDOkbAUqRHP5/oeOmH/L2Bn6+FQPxVLZtPbcmKZC63a1F3uu5EefYOssgZXG3u/zBlubbJ5PJdITdMVggbw==",
+ "version": "6.7.3",
+ "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.7.3.tgz",
+ "integrity": "sha512-EgkT8Z9noqXKbwc3u5FkJA+r48jwZ5DTUiOkJMOTEEH//n5Am6wfQGz7nvSFEA2oIAMv9jRzn5JKTyWeSKOPgg==",
"license": "MIT",
"dependencies": {
- "builder-util-runtime": "9.3.1",
+ "builder-util-runtime": "9.5.1",
"fs-extra": "^10.1.0",
"js-yaml": "^4.1.0",
"lazy-val": "^1.0.5",
"lodash.escaperegexp": "^4.1.2",
"lodash.isequal": "^4.5.0",
- "semver": "^7.6.3",
+ "semver": "~7.7.3",
"tiny-typed-emitter": "^2.1.0"
}
},
@@ -2744,6 +2579,16 @@
"node": ">= 0.8"
}
},
+ "node_modules/encoding": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
+ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "iconv-lite": "^0.6.2"
+ }
+ },
"node_modules/end-of-stream": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
@@ -2932,15 +2777,6 @@
"express": ">= 4.11"
}
},
- "node_modules/express-rate-limit/node_modules/ip-address": {
- "version": "10.0.1",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz",
- "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==",
- "license": "MIT",
- "engines": {
- "node": ">= 12"
- }
- },
"node_modules/extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
@@ -2997,6 +2833,24 @@
"pend": "~1.2.0"
}
},
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
"node_modules/fecha": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
@@ -3183,16 +3037,16 @@
}
},
"node_modules/fs-minipass": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
- "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz",
+ "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==",
"dev": true,
"license": "ISC",
"dependencies": {
- "minipass": "^3.0.0"
+ "minipass": "^7.0.3"
},
"engines": {
- "node": ">= 8"
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/fs.realpath": {
@@ -3549,16 +3403,6 @@
"node": ">= 14"
}
},
- "node_modules/humanize-ms": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
- "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.0.0"
- }
- },
"node_modules/iconv-corefoundation": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz",
@@ -3581,7 +3425,7 @@
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
@@ -3621,23 +3465,6 @@
"node": ">=0.8.19"
}
},
- "node_modules/indent-string": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
- "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/infer-owner": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
- "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -3657,10 +3484,9 @@
"license": "ISC"
},
"node_modules/ip-address": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
- "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
- "dev": true,
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz",
+ "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==",
"license": "MIT",
"engines": {
"node": ">= 12"
@@ -3675,19 +3501,6 @@
"node": ">= 0.10"
}
},
- "node_modules/is-ci": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz",
- "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ci-info": "^3.2.0"
- },
- "bin": {
- "is-ci": "bin.js"
- }
- },
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
@@ -3708,13 +3521,6 @@
"node": ">=8"
}
},
- "node_modules/is-lambda": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
- "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/is-promise": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
@@ -3760,11 +3566,14 @@
}
},
"node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
+ "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
"dev": true,
- "license": "ISC"
+ "license": "ISC",
+ "engines": {
+ "node": ">=16"
+ }
},
"node_modules/jackspeak": {
"version": "3.4.3",
@@ -3800,6 +3609,16 @@
"node": ">=10"
}
},
+ "node_modules/jiti": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
+ "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jiti": "lib/jiti-cli.mjs"
+ }
+ },
"node_modules/js-yaml": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
@@ -3957,93 +3776,26 @@
}
},
"node_modules/make-fetch-happen": {
- "version": "10.2.1",
- "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz",
- "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==",
+ "version": "14.0.3",
+ "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz",
+ "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==",
"dev": true,
"license": "ISC",
"dependencies": {
- "agentkeepalive": "^4.2.1",
- "cacache": "^16.1.0",
- "http-cache-semantics": "^4.1.0",
- "http-proxy-agent": "^5.0.0",
- "https-proxy-agent": "^5.0.0",
- "is-lambda": "^1.0.1",
- "lru-cache": "^7.7.1",
- "minipass": "^3.1.6",
- "minipass-collect": "^1.0.2",
- "minipass-fetch": "^2.0.3",
+ "@npmcli/agent": "^3.0.0",
+ "cacache": "^19.0.1",
+ "http-cache-semantics": "^4.1.1",
+ "minipass": "^7.0.2",
+ "minipass-fetch": "^4.0.0",
"minipass-flush": "^1.0.5",
"minipass-pipeline": "^1.2.4",
- "negotiator": "^0.6.3",
+ "negotiator": "^1.0.0",
+ "proc-log": "^5.0.0",
"promise-retry": "^2.0.1",
- "socks-proxy-agent": "^7.0.0",
- "ssri": "^9.0.0"
+ "ssri": "^12.0.0"
},
"engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/make-fetch-happen/node_modules/agent-base": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
- "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "debug": "4"
- },
- "engines": {
- "node": ">= 6.0.0"
- }
- },
- "node_modules/make-fetch-happen/node_modules/http-proxy-agent": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
- "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@tootallnate/once": "2",
- "agent-base": "6",
- "debug": "4"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/make-fetch-happen/node_modules/https-proxy-agent": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
- "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "agent-base": "6",
- "debug": "4"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/make-fetch-happen/node_modules/lru-cache": {
- "version": "7.18.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
- "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/make-fetch-happen/node_modules/negotiator": {
- "version": "0.6.4",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
- "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
+ "node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/matcher": {
@@ -4175,44 +3927,41 @@
}
},
"node_modules/minipass": {
- "version": "3.3.6",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
- "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"dev": true,
"license": "ISC",
- "dependencies": {
- "yallist": "^4.0.0"
- },
"engines": {
- "node": ">=8"
+ "node": ">=16 || 14 >=14.17"
}
},
"node_modules/minipass-collect": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
- "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz",
+ "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==",
"dev": true,
"license": "ISC",
"dependencies": {
- "minipass": "^3.0.0"
+ "minipass": "^7.0.3"
},
"engines": {
- "node": ">= 8"
+ "node": ">=16 || 14 >=14.17"
}
},
"node_modules/minipass-fetch": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz",
- "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.1.tgz",
+ "integrity": "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "minipass": "^3.1.6",
+ "minipass": "^7.0.3",
"minipass-sized": "^1.0.3",
- "minizlib": "^2.1.2"
+ "minizlib": "^3.0.1"
},
"engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ "node": "^18.17.0 || >=20.5.0"
},
"optionalDependencies": {
"encoding": "^0.1.13"
@@ -4231,6 +3980,19 @@
"node": ">= 8"
}
},
+ "node_modules/minipass-flush/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/minipass-pipeline": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
@@ -4244,6 +4006,19 @@
"node": ">=8"
}
},
+ "node_modules/minipass-pipeline/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/minipass-sized": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
@@ -4257,18 +4032,30 @@
"node": ">=8"
}
},
- "node_modules/minizlib": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
- "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "node_modules/minipass-sized/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"dev": true,
- "license": "MIT",
+ "license": "ISC",
"dependencies": {
- "minipass": "^3.0.0",
"yallist": "^4.0.0"
},
"engines": {
- "node": ">= 8"
+ "node": ">=8"
+ }
+ },
+ "node_modules/minizlib": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
+ "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minipass": "^7.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
}
},
"node_modules/mkdirp": {
@@ -4309,16 +4096,16 @@
}
},
"node_modules/node-abi": {
- "version": "3.85.0",
- "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz",
- "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==",
+ "version": "4.24.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-4.24.0.tgz",
+ "integrity": "sha512-u2EC1CeNe25uVtX3EZbdQ275c74zdZmmpzrHEQh2aIYqoVjlglfUpOX9YY85x1nlBydEKDVaSmMNhR7N82Qj8A==",
"dev": true,
"license": "MIT",
"dependencies": {
- "semver": "^7.3.5"
+ "semver": "^7.6.3"
},
"engines": {
- "node": ">=10"
+ "node": ">=22.12.0"
}
},
"node_modules/node-abi/node_modules/semver": {
@@ -4384,20 +4171,95 @@
}
}
},
+ "node_modules/node-gyp": {
+ "version": "11.5.0",
+ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.5.0.tgz",
+ "integrity": "sha512-ra7Kvlhxn5V9Slyus0ygMa2h+UqExPqUIkfk7Pc8QTLT956JLSy51uWFwHtIYy0vI8cB4BDhc/S03+880My/LQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "env-paths": "^2.2.0",
+ "exponential-backoff": "^3.1.1",
+ "graceful-fs": "^4.2.6",
+ "make-fetch-happen": "^14.0.3",
+ "nopt": "^8.0.0",
+ "proc-log": "^5.0.0",
+ "semver": "^7.3.5",
+ "tar": "^7.4.3",
+ "tinyglobby": "^0.2.12",
+ "which": "^5.0.0"
+ },
+ "bin": {
+ "node-gyp": "bin/node-gyp.js"
+ },
+ "engines": {
+ "node": "^18.17.0 || >=20.5.0"
+ }
+ },
+ "node_modules/node-gyp/node_modules/chownr": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
+ "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/node-gyp/node_modules/semver": {
+ "version": "7.7.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
+ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/node-gyp/node_modules/tar": {
+ "version": "7.5.2",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz",
+ "integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/fs-minipass": "^4.0.0",
+ "chownr": "^3.0.0",
+ "minipass": "^7.1.2",
+ "minizlib": "^3.1.0",
+ "yallist": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/node-gyp/node_modules/yallist": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
+ "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/nopt": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz",
- "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz",
+ "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==",
"dev": true,
"license": "ISC",
"dependencies": {
- "abbrev": "^1.0.0"
+ "abbrev": "^3.0.0"
},
"bin": {
"nopt": "bin/nopt.js"
},
"engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ "node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/normalize-url": {
@@ -4542,16 +4404,13 @@
}
},
"node_modules/p-map": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
- "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz",
+ "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "aggregate-error": "^3.0.0"
- },
"engines": {
- "node": ">=10"
+ "node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -4617,16 +4476,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/path-scurry/node_modules/minipass": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
- "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
"node_modules/path-to-regexp": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
@@ -4666,6 +4515,19 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/plist": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz",
@@ -4712,13 +4574,13 @@
}
},
"node_modules/proc-log": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz",
- "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz",
+ "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==",
"dev": true,
"license": "ISC",
"engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ "node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/progress": {
@@ -4731,13 +4593,6 @@
"node": ">=0.4.0"
}
},
- "node_modules/promise-inflight": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
- "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/promise-retry": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
@@ -4787,9 +4642,9 @@
}
},
"node_modules/qs": {
- "version": "6.14.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
- "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
+ "version": "6.14.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
+ "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.1.0"
@@ -4839,9 +4694,9 @@
}
},
"node_modules/raw-body/node_modules/iconv-lite": {
- "version": "0.7.1",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz",
- "integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==",
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
+ "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
@@ -4965,20 +4820,18 @@
}
},
"node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
"deprecated": "Rimraf versions prior to v4 are no longer supported",
"dev": true,
"license": "ISC",
+ "peer": true,
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/roarr": {
@@ -5062,10 +4915,13 @@
}
},
"node_modules/sax": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz",
- "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==",
- "license": "BlueOak-1.0.0"
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz",
+ "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=11.0.0"
+ }
},
"node_modules/semver": {
"version": "6.3.1",
@@ -5324,31 +5180,18 @@
}
},
"node_modules/socks-proxy-agent": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz",
- "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==",
+ "version": "8.0.5",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz",
+ "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "agent-base": "^6.0.2",
- "debug": "^4.3.3",
- "socks": "^2.6.2"
+ "agent-base": "^7.1.2",
+ "debug": "^4.3.4",
+ "socks": "^2.8.3"
},
"engines": {
- "node": ">= 10"
- }
- },
- "node_modules/socks-proxy-agent/node_modules/agent-base": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
- "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "debug": "4"
- },
- "engines": {
- "node": ">= 6.0.0"
+ "node": ">= 14"
}
},
"node_modules/source-map": {
@@ -5381,16 +5224,16 @@
"optional": true
},
"node_modules/ssri": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz",
- "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==",
+ "version": "12.0.0",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz",
+ "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==",
"dev": true,
"license": "ISC",
"dependencies": {
- "minipass": "^3.1.1"
+ "minipass": "^7.0.3"
},
"engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ "node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/stack-trace": {
@@ -5531,6 +5374,32 @@
"node": ">=10"
}
},
+ "node_modules/tar/node_modules/fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/tar/node_modules/minipass": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
@@ -5541,6 +5410,33 @@
"node": ">=8"
}
},
+ "node_modules/tar/node_modules/minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/tar/node_modules/minizlib/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/temp": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz",
@@ -5619,21 +5515,6 @@
"mkdirp": "bin/cmd.js"
}
},
- "node_modules/temp/node_modules/rimraf": {
- "version": "2.6.3",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
- "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
- "deprecated": "Rimraf versions prior to v4 are no longer supported",
- "dev": true,
- "license": "ISC",
- "peer": true,
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- }
- },
"node_modules/text-hex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
@@ -5666,6 +5547,23 @@
"integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==",
"license": "MIT"
},
+ "node_modules/tinyglobby": {
+ "version": "0.2.15",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
+ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
"node_modules/tmp": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz",
@@ -5748,20 +5646,6 @@
"node": ">= 0.6"
}
},
- "node_modules/typescript": {
- "version": "5.9.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
- "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
- "dev": true,
- "license": "Apache-2.0",
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
@@ -5770,29 +5654,29 @@
"license": "MIT"
},
"node_modules/unique-filename": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz",
- "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz",
+ "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==",
"dev": true,
"license": "ISC",
"dependencies": {
- "unique-slug": "^3.0.0"
+ "unique-slug": "^5.0.0"
},
"engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ "node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/unique-slug": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz",
- "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz",
+ "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==",
"dev": true,
"license": "ISC",
"dependencies": {
"imurmurhash": "^0.1.4"
},
"engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ "node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/universalify": {
@@ -5873,9 +5757,9 @@
}
},
"node_modules/webidl-conversions": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.0.tgz",
- "integrity": "sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==",
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz",
+ "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=20"
@@ -5898,19 +5782,19 @@
"license": "BSD-2-Clause"
},
"node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz",
+ "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==",
"dev": true,
"license": "ISC",
"dependencies": {
- "isexe": "^2.0.0"
+ "isexe": "^3.1.1"
},
"bin": {
- "node-which": "bin/node-which"
+ "node-which": "bin/which.js"
},
"engines": {
- "node": ">= 8"
+ "node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/winston": {
diff --git a/package.json b/package.json
index da90d5f..4bcfd13 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,7 @@
"main": "main.js",
"scripts": {
"start": "electron --trace-warnings .",
- "dist": "electron-builder",
+ "build": "electron-builder",
"update": "npm update"
},
"dependencies": {
From 42ae0e7204bc33343bc4034a276886541dea77e2 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Wed, 14 Jan 2026 10:06:17 +0100
Subject: [PATCH 08/46] =?UTF-8?q?Feat:=20Add=20Codec=20H264=20to=20vid?=
=?UTF-8?q?=C3=A9o=20output?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
server/helpers/buildArgs.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/server/helpers/buildArgs.js b/server/helpers/buildArgs.js
index 6d16353..eb48215 100644
--- a/server/helpers/buildArgs.js
+++ b/server/helpers/buildArgs.js
@@ -17,7 +17,8 @@ function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) {
"--fragment-retries", "10",
"--ffmpeg-location", ffmpegPath,
"--extractor-args","youtube:player_client=default",
- "--js-runtimes", `deno:${denoPath}`
+ "--js-runtimes", `deno:${denoPath}`,
+ "-S", "vcodec:h264" // Will be replaced with a variables when i will add the settings panel (Next Update ?)
];
if (audioOnly) args.push("-f", "bestaudio", "--extract-audio", "--audio-format", "mp3");
From 31d8b20a761c4ed693ac5bc4edc96afa70ee195b Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Wed, 14 Jan 2026 14:03:32 +0100
Subject: [PATCH 09/46] Feat: Implement Config File. Read by Front and Back. It
aims to give possibility to disable some features quickly. Currenty:
DiscordRPC, AutoCheckInfo, AutoUpdate, Custom TopBar, AddMetadata, Add
Thumbail were put and implement. Other need to be implement. That's the begin
of Settings Panel
---
config.js | 29 ++--
config/config.json | 13 ++
main.js | 15 ++-
preload.js | 3 +-
public/index.html | 6 +-
public/script/fetchinfo.js | 262 +++++++++++++++++++-----------------
public/script/topbar.js | 10 +-
server/helpers/buildArgs.js | 7 +-
8 files changed, 193 insertions(+), 152 deletions(-)
create mode 100644 config/config.json
diff --git a/config.js b/config.js
index a8362a8..0df8abb 100644
--- a/config.js
+++ b/config.js
@@ -1,5 +1,20 @@
const packageJson = require("./package.json");
const { app } = require("electron");
+const fs = require("fs");
+const path = require("path");
+
+const featuresPath = path.join(__dirname, "./config/config.json");
+
+let features = {};
+
+function loadFeatures() {
+ const raw = fs.readFileSync(featuresPath, "utf-8");
+ features = JSON.parse(raw);
+ console.log(features)
+ return features;
+}
+
+const configFeatures = loadFeatures();
module.exports = {
version: packageJson.version,
@@ -7,17 +22,5 @@ module.exports = {
debugMode: true,
localMode: !app.isPackaged,
DiscordRPCID: "1410934537051181146",
-
- // Variables Used to toggle main features
- autoUpdate: true,
- discordRPC: true,
- customTopBar: true, // (Will be active on next launch)
- autoDownloadPlaylist: true,
- logSystem: true, // Disable = Dangerous
- autoCheckInfo: true, // To Improve speed ? (NO)
- outputTitleCheck: true, // For Non latin characters (Russian)
- addThumbail: true, // The Pictures in the files (audio files)
- addMetadata: true, // Looks Explicit
- downloadSystem: true, // Why would you disable this ? I don't know but why not
- notifySystem: true // Notification when download
+ configFeatures
}
\ No newline at end of file
diff --git a/config/config.json b/config/config.json
new file mode 100644
index 0000000..f969fb6
--- /dev/null
+++ b/config/config.json
@@ -0,0 +1,13 @@
+{
+ "autoUpdate": true,
+ "discordRPC": true,
+ "customTopBar": true,
+ "autoDownloadPlaylist": true,
+ "logSystem": true,
+ "autoCheckInfo": true,
+ "outputTitleCheck": true,
+ "addThumbnail": true,
+ "addMetadata": true,
+ "downloadSystem": true,
+ "notifySystem": true
+}
\ No newline at end of file
diff --git a/main.js b/main.js
index aa43415..b8680de 100644
--- a/main.js
+++ b/main.js
@@ -3,8 +3,11 @@ const { app, BrowserWindow, ipcMain, dialog, Menu, shell } = require("electron")
const path = require("path");
const os = require("os");
const fs = require("fs");
+
const { logger, logSessionStart, logSessionEnd, logDir } = require("./server/logger");
const { AutoUpdater } = require("./server/update.js");
+const { configFeatures } = require("./config.js");
+const { startRPC } = require("./server/discordRPC");
let mainWindow;
const logsFolderPath = logDir;
@@ -77,7 +80,7 @@ async function createMainWindow() {
height: 800,
minWidth: 750,
minHeight: 800,
- frame:false,
+ frame: !configFeatures.customTopBar,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
@@ -163,11 +166,15 @@ app.whenReady().then(async () => {
await expressServer.startServer();
logger.info("Express Server Started");
- const { startRPC } = require("./server/discordRPC");
- startRPC();
+ ipcMain.handle("features", () => {
+ return configFeatures;
+ });
+
+ configFeatures.discordRPC ? startRPC() : "";
await createMainWindow();
- AutoUpdater(mainWindow);
+ configFeatures.AutoUpdater ? AutoUpdater(mainWindow) : ""; // Auto Update
+
} catch (err) {
logger.error("Window or Server error :", err);
app.quit();
diff --git a/preload.js b/preload.js
index 2f0e8e8..5da0c1c 100644
--- a/preload.js
+++ b/preload.js
@@ -3,7 +3,8 @@ const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("electronAPI", {
getDefaultDownloadPath: () => ipcRenderer.invoke("get-default-download-path"),
selectDownloadFolder: () => ipcRenderer.invoke("select-download-folder"),
- setProgress: (percent) => ipcRenderer.send("set-progress", percent)
+ setProgress: (percent) => ipcRenderer.send("set-progress", percent),
+ getFeatures: () => ipcRenderer.invoke("features")
});
// Contrôles de fenêtre et outils custom pour la topbar
diff --git a/public/index.html b/public/index.html
index 76d9296..3f8e077 100644
--- a/public/index.html
+++ b/public/index.html
@@ -17,7 +17,7 @@
-
+
@@ -31,12 +31,12 @@
-
+
-
+
Freedom Loader
diff --git a/public/script/fetchinfo.js b/public/script/fetchinfo.js
index bffb928..9db3040 100644
--- a/public/script/fetchinfo.js
+++ b/public/script/fetchinfo.js
@@ -25,156 +25,164 @@ async function fetchVideoInfo(url) {
return { error: "Network or JSON Issue" };
}
}
+async function init() {
+ const configFeatures = await window.electronAPI.getFeatures();
-document.addEventListener("DOMContentLoaded", () => {
- const urlInput = document.getElementById("UrlInput");
- const infoDiv = document.getElementById("videoInfo");
- const loaderBox = document.getElementById("loaderBox");
+ if (!configFeatures.autoCheckInfo) return;
- let lastFetchedUrl = "";
+ document.addEventListener("DOMContentLoaded", () => {
+ const urlInput = document.getElementById("UrlInput");
+ const infoDiv = document.getElementById("videoInfo");
+ const loaderBox = document.getElementById("loaderBox");
- urlInput.addEventListener("input", async () => {
- const url = urlInput.value.trim();
+ let lastFetchedUrl = "";
- // Si champ vide -> reset total
- if (!url || url.length < 2) {
- infoDiv.innerHTML = "";
- infoDiv.classList.remove("visible", "playlist-mode");
- lastFetchedUrl = "";
- return;
- }
+ urlInput.addEventListener("input", async () => {
+ const url = urlInput.value.trim();
- if (url === lastFetchedUrl) return;
- lastFetchedUrl = url;
+ // Si champ vide -> reset total
+ if (!url || url.length < 2) {
+ infoDiv.innerHTML = "";
+ infoDiv.classList.remove("visible", "playlist-mode");
+ lastFetchedUrl = "";
+ return;
+ }
- loaderBox.style.display = "flex";
- const data = await fetchVideoInfo(url);
- loaderBox.style.display = "none";
+ if (url === lastFetchedUrl) return;
+ lastFetchedUrl = url;
- // Gestion des erreurs
- if (data.error) {
- infoDiv.innerHTML = `
-
- ${data.error}
-
- `;
- infoDiv.classList.add("visible");
- infoDiv.classList.remove("playlist-mode");
+ loaderBox.style.display = "flex";
+ const data = await fetchVideoInfo(url);
loaderBox.style.display = "none";
- return;
- }
- // ---------- PLAYLIST ----------
- if (data.type === "playlist") {
- infoDiv.classList.add("playlist-mode");
- infoDiv.innerHTML = `
- Playlist Detected: ${data.title}
- Video Count: ${data.count}
- Channel : ${data.channel || "Unknown"}
-
- `;
-
- const listDiv = document.getElementById("playlistVideos");
-
- data.videos.forEach(v => {
- const durationStr = v.duration
- ? `${Math.floor(v.duration / 60)}m ${(v.duration % 60).toString().padStart(2,"0")}s` : "Inconnue";
-
- const videoUrl = v.id ? `https://www.youtube.com/watch?v=${v.id}` : v.url;
-
- listDiv.innerHTML += `
-
-

-
${v.title}
-
Duration : ${durationStr}
-
URL
-
-
+ // Gestion des erreurs
+ if (data.error) {
+ infoDiv.innerHTML = `
+
+ ${data.error}
`;
- });
+ infoDiv.classList.add("visible");
+ infoDiv.classList.remove("playlist-mode");
+ loaderBox.style.display = "none";
+ return;
+ }
- // Gestion du bouton copier
- listDiv.addEventListener("click", (event) => {
- if (event.target.classList.contains("copy-btn")) {
- const btn = event.target;
- if (btn.disabled) return;
+ // ---------- PLAYLIST ----------
+ if (data.type === "playlist") {
+ infoDiv.classList.add("playlist-mode");
+ infoDiv.innerHTML = `
+
Playlist Detected: ${data.title}
+
Video Count: ${data.count}
+
Channel : ${data.channel || "Unknown"}
+
+ `;
- btn.disabled = true;
- const url = btn.dataset.url;
- navigator.clipboard.writeText(url)
- .then(() => {
- const original = btn.textContent;
+ const listDiv = document.getElementById("playlistVideos");
- btn.style.opacity = 0;
- btn.style.transform = "scale(0.7)";
+ data.videos.forEach(v => {
+ const durationStr = v.duration
+ ? `${Math.floor(v.duration / 60)}m ${(v.duration % 60).toString().padStart(2,"0")}s` : "Inconnue";
- setTimeout(() => {
- btn.textContent = "✅";
- btn.style.opacity = 1;
- btn.style.transform = "scale(1)";
+ const videoUrl = v.id ? `https://www.youtube.com/watch?v=${v.id}` : v.url;
+
+ listDiv.innerHTML += `
+
+

+
${v.title}
+
Duration : ${durationStr}
+
URL
+
+
+
+ `;
+ });
+
+ // Gestion du bouton copier
+ listDiv.addEventListener("click", (event) => {
+ if (event.target.classList.contains("copy-btn")) {
+ const btn = event.target;
+ if (btn.disabled) return;
+
+ btn.disabled = true;
+ const url = btn.dataset.url;
+ navigator.clipboard.writeText(url)
+ .then(() => {
+ const original = btn.textContent;
+
+ btn.style.opacity = 0;
+ btn.style.transform = "scale(0.7)";
setTimeout(() => {
- btn.style.opacity = 0;
- btn.style.transform = "scale(0.7)";
+ btn.textContent = "✅";
+ btn.style.opacity = 1;
+ btn.style.transform = "scale(1)";
setTimeout(() => {
- btn.textContent = original;
- btn.style.opacity = 1;
- btn.style.transform = "scale(1)";
- btn.disabled = false;
- }, 300);
+ btn.style.opacity = 0;
+ btn.style.transform = "scale(0.7)";
- }, 1000);
+ setTimeout(() => {
+ btn.textContent = original;
+ btn.style.opacity = 1;
+ btn.style.transform = "scale(1)";
+ btn.disabled = false;
+ }, 300);
- }, 300);
- })
- .catch(() => {
- const original = btn.textContent;
- btn.textContent = "❌";
- setTimeout(() => {
- btn.textContent = original;
- btn.disabled = false;
- }, 1500);
- });
- }
- });
+ }, 1000);
+
+ }, 300);
+ })
+ .catch(() => {
+ const original = btn.textContent;
+ btn.textContent = "❌";
+ setTimeout(() => {
+ btn.textContent = original;
+ btn.disabled = false;
+ }, 1500);
+ });
+ }
+ });
+
+ infoDiv.classList.add("visible");
+ return;
+ }
+
+ infoDiv.classList.remove("playlist-mode");
+
+ // ---------- VIDEO NORMALE ----------
+ const durationStr = data.duration
+ ? `${Math.floor(data.duration/60)}m ${(data.duration%60).toString().padStart(2,"0")}s`
+ : "Unknown";
+
+ const sizeStr = formatSize(data.filesize_approx);
+ const readableDate = formatDate(data.upload_date);
+ const categories = data.categories?.join(", ") || "Non spécifiées";
+
+ infoDiv.innerHTML = `
+
${data.title}
+

+
+ - Duration : ${durationStr}
+ - Uploader : ${data.uploader || "Inconnu"}
+ - Upload Date : ${readableDate}
+ - Views : ${data.view_count?.toLocaleString() || "?"}
+ - Likes : ${data.like_count?.toLocaleString() || "?"}
+ - URL : ${data.webpage_url}
+ - Channel : ${data.channel_url}
+ - Estimed Size : ${sizeStr}
+ - Category : ${categories}
+
+ `;
infoDiv.classList.add("visible");
- return;
- }
+ });
- infoDiv.classList.remove("playlist-mode");
+ })
- // ---------- VIDEO NORMALE ----------
- const durationStr = data.duration
- ? `${Math.floor(data.duration/60)}m ${(data.duration%60).toString().padStart(2,"0")}s`
- : "Unknown";
+};
- const sizeStr = formatSize(data.filesize_approx);
- const readableDate = formatDate(data.upload_date);
- const categories = data.categories?.join(", ") || "Non spécifiées";
-
- infoDiv.innerHTML = `
-
${data.title}
-

-
- - Duration : ${durationStr}
- - Uploader : ${data.uploader || "Inconnu"}
- - Upload Date : ${readableDate}
- - Views : ${data.view_count?.toLocaleString() || "?"}
- - Likes : ${data.like_count?.toLocaleString() || "?"}
- - URL : ${data.webpage_url}
- - Channel : ${data.channel_url}
- - Estimed Size : ${sizeStr}
- - Category : ${categories}
-
- `;
-
- infoDiv.classList.add("visible");
- });
-
-})
\ No newline at end of file
+init();
\ No newline at end of file
diff --git a/public/script/topbar.js b/public/script/topbar.js
index 0225ea8..2221667 100644
--- a/public/script/topbar.js
+++ b/public/script/topbar.js
@@ -21,4 +21,12 @@ function setupTopbarListeners() {
});
}
-setupTopbarListeners();
+setupTopbarListeners(); // IF it put it the if check. It don't work. Why ?
+
+const features = await window.electronAPI.getFeatures();
+
+if(!features.customTopBar){
+ document.getElementById("topbar").style.display = "none";
+ document.getElementById("container").style.marginTop = "0";
+ document.getElementById("theme-switcher").style.top = "30px";
+}
\ No newline at end of file
diff --git a/server/helpers/buildArgs.js b/server/helpers/buildArgs.js
index eb48215..16586f3 100644
--- a/server/helpers/buildArgs.js
+++ b/server/helpers/buildArgs.js
@@ -2,6 +2,7 @@ const path = require("path");
const getUserBrowser = require("./getBrowser");
const { ffmpegPath, denoPath} = require("./path");
+const { configFeatures } = require("../../config.js");
function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) {
@@ -10,8 +11,8 @@ function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) {
"--cookies-from-browser", `${getUserBrowser()}`,
"--no-continue",
"--no-overwrites",
- "--embed-thumbnail",
- "--add-metadata",
+ configFeatures.addThumbail ? "--embed-thumbnail" : null,
+ configFeatures.addMetadata ? "--add-metadata" : null,
"--concurrent-fragments", "8",
"--retries", "10",
"--fragment-retries", "10",
@@ -37,7 +38,7 @@ function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) {
args.push("-o", path.join(outputFolder, "%(title)s.%(ext)s"));
args.push(url);
- return args;
+ return args.filter(Boolean);
}
module.exports = { buildYtDlpArgs };
From b867d819b74698b3b41fcae49040268971a598f4 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Wed, 14 Jan 2026 14:04:06 +0100
Subject: [PATCH 10/46] Fix: Increment App Version for 1.3.2
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 4bcfd13..9d34697 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "freedom-loader",
"productName": "Freedom Loader",
- "version": "1.3.1",
+ "version": "1.3.2",
"author": "MasterAcnolo",
"description": "Freedom Loader",
"main": "main.js",
From adcee623868e15f95e0be02d4301a0c3a5c44be5 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Wed, 14 Jan 2026 20:41:55 +0100
Subject: [PATCH 11/46] Fix: ReadME Badge Version
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 0476cc4..29fc38d 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
From 489a4766fab0f775a23501bf18b93d53fda2f6b2 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Wed, 14 Jan 2026 21:47:38 +0100
Subject: [PATCH 12/46] Feat: Path Verification (Security #4)
---
main.js | 29 ++++++++++++--
preload.js | 3 +-
public/script/custompath.js | 75 ++++++++++++++++++++++++-------------
3 files changed, 76 insertions(+), 31 deletions(-)
diff --git a/main.js b/main.js
index b8680de..afe90f4 100644
--- a/main.js
+++ b/main.js
@@ -101,21 +101,44 @@ async function createMainWindow() {
});
}
+function validateDownloadPath(userPath) {
+ const userHome = os.homedir(); // C:\Users\
+
+ if (!userPath) return path.join(userHome, "Downloads", "Freedom Loader");
+
+ // Résolution canonique et suivi des symlinks
+ const resolved = fs.realpathSync(path.resolve(userPath));
+ const normalizedHome = path.resolve(userHome) + path.sep;
+
+ if (!resolved.startsWith(normalizedHome)) {
+ throw new Error("Chemin non autorisé : uniquement les sous-dossiers du dossier utilisateur sont permis !");
+ }
+
+ return resolved;
+}
+
+
// IPC
ipcMain.handle("select-download-folder", async () => {
try {
const result = await dialog.showOpenDialog({ properties: ["openDirectory"] });
if (!result.canceled && result.filePaths.length > 0) {
- logger.info(`Dossier sélectionné : ${result.filePaths[0]}`);
- return result.filePaths[0];
+ const validatedPath = validateDownloadPath(result.filePaths[0]);
+ logger.info(`Folder Checked and Valid : ${validatedPath}`);
+ return validatedPath;
}
return null;
} catch (err) {
- logger.error(`Error when creating Output Folder : ${err.message}`);
+ logger.error(`An Error Occured when validating folder : ${err.message}`);
return null;
}
});
+ipcMain.handle("validate-download-path", (event, userPath) => {
+ return validateDownloadPath(userPath);
+});
+
+
ipcMain.handle("get-default-download-path", () => defaultDownloadPath);
ipcMain.on("set-progress", (event, percent) => {
diff --git a/preload.js b/preload.js
index 5da0c1c..4e5eb5f 100644
--- a/preload.js
+++ b/preload.js
@@ -4,7 +4,8 @@ contextBridge.exposeInMainWorld("electronAPI", {
getDefaultDownloadPath: () => ipcRenderer.invoke("get-default-download-path"),
selectDownloadFolder: () => ipcRenderer.invoke("select-download-folder"),
setProgress: (percent) => ipcRenderer.send("set-progress", percent),
- getFeatures: () => ipcRenderer.invoke("features")
+ getFeatures: () => ipcRenderer.invoke("features"),
+ getValidatedDownloadPath: (path) => ipcRenderer.invoke("validate-download-path", path)
});
// Contrôles de fenêtre et outils custom pour la topbar
diff --git a/public/script/custompath.js b/public/script/custompath.js
index 4bb81ad..ccf01f0 100644
--- a/public/script/custompath.js
+++ b/public/script/custompath.js
@@ -1,41 +1,62 @@
window.addEventListener("DOMContentLoaded", async () => {
const savePathElem = document.getElementById("savePath");
+ const form = document.getElementById("downloadForm");
- // Essayer de charger depuis le localStorage
- let savedPath = localStorage.getItem("customDownloadPath");
-
- // Sinon demander le chemin par défaut à l'API Electron
- if (!savedPath) {
- savedPath = await window.electronAPI.getDefaultDownloadPath();
- }
-
- // Afficher le chemin
- if (savePathElem) {
- savePathElem.textContent = savedPath;
- }
-
- // Créer l'input caché s'il n'existe pas déjà
+ // input caché = DERNIER chemin validé par le back
let hidden = document.getElementById("savePathInput");
if (!hidden) {
hidden = document.createElement("input");
hidden.type = "hidden";
hidden.name = "savePath";
hidden.id = "savePathInput";
- document.getElementById("downloadForm").appendChild(hidden);
+ form.appendChild(hidden);
}
- hidden.value = savedPath;
- // Gestion du bouton de modification
- document.getElementById("changePath").addEventListener("click", async () => {
- const selectedPath = await window.electronAPI.selectDownloadFolder();
- if (selectedPath) {
- // Met à jour l'affichage
- savePathElem.textContent = selectedPath;
- hidden.value = selectedPath;
+ async function applyPathFromBack(path) {
+ savePathElem.textContent = path;
+ hidden.value = path;
+ localStorage.setItem("customDownloadPath", path); // UX only
+ }
- // Et le stocke en localStorage pour la prochaine fois
- localStorage.setItem("customDownloadPath", selectedPath);
+ async function loadInitialPath() {
+ // On affiche ce que le user a vu la dernière fois (UX)
+ const cached = localStorage.getItem("customDownloadPath");
+ if (cached) {
+ savePathElem.textContent = cached;
}
- });
-});
+ // MAIS la source de vérité reste le back
+ try {
+ const validatedPath = await window.electronAPI.getValidatedDownloadPath(
+ cached
+ );
+ await applyPathFromBack(validatedPath);
+ } catch {
+ // fallback sûr
+ const defaultPath =
+ await window.electronAPI.getDefaultDownloadPath();
+ await applyPathFromBack(defaultPath);
+ }
+ }
+
+ await loadInitialPath();
+
+ document
+ .getElementById("changePath")
+ .addEventListener("click", async () => {
+ try {
+ const selectedPath =
+ await window.electronAPI.selectDownloadFolder();
+
+ if (!selectedPath) return; // annulé
+
+ // Validation back obligatoire
+ const validatedPath =
+ await window.electronAPI.getValidatedDownloadPath(selectedPath);
+
+ await applyPathFromBack(validatedPath);
+ } catch (err) {
+ alert("Dossier non autorisé.");
+ }
+ });
+});
From a69114edced2339e432109dc7321acc405924c93 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Wed, 14 Jan 2026 22:49:34 +0100
Subject: [PATCH 13/46] Feat: Package Update + Add NSIS Installer Banner
---
build/banner.bmp | Bin 0 -> 154542 bytes
package-lock.json | 4 ++--
package.json | 5 +++++
3 files changed, 7 insertions(+), 2 deletions(-)
create mode 100644 build/banner.bmp
diff --git a/build/banner.bmp b/build/banner.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..5938b74c142ae329e74b60eb7b9097158bb67fd5
GIT binary patch
literal 154542
zcmeI5Khowlj>da7-EfnwJ%DS{b}+$IwStRTH|CjqKdc?cAO30i12(WHKMX2k-&r
zHv5}lH3|)o6iHDMUkR#eo8n*ac>oZk^y>TXzy1Ax{_V{_ufOo`&;0v8{{8h&Z{Gar
z&3}?g*MI!`n>YXb_v!jaT!BC!5C{YUfj}S-2m}IwKp+qZ1OkCTAP@)y0)apv5C{YU
zfj}S-2m}IwKp+qZ1OkCTAP@)y0&NKV{`>F0{`%|xo^t*6+iz_`MXkvQK<`&yef3}G
zUSE9i#ZN!|^v556OrA`1S3m$;{_@K&&n5Y@(O~@J$BzZ+B6}JFI8vbg4El?1Fz{)!
zijEutSo9)9C;bY#9YxbJzW(~_i;TE9Eb2FHdePA*1b+Vc=OW_O0$joS_wT>|{`(()
z{4oXW61vkT`QLu~?c29+t9=v;QNK?D#{cIaKU%B|t{T{moK&WJOs7UhNci*-26Ll&GRF257
z_mi!uz85%Im>i{NaZm
zvg_jtc$Vl!2T;*vAzf22o^dQobV95|ckI7j+`t4*?rcU
zo0?yK`NjL6HAT%reQhS|osWE0SO>9INc`~O1FEPY!rOSdO&wi7(t^OU&}j`cURoC=
z-pP>}MIwtpcAv$wr)=fkO#CgcsKLU(8$^(+jn_mDrZm-DVZYD|(V6vek{VLd1V2-D
zF-D7eqh-UU;Tni|@?s=Msf_ubiR9vAWkWKL>ewuN=UsGfa&0Ok-Z>%|llJzl{61@z
zQ77p9s@hJsp)#w1-n3ynOxx=%tDEtG+-4#5Z5wldeVFbRu1%dZo!EaFcCz~{u$r<`
z>#>IEHawP;F#Fsyf;3G5(0QZArRzGg(qnWta-H=~IFnhzzj{Bwm_2Faf#yL|8=$+9
zYaEeRT5<+EBvDV>-4R!IjgaSA6S;n1Y*zQl
zV0)$pW=AH}mDxo-*dm7i9ME7!Cnb!jYv&3U|OPivs)6Pg+i0G7U0l;=Qdj@qGo4j^;+K?`R_zl^pq=P0uCp;7ygzfL
zHcC~BWDbp2yNK@M8cw}Mv%x$$+B6_9a%)0d0qVFgrkCh;uF=ozxq%Mp7lHjMF|vmb
zyqk1{JOf0xbIpn@x+)3SKh#GZfzok(miAxM{oWYS?ObOa_;C*EI7SZbIUCZJ57K6twh0Nkhz7JxuDwymKC7;52GSJD%8NktwwtA_*X-rry?Zy{D~w>~
z2-lP*v3u2NQ~vu^$iCD8n3vB~hZANM_Te{`W1qE28MJCtla0*s?eSm^zhiA6}FV(q?(`x!AHU$eD>GVxQFovNvszT$y#>00_{DGD6fnp{)
zfgLS^2Fr0)A
zYm94J`2z}J{HnFPv_>NsEyqDN#j~MY?k9Bavy~iNE@lqtT`b^0px8gis0>7r
zdFJ(U*e)n=W&c&-0^iPFn6L^);1TvA6wTqkq`An)6~J#Lz^?R8;{BgohHHI>)-l*4Bx1$GP_jM5iH$u0i_}
z#t;2l+ou8eas$D53Z&V6AAO-(JW?lse>s#w;6NY{2m}IwKp+qZ1OkCTAP@)y0)apv
z5C{YUfj}S-2m}IwKp+qZ1OkCTAP@)y0)apv5D)}-Uzb-yPq-@Y7*KSA01WZ)*T~0S
z`5t&}tj_g7hXYL>{)$>~EiUf%iQxM76w3sIYk}hSiQxM76w3sIYk}hS3C}gZkRoRG
zm;WUfzrOUn>v(nV=O|i@_xE3gG
zp9rpRPq9oexE3gGp9rpRPq9oexE3gGp9rpRPq9oexE3gGp9rpRPq9oexE3gGp9rpR
zPq9oexE3gGp9rpRPq9oexE3gGpJ?YAD9jVat`7*Gk7PXOGMIO9ZQ3q=i)KQ%zWB27
z;xZp99uM^2etx~;OVr8X912u)ejx&U!;o*!n!nP;3;!QJd_Y|nUtcc7tu!=dH(bUxd(TG9((~}g
z9~CV!Hic35LS5;+vB-Fpb_bsNCocH!hL?e8dhK5i^nNpdr}88~5_@
zm{2o!O@}hWHMg5|d!lKDY%2r1lx(b(#!@^B
zR9fjjedJIzN!X92T<
z9tqEf36CBl{)F_dZ`X81CeqDu|ev^9DH
z3(|8WRzm=0HJkWMBcU!eTvHQrb%oQ;CwW4Ry{EUK!oUq>rCZ>tlch^N*G5$^^U^>A
z`H<)X00cJ91PReGD-lcJfVim8>TKj!LALP
znrq`jv|y6nd|Yx@9$V(c!Y4qbgoc+MbgAds9K!58r8Gn{v=*l2WDi}9<-5YW*~1#R
zDqORenx)e#LuFi3lr>x7I$Nq`lQgT6={ar%0SFSHQUV4AWL>1GglJY(T}pb-v*WDU
ziWnx~H{ABux
z)WBtqTg7!JB+bUql=|kubzK8n=&o?RGa}L}0%~JK)mHCIsjMrYnWlN%dIT^BV_#y?
zDN*7YsC{o;Iht#~absMOL}bwYYp%1(pesjO5Wqtc6bZIEAvlWM%rK|RY=GrXB
zbfTlLY^bl5fzM&Jj~g{X00uD@NXJZsZp}4CJN>rCxz4qg!K)VTNLQHtTvf|?`!q{A
z2&e0y$!g0*wHQ$bVq8(Stbf)H-1`LSClZSwU{($N6hl+#pO5SFe4K+;l0~NW5@G-&
zuZv?T7#%Qjk>GTN6_X9`+$m^6lNB>AYlJz>K?goLm|qc3mtykd#BQsL7fb_4VOBh6
zHUSsF-qmxZvUb$j;Tkg&*)^_~!K85!GMz}25b%!_4UE}a
zIGRHDEYl9IOZ-ay7}1ISS#D&x1z*Df5
z3bRbRB5J(|!EjLQyz14STuLl0e35`ey?xe2az+YVXoB|!K>cJS7oR(}pxGpCe4sAX
zTqnA9DQSPMHEa5)mR!g@tJ_EQV_x~ds11^uO~W-nk)tc%A||4Tm*8Z~9F?cxa4GTU
zU3#G=pweUktm#3QdahX<;daliW&9v16ZKh3EdffIjZo%m4=D3flVBQk|SfXEvb~Mh0
zYk!2!vCJ5B-o41Uti?#kZjQ}hx)6g*sbCVrGK@+7TCI#9PS61+FDjTK;TlcQ?+FOn
zP&PLA>`!;$>8KusG}hXVxqo&OTyLVc
zxxFoMjlbROyk5a@U0J4mKYl^c&u)DE$Vmv`Ik73@QH6*s*IhPP!kK_dMj_F~wf9Kv
z{=X#8bMh18KFT#*b31D@YvS-O{h_kflRY8gb13#Rg>hiB@z_`fYB^}22yj|&Nvj9wg=s!7?lY|5eUEq#Es$KvbF}-i>Mh6w#%HoN^H^{
zTra})utjUqWk;5sRB)Yz<>XA_8BN)6y1pq6u1}^lJ6y@A`GF6iT8eC8DqR>aXI!O2
zRJLQ;A;_fpuoiVSjM%J10V}mf5(|amQWNrNWll9yCv12ttv>0?vHwT5iVROK!V(SF
z5DghEn0UHz5iJd)&Ls%olMUDP5K9Y*N*HHeU$S-ENS}{@=eo-WnrC6txkjDRDH$Gv
z&bc^PpD(vgKl(RD8?TauR
zgJIW{&G$=L!MmDgDb)yACzw{#mL#NHYiT3G``V>(?i<;8=V}=%im#tGW
z84uLXoM9Jgyb5BVJc6g^Iu*gVDKZVEhvy{L=i2Pu%s$-^YKSw|&8?~MsN40qHhf{`
znxHz@JCFYKKsQLQ&$U@Q%vw;X*3>;Iw#a~W^nEC~KtIgwu~M52NK^l3sj)1W;u5Xy4rWf1v&{do2v
z;M5a1Z4c~b4hBAp?vf`rGRQ0p*W4ZyPRNM&NU$;*NZW4#8JecxKtCoX_hQIEn(K)w
zC;i_t!5Zfw?aG9Do
zsldQnECmYu``ab;xIKoiGC^aZ?Pn1%iwo7xzeP!21(y5C316Blc*kJdr)hk`aD=B-u+s3F7)hm
zkBE`D0+Cv-Mn%nze)~+oF>XBF;-5JiVY@0jZW5sFSx)u$FO&>tB!T7NZmtGGlL5K+
zcE3@3_cFZt&jsgxz2Uce`PKDzo{r)%%u(%r<+&e6vu1>=G-zuo>*@Ul7)Cvd$HsnG
zng^_VKhcOsCq|vRwtkHhjA|MItULR9fFUB?q8PInG0#xwpCC{R7U_c!0Ova6uskSmK%3VyhOx>cjbrhP|rnzh`oh{b70ACANFtk&JjLF=|Uj5
z?t<&3D+kxT^bvmJmZx03L+`8~T=xR#W8iGm-I96od1i1OT=ydIocgb8*Q`63wz*we|aQz&vIUgf_W|`A3kEK)4_P0UOmW{5SgWHSF6t49XE?x&c
zdH3|9xV@a%7^5bdbeQMMk=Q6Odlr38vhxj-#zCXnB?y?;QDT332@59-%3-)RYSO{=
z39w%>gn!YCNB@^d5`!L%faf|)`)JIs>K~77e0aKLugzDm%u(~^Z3OUF@z^ph>}0tf
z%Zy!l3+5Nri8Im*!9RIujB(70eXFqRlerrh&i`o6^VpITTn~VMeiH(6bEwinuBj7T
zpHJM_i2JQOxE@3P6nPa#C1PsyaqX#;PChH?$j>I`dSzqRm
za0~(cItsBCu6wMXXtg*3oST{OJDzhbPT8<{#(`tk@tf9RFc)tKvu2MR&omdOY*;+c
zHPnCn_;I+yXt*o_rDvM#ug&)gT5jW+=CVX5!AxvsTzc0nr!I?6_Tl2iGtK8H0LD1W
zw8O5~SDS2v*5$oZ<=}dKu91)+P5=61fM}Wo*Dt|!5)#H)zWLHvaQ#B8g{Xl*AP@)y
z0)apv5C{YUfj}S-2m}IwKp+qZ1OkCTAP@)y0)apv5C{YUfj}S-2m}IwKp+qZ1Og91
G;Qs*`H}{DE
literal 0
HcmV?d00001
diff --git a/package-lock.json b/package-lock.json
index e2c08aa..84cb76d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "freedom-loader",
- "version": "1.3.1",
+ "version": "1.3.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "freedom-loader",
- "version": "1.3.1",
+ "version": "1.3.2",
"dependencies": {
"chalk": "^4.1.2",
"debug": "^4.4.1",
diff --git a/package.json b/package.json
index 9d34697..07fc418 100644
--- a/package.json
+++ b/package.json
@@ -56,6 +56,10 @@
"from": "build/app-icon.ico",
"to": "app-icon.ico"
},
+ {
+ "from": "build/banner.bmp",
+ "to": "banner.bmp"
+ },
{
"from": "build/error.png",
"to": "error.png"
@@ -91,6 +95,7 @@
"allowToChangeInstallationDirectory": true,
"installerIcon": "build/app-icon.ico",
"uninstallerIcon": "build/uninstaller-icon.ico",
+ "installerSidebar": "build/banner.bmp",
"createDesktopShortcut": true,
"createStartMenuShortcut": true,
"shortcutName": "Freedom Loader"
From 745a73a5b05846a70605467d85d6ca67b43e4242 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Thu, 15 Jan 2026 09:03:50 +0100
Subject: [PATCH 14/46] Feat: Add version badge controlled. Before we needed to
write with the hand for the front. But now there is an IPC event that provide
App Version from package.json
---
main.js | 1 +
preload.js | 1 +
public/index.html | 3 ++-
public/script/appVersion.js | 6 ++++++
4 files changed, 10 insertions(+), 1 deletion(-)
create mode 100644 public/script/appVersion.js
diff --git a/main.js b/main.js
index afe90f4..c690b5e 100644
--- a/main.js
+++ b/main.js
@@ -16,6 +16,7 @@ const defaultDownloadPath = path.join(os.homedir(), "Downloads", "Freedom Loader
app.setAppUserModelId("com.masteracnolo.freedomloader"); // pour notifications Windows
app.disableHardwareAcceleration();
+ipcMain.handle("version", () => config.version);
// Gestion single instance
const gotLock = app.requestSingleInstanceLock();
diff --git a/preload.js b/preload.js
index 4e5eb5f..150ec42 100644
--- a/preload.js
+++ b/preload.js
@@ -5,6 +5,7 @@ contextBridge.exposeInMainWorld("electronAPI", {
selectDownloadFolder: () => ipcRenderer.invoke("select-download-folder"),
setProgress: (percent) => ipcRenderer.send("set-progress", percent),
getFeatures: () => ipcRenderer.invoke("features"),
+ getVersion: () => ipcRenderer.invoke("version"),
getValidatedDownloadPath: (path) => ipcRenderer.invoke("validate-download-path", path)
});
diff --git a/public/index.html b/public/index.html
index 3f8e077..ebafd10 100644
--- a/public/index.html
+++ b/public/index.html
@@ -95,10 +95,11 @@
-
v1.3.1
+
+
diff --git a/public/script/appVersion.js b/public/script/appVersion.js
new file mode 100644
index 0000000..ad9aaa0
--- /dev/null
+++ b/public/script/appVersion.js
@@ -0,0 +1,6 @@
+async function versionLabel(){
+ const appVersion = await window.electronAPI.getVersion();
+ document.getElementById("version-badge").textContent = `v${appVersion}`;
+};
+
+versionLabel();
\ No newline at end of file
From 0ff4715b3515a2bbf459fe5cb3a950d1c78a7310 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Thu, 15 Jan 2026 09:28:46 +0100
Subject: [PATCH 15/46] Fix: Correct Config.json file for packaged version
---
config.js | 6 ++++--
package.json | 4 ++++
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/config.js b/config.js
index 0df8abb..b4ffc4a 100644
--- a/config.js
+++ b/config.js
@@ -3,7 +3,9 @@ const { app } = require("electron");
const fs = require("fs");
const path = require("path");
-const featuresPath = path.join(__dirname, "./config/config.json");
+const localMode = !app.isPackaged;
+
+const featuresPath = localMode ? path.join(__dirname, "./config/config.json") : path.join(path.join(process.resourcesPath, "config.json"));
let features = {};
@@ -20,7 +22,7 @@ module.exports = {
version: packageJson.version,
applicationPort: "8787",
debugMode: true,
- localMode: !app.isPackaged,
+ localMode,
DiscordRPCID: "1410934537051181146",
configFeatures
}
\ No newline at end of file
diff --git a/package.json b/package.json
index 07fc418..d19f5ab 100644
--- a/package.json
+++ b/package.json
@@ -83,6 +83,10 @@
{
"from": "server",
"to": "server"
+ },
+ {
+ "from": "config/config.json",
+ "to": "config.json"
}
],
"win": {
From 01b6bcd02c951c3f0fa796f6a57f213c89f12ab7 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Thu, 15 Jan 2026 10:00:17 +0100
Subject: [PATCH 16/46] Feat: Add Newline YT-DLP Args. Add Toggle Switches for
verbose, autodownloadplaylist + Fix Thumbail misspell
---
config/config.json | 9 ++++++---
server/helpers/buildArgs.js | 7 +++++--
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/config/config.json b/config/config.json
index f969fb6..872dfb0 100644
--- a/config/config.json
+++ b/config/config.json
@@ -2,12 +2,15 @@
"autoUpdate": true,
"discordRPC": true,
"customTopBar": true,
- "autoDownloadPlaylist": true,
- "logSystem": true,
"autoCheckInfo": true,
- "outputTitleCheck": true,
"addThumbnail": true,
"addMetadata": true,
+ "verboseLogs": false,
+ "autoDownloadPlaylist": true,
+
+
+ "logSystem": true,
+ "outputTitleCheck": true,
"downloadSystem": true,
"notifySystem": true
}
\ No newline at end of file
diff --git a/server/helpers/buildArgs.js b/server/helpers/buildArgs.js
index 16586f3..25c8c25 100644
--- a/server/helpers/buildArgs.js
+++ b/server/helpers/buildArgs.js
@@ -8,10 +8,12 @@ const { configFeatures } = require("../../config.js");
function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) {
const args = [
+ configFeatures.verboseLogs ? "--verbose" : null, // Verbose Logs
"--cookies-from-browser", `${getUserBrowser()}`,
"--no-continue",
"--no-overwrites",
- configFeatures.addThumbail ? "--embed-thumbnail" : null,
+ "--newline", // YT-DLP Logs Format
+ configFeatures.addThumbnail ? "--embed-thumbnail" : null,
configFeatures.addMetadata ? "--add-metadata" : null,
"--concurrent-fragments", "8",
"--retries", "10",
@@ -19,7 +21,8 @@ function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) {
"--ffmpeg-location", ffmpegPath,
"--extractor-args","youtube:player_client=default",
"--js-runtimes", `deno:${denoPath}`,
- "-S", "vcodec:h264" // Will be replaced with a variables when i will add the settings panel (Next Update ?)
+ "-S", "vcodec:h264", // Will be replaced with a variables when i will add the settings panel (Next Update ?)
+ configFeatures.autoDownloadPlaylist ? "--yes-playlist" : "--no-playlist"
];
if (audioOnly) args.push("-f", "bestaudio", "--extract-audio", "--audio-format", "mp3");
From f959171db5d2be446aa26382c581bc9e1033b30d Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Thu, 15 Jan 2026 10:57:37 +0100
Subject: [PATCH 17/46] Feat: Add CustomVideo Codec Choice with verification
in config.json
---
config/config.json | 1 +
server/helpers/buildArgs.js | 17 ++++++++++++++++-
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/config/config.json b/config/config.json
index 872dfb0..2fd13e9 100644
--- a/config/config.json
+++ b/config/config.json
@@ -7,6 +7,7 @@
"addMetadata": true,
"verboseLogs": false,
"autoDownloadPlaylist": true,
+ "customCodec": "h264",
"logSystem": true,
diff --git a/server/helpers/buildArgs.js b/server/helpers/buildArgs.js
index 25c8c25..feae9ce 100644
--- a/server/helpers/buildArgs.js
+++ b/server/helpers/buildArgs.js
@@ -3,7 +3,22 @@ const path = require("path");
const getUserBrowser = require("./getBrowser");
const { ffmpegPath, denoPath} = require("./path");
const { configFeatures } = require("../../config.js");
+const { logger } = require("../logger");
+function validateCodec(codec){
+
+ const validCodec = [
+ "av01","vp9.2", "vp9" , "h265" , "h264" , "vp8" , "h263", "theora"
+ ]
+
+ if(validCodec.includes(codec)){
+ logger.info("Codec Valid:", codec)
+ return codec
+ } else{
+ logger.error(`Codec not valid: ${codec}. Using default codec`)
+ return "h264"
+ }
+}
function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) {
@@ -21,7 +36,7 @@ function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) {
"--ffmpeg-location", ffmpegPath,
"--extractor-args","youtube:player_client=default",
"--js-runtimes", `deno:${denoPath}`,
- "-S", "vcodec:h264", // Will be replaced with a variables when i will add the settings panel (Next Update ?)
+ "-S", `vcodec:${validateCodec(configFeatures.customCodec) || "h264"}`,
configFeatures.autoDownloadPlaylist ? "--yes-playlist" : "--no-playlist"
];
From 5398fed928b7edf0bfd180254a541482a5ab16d0 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Thu, 15 Jan 2026 10:59:45 +0100
Subject: [PATCH 18/46] Fix: Remove unusued Variable
---
config.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/config.js b/config.js
index b4ffc4a..7fa4a84 100644
--- a/config.js
+++ b/config.js
@@ -21,7 +21,6 @@ const configFeatures = loadFeatures();
module.exports = {
version: packageJson.version,
applicationPort: "8787",
- debugMode: true,
localMode,
DiscordRPCID: "1410934537051181146",
configFeatures
From 163faec2213a82be1fbd64e00716692e7cac42a1 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Thu, 15 Jan 2026 16:01:24 +0100
Subject: [PATCH 19/46] Feat: Add Configuration Button. user can edit
config.json as wanted. Linked and IPC
---
main.js | 10 ++++++++++
preload.js | 3 ++-
public/index.html | 1 +
public/script/topbar.js | 2 ++
4 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/main.js b/main.js
index c690b5e..daa1923 100644
--- a/main.js
+++ b/main.js
@@ -11,6 +11,13 @@ const { startRPC } = require("./server/discordRPC");
let mainWindow;
const logsFolderPath = logDir;
+
+const basePath = config.localMode
+ ? path.join(__dirname, "config")
+ : path.join(path.dirname(process.execPath), "resources");
+
+const configFolderPath = path.join(basePath, "config.json");
+
const defaultDownloadPath = path.join(os.homedir(), "Downloads", "Freedom Loader");
app.setAppUserModelId("com.masteracnolo.freedomloader"); // pour notifications Windows
@@ -176,6 +183,9 @@ ipcMain.on("open-website", () => {
ipcMain.on("open-wiki", () => {
shell.openExternal("https://masteracnolo.github.io/FreedomLoader/pages/wiki.html");
});
+ipcMain.on("open-config", () => {
+ if (configFolderPath) shell.openPath(configFolderPath);
+});
// App ready
diff --git a/preload.js b/preload.js
index 150ec42..aacdf74 100644
--- a/preload.js
+++ b/preload.js
@@ -17,5 +17,6 @@ contextBridge.exposeInMainWorld("topbarAPI", {
openDevTools: () => ipcRenderer.send("open-devtools"),
openLogs: () => ipcRenderer.send("open-logs"),
openWebsite: () => ipcRenderer.send("open-website"),
- openWiki: () => ipcRenderer.send("open-wiki")
+ openWiki: () => ipcRenderer.send("open-wiki"),
+ openConfig: () => ipcRenderer.send("open-config")
});
diff --git a/public/index.html b/public/index.html
index ebafd10..d517673 100644
--- a/public/index.html
+++ b/public/index.html
@@ -23,6 +23,7 @@
+
diff --git a/public/script/topbar.js b/public/script/topbar.js
index 2221667..be7f584 100644
--- a/public/script/topbar.js
+++ b/public/script/topbar.js
@@ -10,6 +10,7 @@ function setupTopbarListeners() {
const logsBtn = document.getElementById('logs-btn');
const websiteBtn = document.getElementById('website-btn');
const wikiBtn = document.getElementById('wiki-btn');
+ const configBtn = document.getElementById('config-btn');
if (minBtn) minBtn.onclick = () => topbarAPI.minimize();
if (maxBtn) maxBtn.onclick = () => topbarAPI.maximize();
@@ -18,6 +19,7 @@ function setupTopbarListeners() {
if (logsBtn) logsBtn.onclick = () => topbarAPI.openLogs();
if (websiteBtn) websiteBtn.onclick = () => topbarAPI.openWebsite();
if (wikiBtn) wikiBtn.onclick = () => topbarAPI.openWiki();
+ if (configBtn) configBtn.onclick = () => topbarAPI.openConfig();
});
}
From 55db30febcfe8dbfdb176f64373c4c58f0f459b1 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Thu, 15 Jan 2026 16:21:43 +0100
Subject: [PATCH 20/46] Fix: Remove Useless Console.log
---
config.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/config.js b/config.js
index 7fa4a84..730dd0b 100644
--- a/config.js
+++ b/config.js
@@ -12,7 +12,6 @@ let features = {};
function loadFeatures() {
const raw = fs.readFileSync(featuresPath, "utf-8");
features = JSON.parse(raw);
- console.log(features)
return features;
}
From e45810b54cc55a67ebebce3d12a48965b1707301 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Thu, 15 Jan 2026 16:22:29 +0100
Subject: [PATCH 21/46] Add: Better logs. Write logs when a download is init
---
server/helpers/buildArgs.js | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/server/helpers/buildArgs.js b/server/helpers/buildArgs.js
index feae9ce..011cb8a 100644
--- a/server/helpers/buildArgs.js
+++ b/server/helpers/buildArgs.js
@@ -12,7 +12,7 @@ function validateCodec(codec){
]
if(validCodec.includes(codec)){
- logger.info("Codec Valid:", codec)
+ logger.info(`Codec Valid: ${codec}`)
return codec
} else{
logger.error(`Codec not valid: ${codec}. Using default codec`)
@@ -21,6 +21,26 @@ function validateCodec(codec){
}
function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) {
+
+ logger.info("--- CONFIGURATION ---");
+
+ logger.info(`CONFIG autoUpdate: ${configFeatures.autoUpdate}`);
+ logger.info(`CONFIG discordRPC: ${configFeatures.discordRPC}`);
+ logger.info(`CONFIG customTopBar: ${configFeatures.customTopBar}`);
+ logger.info(`CONFIG autoCheckInfo: ${configFeatures.autoCheckInfo}`);
+ logger.info(`CONFIG addThumbnail: ${configFeatures.addThumbnail}`);
+ logger.info(`CONFIG addMetadata: ${configFeatures.addMetadata}`);
+ logger.info(`CONFIG verboseLogs: ${configFeatures.verboseLogs}`);
+ logger.info(`CONFIG autoDownloadPlaylist: ${configFeatures.autoDownloadPlaylist}`);
+ logger.info(`CONFIG customCodec: ${configFeatures.customCodec}`);
+
+ // ACTIVATE THEM WHEN THE FEATURE IS IMPLEMENTED
+ // logger.info(`CONFIG logSystem: ${configFeatures.logSystem}`);
+ // logger.info(`CONFIG outputTitleCheck: ${configFeatures.outputTitleCheck}`);
+ // logger.info(`CONFIG downloadSystem: ${configFeatures.downloadSystem}`);
+ // logger.info(`CONFIG notifySystem: ${configFeatures.notifySystem}`);
+
+ logger.info("---------------------");
const args = [
configFeatures.verboseLogs ? "--verbose" : null, // Verbose Logs
From c356e2e30d626c73b7af35f9e07951930f29a14f Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Thu, 15 Jan 2026 21:22:40 +0100
Subject: [PATCH 22/46] Fix: Using ASAR for every parts of the projects (the
server is now in it) and i put the binaries in a /binaries folder. It's
better for readability of the resources folder
---
main.js | 11 ++++++-----
package.json | 16 +++++-----------
server/helpers/path.js | 15 +++++++++++----
3 files changed, 22 insertions(+), 20 deletions(-)
diff --git a/main.js b/main.js
index daa1923..abe30e4 100644
--- a/main.js
+++ b/main.js
@@ -31,10 +31,10 @@ const gotLock = app.requestSingleInstanceLock();
// Native dependencies check (yt-dlp.exe, ffmpeg.exe, ffprobe.exe, Deno)
function checkNativeDependencies() {
const deps = [
- { name: "yt-dlp.exe", path: path.join(process.resourcesPath, "yt-dlp.exe") },
- { name: "ffmpeg.exe", path: path.join(process.resourcesPath, "ffmpeg.exe") },
- { name: "ffprobe.exe", path: path.join(process.resourcesPath, "ffprobe.exe") },
- { name: "deno.exe", path: path.join(process.resourcesPath, "deno.exe") },
+ { name: "yt-dlp.exe", path: path.join(process.resourcesPath, "binaries","yt-dlp.exe") },
+ { name: "ffmpeg.exe", path: path.join(process.resourcesPath, "binaries", "ffmpeg.exe") },
+ { name: "ffprobe.exe", path: path.join(process.resourcesPath, "binaries", "ffprobe.exe") },
+ { name: "deno.exe", path: path.join(process.resourcesPath, "binaries", "deno.exe") },
];
const missing = deps.filter(dep => !fs.existsSync(dep.path));
let errorMsg = "";
@@ -193,7 +193,8 @@ app.whenReady().then(async () => {
logSessionStart();
logger.info("App Ready, Server Express starting...");
- const serverPath = path.join(__dirname, "server", "server.js");
+ const serverPath = path.join(__dirname, "server", "server.js")
+
const expressServer = require(serverPath);
try {
diff --git a/package.json b/package.json
index d19f5ab..5c430a8 100644
--- a/package.json
+++ b/package.json
@@ -39,9 +39,7 @@
"files": [
"**/*",
"node_modules/**/*",
- "!logs/*.json",
- "server/**/*",
- "server/node_modules/**/*"
+ "!logs/*.json"
],
"directories": {
"buildResources": "build"
@@ -66,23 +64,19 @@
},
{
"from": "ressources/yt-dlp.exe",
- "to": "yt-dlp.exe"
+ "to": "binaries/yt-dlp.exe"
},
{
"from": "ressources/ffmpeg.exe",
- "to": "ffmpeg.exe"
+ "to": "binaries/ffmpeg.exe"
},
{
"from": "ressources/ffprobe.exe",
- "to": "ffprobe.exe"
+ "to": "binaries/ffprobe.exe"
},
{
"from": "ressources/deno.exe",
- "to": "deno.exe"
- },
- {
- "from": "server",
- "to": "server"
+ "to": "binaries/deno.exe"
},
{
"from": "config/config.json",
diff --git a/server/helpers/path.js b/server/helpers/path.js
index d045c44..bf35f94 100644
--- a/server/helpers/path.js
+++ b/server/helpers/path.js
@@ -3,6 +3,8 @@ const fs = require("fs");
const { app } = require("electron");
const config = require("../../config");
+const { logger } = require("../logger.js");
+
let userYtDlp;
let ffmpegPath;
let denoPath;
@@ -11,16 +13,21 @@ const sourceYtDlp = path.join(process.resourcesPath, "yt-dlp.exe");
if (config.localMode) {
userYtDlp = path.join(__dirname, "../../ressources/yt-dlp.exe");
- ffmpegPath = path.join(__dirname, "../../ressources"); // <- contient ffmpeg.exe et ffprobe.exe
+ ffmpegPath = path.join(__dirname, "../../ressources/"); // <- contient ffmpeg.exe et ffprobe.exe
denoPath = path.join(__dirname, "../../ressources/deno.exe");
} else {
- userYtDlp = path.join(app.getPath("userData"), "yt-dlp.exe");
- ffmpegPath = path.join(process.resourcesPath, "ffmpeg.exe");
- denoPath = path.join(process.resourcesPath, "deno.exe");
+ userYtDlp = path.join(app.getPath("userData"),"binaries","yt-dlp.exe");
+ ffmpegPath = path.join(process.resourcesPath, "binaries","ffmpeg.exe");
+ denoPath = path.join(process.resourcesPath, "binaries","deno.exe");
if (!fs.existsSync(userYtDlp)) {
fs.copyFileSync(sourceYtDlp, userYtDlp);
}
+
}
+if (!userYtDlp){ logger.error("Missing YT-DLP")}
+if (!ffmpegPath){ logger.error("Missing FFMPEG")}
+if (!denoPath){ logger.error("Missing DENO")}
+
module.exports = { userYtDlp, ffmpegPath, denoPath };
From 65364d3095a321c95b7a2c12ca9e96e5f8927b8f Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Thu, 15 Jan 2026 21:22:57 +0100
Subject: [PATCH 23/46] Fix: Update Dependencies
---
package-lock.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 84cb76d..04606d8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -859,9 +859,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "22.19.6",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.6.tgz",
- "integrity": "sha512-qm+G8HuG6hOHQigsi7VGuLjUVu6TtBo/F05zvX04Mw2uCg9Dv0Qxy3Qw7j41SidlTcl5D/5yg0SEZqOB+EqZnQ==",
+ "version": "22.19.7",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.7.tgz",
+ "integrity": "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==",
"dev": true,
"license": "MIT",
"dependencies": {
From b7a193b062379b1518adfe7a0b5ebf0144ede8c0 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Thu, 15 Jan 2026 21:23:26 +0100
Subject: [PATCH 24/46] Fix: Remove unusued import server.js
---
server/server.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/server.js b/server/server.js
index 09c7ec7..e8f1f75 100644
--- a/server/server.js
+++ b/server/server.js
@@ -1,7 +1,7 @@
const express = require("express");
const fs = require("fs");
const path = require("path");
-const { logger, logSessionStart, logSessionEnd } = require("./logger");
+const { logger, logSessionEnd } = require("./logger");
const config = require("../config");
const { execFile } = require("child_process");
const { userYtDlp } = require("./helpers/path");
From 2f105f51457552c905e92dca3e85bb6b5caf3c74 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Thu, 15 Jan 2026 22:01:26 +0100
Subject: [PATCH 25/46] Fix: Put config.json file into config folder for better
readability + Fix Yt-DLP Path
---
config.js | 2 +-
main.js | 4 ++--
package.json | 2 +-
server/helpers/path.js | 4 ++--
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/config.js b/config.js
index 730dd0b..928349d 100644
--- a/config.js
+++ b/config.js
@@ -5,7 +5,7 @@ const path = require("path");
const localMode = !app.isPackaged;
-const featuresPath = localMode ? path.join(__dirname, "./config/config.json") : path.join(path.join(process.resourcesPath, "config.json"));
+const featuresPath = localMode ? path.join(__dirname, "./config/config.json") : path.join(path.join(process.resourcesPath,"config/" ,"config.json"));
let features = {};
diff --git a/main.js b/main.js
index abe30e4..272a9c5 100644
--- a/main.js
+++ b/main.js
@@ -13,10 +13,10 @@ let mainWindow;
const logsFolderPath = logDir;
const basePath = config.localMode
- ? path.join(__dirname, "config")
+ ? path.join(__dirname )
: path.join(path.dirname(process.execPath), "resources");
-const configFolderPath = path.join(basePath, "config.json");
+const configFolderPath = path.join(basePath, "config" ,"config.json");
const defaultDownloadPath = path.join(os.homedir(), "Downloads", "Freedom Loader");
diff --git a/package.json b/package.json
index 5c430a8..f2084d2 100644
--- a/package.json
+++ b/package.json
@@ -80,7 +80,7 @@
},
{
"from": "config/config.json",
- "to": "config.json"
+ "to": "config/config.json"
}
],
"win": {
diff --git a/server/helpers/path.js b/server/helpers/path.js
index bf35f94..8eac1a5 100644
--- a/server/helpers/path.js
+++ b/server/helpers/path.js
@@ -9,14 +9,14 @@ let userYtDlp;
let ffmpegPath;
let denoPath;
-const sourceYtDlp = path.join(process.resourcesPath, "yt-dlp.exe");
+const sourceYtDlp = path.join(process.resourcesPath, "binaries","yt-dlp.exe");
if (config.localMode) {
userYtDlp = path.join(__dirname, "../../ressources/yt-dlp.exe");
ffmpegPath = path.join(__dirname, "../../ressources/"); // <- contient ffmpeg.exe et ffprobe.exe
denoPath = path.join(__dirname, "../../ressources/deno.exe");
} else {
- userYtDlp = path.join(app.getPath("userData"),"binaries","yt-dlp.exe");
+ userYtDlp = path.join(app.getPath("userData"),"yt-dlp.exe");
ffmpegPath = path.join(process.resourcesPath, "binaries","ffmpeg.exe");
denoPath = path.join(process.resourcesPath, "binaries","deno.exe");
From d4c33bcf2d98f688b0983e3cf91d711db2cc617d Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Thu, 15 Jan 2026 22:54:40 +0100
Subject: [PATCH 26/46] FIx: Updated Appliction Version because i did too much
work to be a "minor release"
---
README.md | 2 +-
package-lock.json | 4 ++--
package.json | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 29fc38d..44432ae 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
diff --git a/package-lock.json b/package-lock.json
index 04606d8..27d3a4c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "freedom-loader",
- "version": "1.3.2",
+ "version": "1.4.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "freedom-loader",
- "version": "1.3.2",
+ "version": "1.4.0",
"dependencies": {
"chalk": "^4.1.2",
"debug": "^4.4.1",
diff --git a/package.json b/package.json
index f2084d2..57f7f32 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "freedom-loader",
"productName": "Freedom Loader",
- "version": "1.3.2",
+ "version": "1.4.0",
"author": "MasterAcnolo",
"description": "Freedom Loader",
"main": "main.js",
From 0e48ab3b4c59cc0db37011914e370921cde87e57 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Fri, 16 Jan 2026 09:42:09 +0100
Subject: [PATCH 27/46] Fix: Default Theme Info Color
---
public/styles/theme/default-theme.css | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/public/styles/theme/default-theme.css b/public/styles/theme/default-theme.css
index a3d2017..6694dc1 100644
--- a/public/styles/theme/default-theme.css
+++ b/public/styles/theme/default-theme.css
@@ -29,8 +29,8 @@
--infos-box-color: #0c0140;
--video-info-text-color: #ffffff;
--video-info-heading-color: #007bff;
- --video-info-list-color: #444444;
- --video-info-list-strong-color: #000000;
+ --video-info-list-color: #cccccc;
+ --video-info-list-strong-color: #e6e6e6;
--video-info-link-color: #007bff;
--video-info-link-hover-color: #0056b3;
From 8f0f31041dea675ea2806fbd30d1648ed572e119 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Fri, 16 Jan 2026 09:42:32 +0100
Subject: [PATCH 28/46] Fix: Remove Unusued Dependencies
---
package.json | 1 -
1 file changed, 1 deletion(-)
diff --git a/package.json b/package.json
index 57f7f32..795caca 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,6 @@
"chalk": "^4.1.2",
"debug": "^4.4.1",
"discord-rpc": "^4.0.1",
- "electron-squirrel-startup": "^1.0.1",
"electron-updater": "^6.6.2",
"express": "^5.1.0",
"express-rate-limit": "^8.2.1",
From 5c62ed081a2fd7b842c76de237f2c14ccc4ba9c6 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Sun, 18 Jan 2026 11:28:27 +0100
Subject: [PATCH 29/46] Fix: Update ReadME Banner Redirection
---
README.md | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 44432ae..ddde13c 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,8 @@
-
![]()

-
+ style="width: 50%;;"/>
From fecb123d0e489409d4de0bcdc4d4b08ebd7c3688 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Sun, 18 Jan 2026 13:51:17 +0100
Subject: [PATCH 30/46] Fix: Indent Index.html
---
public/index.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/public/index.html b/public/index.html
index d517673..da15ac5 100644
--- a/public/index.html
+++ b/public/index.html
@@ -35,7 +35,7 @@
-
+
-
+
+
+
+
+
@@ -100,6 +109,7 @@
+
diff --git a/public/script/settingsPanel.js b/public/script/settingsPanel.js
new file mode 100644
index 0000000..6868501
--- /dev/null
+++ b/public/script/settingsPanel.js
@@ -0,0 +1,7 @@
+const settingsButton = document.getElementById("settings-button")
+const settingsPanel = document.getElementById("settings-panel")
+
+function openPanel(){
+ settingsPanel.style.display = "block";
+ console.log("Click")
+}
\ No newline at end of file
diff --git a/public/styles/layout/settingsPanel.css b/public/styles/layout/settingsPanel.css
new file mode 100644
index 0000000..59a234e
--- /dev/null
+++ b/public/styles/layout/settingsPanel.css
@@ -0,0 +1,33 @@
+.settings-button{
+ display:flex;
+ background-color: rgba(219, 219, 219, 0.89);
+ border-radius: 12px;
+ padding: 5px;
+ transition: all ease-in-out 0.2s;
+ position: absolute;
+ top: 60px;
+ right: 40px;
+ border: none;
+}
+
+.settings-button img{
+ width: 50px;
+ height: 50px;
+}
+
+.settings-button:hover{
+ transform: scale(1.2);
+ cursor: pointer;
+}
+
+.settings-button:active{
+ transform: scale(0.9);
+}
+
+.settings-panel{
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ background-color: red;
+ z-index: 9999999;
+}
\ No newline at end of file
diff --git a/public/styles/styles.css b/public/styles/styles.css
index 6472249..06bab5a 100644
--- a/public/styles/styles.css
+++ b/public/styles/styles.css
@@ -1,5 +1,6 @@
/* Layout */
@import url("layout/form.css");
+@import url("layout/settingsPanel.css");
@import url("layout/container.css");
@import url("layout/header.css");
@import url("layout/videoinfo.css");
From 343dbb26a2fc73703e0f34c058badc2518646575 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Tue, 20 Jan 2026 22:28:53 +0100
Subject: [PATCH 34/46] Feat: Settings Panel
---
main.js | 16 ++
preload.js | 1 +
public/assets/icon/settings.png | Bin 28600 -> 0 bytes
public/assets/icon/settings.svg | 2 +
public/index.html | 171 +++++++++++++++++-
public/script/settingsPanel.js | 55 +++++-
public/styles/layout/settingsPanel.css | 241 +++++++++++++++++++++++--
public/styles/variables.css | 10 +
8 files changed, 460 insertions(+), 36 deletions(-)
delete mode 100644 public/assets/icon/settings.png
create mode 100644 public/assets/icon/settings.svg
diff --git a/main.js b/main.js
index 272a9c5..1dced18 100644
--- a/main.js
+++ b/main.js
@@ -204,6 +204,22 @@ app.whenReady().then(async () => {
ipcMain.handle("features", () => {
return configFeatures;
});
+
+ ipcMain.handle("set-feature", (event, { key, value }) => {
+ try {
+ // update mémoire
+ configFeatures[key] = value;
+
+ // écriture directe sur le JSON
+ fs.writeFileSync(configFolderPath, JSON.stringify(configFeatures, null, 2), "utf-8");
+
+ logger.info(`Feature updated: ${key} = ${value}`);
+ return true;
+ } catch (err) {
+ logger.error(`set-feature failed (${key}): ${err.message}`);
+ return false;
+ }
+ });
configFeatures.discordRPC ? startRPC() : "";
diff --git a/preload.js b/preload.js
index aacdf74..e9ca875 100644
--- a/preload.js
+++ b/preload.js
@@ -5,6 +5,7 @@ contextBridge.exposeInMainWorld("electronAPI", {
selectDownloadFolder: () => ipcRenderer.invoke("select-download-folder"),
setProgress: (percent) => ipcRenderer.send("set-progress", percent),
getFeatures: () => ipcRenderer.invoke("features"),
+ setFeature: (key, value) => ipcRenderer.invoke("set-feature", { key, value }),
getVersion: () => ipcRenderer.invoke("version"),
getValidatedDownloadPath: (path) => ipcRenderer.invoke("validate-download-path", path)
});
diff --git a/public/assets/icon/settings.png b/public/assets/icon/settings.png
deleted file mode 100644
index 848e6b11df1aa9f0c85d9f2a4ebb2a88fbee8420..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 28600
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%0A&bJCYCyVmr?t
zvj(PDrBm6#oCQr}Mqa8u?Q{3VJRj=SbwfnXFqz7AKBN2E``_fZ-cs(Tu~>U?`YQca
zq^#!(&gX#7KLL7;jI(9aomFQQL>qB
zg6ptO@c>8IJtC!(A3hs$s>2JtEW)rN%T6o2xIp;rzaq~Pkw^Ugt&6e(9#>a|bfI_Y
zauEkyM-(j^d6Oyf$a%B77b*zTerL70x5dur(=qi4a<&1e_EPFXk>(it+j8qnKD}p0
z$Dyp@SZaxxzdT_(g?g*Y(48{ub5*KBYdMMbgZRD^W}}`eF>Lk!ewQ-5Wt0g}1utXz
zq%m1?S}}H~Y7k151|%&~x=Oka*YbIMxpRlNHdchygU18ufkGe0z*nChH`?moL){X5
z^bprcd&jwb!jW^-xIxu1g2Vs1AJPX^VfA9e%BU~w520hpxL=buhnyYNMGE>+>XP(W
zYP=&z&8M2Wg&pj>UOfG43BE`%7Bs;<_w{(O%{N`#4&GECVmJA9jG_@v#xVlCd`(by
zor=5b*6R9l-|;;WOHvCL>rsNGha&5(|D#zR>pG-Bei@S>K^TZ!g+k>{C-3Z;)&nDHDElSTdJPssCs4&NrgWE;am*Y208d|z#NG{1KuYsv
zBp1%Gne~-C6EQQ!r^kN1*4)kjcbz^eMvlmr)QGv61_B;-
zZHhDNw~w?9fgqLC1?2LJt*8&8t9l&V5=?6bYg_yNWz{A`aJl0E!gtk%!*-5?ai{Rr
z(PH-!{q|xeH_56ntclvJ<#eA<_#)jM{$=JHyOf#3clXO0${t^s`yB+8Il9(u=n4|N
z-T@t)cWSaHpx}DtAcSPhTWJt=`FdogsZlQG<^^Q(*~~^D-Ys=D2mHLffP_*>8o+th
zbBW3H6X3g-=>pkD*mnU3j!*b25;&|aCVe7M`3KD!pAJr-o=A~LyaL8Tmd*dy$mJr7
z?g&B+X+L^K;eow*#cZP%!QXXpc-%;VeP=SWCEx+C0?OVDG~<088~
zvZ|b8NI?P3gWKN8o-(T@RL2bztPg9t_`{*z3fydL$Q}>>p6G*f?%>fx6ZUM&CyI
zR8V$o>1<{p7)Qdz&3a5rZlP+vMkSVX+qhx$d0p=fLUDUWD+KW#+&?2goplJgan}Ea
zfFt2D@;FjARrT}Bw@J#CGWc4SyMSC7)W#6ce!_eNwVoje`IJ#SXR>ZK7VnNmt!8bl
z(rN)jA&4?;giT;Gw{55KV=JFU9gni0Y&{)v0{DtYS;JOc9=m3PLvn!od30H!?M6>e
zH6H=Ql!drayEhyTn}!4+n{|a}{3|Wq35lr9z
zepDL}MY(x$wVy#5O!_vEVG!@L7_M`}b4=GL0^fe2jX&!di(Q%p=8#r8GqNVOq
z)MrAC4Lf#IeibB%<8DBL*-t-@LI|1%-?HF(gbg!ckd!BFnOV3kfVZffa29xb
z(ON$IEwwSXQeXUf$>tyScNdzl7n%Zie3GS?+Jd#+UPq>wqQ7Xo*&69f$@a^q2fKZt%Wu?%yoe>!X
z7!Y{jN$8rNHY)36=wWm1Mhv${dPyu(u!7qskuv@dAvA0FUVXwWNNlvs-ik9cdgR65
zb?XqkLJdIZs#msX9&l-A@cz|p)5|*lT^wQRM6e?7(IWn|A^KGpdyFRE=FA%~ZrR6B
z=lliw|D4NVd%`Nqq-41Hv{x|7;Q&aN#D2eu?;(^G-XN%pS8!G!E4V6d
z4BSI`NmqCmE*^Cm0PS{%6l5{vmx62DJs%1
z`^f+phdhuOD}V8KAcK!6CP0ERu71;Zg4}ftyIO5^{c&cL
z1?fZMkC2y?@O!Fr79)B+W?6bT#;jKO&Z;+qv4^X;PmP>Xkd7IadxL>$0v6aAfW|I72T~D)sS`)SM|Xde!cADsN#3
zKBzDf+7Rx#+1yKXBn3z}0UrxT84e;XO_x36yPU%F9>)vPnx_cA)#(}SmsvucUX>mf
zK;*}BMe1?JdqYoti5I1k{`w1CsQ|hu+Cc{clq;+8b5_%xwk8F3to$!1m6=vhewwOW
zkfh|=#Z$tNOW0w)P45HCl6Vl6_~!}DLyQqFZvnsyKDs&xj4P7g8RE1Rt2!kZ
z@R-4usSiNW{bJ_6$7Jpfj(NdP9?vGJkCfpK)DpF(6(qha`q8lft)%a3-4DT4vW(IC
zIgV=Uhua$Gd5i*vdJ6pp54s%%Pg~FJKW%vM(z($v)gT12ihubx=;e`H7r|HWQ|bZP
zTOaoMXA!68InZtkL#32Pl6g)iX#s2wp1XS@Aqgh?g~Pr4mvBFy>l&BqN-J-~4Y&j#
zp}uUAl;7ZIi6EBpDTSxv{2GV=6
zPu?|Pu%C0)SW4fPZ=jCcW-~)tW>y`nkXgPkL4K3aqFZHVr3xvPa&A~I;#BGdZrr9T
zlV9wIEK}eEaAs87YQ~_u!D2x*(qXl7d?dDz;$hIT`5fX
z7j)4rcLn4uFLn#%Lj+lcH5H#MYTxYL53{rVwo&0mgF-Vk+55iRX8}SW7c*%qcailX
zu3v(?;K$^}xoad!lgLnxs^{BVg?`fx
z?D!eyj>XDZ6#OsDBJ`~d(ae5vtqMg|Ak;uUXdfl}ybfP*q`*&M8MDFxW4badK+?Gs
zt=@iwVF;u0z``p%ev0WsSAQ>$pWL=v{D;7sy?Hh~(DFmjawMjXV@NExks7U~xq&pg
zdz~%`Tc$PHF4z8775Vd+?IZ|P*gb9(jW`WUXs2IGP>(V^i^`8toF&f%Fgmlswu>mJ-@&T
z&|;$s^`#IME5y1czOAuTlu(oi3%{NoJL%ZXrNH6$4Knuj-h4bq(_};{$?0KXUQ`ZdWwRNXd(w0wDBv5%x
z8szmO%JFx3iaaC#-b#DJV=ovn`b~HkGQD03e0Anql8H*1lJL+i`f(F2!(%aKpeh2=
z<5I5fSEYPJmnV5zo6xz)F!YVPDK~Hbb{)@aym_Vqw;YbM`NIV>
z;aKuO8Zm&qQtyP>pg8LnaRLEug&)H_umduz^AmiXn!Xd6qUs9{p14oRJJ(=a(f2qx
zZBF8;9k%i|#IAW^{Fo~yE;mW3avk4nqNTiSbNF})VXhleNSq7R&uVgkP(`?$2q$_i
z{bl(bs&lh;SH)SwyLLJ+?v8T;R?+p$ds^)@9q#Q`xkXQMc9oGo$O>SXX7|lRB$<6Y
zni!C*{WZPR`z5mMLQk{F_pDz*u4tdg+e_*k1vVhh?&e6CgETZhdY)#Ao88=TAbgK9
zz&zziB|gnxrtvT%!l^G9`4fM2ckPAD;j;RC^Wo@6_f9&U3A3v@pB9fTqo*
z9R&b_g4+OKP)$}9s%w+;vcZOySXkbkU&so`bOb(%0r)SEv0h4yU<4PwvQw_ii%QJ>
z2J-(;_dOV=|NW~e-;__mOlN7>^y42$iAp(c>c;eXgVM}4GW{of34u>3+-p}~L?~CD
zC)DUN4`s7qo*8Nq?(T{#
z5{sMuU_{%1d>@}RKz#HbBm^Rs{~Zgc8aiVyhqnt-i~*L!5HV(dZ5COqz5W5tcTCg+
zlmxLOy`IaZe&cT}A4(eh4?Gz|QaV_YuAVZwdp78xWQ^ZO^tqqZK7WDUtC_6~aXrBz
zplXe=C{2q*?~OyAwFT567C}A1FOmQYVn_j47(k3v$)xk!
zm^2*QH@UKJ@&vvIYVNW%G#LY#CyoLI01&}-(=w#;Z1R5;O=R#@Jg1iU2^`XMiQBh)
zoY@RV)z6(6y9}08$uDvQ=$;5x>+ldZ2*cKpN?hEdf}I%Oh?Fpi(F#&_7m=qx2w9>W
zF=s5C*O<(w*9a8*7#HaYu-&=bJCmW4@hzbLIX^?JR^&1%+kBBr@L1k~+~mdwe0o}7
zsE*+`VckSJ^q?oN%bB@o@ZOUB7D(Wr4BQsPag+Uq9pMV
zXkDU&Yc3UIlz==wUDo#L2;+u*)4s8NQGV4VN-0{DJuLpW`pZGY85xttXWbtj-*R#7Qt(%8osJ{Iuk
z0SCe=QUtPrY*>~G>mPB5LA#bsWhttX{@Ri;O3@%}@R~MX3KQUL_$o}t?)V$Ae?N|J
tEE&Z1?W{^NjPZL+`#^BY+|VAo;*WT>XVy{z;FLWGZ(w$zOwaz_{{d(CMc)7b
diff --git a/public/assets/icon/settings.svg b/public/assets/icon/settings.svg
new file mode 100644
index 0000000..39ab649
--- /dev/null
+++ b/public/assets/icon/settings.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/public/index.html b/public/index.html
index f4bfa4f..7050fe2 100644
--- a/public/index.html
+++ b/public/index.html
@@ -23,7 +23,6 @@
-
@@ -31,18 +30,167 @@
-
-
-
-
-
-
+
-
-
Settings Panel
-
+
+
+
+
+
+
+
SETTINGS
+
Changes are saved automatically.
Somes changes could need a restart
+
+
+
+
+
Basic Settings
+
+
+
+
+ Thème
+
+
+
+
Choose the theme of the application
+
+
+
+
+
+
+
+ Discord RPC
+ Enable/disable Discord Rich Presence for your app.
+
+
+
+
+
+
+ Download Playlist automatically?
+ If enabled, playlists will download without confirmation.
+
+
+
+
+
+
+
+
+ Custom Top bar
+ Use this if the topbar is missing or you prefer a custom one.
+
+
+
+
+
+
+ Auto Fetch Info
+ Automatically fetch information for new downloads.
+
+
+
+
+
+
+
+ Advanced Settings
+
+
+
+
+ Auto Update
+ Enable automatic app updates.
+
+
+
+
+
+
+
+
+ Add Metadata
+ Include metadata in downloaded files.
+
+
+
+
+
+
+ Add Thumbnail
+ Include thumbnails in downloaded files.
+
+
+
+
+
+ Custom Codec
+
+ Choose your preferred video codec.
+
+
+
+
+
+
+
+ Developer Settings
+
+
+
+
+
+
+
+
+ Verbose Logs
+ Show verbose logs for debugging purposes.
+
+
+
+
+
+
+
+
@@ -106,6 +254,9 @@
+
+
Because Why Not ?
+
diff --git a/public/script/settingsPanel.js b/public/script/settingsPanel.js
index 6868501..ae8f2f9 100644
--- a/public/script/settingsPanel.js
+++ b/public/script/settingsPanel.js
@@ -1,7 +1,50 @@
-const settingsButton = document.getElementById("settings-button")
-const settingsPanel = document.getElementById("settings-panel")
+const settingsPanel = document.getElementById("settings-panel");
+const settingsModal = document.querySelector(".settings-modal");
-function openPanel(){
- settingsPanel.style.display = "block";
- console.log("Click")
-}
\ No newline at end of file
+const settingsButton = document.getElementById("settings-button");
+
+let isOpen = false;
+
+settingsButton.addEventListener("click", () => {
+ const isOpen = settingsPanel.style.display === "block";
+ settingsPanel.style.display = isOpen ? "none" : "block";
+});
+
+function closePanel() {
+ isOpen = false;
+ settingsPanel.style.display = "none";
+}
+
+// charge les features
+async function loadSettings() {
+ const features = await window.electronAPI.getFeatures();
+
+ document.querySelectorAll(".settings-section input, .settings-section select").forEach(el => {
+ const key = el.dataset.key;
+ if (features[key] !== undefined) {
+ if (el.type === "checkbox") el.checked = features[key];
+ else if (el.tagName === "SELECT") el.value = features[key];
+ }
+
+ el.addEventListener("change", () => {
+ let value = el.type === "checkbox" ? el.checked : el.value;
+ window.electronAPI.setFeature(key, value);
+ });
+ });
+}
+
+// ouvrir le JSON
+document.getElementById("open-json-btn").addEventListener("click", () => {
+ window.topbarAPI.openConfig(); // ton IPC existant
+});
+
+
+/* clic sur l'overlay = fermer */
+settingsPanel.addEventListener("click", closePanel);
+
+/* clic dans la modal = stop propagation */
+settingsModal.addEventListener("click", (e) => {
+ e.stopPropagation();
+});
+
+loadSettings();
diff --git a/public/styles/layout/settingsPanel.css b/public/styles/layout/settingsPanel.css
index 59a234e..0fa7b3d 100644
--- a/public/styles/layout/settingsPanel.css
+++ b/public/styles/layout/settingsPanel.css
@@ -1,33 +1,234 @@
-.settings-button{
- display:flex;
- background-color: rgba(219, 219, 219, 0.89);
- border-radius: 12px;
- padding: 5px;
- transition: all ease-in-out 0.2s;
- position: absolute;
+/* SETTINGS BUTTON */
+.settings-button {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ position: fixed;
+ top: 60px;
+ right: 20px;
+ opacity: 0.8;
+ background-color: var(--settings-button-bg-color);
+ border-radius: 14px;
+ padding: 8px;
+ border: none;
+ box-shadow: 0 6px 16px rgba(0,0,0,0.25);
+ transition: transform 0.15s ease, box-shadow 0.15s ease;
+}
+
+.settings-button svg {
+ width: 40px;
+ height: 40px;
+ stroke: var(--settings-button-text-color);
+}
+
+.settings-button:hover {
+ transform: scale(1.1);
+ cursor: pointer;
+ box-shadow: 0 10px 24px rgba(0,0,0,0.35);
+}
+
+.settings-button:active {
+ transform: scale(0.95);
+}
+
+
+/* SETTINGS PANEL */
+.settings-panel {
+ position: fixed;
top: 60px;
right: 40px;
- border: none;
+ width: 40vw;
+ max-width: 320px;
+ max-height: 80vh;
+ background-color: var(--settings-bg-primary-color);
+ border-radius: 12px;
+ padding: 20px;
+ box-shadow: 0 8px 24px rgba(0,0,0,0.4);
+ display: none;
+ overflow-y: auto;
+ z-index: 9999;
+ animation: slideIn 0.2s ease-out;
+ color: var(--settings-text-color);
}
-.settings-button img{
- width: 50px;
- height: 50px;
+.settings-panel::-webkit-scrollbar {
+ width: 0px;
+ background: transparent;
}
-.settings-button:hover{
- transform: scale(1.2);
+.settings-modal {
+ width: 100%;
+ min-height: auto;
+ max-height: none;
+ padding: 0;
+ background: none;
+ box-shadow: none;
+ border-radius: none;
+
+}
+
+/* TITLE */
+.settings-title {
+ margin-bottom: 20px;
+}
+
+.settings-title h2 {
+ margin: 0;
+ font-size: 24px;
+}
+
+.settings-title p {
+ font-size: 14px;
+ color: #ccc;
+ margin-top: 4px;
+}
+
+/* SECTION */
+.settings-section {
+ display: flex;
+ flex-direction: column;
+ margin-bottom: 20px;
+ padding: 10px 15px;
+ background: var(--settings-bg-secondary-color);
+ border-radius: 12px;
+ gap: 6px;
+}
+
+.settings-section h3 {
+ margin: 0 0 10px 0;
+ font-size: 18px;
+}
+
+/* SETTING ITEM */
+.setting-item {
+ display: flex;
+ align-items: flex-start;
+ gap: 12px;
+ margin-bottom: 8px;
+ margin-top: 8px;
+}
+
+.setting-item input[type="checkbox"] {
+ margin: 0;
+ flex-shrink: 0;
+ width: 20px;
+ height: 20px;
+}
+
+.setting-info {
+ display: flex;
+ flex-direction: column;
+}
+
+.setting-title {
+ font-size: 14px;
+ font-weight: 500;
+}
+
+.setting-info small {
+ font-size: 12px;
+ color: var(--settings-subtitle-color);
+ margin-top: 2px;
+ font-style: italic;
+}
+
+#theme .settings-title{
+ display: flex;
+}
+
+.setting-item select {
+ width: 70%;
+ background: #fff;
+ border: 1px solid #242424;
+ border-radius: 6px;
+ padding: 4px 8px;
+ color: #000;
+ cursor: pointer;
+ font-weight: 600;
+ transition: background 0.3s ease, color 0.3s ease;
+}
+
+.setting-item select:hover,
+.setting-item select:focus {
+ background: #474747;
+ color: #fff;
+ outline: none;
+}
+
+/* SELECT */
+.settings-section select {
+ margin-left: 10px;
+}
+
+/* DETAILS / DROPDOWN */
+details {
+ margin-bottom: 20px;
+ padding: 10px 15px;
+ background: #2a2a2a;
+ border-radius: 12px;
+}
+
+details[open] {
+ box-shadow: 0 4px 15px rgba(0,0,0,0.3);
+}
+
+details summary {
cursor: pointer;
}
-.settings-button:active{
- transform: scale(0.9);
+/* FOOTER */
+.settings-footer {
+ margin-top: 20px;
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
}
-.settings-panel{
- position: absolute;
+#open-json-btn {
+ padding: 6px 12px;
+ border-radius: 8px;
+ border: none;
+ cursor: pointer;
+ font-weight: 600;
+ background-color: var(--form-button-bg-color);
+ color: #fff;
+}
+
+#experimental-args {
width: 100%;
- height: 100%;
- background-color: red;
- z-index: 9999999;
+ min-height: 80px;
+ background-color: #1e1e1e;
+ border-radius: 8px;
+ padding: 8px;
+ color: #fff;
+ border: 1px solid #333;
+ resize: vertical;
+}
+
+/* CLOSE BTN */
+.close-btn {
+ position: absolute;
+ top: 20px;
+ right: 20px;
+ background: none;
+ border: none;
+ color: white;
+ font-size: 24px;
+ cursor: pointer;
+ opacity: 0.6;
+}
+
+.close-btn:hover {
+ opacity: 1;
+}
+
+/* ANIMATION */
+@keyframes popIn {
+ from { transform: scale(0.95); opacity: 0; }
+ to { transform: scale(1); opacity: 1; }
+}
+
+@keyframes slideIn {
+ from { transform: translateX(20px); opacity: 0; }
+ to { transform: translateX(0); opacity: 1; }
}
\ No newline at end of file
diff --git a/public/styles/variables.css b/public/styles/variables.css
index cfbb85d..29362d3 100644
--- a/public/styles/variables.css
+++ b/public/styles/variables.css
@@ -33,4 +33,14 @@
--video-info-list-strong-color: #000000;
--video-info-link-color: #007bff;
--video-info-link-hover-color: #0056b3;
+
+ /* Settings */
+ --settings-button-bg-color: var(--form-bg-color);
+ --settings-button-text-color: var(--default-text-color);
+
+ --settings-bg-primary-color: var(--form-bg-color);
+ --settings-bg-secondary-color: var(--form-bg-color);
+ --settings-text-color: var(--default-text-color);
+ --settings-subtitle-color: #aaa;
+
}
From 8d070ed10d594dee81bd60136b6c6e4dbacd6fdd Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Tue, 20 Jan 2026 22:29:22 +0100
Subject: [PATCH 35/46] Fix: Neon Theme rename
---
public/script/customthemes.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/public/script/customthemes.js b/public/script/customthemes.js
index 34b5ec0..129a7e7 100644
--- a/public/script/customthemes.js
+++ b/public/script/customthemes.js
@@ -1,8 +1,7 @@
const themes = {
- default: { label: "Default", subtitle: "Because why not?" },
dark: { label: "Sombre", subtitle: "Darkness is my ally" },
light: { label: "Clair", subtitle: "Qui aime ce thème ?" },
- neon: { label: "Néon", subtitle: "How was your day ?"},
+ neon: { label: "Purple", subtitle: "How was your day ?"},
nf: { label: "NF", subtitle: "You call it music, i call it my Therapist" },
songbird: { label: "Songbird", subtitle: "From Her to Eternity" },
drift: { label: "Drift", subtitle: "Si la route t'appelle, contre appel" },
From ccb090e4b21e814b7d157974dc2ab038eb9c5af6 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Tue, 20 Jan 2026 22:29:56 +0100
Subject: [PATCH 36/46] Add: Settings theme color
---
public/styles/theme/chirac-theme.css | 10 ++++++++++
public/styles/theme/dark-theme.css | 10 ++++++++++
public/styles/theme/drift-theme.css | 12 +++++++++++-
public/styles/theme/fanatic-theme.css | 10 ++++++++++
public/styles/theme/light-theme.css | 9 +++++++++
public/styles/theme/neon-theme.css | 9 +++++++++
public/styles/theme/nf-theme.css | 9 +++++++++
public/styles/theme/songbird-theme.css | 9 +++++++++
public/styles/theme/spicy-theme.css | 11 +++++++++++
9 files changed, 88 insertions(+), 1 deletion(-)
diff --git a/public/styles/theme/chirac-theme.css b/public/styles/theme/chirac-theme.css
index daee9f3..2645be5 100644
--- a/public/styles/theme/chirac-theme.css
+++ b/public/styles/theme/chirac-theme.css
@@ -42,6 +42,16 @@ body.chirac {
/* Playlist Color */
--playlist-background-color: #d1d1d1ca;
+
+ /* Settings */
+ --settings-button-bg-color: #00196a;
+ --settings-button-text-color: #dcdcdc;
+
+ --settings-bg-primary-color: #0b0528;
+ --settings-bg-secondary-color: #1c1055;
+
+ --settings-text-color: #cecece;
+ --settings-subtitle-color: #adadad;
}
diff --git a/public/styles/theme/dark-theme.css b/public/styles/theme/dark-theme.css
index b259c33..e1bd48f 100644
--- a/public/styles/theme/dark-theme.css
+++ b/public/styles/theme/dark-theme.css
@@ -36,4 +36,14 @@ body.dark {
/* Playlist Color */
--playlist-background-color: #303030;
+
+ /* Settings */
+ --settings-button-bg-color: #1e1e1e;
+ --settings-button-text-color: var(--default-text-color);
+
+ --settings-bg-primary-color: #1e1e1e;
+ --settings-bg-secondary-color: #2a2a2a;
+ --settings-text-color: var(--default-text-color);
+ --settings-subtitle-color: #aaa;
+
}
diff --git a/public/styles/theme/drift-theme.css b/public/styles/theme/drift-theme.css
index 9d318a7..f55f365 100644
--- a/public/styles/theme/drift-theme.css
+++ b/public/styles/theme/drift-theme.css
@@ -42,7 +42,17 @@ body.drift {
/* Playlist Color */
--playlist-background-color: #424b5cc2;
- }
+
+ /* Settings */
+ --settings-button-bg-color: #1e222ace;
+ --settings-button-text-color: #b3b3b4;
+
+ --settings-bg-primary-color: #1e222a;
+ --settings-bg-secondary-color: #272d38;
+
+ --settings-text-color: #bababa;
+ --settings-subtitle-color: #cacaca;
+}
diff --git a/public/styles/theme/fanatic-theme.css b/public/styles/theme/fanatic-theme.css
index 3f8ff0c..401fd67 100644
--- a/public/styles/theme/fanatic-theme.css
+++ b/public/styles/theme/fanatic-theme.css
@@ -36,4 +36,14 @@ body.fanatic{
/* Playlist Color */
--playlist-background-color: #2b2b2b;
+
+ /* Settings */
+ --settings-button-bg-color: #1e1e1e;
+ --settings-button-text-color: #dcdcdc;
+
+ --settings-bg-primary-color: #1e1e1e;
+ --settings-bg-secondary-color: #2d2d2d;
+
+ --settings-text-color: #cecece;
+ --settings-subtitle-color: #adadad;
}
diff --git a/public/styles/theme/light-theme.css b/public/styles/theme/light-theme.css
index 862f47d..4b1d2b1 100644
--- a/public/styles/theme/light-theme.css
+++ b/public/styles/theme/light-theme.css
@@ -36,4 +36,13 @@ body.light {
/* Playlist Color */
--playlist-background-color: #c5c5c5b2;
+
+ /* Settings */
+ --settings-button-bg-color: #e4e4e4;
+ --settings-button-text-color: var(--default-text-color);
+
+ --settings-bg-primary-color: #cbcbcb;
+ --settings-bg-secondary-color: #cbcbcb;
+ --settings-text-color: var(--default-text-color);
+ --settings-subtitle-color: #656565;
}
diff --git a/public/styles/theme/neon-theme.css b/public/styles/theme/neon-theme.css
index 987cd83..63c87da 100644
--- a/public/styles/theme/neon-theme.css
+++ b/public/styles/theme/neon-theme.css
@@ -43,6 +43,15 @@ body.neon {
/* Playlist Color */
--playlist-background-color: #3e3e64;
+
+ /* Settings */
+ --settings-button-bg-color: #202038;
+ --settings-button-text-color: var(--default-text-color);
+
+ --settings-bg-primary-color: #242454;
+ --settings-bg-secondary-color: #2f2f6f;
+ --settings-text-color: var(--default-text-color);
+ --settings-subtitle-color: #d2d2d2;
}
body.neon .download-path {
diff --git a/public/styles/theme/nf-theme.css b/public/styles/theme/nf-theme.css
index 65b086a..5b7ac42 100644
--- a/public/styles/theme/nf-theme.css
+++ b/public/styles/theme/nf-theme.css
@@ -42,6 +42,15 @@ body.nf {
/* Playlist Color */
--playlist-background-color: #4f4f4f;
+
+ /* Settings */
+ --settings-button-bg-color: #2a2a2a;
+ --settings-button-text-color: var(--default-text-color);
+
+ --settings-bg-primary-color: #2a2a2a;
+ --settings-bg-secondary-color: #313131;
+ --settings-text-color: var(--default-text-color);
+ --settings-subtitle-color: #7a7979;
}
body.nf .download-path {
diff --git a/public/styles/theme/songbird-theme.css b/public/styles/theme/songbird-theme.css
index 3eaaab3..976d0cc 100644
--- a/public/styles/theme/songbird-theme.css
+++ b/public/styles/theme/songbird-theme.css
@@ -42,6 +42,15 @@ body.songbird {
/* Playlist Color */
--playlist-background-color: #3f0000;
+
+ /* Settings */
+ --settings-button-bg-color: rgba(29, 0, 0, 0.784);
+ --settings-button-text-color: var(--default-text-color);
+
+ --settings-bg-primary-color: #121212;
+ --settings-bg-secondary-color: #1a1a1a;
+ --settings-text-color: var(--default-text-color);
+ --settings-subtitle-color: #7a7979;
}
body.cyberpunk .download-path {
diff --git a/public/styles/theme/spicy-theme.css b/public/styles/theme/spicy-theme.css
index 3866a59..a001407 100644
--- a/public/styles/theme/spicy-theme.css
+++ b/public/styles/theme/spicy-theme.css
@@ -36,6 +36,17 @@ body.spicy {
/* Playlist Color */
--playlist-background-color: #353232;
+
+ /* Settings */
+ --settings-button-bg-color: #1a1a1a;
+ --settings-button-text-color: #dcdcdc;
+
+ --settings-bg-primary-color: #1a1a1a;
+ --settings-bg-secondary-color: #292929;
+
+ --settings-text-color: #cecece;
+ --settings-subtitle-color: #adadad;
+
}
/* Optionnel: background piments */
From caa987fa42d26244942102bf9ca0ed3d2dbc5f2a Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Tue, 20 Jan 2026 22:30:22 +0100
Subject: [PATCH 37/46] Fix: Remove unusued files
---
public/styles/components/themebutton.css | 38 ---------------------
public/styles/theme/default-theme.css | 43 ------------------------
public/styles/theme/themeimport.css | 1 -
3 files changed, 82 deletions(-)
delete mode 100644 public/styles/components/themebutton.css
delete mode 100644 public/styles/theme/default-theme.css
diff --git a/public/styles/components/themebutton.css b/public/styles/components/themebutton.css
deleted file mode 100644
index 3031696..0000000
--- a/public/styles/components/themebutton.css
+++ /dev/null
@@ -1,38 +0,0 @@
-.theme-switcher {
- position: absolute;
- top: 60px;
- right: 10px;
- background: #242424;
- padding: 8px 12px;
- border-radius: 8px;
- color: #fff;
- font-family: sans-serif;
- font-size: 0.9rem;
- display: flex;
- align-items: center;
- gap: 8px;
- z-index: 1050;
-}
-
-.theme-switcher label {
- cursor: pointer;
- font-weight: 600;
-}
-
-.theme-switcher select {
- background: #fff;
- border: 1px solid #242424;
- border-radius: 6px;
- padding: 4px 8px;
- color: #000;
- cursor: pointer;
- font-weight: 600;
- transition: background 0.3s ease, color 0.3s ease;
-}
-
-.theme-switcher select:hover,
-.theme-switcher select:focus {
- background: #474747;
- color: #fff;
- outline: none;
-}
diff --git a/public/styles/theme/default-theme.css b/public/styles/theme/default-theme.css
deleted file mode 100644
index 6694dc1..0000000
--- a/public/styles/theme/default-theme.css
+++ /dev/null
@@ -1,43 +0,0 @@
-:root {
- /* Couleurs générales */
- --background-color: #001224; /* body background bleu nuit */
- --default-text-color: #eee; /* texte clair principal */
- --subtitle-color: #007bff; /* sous-titres, header p */
- --mp3-text-color: #000000; /* couleur texte checkbox inline */
-
- /* Formulaire */
- --form-bg-color: #ffffff; /* fond du formulaire */
- --form-input-bg-color: #f9f9f9; /* fond inputs */
- --form-input-border-color: #cccccc; /* bordure inputs */
- --form-input-border-focus-color: #0056b3; /* bordure focus */
- --form-input-text-color: #333333; /* texte inputs */
- --form-input-placeholder-color: #aaaaaa; /* placeholder */
- --form-button-bg-color: #007bff; /* bouton bg */
- --form-button-text-color: #ffffff; /* texte bouton */
- --form-button-bg-hover-color: #0056b3; /* bouton hover */
-
- /* Checkbox */
- --checkbox-bg-default: #cccccc;
- --checkbox-bg-checked: #3B82F6;
- --checkbox-checkmark-border-color: #E0E0E2;
- --checkbox-pulse-color: rgba(59, 130, 246, 0.5);
-
- /* Download status */
- --download-status-color: #007bff;
-
- /* Video Info Box */
- --infos-box-color: #0c0140;
- --video-info-text-color: #ffffff;
- --video-info-heading-color: #007bff;
- --video-info-list-color: #cccccc;
- --video-info-list-strong-color: #e6e6e6;
- --video-info-link-color: #007bff;
- --video-info-link-hover-color: #0056b3;
-
- /* Playlist Color */
- --playlist-background-color: #070823a3;
-}
-
-body.default .download-path #savePath {
- color: #ffffff;
-}
\ No newline at end of file
diff --git a/public/styles/theme/themeimport.css b/public/styles/theme/themeimport.css
index eb320a6..7de5d07 100644
--- a/public/styles/theme/themeimport.css
+++ b/public/styles/theme/themeimport.css
@@ -1,6 +1,5 @@
@import url("chirac-theme.css");
@import url("dark-theme.css");
-@import url("default-theme.css");
@import url("fanatic-theme.css");
@import url("light-theme.css");
@import url("nf-theme.css");
From 26c7d4d2ee66d7dc27a38e8204760993f8e84f9d Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Tue, 20 Jan 2026 22:30:41 +0100
Subject: [PATCH 38/46] Because why not ?
---
public/styles/styles.css | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/public/styles/styles.css b/public/styles/styles.css
index 06bab5a..25cfbea 100644
--- a/public/styles/styles.css
+++ b/public/styles/styles.css
@@ -50,6 +50,16 @@ body {
}
+/* Because why not */
+#reference{
+ position: absolute;
+ pointer-events: none;
+ bottom: 0;
+ left: 10px;
+ font-size: 1em;
+ color: #b0b0b02f;
+}
+
/* Scrollbar globale pour Chromium/Electron */
body::-webkit-scrollbar {
width: 10px;
From 590060e50480627eb2064cf15f0bc2ec9132a50e Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Tue, 20 Jan 2026 22:34:33 +0100
Subject: [PATCH 39/46] Fix: Reference position bottom
---
public/styles/styles.css | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/public/styles/styles.css b/public/styles/styles.css
index 25cfbea..0b606e7 100644
--- a/public/styles/styles.css
+++ b/public/styles/styles.css
@@ -52,9 +52,9 @@ body {
/* Because why not */
#reference{
- position: absolute;
+ position: fixed;
pointer-events: none;
- bottom: 0;
+ bottom:0vh;
left: 10px;
font-size: 1em;
color: #b0b0b02f;
From cd8eb050206738498f08aca8ee790840156f75ba Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Wed, 21 Jan 2026 11:08:20 +0100
Subject: [PATCH 40/46] Fix: Remove Unusued Import
---
public/styles/styles.css | 1 -
1 file changed, 1 deletion(-)
diff --git a/public/styles/styles.css b/public/styles/styles.css
index 0b606e7..2a4aa3e 100644
--- a/public/styles/styles.css
+++ b/public/styles/styles.css
@@ -7,7 +7,6 @@
/* Components */
@import url("components/checkbox.css");
-@import url("components/themebutton.css");
@import url("components/loader.css");
@import url("theme/themeimport.css");
From 967144bd55ff7bc50a1340f2b63b305bc1ae7301 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Wed, 21 Jan 2026 11:08:42 +0100
Subject: [PATCH 41/46] Fix: Config not working propely
---
config/config.json | 2 --
main.js | 51 +++++++++++++++++++++++++++++++++++-----------
2 files changed, 39 insertions(+), 14 deletions(-)
diff --git a/config/config.json b/config/config.json
index 2fd13e9..d73ef86 100644
--- a/config/config.json
+++ b/config/config.json
@@ -8,8 +8,6 @@
"verboseLogs": false,
"autoDownloadPlaylist": true,
"customCodec": "h264",
-
-
"logSystem": true,
"outputTitleCheck": true,
"downloadSystem": true,
diff --git a/main.js b/main.js
index 1dced18..e8a3a07 100644
--- a/main.js
+++ b/main.js
@@ -204,22 +204,49 @@ app.whenReady().then(async () => {
ipcMain.handle("features", () => {
return configFeatures;
});
+
+ const featureWhitelist = new Set([
+ "autoUpdate",
+ "discordRPC",
+ "customTopBar",
+ "autoCheckInfo",
+ "addThumbnail",
+ "addMetadata",
+ "verboseLogs",
+ "autoDownloadPlaylist",
+ "customCodec"
+ ]);
+
ipcMain.handle("set-feature", (event, { key, value }) => {
- try {
- // update mémoire
- configFeatures[key] = value;
+ try {
+ if (!featureWhitelist.has(key)) {
+ logger.warn(`Rejected feature (not whitelisted): ${key}`);
+ return false;
+ }
- // écriture directe sur le JSON
- fs.writeFileSync(configFolderPath, JSON.stringify(configFeatures, null, 2), "utf-8");
+ // optionnel mais propre
+ if (configFeatures[key] === value) {
+ return true;
+ }
+
+ configFeatures[key] = value;
+
+ fs.writeFileSync(
+ configFolderPath,
+ JSON.stringify(configFeatures, null, 2),
+ "utf-8"
+ );
+
+ logger.info(`Feature updated: ${key} = ${value}`);
+ return true;
+
+ } catch (err) {
+ logger.error(`set-feature failed (${key}): ${err.message}`);
+ return false;
+ }
+ });
- logger.info(`Feature updated: ${key} = ${value}`);
- return true;
- } catch (err) {
- logger.error(`set-feature failed (${key}): ${err.message}`);
- return false;
- }
- });
configFeatures.discordRPC ? startRPC() : "";
From fd8c4ae33cebe627e6c9d3ef10f8ba4a503d2b25 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Wed, 21 Jan 2026 11:16:53 +0100
Subject: [PATCH 42/46] Fix: Check Info config every request
---
public/script/fetchinfo.js | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/public/script/fetchinfo.js b/public/script/fetchinfo.js
index 9db3040..af9c9b7 100644
--- a/public/script/fetchinfo.js
+++ b/public/script/fetchinfo.js
@@ -25,10 +25,9 @@ async function fetchVideoInfo(url) {
return { error: "Network or JSON Issue" };
}
}
-async function init() {
- const configFeatures = await window.electronAPI.getFeatures();
- if (!configFeatures.autoCheckInfo) return;
+
+async function init() {
document.addEventListener("DOMContentLoaded", () => {
const urlInput = document.getElementById("UrlInput");
@@ -38,6 +37,10 @@ async function init() {
let lastFetchedUrl = "";
urlInput.addEventListener("input", async () => {
+
+ const configFeatures = await window.electronAPI.getFeatures();
+ if (!configFeatures.autoCheckInfo) return;
+
const url = urlInput.value.trim();
// Si champ vide -> reset total
From 9824e107fe25d8b4133b35b9d3afaff632a94643 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Wed, 21 Jan 2026 13:29:33 +0100
Subject: [PATCH 43/46] Fix: Try to force AAC Audio Codec
---
server/helpers/buildArgs.js | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/server/helpers/buildArgs.js b/server/helpers/buildArgs.js
index 011cb8a..bdabf95 100644
--- a/server/helpers/buildArgs.js
+++ b/server/helpers/buildArgs.js
@@ -56,7 +56,9 @@ function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) {
"--ffmpeg-location", ffmpegPath,
"--extractor-args","youtube:player_client=default",
"--js-runtimes", `deno:${denoPath}`,
- "-S", `vcodec:${validateCodec(configFeatures.customCodec) || "h264"}`,
+ "-S",
+ `vcodec:${validateCodec(configFeatures.customCodec) || "h264"}`+
+ `,acodec:aac`,
configFeatures.autoDownloadPlaylist ? "--yes-playlist" : "--no-playlist"
];
From d3755ab57d60626ffca28633ec5a630ff06a0e04 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Wed, 21 Jan 2026 20:25:34 +0100
Subject: [PATCH 44/46] Fix: Remove unusued "Settings.svg" icon
---
public/assets/icon/settings.svg | 2 --
1 file changed, 2 deletions(-)
delete mode 100644 public/assets/icon/settings.svg
diff --git a/public/assets/icon/settings.svg b/public/assets/icon/settings.svg
deleted file mode 100644
index 39ab649..0000000
--- a/public/assets/icon/settings.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
From 2a3905bdfbeb7170508bd1499cc4c69aada33ac7 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Wed, 21 Jan 2026 20:43:15 +0100
Subject: [PATCH 45/46] Add: Video Codec
---
public/index.html | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/public/index.html b/public/index.html
index 7050fe2..2304b0d 100644
--- a/public/index.html
+++ b/public/index.html
@@ -147,8 +147,12 @@
Custom Codec
Choose your preferred video codec.
From 29ca2ea4962dd133d4b9899880d3b68206488ae8 Mon Sep 17 00:00:00 2001
From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com>
Date: Thu, 22 Jan 2026 21:39:07 +0100
Subject: [PATCH 46/46] Fix: Auto Update mispelling (Am a monkey)
---
main.js | 2 +-
server/update.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/main.js b/main.js
index e8a3a07..3bc0439 100644
--- a/main.js
+++ b/main.js
@@ -251,7 +251,7 @@ app.whenReady().then(async () => {
configFeatures.discordRPC ? startRPC() : "";
await createMainWindow();
- configFeatures.AutoUpdater ? AutoUpdater(mainWindow) : ""; // Auto Update
+ configFeatures.autoUpdate ? AutoUpdater(mainWindow) : ""; // Auto Update
} catch (err) {
logger.error("Window or Server error :", err);
diff --git a/server/update.js b/server/update.js
index a21908e..d38aa70 100644
--- a/server/update.js
+++ b/server/update.js
@@ -1,5 +1,5 @@
const { autoUpdater } = require("electron-updater");
-const { app, Notification } = require("electron");
+const { app, Notification, shell} = require("electron");
const { logger } = require("./logger");
function AutoUpdater() {