hutatools / lib /twt.js
fullpwerr's picture
p
4b17ed0
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<Object>} - 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;