mirror of
https://github.com/MasterAcnolo/Freedom-Loader.git
synced 2026-07-29 18:25:47 +02:00
125 lines
4.7 KiB
JavaScript
125 lines
4.7 KiB
JavaScript
/*
|
||
This file is part of Freedom Loader.
|
||
|
||
Copyright (C) 2025 MasterAcnolo
|
||
|
||
Freedom Loader is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License.
|
||
|
||
Freedom Loader is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||
See the GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
const express = require("express"); // importe le framework Express
|
||
const router = express.Router(); // crée un routeur Express pour modulariser les routes
|
||
const { execFile } = require("child_process"); // permet d’exécuter un binaire externe sans passer par un shell
|
||
const path = require("path"); // module Node.js pour gérer les chemins de fichiers
|
||
const fs = require("fs"); // module Node.js pour manipuler le système de fichiers
|
||
|
||
const logger = require("../logger").logger; // récupère l'instance de logger Winston personnalisée
|
||
|
||
// chemin vers l’exécutable yt-dlp packagé avec l’appli
|
||
const ytDlpPath = path.join(__dirname, '../../yt-dlp.exe');
|
||
|
||
// route POST sur la racine (ex: POST /download)
|
||
router.post("/", (req, res) => {
|
||
try {
|
||
// récupère les options envoyées depuis le frontend (via formulaire ou requête AJAX)
|
||
const options = {
|
||
url: req.body.url, // URL à télécharger
|
||
audioOnly: req.body.audioOnly === "1", // conversion audio uniquement (mp3)
|
||
quality: req.body.quality || "best", // qualité vidéo à télécharger
|
||
subtitles: req.body.subs === "1", // récupérer les sous-titres anglais
|
||
};
|
||
|
||
if (!options.url) {
|
||
// si l’URL est absente, on log et on renvoie 400
|
||
logger.warn("Requête POST /download sans URL");
|
||
return res.status(400).send("❌ URL manquante !");
|
||
}
|
||
|
||
// on récupère le dossier de sortie depuis app.locals (défini ailleurs dans le serveur)
|
||
const outputFolder = req.app.locals.outputFolder;
|
||
|
||
// s'il n'existe pas, on le crée automatiquement
|
||
if (!fs.existsSync(outputFolder)) {
|
||
fs.mkdirSync(outputFolder, { recursive: true });
|
||
logger.info("Dossier Freedom Loader Output créé à la volée dans Téléchargements.");
|
||
}
|
||
|
||
// template du nom de fichier de sortie (ex: MonTitre.mp4 ou MonTitre.mp3)
|
||
const outputTemplate = path.join(outputFolder, "%(title)s.%(ext)s");
|
||
|
||
// tableau d'arguments pour yt-dlp
|
||
const args = [];
|
||
|
||
if (options.audioOnly) {
|
||
// si audioOnly, on force extraction audio en mp3
|
||
args.push("--extract-audio", "--audio-format", "mp3");
|
||
}
|
||
|
||
if (options.subtitles) {
|
||
// si l’utilisateur veut des sous-titres
|
||
args.push("--write-subs", "--sub-lang", "en");
|
||
}
|
||
|
||
// qualité souhaitée
|
||
args.push("-f", options.quality);
|
||
// modèle de sortie
|
||
args.push("-o", outputTemplate);
|
||
// enfin, l'URL à télécharger
|
||
args.push(options.url);
|
||
|
||
// log de la commande complète pour debug
|
||
logger.info(`Commande yt-dlp : ${ytDlpPath} ${args.join(" ")}`);
|
||
|
||
// exécution du binaire yt-dlp
|
||
const child = execFile(ytDlpPath, args);
|
||
|
||
// gestion des logs stdout de yt-dlp
|
||
child.stdout.on("data", (data) => {
|
||
data.toString().split("\n").forEach(line => {
|
||
if(line.trim()) logger.info(`[yt-dlp stdout] ${line.trim()}`);
|
||
});
|
||
});
|
||
|
||
// gestion des logs stderr de yt-dlp (les erreurs)
|
||
child.stderr.on("data", (data) => {
|
||
data.toString().split("\n").forEach(line => {
|
||
if(line.trim()) logger.error(`[yt-dlp stderr] ${line.trim()}`);
|
||
});
|
||
});
|
||
|
||
// si une erreur système survient (par ex : yt-dlp.exe introuvable)
|
||
child.on("error", (err) => {
|
||
logger.error(`Erreur lancement yt-dlp : ${err.message}`);
|
||
res.status(500).send(`❌ Erreur lors de l'exécution : ${err.message}`);
|
||
});
|
||
|
||
// callback quand le processus se termine
|
||
child.on("close", (code) => {
|
||
logger.info(`yt-dlp terminé avec code de sortie : ${code}`);
|
||
if(code === 0) {
|
||
// succès
|
||
res.send("✅ Téléchargement terminé !");
|
||
} else {
|
||
// yt-dlp a échoué
|
||
res.status(500).send(`❌ yt-dlp a échoué avec le code : ${code}`);
|
||
}
|
||
});
|
||
|
||
} catch (err) {
|
||
// en cas d'erreur JavaScript
|
||
logger.error(`Erreur serveur dans /download : ${err.message}`);
|
||
res.status(500).send(`Erreur serveur : ${err.message}`);
|
||
}
|
||
});
|
||
|
||
// on exporte ce routeur pour qu'il soit utilisé par l'app principale
|
||
module.exports = router; |