fullpwerr commited on
Commit
4b17ed0
·
1 Parent(s): c90a7ee
Files changed (1) hide show
  1. lib/twt.js +52 -45
lib/twt.js CHANGED
@@ -1,54 +1,61 @@
1
- const { exec } = require("child_process");
2
  const path = require("path");
3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  /**
5
  * Mengambil metadata video Twitter menggunakan yt-dlp.
6
  * @param {string} url - URL tweet yang berisi video.
7
  * @returns {Promise<Object>} - Metadata video dalam format JSON.
8
  */
9
  async function getTwitterVideoInfo(url) {
10
- return new Promise((resolve, reject) => {
11
- exec(`${path.join(__dirname, "./yt-dlp")} -j "${url}" --cookies ${path.join(__dirname, "./cookies/twt.txt")}`, (error, stdout, stderr) => {
12
- if (error) {
13
- reject(`Error: ${stderr || error.message}`);
14
- return;
15
- }
16
- try {
17
- const x = JSON.parse(stdout);
18
-
19
- // Filter video yang benar-benar memiliki video (video_ext valid atau URL mengandung .mp4)
20
- const videoFormats = x.formats.filter(f =>
21
- (f.video_ext !== 'none' && f.audio_ext !== 'none') ||
22
- (f.url.includes(".mp4"))
23
- );
24
-
25
- // Filter audio yang benar-benar hanya audio
26
- const audioFormats = x.formats.filter(f => f.video_ext === 'none' && f.audio_ext !== 'none');
27
-
28
- const res = {
29
- status: 200,
30
- title: x.title,
31
- description: x.description,
32
- thumbnail: x.thumbnail,
33
- video: videoFormats.map(v => ({
34
- format_id: v.format_id,
35
- resolution: v.resolution || `${v.width}x${v.height}`,
36
- url: v.url
37
- })),
38
- audio: audioFormats.map(a => ({
39
- format_id: a.format_id,
40
- bitrate: a.abr,
41
- url: a.url
42
- }))
43
- };
44
-
45
- resolve(res);
46
- } catch (parseError) {
47
- return { status: 500, message: e.message}
48
- }
49
- });
50
- });
51
  }
52
-
53
-
54
- module.exports = getTwitterVideoInfo
 
1
+ const { spawn } = require("child_process");
2
  const path = require("path");
3
 
4
+ const ytdlp = "yt-dlp"; // Asumsi yt-dlp sudah terinstall global di Docker
5
+ const cookiesPath = path.join(__dirname, "./cookies/twt.txt");
6
+
7
+ function runYtDlp(args) {
8
+ return new Promise((resolve, reject) => {
9
+ const process = spawn(ytdlp, args, { stdio: ["ignore", "pipe", "pipe"] });
10
+ let stdout = "";
11
+ let stderr = "";
12
+
13
+ process.stdout.on("data", (data) => (stdout += data.toString()));
14
+ process.stderr.on("data", (data) => (stderr += data.toString()));
15
+
16
+ process.on("close", (code) => {
17
+ if (code === 0) resolve(stdout.trim());
18
+ else reject(new Error(stderr.trim() || `yt-dlp exited with code ${code}`));
19
+ });
20
+ });
21
+ }
22
+
23
  /**
24
  * Mengambil metadata video Twitter menggunakan yt-dlp.
25
  * @param {string} url - URL tweet yang berisi video.
26
  * @returns {Promise<Object>} - Metadata video dalam format JSON.
27
  */
28
  async function getTwitterVideoInfo(url) {
29
+ try {
30
+ const result = await runYtDlp(["-j", "--cookies", cookiesPath, url]);
31
+ const info = JSON.parse(result);
32
+
33
+ // Pastikan `formats` ada, jika tidak buat array kosong
34
+ const videoFormats = (info.formats || []).filter(
35
+ (f) => (f.video_ext !== "none" && f.audio_ext !== "none") || f.url.includes(".mp4")
36
+ );
37
+
38
+ const audioFormats = (info.formats || []).filter((f) => f.video_ext === "none" && f.audio_ext !== "none");
39
+
40
+ return {
41
+ status: 200,
42
+ title: info.title || "No Title",
43
+ description: info.description || "",
44
+ thumbnail: info.thumbnail || "",
45
+ video: videoFormats.map((v) => ({
46
+ format_id: v.format_id,
47
+ resolution: v.resolution || `${v.width}x${v.height}`,
48
+ url: v.url,
49
+ })),
50
+ audio: audioFormats.map((a) => ({
51
+ format_id: a.format_id,
52
+ bitrate: a.abr,
53
+ url: a.url,
54
+ })),
55
+ };
56
+ } catch (err) {
57
+ throw new Error(`Failed to get video info: ${err.message}`);
58
+ }
 
 
 
 
 
 
 
 
 
 
 
59
  }
60
+
61
+ module.exports = getTwitterVideoInfo;