const { spawn } = require("child_process"); const path = require("path"); const ytdlp = "yt-dlp"; // Asumsi yt-dlp sudah terinstall global di Docker const cookiesPath = path.join(__dirname, "./cookies/twt.txt"); function runYtDlp(args) { return new Promise((resolve, reject) => { const process = spawn(ytdlp, args, { stdio: ["ignore", "pipe", "pipe"] }); let stdout = ""; let stderr = ""; process.stdout.on("data", (data) => (stdout += data.toString())); process.stderr.on("data", (data) => (stderr += data.toString())); process.on("close", (code) => { if (code === 0) resolve(stdout.trim()); else reject(new Error(stderr.trim() || `yt-dlp exited with code ${code}`)); }); }); } /** * Mengambil metadata video Twitter menggunakan yt-dlp. * @param {string} url - URL tweet yang berisi video. * @returns {Promise} - Metadata video dalam format JSON. */ async function getTwitterVideoInfo(url) { try { const result = await runYtDlp(["-j", "--cookies", cookiesPath, url]); const info = JSON.parse(result); // Pastikan `formats` ada, jika tidak buat array kosong const videoFormats = (info.formats || []).filter( (f) => (f.video_ext !== "none" && f.audio_ext !== "none") || f.url.includes(".mp4") ); const audioFormats = (info.formats || []).filter((f) => f.video_ext === "none" && f.audio_ext !== "none"); return { status: 200, title: info.title || "No Title", description: info.description || "", thumbnail: info.thumbnail || "", video: videoFormats.map((v) => ({ format_id: v.format_id, resolution: v.resolution || `${v.width}x${v.height}`, url: v.url, })), audio: audioFormats.map((a) => ({ format_id: a.format_id, bitrate: a.abr, url: a.url, })), }; } catch (err) { throw new Error(`Failed to get video info: ${err.message}`); } } module.exports = getTwitterVideoInfo;