mirror of
https://github.com/MasterAcnolo/Freedom-Loader.git
synced 2026-07-29 18:25:47 +02:00
Removed Cyberpunk | Spicy | Vilbrequin Theme, Info Fix, Fix Progress Bar. Centralized Ressources
This commit is contained in:
@@ -1,25 +0,0 @@
|
||||
const { FusesPlugin } = require('@electron-forge/plugin-fuses');
|
||||
const { FuseV1Options, FuseVersion } = require('@electron/fuses');
|
||||
|
||||
module.exports = {
|
||||
packagerConfig: { asar: true },
|
||||
rebuildConfig: {},
|
||||
makers: [
|
||||
{
|
||||
name: '@electron-forge/maker-squirrel',
|
||||
config: {},
|
||||
},
|
||||
],
|
||||
plugins: [
|
||||
{ name: '@electron-forge/plugin-auto-unpack-natives', config: {} },
|
||||
new FusesPlugin({
|
||||
version: FuseVersion.V1,
|
||||
[FuseV1Options.RunAsNode]: false,
|
||||
[FuseV1Options.EnableCookieEncryption]: true,
|
||||
[FuseV1Options.EnableNodeOptionsEnvironmentVariable]: false,
|
||||
[FuseV1Options.EnableNodeCliInspectArguments]: false,
|
||||
[FuseV1Options.EnableEmbeddedAsarIntegrityValidation]: true,
|
||||
[FuseV1Options.OnlyLoadAppFromAsar]: true,
|
||||
}),
|
||||
],
|
||||
};
|
||||
6
main.js
6
main.js
@@ -20,7 +20,7 @@ if (!gotLock) {
|
||||
});
|
||||
}
|
||||
|
||||
app.disableHardwareAcceleration(); // safe sur GPU old / soucis Electron
|
||||
app.disableHardwareAcceleration();
|
||||
|
||||
const logsFolderPath = logDir;
|
||||
const defaultDownloadPath = path.join(os.homedir(), "Downloads", "Freedom Loader");
|
||||
@@ -110,7 +110,9 @@ app.whenReady().then(async () => {
|
||||
logSessionStart();
|
||||
logger.info("App prête, démarrage du serveur Express...");
|
||||
|
||||
const expressServer = require("./server/server.js");
|
||||
const serverPath = path.join(__dirname, "server", "server.js");
|
||||
const expressServer = require(serverPath);
|
||||
|
||||
try {
|
||||
await expressServer.startServer();
|
||||
logger.info("Serveur Express démarré");
|
||||
|
||||
4771
package-lock.json
generated
4771
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
19
package.json
19
package.json
@@ -6,7 +6,7 @@
|
||||
"description": "Freedom Loader",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"start": "electron-forge start",
|
||||
"start": "electron .",
|
||||
"dist": "electron-builder"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -16,18 +16,11 @@
|
||||
"electron-squirrel-startup": "^1.0.1",
|
||||
"electron-updater": "^6.6.2",
|
||||
"express": "^5.1.0",
|
||||
"webidl-conversions": "^8.0.0",
|
||||
"winston": "^3.17.0",
|
||||
"winston-daily-rotate-file": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron-forge/cli": "^7.8.1",
|
||||
"@electron-forge/maker-deb": "^7.8.1",
|
||||
"@electron-forge/maker-rpm": "^7.8.1",
|
||||
"@electron-forge/maker-squirrel": "^7.8.1",
|
||||
"@electron-forge/maker-zip": "^7.8.1",
|
||||
"@electron-forge/plugin-auto-unpack-natives": "^7.8.1",
|
||||
"@electron-forge/plugin-fuses": "^7.8.1",
|
||||
"@electron/fuses": "^1.8.0",
|
||||
"electron": "^37.1.0",
|
||||
"electron-builder": "^26.0.12"
|
||||
},
|
||||
@@ -44,7 +37,9 @@
|
||||
"files": [
|
||||
"**/*",
|
||||
"node_modules/**/*",
|
||||
"!logs/*.json"
|
||||
"!logs/*.json",
|
||||
"server/**/*",
|
||||
"server/node_modules/**/*"
|
||||
],
|
||||
"directories": {
|
||||
"buildResources": "build"
|
||||
@@ -70,6 +65,10 @@
|
||||
{
|
||||
"from": "ressources/ffprobe.exe",
|
||||
"to": "ffprobe.exe"
|
||||
},
|
||||
{
|
||||
"from": "server",
|
||||
"to": "server"
|
||||
}
|
||||
],
|
||||
"win": {
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 805 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 28 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
@@ -1,6 +1,3 @@
|
||||
|
||||
// Définition des thèmes disponibles
|
||||
// Chaque thème a un label (affiché dans le select) et un subtitle (texte sous le titre)
|
||||
const themes = {
|
||||
default: { label: "Default", subtitle: "Because why not?" },
|
||||
dark: { label: "Sombre", subtitle: "Darkness is my ally" },
|
||||
@@ -9,16 +6,11 @@ const themes = {
|
||||
nf: { label: "NF", subtitle: "You call it music, i call it my Therapist" },
|
||||
drift: { label: "Drift", subtitle: "Si la route t'appelle, contre appel" },
|
||||
fanatic: { label: "Fanatic", subtitle: "Always Fnatic !" },
|
||||
cyberpunk: { label: "Cyberpunk", subtitle: "Wake up, choom. We’ve got a city to burn." },
|
||||
chirac: { label: "Chirac", subtitle: "J'aime les pommes" },
|
||||
spicy: { label: "Spicy", subtitle: "The Spiciest One" },
|
||||
vilbrequin: { label: "Vilbrequin", subtitle: "Rend l'argent" }
|
||||
};
|
||||
|
||||
|
||||
const themeSelect = document.getElementById("themeSelect");
|
||||
|
||||
// Remplir le select avec les options à partir du dictionnaire
|
||||
function populateThemeSelect() {
|
||||
for (const [themeKey, themeInfo] of Object.entries(themes)) {
|
||||
const option = document.createElement("option");
|
||||
@@ -28,14 +20,10 @@ function populateThemeSelect() {
|
||||
}
|
||||
}
|
||||
|
||||
// Appliquer un thème sur le body et mettre à jour le subtitle
|
||||
function applyTheme(themeKey) {
|
||||
// Supprimer les classes de tous les thèmes
|
||||
document.body.classList.remove(...Object.keys(themes));
|
||||
// Ajouter la classe correspondant au thème sélectionné
|
||||
document.body.classList.add(themeKey);
|
||||
|
||||
// Mettre à jour le subtitle
|
||||
const subtitleElement = document.getElementById("subtitle");
|
||||
if (subtitleElement && themes[themeKey]) {
|
||||
subtitleElement.textContent = themes[themeKey].subtitle;
|
||||
@@ -43,12 +31,10 @@ function applyTheme(themeKey) {
|
||||
|
||||
}
|
||||
|
||||
// Sauvegarder le thème choisi dans le navigateur
|
||||
function saveTheme(themeKey) {
|
||||
localStorage.setItem("selectedTheme", themeKey);
|
||||
}
|
||||
|
||||
// Charger le thème sauvegardé au démarrage
|
||||
function loadTheme() {
|
||||
const savedTheme = localStorage.getItem("selectedTheme");
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ form.addEventListener("submit", async (e) => {
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
statusDiv.textContent = "❌ Erreur pendant le téléchargement.";
|
||||
statusDiv.textContent = res;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,14 +16,27 @@ function resetProgress() {
|
||||
progressWrapper.style.display = "none";
|
||||
}
|
||||
|
||||
function resetProgressFile() {
|
||||
progressBar.style.width = "0%";
|
||||
// progressWrapper reste visible
|
||||
}
|
||||
|
||||
// Connexion SSE, c'est Server-sent events est une technologie grâce à laquelle un navigateur reçoit des mises à jour automatiques à partir d'un serveur via une connexion HTTP.
|
||||
const evtSource = new EventSource("/download/progress");
|
||||
evtSource.onmessage = e => {
|
||||
if (e.data === "reset") {
|
||||
startProgress();
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.data === "done") {
|
||||
resetProgress();
|
||||
return;
|
||||
}
|
||||
|
||||
const percent = parseFloat(e.data);
|
||||
if (!isNaN(percent)) {
|
||||
updateProgress(percent);
|
||||
if (percent >= 100) {
|
||||
setTimeout(resetProgress, 500);
|
||||
}
|
||||
if (percent >= 100) setTimeout(resetProgressFile, 500);
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -1,43 +0,0 @@
|
||||
body.cyberpunk {
|
||||
|
||||
background-image: url('../../assets/images/Cyberpunk.webp');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
|
||||
/* Couleurs générales */
|
||||
--background-color: #0d0d0d;
|
||||
--default-text-color: #e0e0e0;
|
||||
--subtitle-color: #ffea00;
|
||||
--mp3-text-color: #ffea00;
|
||||
|
||||
/* Formulaire */
|
||||
--form-bg-color: #141414;
|
||||
--form-input-bg-color: #1a1a1a;
|
||||
--form-input-border-color: #333333;
|
||||
--form-input-border-focus-color: #ffea00;
|
||||
--form-input-text-color: #e0e0e0;
|
||||
--form-input-placeholder-color: #777777;
|
||||
--form-button-bg-color: #ffea00;
|
||||
--form-button-text-color: #0d0d0d;
|
||||
--form-button-bg-hover-color: #d4c000;
|
||||
|
||||
/* Checkbox */
|
||||
--checkbox-bg-default: #333333;
|
||||
--checkbox-bg-checked: #ffea00;
|
||||
--checkbox-checkmark-border-color: #0d0d0d;
|
||||
--checkbox-pulse-color: rgba(255, 234, 0, 0.5);
|
||||
|
||||
/* Download status */
|
||||
--download-status-color: #fffbd1;
|
||||
|
||||
/* Video Info Box */
|
||||
--infos-box-color: #1a1a1a;
|
||||
--video-info-text-color: #e0e0e0;
|
||||
--video-info-heading-color: #ffea00;
|
||||
--video-info-list-color: #cccccc;
|
||||
--video-info-list-strong-color: #ffffff;
|
||||
--video-info-link-color: #ffea00;
|
||||
--video-info-link-hover-color: #d4c000;
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
body.spicy {
|
||||
|
||||
background-image: url('../../assets/images/spicy.webp');
|
||||
background-size:contain;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
background-repeat: no-repeat;
|
||||
|
||||
/* Couleurs générales */
|
||||
--background-color: #121212;
|
||||
--default-text-color: #581010;
|
||||
--subtitle-color: #3d0909;
|
||||
--mp3-text-color: #ffffff;
|
||||
|
||||
/* Formulaire */
|
||||
--form-bg-color: #1a1a1a;
|
||||
--form-input-bg-color: #2b2b2b;
|
||||
--form-input-border-color: #444444;
|
||||
--form-input-border-focus-color: #ff1a1a;
|
||||
--form-input-text-color: #eeeeee;
|
||||
--form-input-placeholder-color: #888888;
|
||||
--form-button-bg-color: #ff1a1a;
|
||||
--form-button-text-color: #ffffff;
|
||||
--form-button-bg-hover-color: #cc0000;
|
||||
|
||||
/* Checkbox */
|
||||
--checkbox-bg-default: #555555;
|
||||
--checkbox-bg-checked: #ff1a1a;
|
||||
--checkbox-checkmark-border-color: #f5f5f5;
|
||||
--checkbox-pulse-color: rgba(255, 26, 26, 0.5);
|
||||
|
||||
/* Download status */
|
||||
--download-status-color: #ffffff;
|
||||
|
||||
/* Video Info Box */
|
||||
--infos-box-color: #1a1a1a;
|
||||
--video-info-text-color: #f5f5f5;
|
||||
--video-info-heading-color: #ff1a1a;
|
||||
--video-info-list-color: #cccccc;
|
||||
--video-info-list-strong-color: #ffffff;
|
||||
--video-info-link-color: #ff1a1a;
|
||||
--video-info-link-hover-color: #cc0000;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
body.vilbrequin {
|
||||
|
||||
background-image: url('../../assets/images/Vilbrequin.webp');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
|
||||
/* Couleurs générales */
|
||||
--background-color: #0a1f3d;
|
||||
--default-text-color: #535353;
|
||||
--subtitle-color: #001696;
|
||||
--mp3-text-color: #ffffff;
|
||||
|
||||
/* Formulaire */
|
||||
--form-bg-color: #12284f;
|
||||
--form-input-bg-color: #1c3760;
|
||||
--form-input-border-color: #2a4b80;
|
||||
--form-input-border-focus-color: #00bfff;
|
||||
--form-input-text-color: #f0f0f0;
|
||||
--form-input-placeholder-color: #b0c4de;
|
||||
--form-button-bg-color: #ffd700;
|
||||
--form-button-text-color: #0a1f3d;
|
||||
--form-button-bg-hover-color: #e6c200;
|
||||
|
||||
/* Checkbox */
|
||||
--checkbox-bg-default: #2a4b80;
|
||||
--checkbox-bg-checked: #00bfff;
|
||||
--checkbox-checkmark-border-color: #f0f0f0;
|
||||
--checkbox-pulse-color: rgba(0,191,255,0.5);
|
||||
|
||||
/* Download status */
|
||||
--download-status-color: #ffd700;
|
||||
|
||||
/* Video Info Box */
|
||||
--infos-box-color: #12284f;
|
||||
--video-info-text-color: #f0f0f0;
|
||||
--video-info-heading-color: #00bfff;
|
||||
--video-info-list-color: #dcdcdc;
|
||||
--video-info-list-strong-color: #ffffff;
|
||||
--video-info-link-color: #00bfff;
|
||||
--video-info-link-hover-color: #009acd;
|
||||
}
|
||||
|
||||
body.vilbrequin .download-path{
|
||||
color: white;
|
||||
}
|
||||
@@ -4,15 +4,20 @@ const { app } = require("electron");
|
||||
const config = require("../../config");
|
||||
|
||||
let userYtDlp;
|
||||
let ffmpegPath;
|
||||
|
||||
const sourceYtDlp = path.join(process.resourcesPath, "yt-dlp.exe");
|
||||
|
||||
if (config.localMode === true) {
|
||||
|
||||
userYtDlp = path.join(__dirname, "../../ressources/yt-dlp.exe");
|
||||
if (config.localMode) {
|
||||
userYtDlp = path.join(__dirname, "../../ressources/yt-dlp.exe");
|
||||
ffmpegPath = path.join(__dirname, "../../ressources/ffmpeg.exe");
|
||||
} else {
|
||||
userYtDlp = path.join(app.getPath("userData"), "yt-dlp.exe");
|
||||
ffmpegPath = path.join(process.resourcesPath, "ffmpeg.exe");
|
||||
|
||||
userYtDlp = path.join(app.getPath("userData"), "yt-dlp.exe");
|
||||
if (!fs.existsSync(userYtDlp)) fs.copyFileSync(sourceYtDlp, userYtDlp);
|
||||
if (!fs.existsSync(userYtDlp)) {
|
||||
fs.copyFileSync(sourceYtDlp, userYtDlp);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { userYtDlp, sourceYtDlp };
|
||||
module.exports = { userYtDlp, sourceYtDlp, ffmpegPath };
|
||||
|
||||
@@ -9,7 +9,6 @@ const config = require("../../config");
|
||||
const { isValidUrl, isSafePath } = require("../helpers/validation");
|
||||
const { buildYtDlpArgs } = require("../helpers/buildArgs");
|
||||
const { notifyDownloadFinished } = require("../helpers/notify");
|
||||
|
||||
const { userYtDlp } = require("../helpers/path");
|
||||
|
||||
const listeners = [];
|
||||
@@ -23,43 +22,62 @@ router.post("/", (req, res) => {
|
||||
outputFolder: req.body.savePath || path.join(process.env.USERPROFILE, "Downloads", "Freedom Loader"),
|
||||
};
|
||||
|
||||
// Vérifications
|
||||
if (!options.url || !isValidUrl(options.url)) return res.status(400).send("❌ URL invalide !");
|
||||
|
||||
if (!isSafePath(options.outputFolder)) return res.status(400).send("❌ Chemin de sauvegarde non autorisé.");
|
||||
|
||||
// Création dossier si inexistant
|
||||
fs.mkdirSync(options.outputFolder, { recursive: true });
|
||||
|
||||
// Construire les arguments yt-dlp
|
||||
const args = buildYtDlpArgs(options);
|
||||
logger.info(args)
|
||||
logger.info(`[yt-dlp args] ${args.join(" ")}`);
|
||||
|
||||
const child = execFile(userYtDlp, args);
|
||||
|
||||
|
||||
// Gestion erreurs
|
||||
child.on("error", err => {
|
||||
logger.error(`Erreur yt-dlp : ${err.message}`);
|
||||
res.status(500).send(`❌ Erreur yt-dlp : ${err.message}`);
|
||||
});
|
||||
|
||||
// Téléchargement terminé
|
||||
child.on("close", code => {
|
||||
if (code === 0) {
|
||||
notifyDownloadFinished(options.outputFolder);
|
||||
|
||||
// signal SSE fin de playlist
|
||||
listeners.forEach(fn => fn("done"));
|
||||
|
||||
res.send("✅ Téléchargement terminé !");
|
||||
} else res.status(500).send(`❌ yt-dlp a échoué avec le code : ${code}`);
|
||||
} else {
|
||||
res.status(500).send(`❌ yt-dlp a échoué avec le code : ${code}`);
|
||||
listeners.forEach(fn => fn("done"));
|
||||
}
|
||||
});
|
||||
|
||||
if (config.debugMode == true) {
|
||||
child.stdout.on("data", data => data.toString().split("\n").forEach(line => line.trim() && logger.info(`[yt-dlp stdout] ${line}`)));
|
||||
child.stderr.on("data", data => data.toString().split("\n").forEach(line => line.trim() && logger.error(`[yt-dlp stderr] ${line}`)));
|
||||
}
|
||||
child.stdout.on("data", data => {
|
||||
data.toString().split("\n").forEach(line => line.trim() && logger.info(`[yt-dlp stdout] ${line}`));
|
||||
});
|
||||
|
||||
child.stderr.on("data", data => {
|
||||
data.toString().split("\n").forEach(line => line.trim() && logger.error(`[yt-dlp stderr] ${line}`));
|
||||
});
|
||||
|
||||
|
||||
child.stdout.on("data", data => {
|
||||
const lines = data.toString().split("\n");
|
||||
lines.forEach(line => {
|
||||
// reset progress si nouveau fichier
|
||||
if (line.startsWith("[download] Destination:")) {
|
||||
listeners.forEach(fn => fn("reset")); // tu peux envoyer un signal spécial
|
||||
}
|
||||
|
||||
// envoyer le % classique
|
||||
const match = line.match(/\[download\]\s+(\d+\.\d+)%/);
|
||||
if (match) {
|
||||
const percent = parseFloat(match[1]);
|
||||
if (listeners.length > 0) {
|
||||
listeners.forEach(fn => fn(percent));
|
||||
}
|
||||
listeners.forEach(fn => fn(percent));
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -78,10 +96,7 @@ router.get("/progress", (req, res) => {
|
||||
'Connection': 'keep-alive',
|
||||
});
|
||||
|
||||
const sendProgress = (percent) => {
|
||||
res.write(`data: ${percent}\n\n`);
|
||||
};
|
||||
|
||||
const sendProgress = percent => res.write(`data: ${percent}\n\n`);
|
||||
listeners.push(sendProgress);
|
||||
|
||||
req.on('close', () => {
|
||||
@@ -90,5 +105,4 @@ router.get("/progress", (req, res) => {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
module.exports = router;
|
||||
module.exports = router;
|
||||
|
||||
@@ -28,7 +28,9 @@ router.post("/", (req, res) => {
|
||||
"--cookies-from-browser",
|
||||
`${getUserBrowser()}`,
|
||||
"--extractor-args",
|
||||
"youtube:player_client=default"
|
||||
"youtube:player_client=default",
|
||||
"--ignore-no-formats-error"
|
||||
|
||||
];
|
||||
|
||||
execFile(userYtDlp, args, { timeout: 30_000, maxBuffer: 10 * 1024 * 1024 }, (error, stdout, stderr) => {
|
||||
|
||||
Reference in New Issue
Block a user