ilhamdev commited on
Commit
7f6be0b
·
verified ·
1 Parent(s): 0a1cdb4

Update index.js

Browse files
Files changed (1) hide show
  1. index.js +743 -666
index.js CHANGED
@@ -1,7 +1,7 @@
1
  const yts = require('yt-search');
2
  const morgan = require('morgan');
3
  const express = require('express');
4
- const youtubedl = require('youtubedl-core');
5
  const { Writable, pipeline } = require('stream');
6
  const util = require('util');
7
  const axios = require('axios');
@@ -11,138 +11,148 @@ const os = require('os')
11
  const cheerio = require('cheerio')
12
  const cloudscraper = require('cloudscraper')
13
  const acrcloud = require("acrcloud");
14
- const { File } = require('megajs')
15
  const { BingChat } = require("bing-chat-cjs-rnz");
16
  const path = require("path")
17
  const fs = require("fs")
18
  let fetch;
19
 
20
  (async () => {
21
- fetch = (await import('node-fetch')).default;
22
  })();
23
 
24
-
25
  // Regex untuk mengidentifikasi URL YouTube dan Mega
26
- const ytIdRegex = /(?:http(?:s|):\/\/|)(?:(?:www\.|)?youtube(?:\-nocookie|)\.com\/(?:shorts\/)?(?:watch\?.*(?:|\&)v=|embed\/|v\/)?|youtu\.be\/)([-_0-9A-Za-z]{11})/;
 
 
 
 
 
27
 
28
  // Fungsi untuk melakukan HTTP POST request
29
  const post = async (url, form, headers = {}) => {
30
- const response = await fetch(url, {
31
- method: 'post',
32
- body: new URLSearchParams(form),
33
- headers
34
- });
35
- return response;
36
  };
37
 
38
  // isURL
39
  function isUrl(url) {
40
- let regex = new RegExp(/(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,9}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/, 'gi');
41
- if (!regex.test(url)) return false;
42
- return url?.match(regex);
43
  }
44
 
45
-
46
  //RANDOM
47
- function generateRandomUserAgent() {
48
- const androidVersions = ['4.0.3', '4.1.1', '4.2.2', '4.3', '4.4', '5.0.2', '5.1', '6.0', '7.0', '8.0', '9.0', '10.0', '11.0', '12.0', '13.0'];
49
- const deviceModels = ['M2004J19C', 'S2020X3', 'Xiaomi4S', 'RedmiNote9', 'SamsungS21', 'GooglePixel5', 'iPhone13,4', 'SM-A526B', 'SM-G991B', 'SM-G998B', 'iPhone13,2', 'iPhone13,3', 'iPhone13,1', 'SM-G996B', 'SM-G970F'];
50
- const buildVersions = ['RP1A.200720.011', 'RP1A.210505.003', 'RP1A.210812.016', 'QKQ1.200114.002', 'RQ2A.210505.003', 'RQ3A.211001.001', 'SD1A.210817.036', 'T825YDXU3CTK1', 'QKQ1.191014.012', 'QKQ1.190918.001', 'QKQ1.190626.002', 'QKQ1.190716.003', 'QKQ1.190626.002', 'QKQ1.190626.002', 'QKQ1.190626.002'];
51
- const browsers = ['Chrome', 'Firefox', 'Safari', 'Edge', 'Opera'];
52
-
53
- const getRandomElement = (arr) => arr[Math.floor(Math.random() * arr.length)];
54
- const getRandomNumber = (max) => Math.floor(Math.random() * max) + 1;
55
-
56
- const selectedModel = getRandomElement(deviceModels);
57
- const selectedBuild = getRandomElement(buildVersions);
58
- const selectedBrowser = getRandomElement(browsers);
59
- const browserVersion = `${selectedBrowser}/${getRandomNumber(96)}.${getRandomNumber(999)}.${getRandomNumber(9999)}.${getRandomNumber(99)}`;
60
- const userAgent = `Mozilla/5.0 (Linux; Android ${getRandomElement(androidVersions)}; ${selectedModel} Build/${selectedBuild}) AppleWebKit/537.36 (KHTML, like Gecko) ${browserVersion} Mobile Safari/537.36`;
61
-
62
- return userAgent;
 
 
63
  }
64
- function generateRandomIP() {
65
- return Array(4)
66
- .fill(0)
67
- .map(() => Math.floor(Math.random() * 256))
68
- .join('.');
69
  }
70
  //BIMG
71
  async function bimg(query) {
72
- const { BingApi } = await import("bing-nodejs");
73
  const bing = new BingApi({
74
- cookie: process.env.BING_IMAGE_COOKIE
75
  });
76
- let data = await bing.createImage(query).then((res) => {
77
- return res.urls; // string[]
78
  });
79
-
80
- // Filter out links that end with '.svg'
81
- let filteredData = data.filter(i => !i.includes('.svg'));
82
- return filteredData
83
  }
84
  async function bingChat(text) {
85
- const api = new BingChat({
86
- cookie: process.env.BING_IMAGE_COOKIE
87
- })
88
  const res = await api.sendMessage(text, { variant: 'Precise' })
89
  return res?.text
90
  }
91
 
92
  async function acrCloud(buffer) {
93
- let { mime } = await (await import('file-type')).fileTypeFromBuffer(buffer);
94
- if (/audio|video/.test(mime)) {
95
- const wow = new acrcloud({
96
- host: "identify-ap-southeast-1.acrcloud.com",
97
- access_key: "b1cc283b4fb72483ebb6ea9c53512331",
98
- access_secret: "xyqJGTZRTrUotaraHEjji00WBClx7RpWozywdANq"
99
- });
100
- let { status, metadata } = await wow.identify(buffer);
101
- if (status.code !== 0) throw new Error(status.msg);
102
- //console.log(metadata.music[0])
103
- return metadata.music[0];
104
- } else {
105
- throw new Error('Error: only audio/video files are supported');
106
- }
107
  }
108
 
109
-
110
  // MEDIAFIRE DL
111
  async function mediafire(url) {
112
- return new Promise(async(resolve, reject) => {
113
- var a, b;
114
- if (!/https?:\/\/(www\.)?mediafire\.com/.test(url)) return resolve()
115
- const data = await axios.get(url, {headers: {
116
- 'User-Agent': generateRandomUserAgent(),
117
- 'X-Forwarded-For': generateRandomIP(),
118
- }}).catch(function (error) {})
119
- if (!data) {
120
- resolve()
121
- } else {
122
- const $ = cheerio.load(data.data);
123
- const Url = ($('#downloadButton').attr('href') || '').trim();
124
- const url2 = ($('#download_link > a.retry').attr('href') || '').trim();
125
- const $intro = $('div.dl-info > div.intro');
126
- const filename = $intro.find('div.filename').text().trim();
127
- const filetype = $intro.find('div.filetype > span').eq(0).text().trim();
128
- const ext = ((b = (a = /\(\.(.*?)\)/.exec($intro.find('div.filetype > span').eq(1).text())) === null || a === void 0 ? void 0 : a[1]) === null || b === void 0 ? void 0 : b.trim()) || 'bin';
129
- const $li = $('div.dl-info > ul.details > li');
130
- const aploud = $li.eq(1).find('span').text().trim();
131
- const filesize = $li.eq(0).find('span').text().trim();
132
- const filesizeB = (0, formatSize)(filesize);
133
- const result = {
134
- url: Url || url2,
135
- url2,
136
- filename,
137
- filetype,
138
- ext,
139
- upload_date: aploud,
140
- filesize,
141
- filesizeB
142
- };
143
- resolve(result)
144
- }
145
- })
 
 
 
 
 
 
146
  }
147
 
148
 
@@ -150,13 +160,13 @@ async function mediafire(url) {
150
  async function igdl(query) {
151
  url_dl = [];
152
  let headers = {
153
- 'Accept': '*/*',
154
- 'Accept-Language': 'en-US,en;q=0.9',
155
- 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
156
- 'Referer': 'https://saveig.app/',
157
- 'Referrer-Policy': 'strict-origin-when-cross-origin',
158
- 'X-Requested-With': 'XMLHttpRequest'
159
- }
160
  let options = {
161
  method: 'POST',
162
  uri: 'https://saveig.app/api/ajaxSearch',
@@ -173,290 +183,335 @@ return url_dl;
173
  //FBDL
174
  async function fby2mate(url) {
175
  try {
176
- let form = new FormData()
177
- form.append('q', url)
178
- form.append('vt', 'facebook')
179
- let data = await fetch(`https://y2mate.mx/api/ajaxSearch/facebook`, {
180
- method: 'POST',
181
- body: form,
182
- headers: {
183
- 'User-Agent': generateRandomUserAgent(),
184
- 'X-Forwarded-For': generateRandomIP(),
185
- ...form.getHeaders()
186
- }
187
- })
188
- data = await data.json()
189
- return data
190
  } catch (e) {
191
- return e
192
  }
193
  }
194
 
195
  //YTDL-CORE
196
  async function uploadBuffer(media) {
197
- return new Promise(async (resolve, reject) => {
198
- try {
199
- let {fileTypeFromBuffer} = await (await import('file-type'))
200
- let mime = await fileTypeFromBuffer(media);
201
- let form = new FormData();
202
- form.append("files[]", media, `file-${new Date().getTime()}.${mime.ext}`);
203
-
204
- let response = await axios.post("https://pomf.lain.la/upload.php", form, {
205
- headers: {
206
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0",
207
- ...form.getHeaders()
208
- }
209
- });
210
-
211
- resolve(response.data?.files[0]?.url || null);
212
- } catch (error) {
213
- console.error(error);
214
- resolve(null); // Ensure null is returned if there's an error
215
- }
216
- });
217
  }
218
  async function streamToBuffer(stream) {
219
- const chunks = [];
220
- const captureChunks = new Writable({
221
- write(chunk, encoding, callback) {
222
- chunks.push(chunk);
223
- callback();
224
- }
225
- });
226
-
227
- await util.promisify(pipeline)(stream, captureChunks);
228
 
229
- return Buffer.concat(chunks);
230
- }
 
 
231
  function formatViews(viewCount) {
232
- if (viewCount >= 1000000000) {
233
- return (viewCount / 1000000000).toFixed(1) + 'B';
234
- } else if (viewCount >= 1000000) {
235
- return (viewCount / 1000000).toFixed(1) + 'M';
236
- } else {
237
- return viewCount >= 1000
238
- ? (viewCount / 1000).toFixed(1) + 'K'
239
- : viewCount.toString();
240
- }
241
  }
242
 
243
  function formatDuration(durationInSeconds) {
244
- const hours = Math.floor(durationInSeconds / 3600);
245
- const minutes = Math.floor((durationInSeconds % 3600) / 60);
246
- const seconds = durationInSeconds % 60;
247
-
248
- return hours > 0
249
- ? hours +
250
- ':' +
251
- minutes.toString().padStart(2, '0') +
252
- ':' +
253
- seconds.toString().padStart(2, '0')
254
- : minutes + ':' + seconds.toString().padStart(2, '0');
255
  }
256
 
257
  function formatSize(bytes, si = false, dp = 2) {
258
- const thresh = si ? 1000 : 1024;
259
-
260
- if (Math.abs(bytes) < thresh) {
261
- return `${bytes} B`;
262
- }
263
 
264
- const units = si
265
- ? ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
266
- : ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
267
- let u = -1;
268
- const r = 10 ** dp;
269
 
270
- do {
271
- bytes /= thresh;
272
- ++u;
273
- } while (
274
- Math.round(Math.abs(bytes) * r) / r >= thresh &&
275
- u < units.length - 1
276
- );
 
 
 
 
 
 
 
 
 
277
 
278
- return `${bytes.toFixed(dp)} ${units[u]}`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
  }
280
 
281
- async function ytmp4(url, quality = 'highest') {
282
- try {
283
- const info = await youtubedl.getInfo(url);
284
- const videoStream = youtubedl(url, {
285
- quality: 'highestvideo',
286
- filter: (format) => format.container === 'mp4' && format.qualityLabel === quality
287
- });
288
 
289
- let buffer = await streamToBuffer(videoStream);
290
- let upload = await uploadBuffer(buffer);
291
- let urel = upload != null ? { url_v2: upload } : null;
292
-
293
- return {
294
- title: info.title,
295
- description: info.description,
296
- channel: info.channel,
297
- views: formatViews(info.view_count),
298
- publish: info.upload_date,
299
- duration: formatDuration(info.duration),
300
- size: info.formats[0].filesize,
301
- quality: info.formats[0].quality,
302
- thumb: info.thumbnail,
303
- dl_url: info.url,
304
- ...urel,
305
- };
306
- } catch (error) {
307
- console.error('Error occurred:', error);
308
- return error;
309
- }
310
- }
311
 
312
- async function ytmp3(url, bitrate = 'lowest') {
313
  try {
314
- const info = await youtubedl.getInfo(url);
315
- const audioStream = youtubedl(url, {
316
- quality: 'highestaudio',
317
- filter: 'audioonly'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
318
  });
319
 
320
- let buffer = await streamToBuffer(audioStream);
321
- let konver = await convertToAudio(buffer, "mp4");
322
- let upload = await uploadBuffer(konver);
323
- let urel = upload != null ? { url_v2: upload } : null;
324
-
325
- return {
326
- title: info.title,
327
- description: info.description,
328
- channel: info.channel,
329
- views: formatViews(info.view_count),
330
- publish: info.upload_date,
331
- duration: formatDuration(info.duration),
332
- size: info.formats[0].filesize,
333
- quality: info.formats[0].quality,
334
- thumb: info.thumbnail,
335
- dl_url: info.url,
336
- ...urel,
337
- };
338
- } catch (error) {
339
- console.error('Error occurred:', error);
340
- return error;
341
  }
342
  }
343
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344
 
345
  // Fungsi untuk mengkonversi video dari YouTube
346
  const convert = async (url, v_id, ftype, fquality, fname, token, timeExpire) => {
347
- let params = {
348
- v_id,
349
- ftype,
350
- fquality,
351
- fname,
352
- token,
353
- timeExpire,
354
- client: 'yt5s.com'
355
- };
356
-
357
- // Mengirim permintaan konversi
358
- let resServer = await (await post(url, params, { 'x-requested-key': 'de0cfuirtgf67a' })).json();
359
- let server = resServer.c_server;
360
-
361
- // Jika tidak ada server dan tipe file adalah mp3, kembalikan null
362
- if (!server && ftype === 'mp3') return server || resServer.d_url || '';
363
-
364
- // Mengambil data hasil konversi
365
- let data = await (await post(`${server}/api/json/convert`, params)).json();
366
- let result;
367
-
368
- // Memeriksa status kode hasil konversi
369
- if (data.statusCode === 200) result = data.result;
370
- while (!result) {
371
- let json = await (await post(`${server}/api/json/convert`, params)).json();
372
- if (json.statusCode === 200) {
373
- result = json.result;
374
- break;
375
- }
376
- await new Promise(resolve => setTimeout(resolve, 2000));
377
  }
378
- return result;
 
 
379
  };
380
 
381
  // Fungsi untuk mendownload video dari YouTube
382
- const youtubedl_2 = async (url) => {
383
- let html = await (await fetch('https://yt5s.com/en32', {headers: {
384
- 'User-Agent': generateRandomUserAgent(),
385
- 'X-Forwarded-For': generateRandomIP(),
386
  }})).text();
387
- let urlAjax = (html.match(/k_url_search="(.*?)"/) || [])[1];
388
- let urlConvert = (html.match(/k_url_convert="(.*?)"/) || [])[1];
389
- let json = await (await post(urlAjax, { q: url, vt: 'home' })).json();
390
- let video = {}, audio = {};
391
- if (!json?.links) throw json.mess;
392
- Object.values(json.links.mp4).map(({ k, size }) => video[k] = {
393
- quality: k,
394
- fileSizeH: size,
395
- fileSize: parseFloat(size) * (/MB$/.test(size) ? 1000 : 1),
396
- download: convert.bind(null, urlConvert, json.vid, 'mp4', k, json.fn, json.token, parseInt(json.timeExpires))
397
- });
398
 
399
- Object.values(json.links.mp3).map(({ key, size }) => audio[key] = {
400
- quality: key,
401
- fileSizeH: size,
402
- fileSize: parseFloat(size) * (/MB$/.test(size) ? 1000 : 1),
403
- download: convert.bind(null, urlConvert, json.vid, 'mp3', key.replace(/kbps/i, ''), json.fn, json.token, parseInt(json.timeExpires))
404
- });
405
 
406
- return {
407
- id: json.vid,
408
- title: json.title,
409
- thumbnail: `https://i.ytimg.com/vi/${json.vid}/0.jpg`,
410
- video,
411
- audio
412
- };
413
  };
414
 
415
  //TWITTER API
416
  async function twitterDL(url) {
417
- try {
418
- let form = new FormData();
419
- form.append('q', url);
420
- form.append('lang', 'en');
 
 
 
 
 
 
 
 
 
421
 
422
- let response = await fetch('https://x2twitter.com/api/ajaxSearch', {
423
- method: 'POST',
424
- body: form,
425
- headers: {
426
- 'User-Agent': generateRandomUserAgent(),
427
- 'X-Forwarded-For': generateRandomIP(),
428
- ...form.getHeaders()
429
- }
430
- });
431
 
432
- let data = await response.json();
433
- const $ = cheerio.load(data?.data);
434
- let downloads = [];
 
 
 
 
435
 
436
- $('.dl-action a').each((index, element) => {
437
- const format = $(element).text().trim();
438
- const url = $(element).attr('href');
439
- if (url !== '#') {
440
- downloads.push({ format, url });
 
441
  }
442
  });
443
-
444
- // Jika tidak ada unduhan dari load pertama, coba load kedua
445
- if (downloads.length === 0) {
446
- $('a').each((index, element) => {
447
- const href = $(element).attr('href');
448
- if (href && href !== '/' && href !== '#') {
449
- downloads.push(href);
450
- }
451
- });
452
- }
453
-
454
- return { downloads };
455
- } catch (error) {
456
- return error;
457
  }
458
- }
459
 
 
 
 
 
 
460
 
461
  const app = express();
462
  app.set('json spaces', 4);
@@ -465,347 +520,369 @@ app.use(express.json());
465
 
466
  const v8 = require('v8');
467
 
468
- app.all('/', async (req, res) => {
469
- const status = {}
470
- status['diskUsage'] = cp.execSync('du -sh').toString().split('M')[0] + ' MB'
471
-
472
- const used = process.memoryUsage()
473
- for (let x in used) status[x] = formatSize(used[x])
474
-
475
- const totalmem = os.totalmem()
476
- const freemem = os.freemem()
477
- status['memoryUsage'] = `${formatSize(totalmem - freemem)} / ${formatSize(totalmem)}`
478
-
479
- // Menambahkan statistik heap V8
480
- const heapStats = v8.getHeapStatistics();
481
- for (let x in heapStats) status[x] = formatSize(heapStats[x])
482
-
483
- // Menambahkan semua properti dan metode dari v8
484
- for (let x in v8) {
485
- if (typeof v8[x] !== 'function') {
486
- status[x] = v8[x]
487
- }
488
- }
489
-
490
- const host = 'https://' + req.get('host');
491
-
492
- res.json({
493
- creator: `@${process.env['SPACE_AUTHOR_NAME'] || 'ALOK FF'}`,
494
- message: 'Hello World!',
495
- uptime: new Date(process.uptime() * 1000).toUTCString().split(' ')[4],
496
- status, // Menambahkan latency ke JSON
497
- "list": [
498
- {
499
- "title": "BING AI",
500
- "method": "GET",
501
- "example": "${host}/bing?q="
502
- },
503
- {
504
- "title": "Facebook Downloader",
505
- "method": "GET",
506
- "example": "${host}/fb?url="
507
- },
508
- {
509
- "title": "Instagram Downloader",
510
- "method": "GET",
511
- "example": "${host}/ig?url="
512
- },
513
- {
514
- "title": "Mediafire Downloader",
515
- "method": "GET",
516
- "example": "${host}/mediafire?url="
517
- },
518
- {
519
- "title": "Mega Downloader",
520
- "method": "GET",
521
- "example": "${host}/mega?url="+ "${encodeURIComponent('url')}"
522
- },
523
- {
524
- "title": "Pinterest Downloader",
525
- "method": "GET",
526
- "example": "${host}/pindl?url="
527
- },
528
- {
529
- "title": "Tiktok Downloader",
530
- "method": "GET",
531
- "example": "${host}/tt?url="
532
- },
533
- {
534
- "title": "Twitter/X Downloader",
535
- "method": "GET",
536
- "example": "${host}/twitter?url="
537
- },
538
- {
539
- "title": "Whatmusic Search",
540
- "method": "GET",
541
- "example": "${host}/whatmusic?url="
542
- },
543
- {
544
- "title": "Youtube Downloader",
545
- "method": "GET",
546
- "example": "${host}/ytdl?url="
547
- },
548
- {
549
- "title": "Youtube Search",
550
- "method": "GET",
551
- "example": "${host}/ytsearch?q="
552
- }
553
- ]
554
 
555
- });
556
- });
557
 
 
 
 
558
 
559
- app.get('/yt', async (req, res) => {
560
- const host = 'https://' + req.get('host');
561
- try {
562
- let { url, type, quality, json } = req.query;
563
- if (!ytIdRegex.test(url)) return res.json({ message: 'Invalid URL' });
564
- if (!!json) {
565
- let ytId = ytIdRegex.exec(url)?.[1];
566
- if (!ytId) return res.json({ message: 'No video id found' });
567
- let data = await yts({ videoId: ytId });
568
- const downloadUrls = {
569
- audio: `${host}/yt?url=${url}&type=audio&quality=128kbps`,
570
- video: `${host}/yt?url=${url}&type=video&quality=`,
571
- };
572
- return res.json({
573
- ...data,
574
- download: downloadUrls
575
- });
576
- }
577
- if (!type || !/audio|video/i.test(type)) type = 'video';
578
- let data = await youtubedl_2(url).catch(e => console.log(e));
579
- if (!data) return res.json({ message: 'Error: link download not found' });
580
- type = type.toLowerCase();
581
- let result = quality ? Object.values(data[type]).find(x => x.quality == quality) : Object.values(data[type])[0];
582
- if (quality && !result) return res.json({ message: `Invalid quality: ${quality}, available quality (${Object.keys(data[type]).join('/')})` });
583
- if (!result) return res.json({ message: 'Error: can\'t download' });
584
- res.redirect(await result.download());
585
- } catch (e) {
586
- console.log(e);
587
- return res.json({ message: e.message });
588
- }
589
- });
590
- app.get('/ig', async (req,res) => {
591
- try {
592
- let {url} = req.query
593
- let regex = /https?:\/\/(www\.)?instagram\.com\/(p|reel|tv)/;
594
- if (!regex.test(url)) return res.json({ message: 'Invalid URL' });
595
- let data = await igdl(url)
596
- return res.json(data)
597
- } catch (e) {
598
- console.log(e);
599
- return res.json({ message: e.message });
600
- }
601
- });
602
- app.get('/tt', async (req, res) => {
603
- try {
604
- let { url } = req.query
605
- let regex = /https?:\/\/(www\.|v(t|m|vt)\.|t\.)?tiktok\.com/;
606
- if (!regex.test(url)) return res.json({ message: 'Invalid URL' });
607
- let data = await fetch(`https://tikwm.com/api/?url=` + url, {headers: {'User-Agent': generateRandomUserAgent(),
608
- 'X-Forwarded-For': generateRandomIP(),}})
609
- data = await data.json()
610
- if (!data) return res.json({ message: 'API TO API KOID:v' });
611
- return res.json(data)
612
- } catch (e) {
613
- console.log(e);
614
- return res.json({ message: e.message });
615
- }
616
- });
617
- app.get('/pindl', async (req, res) => {
618
- try {
619
- let { url } = req.query
620
- let regex = /https:\/\/pin\.it\/\w+|https:\/\/[a-z]{2}\.pinterest\.com\/pin\/\d+/;
621
- if (!regex.test(url)) return res.json({ message: 'Invalid URL' });
622
- let data = await fetch(`https://pinterestdownloader.io/id/frontendService/DownloaderService?url=` + url, {headers:{'User-Agent': generateRandomUserAgent(),
623
- 'X-Forwarded-For': generateRandomIP(),}})
624
- data = await data.json()
625
- if (!data) return res.json({ message: 'API TO API KOID:v' });
626
- return res.json(data)
627
- } catch (e) {
628
- console.log(e);
629
- return res.json({ message: e.message });
630
- }
631
- });
632
- app.get('/fb', async (req, res) => {
633
- try {
634
- let {url} = req.query
635
- let regex = /https?:\/\/(fb\.watch|(www\.|web\.|m\.)?facebook\.com)/;
636
- if (!regex.test(url)) return res.json({ message: 'Invalid URL' });
637
- let data = await fby2mate(url)
638
- return res.json(data)
639
- } catch (e) {
640
- console.log(e);
641
- return res.json({ message: e.message });
642
- }
643
- });
644
- app.get('/bimg', async (req, res) => {
645
- try {
646
- let q = req.query.q || req.query.query;
647
- if (!q) return res.json({ message: 'Input parameter q' });
648
- let data = await bimg(q)
649
- return res.json({query: q, data: data})
650
- } catch (e) {
651
- console.log(e);
652
- return res.json({ message: e.message });
653
- }
654
- });
655
- app.get('/bing', async (req, res) => {
656
- try {
657
- let q = req.query.q || req.query.query;
658
- if (!q) return res.json({ message: 'Input parameter q' });
659
- let data = await bingChat(q)
660
- if (data.length === 0) {
661
- async function gpt4o(prompt) {
662
- let session_hash = Math.random().toString(36).substring(2).slice(1)
663
- let resPrompt = await axios.post('https://kingnish-opengpt-4o.hf.space/run/predict?__theme=light', {
664
- "data":[{
665
- "text":prompt,
666
- "files":[]
667
- }],
668
- "event_data":null,
669
- "fn_index":3,
670
- "trigger_id":34,
671
- "session_hash":session_hash})
672
- let res = await axios.post('https://kingnish-opengpt-4o.hf.space/queue/join?__theme=light', {
673
- "data":[
674
- null,
675
- null,
676
- "idefics2-8b-chatty",
677
- "Top P Sampling",
678
- 0.5,
679
- 4096,
680
- 1,
681
- 0.9,
682
- true
683
- ],
684
- "event_data":null,
685
- "fn_index":5,
686
- "trigger_id":34,
687
- "session_hash": session_hash
688
- })
689
- let event_ID = res.data.event_id
690
- let anu = await axios.get('https://kingnish-opengpt-4o.hf.space/queue/data?session_hash=' + session_hash)
691
- const lines = anu.data.split('\n');
692
- const processStartsLine = lines.find(line => line.includes('process_completed'));
693
- if (processStartsLine) {
694
- const processStartsData = JSON.parse(processStartsLine.replace('data: ', ''));
695
- let ress = processStartsData.output.data
696
- let result = ress[0][0][1]
697
- return result
698
- } else {
699
- return 'error kang!'
700
  }
701
  }
702
- data = await gpt4o(q)
703
- //return res.json({message: 'Terkena Chaptcha BOT!!!'})
704
- }
705
- return res.json({result:data})
706
- } catch (e) {
707
- console.log(e);
708
- return res.json({ message: e.message });
709
- }
710
- })
711
- app.get('/whatmusic', async (req, res) => {
712
- try {
713
- let { url } = req.query
714
- async function downloadBuffer(url) {
715
- try {
716
- const response = await axios({
717
- method: 'get',
718
- url: url,
719
- responseType: 'arraybuffer'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
720
  });
721
- return Buffer.from(response.data, 'binary');
722
- } catch (error) {
723
- throw new Error(`Failed to download the file: ${error.message}`);
724
- }
725
- }
726
- if (!url) return res.json({ message: 'Input parameter url' });
727
- if (!isUrl(url)) return res.json({ message: 'Invalit Input Link' })
728
- let data = await acrCloud(await downloadBuffer(isUrl(url)[0]))
729
- if (!data) return res.json({ error: 'Error:v'})
730
- return res.json(data);
731
- } catch (e) {
732
- console.log(e);
733
- return res.json({ message: e.message });
734
- }
735
- })
736
- app.get('/ytsearch', async (req, res) => {
737
- try {
738
- let q = req.query.q || req.query.query;
739
- if (!q) return res.json({ message: 'Input parameter q' });
740
- let data = await yts(q);
741
- if (!data.all[0]) return res.json({ message: 'Not found' });
742
- return res.json(data.all);
743
- } catch (e) {
744
- console.log(e);
745
- return res.json({ message: e.message });
746
- }
747
- });
748
- app.get('/mediafire', async (req, res) => {
749
- try {
750
- let { url } = req.query
751
- //console.log(url)
752
- if (!/https?:\/\/(www\.)?mediafire\.com\/(file|download)/i.test(url)) {
753
- return res.json({ message: 'Invalid URL' });
754
- }
755
- let data = await mediafire(url)
756
- return res.json(data)
757
- } catch (e) {
758
- console.log(e);
759
- return res.json({ message: e.message });
760
- }
761
- });
762
- app.get('/ytdl', async (req, res) => {
763
- try {
764
- let { url } = req.query
765
- if (!ytIdRegex.test(url)) return res.json({ message: 'Invalid URL' });
766
- let video = await ytmp4(url)
767
- let audio = await ytmp3(url)
768
- return res.json({
769
- video: video,
770
- audio: audio
771
- })
772
- } catch (e) {
773
- console.log(e);
774
- return res.json({ message: e.message });
775
- }
776
- });
777
- app.get('/twitter', async (req, res) => {
778
- try {
779
- let { url } = req.query;
780
- url = url.replace('x.com', 'twitter.com'); // Mengganti x.com dengan twitter.com dalam URL
781
- if (!/https?:\/\/(www\.)?(twitter|x)\.com\/.*\/status/.test(url)) {
782
- return res.json({ message: 'Invalid URL' });
783
- }
784
- let data = await twitterDL(url);
785
- return res.json(data);
786
- } catch (e) {
787
  console.log(e);
788
  return res.json({ message: e.message });
789
  }
790
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
791
 
792
- app.get('/mega', async (req, res) => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
793
  try {
794
- let { url } = req.query;
795
- if (!/https:\/\/mega\.nz\/file\/[a-zA-Z0-9]{8}#[a-zA-Z0-9-_]{43}/.test(url)) {
796
- return res.json({ message: 'Invalid URL' });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
797
  }
798
- const file = File.fromURL(url);
799
- await file.loadAttributes();
800
- let data = await file.downloadBuffer();
801
- return res.json({
802
- title: file.name,
803
- size: formatSize(file.size),
804
- base64: data.toString('base64')
805
- })
806
- } catch (e) {
807
- console.log(e);
808
- return res.json({ message: e.message });
809
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
810
  });
811
- app.listen(7860, () => console.log('App running on port 7860'));
 
1
  const yts = require('yt-search');
2
  const morgan = require('morgan');
3
  const express = require('express');
4
+ const ytdl = require('ytdl-core');
5
  const { Writable, pipeline } = require('stream');
6
  const util = require('util');
7
  const axios = require('axios');
 
11
  const cheerio = require('cheerio')
12
  const cloudscraper = require('cloudscraper')
13
  const acrcloud = require("acrcloud");
14
+ const { File } = require('megajs')
15
  const { BingChat } = require("bing-chat-cjs-rnz");
16
  const path = require("path")
17
  const fs = require("fs")
18
  let fetch;
19
 
20
  (async () => {
21
+ fetch = (await import('node-fetch')).default;
22
  })();
23
 
 
24
  // Regex untuk mengidentifikasi URL YouTube dan Mega
25
+ const ytIdRegex = /(?
26
+ (?
27
+ |)://|)(?:(?
28
+ .|)?youtube(?:-nocookie|).com/(?
29
+ /)?(?
30
+ ?.*(?:|&)v=|embed/|v/)?|youtu.be/)([-_0-9A-Za-z]{11})/;
31
 
32
  // Fungsi untuk melakukan HTTP POST request
33
  const post = async (url, form, headers = {}) => {
34
+ const response = await fetch(url, {
35
+ method: 'post',
36
+ body: new URLSearchParams(form),
37
+ headers
38
+ });
39
+ return response;
40
  };
41
 
42
  // isURL
43
  function isUrl(url) {
44
+ let regex = new RegExp(/(https?://)?(www.)?[-a-zA-Z0-9@:%.+~#=]{1,256}.[a-zA-Z0-9()]{1,9}\b([-a-zA-Z0-9()@:%+.~#?&//=]*)/, 'gi');
45
+ if (!regex.test(url)) return false;
46
+ return url?.match(regex);
47
  }
48
 
 
49
  //RANDOM
50
+ function generateRandomUserAgent() {
51
+ const androidVersions = ['4.0.3', '4.1.1', '4.2.2', '4.3', '4.4', '5.0.2', '5.1', '6.0', '7.0', '8.0', '9.0', '10.0', '11.0', '12.0', '13.0'];
52
+ const deviceModels = ['M2004J19C', 'S2020X3', 'Xiaomi4S', 'RedmiNote9', 'SamsungS21', 'GooglePixel5', 'iPhone13,4', 'SM-A526B', 'SM-G991B', 'SM-G998B', 'iPhone13,2', 'iPhone13,3', 'iPhone13,1', 'SM-G996B', 'SM-G970F'];
53
+ const buildVersions = ['RP1A.200720.011', 'RP1A.210505.003', 'RP1A.210812.016', 'QKQ1.200114.002', 'RQ2A.210505.003', 'RQ3A.211001.001', 'SD1A.210817.036', 'T825YDXU3CTK1', 'QKQ1.191014.012', 'QKQ1.190918.001', 'QKQ1.190626.002', 'QKQ1.190716.003', 'QKQ1.190626.002', 'QKQ1.190626.002', 'QKQ1.190626.002'];
54
+ const browsers = ['Chrome', 'Firefox', 'Safari', 'Edge', 'Opera'];
55
+
56
+ javascript
57
+ Salin kode
58
+ const getRandomElement = (arr) => arr[Math.floor(Math.random() * arr.length)];
59
+ const getRandomNumber = (max) => Math.floor(Math.random() * max) + 1;
60
+
61
+ const selectedModel = getRandomElement(deviceModels);
62
+ const selectedBuild = getRandomElement(buildVersions);
63
+ const selectedBrowser = getRandomElement(browsers);
64
+ const browserVersion = `${selectedBrowser}/${getRandomNumber(96)}.${getRandomNumber(999)}.${getRandomNumber(9999)}.${getRandomNumber(99)}`;
65
+ const userAgent = `Mozilla/5.0 (Linux; Android ${getRandomElement(androidVersions)}; ${selectedModel} Build/${selectedBuild}) AppleWebKit/537.36 (KHTML, like Gecko) ${browserVersion} Mobile Safari/537.36`;
66
+
67
+ return userAgent;
68
  }
69
+ function generateRandomIP() {
70
+ return Array(4)
71
+ .fill(0)
72
+ .map(() => Math.floor(Math.random() * 256))
73
+ .join('.');
74
  }
75
  //BIMG
76
  async function bimg(query) {
77
+ const { BingApi } = await import("bing-nodejs");
78
  const bing = new BingApi({
79
+ cookie: process.env.BING_IMAGE_COOKIE
80
  });
81
+ let data = await bing.createImage(query).then((res) => {
82
+ return res.urls; // string[]
83
  });
84
+
85
+ // Filter out links that end with '.svg'
86
+ let filteredData = data.filter(i => !i.includes('.svg'));
87
+ return filteredData
88
  }
89
  async function bingChat(text) {
90
+ const api = new BingChat({
91
+ cookie: process.env.BING_IMAGE_COOKIE
92
+ })
93
  const res = await api.sendMessage(text, { variant: 'Precise' })
94
  return res?.text
95
  }
96
 
97
  async function acrCloud(buffer) {
98
+ let { mime } = await (await import('file-type')).fileTypeFromBuffer(buffer);
99
+ if (/audio|video/.test(mime)) {
100
+ const wow = new acrcloud({
101
+ host: "identify-ap-southeast-1.acrcloud.com",
102
+ access_key: "b1cc283b4fb72483ebb6ea9c53512331",
103
+ access_secret: "xyqJGTZRTrUotaraHEjji00WBClx7RpWozywdANq"
104
+ });
105
+ let { status, metadata } = await wow.identify(buffer);
106
+ if (status.code !== 0) throw new Error(status.msg);
107
+ //console.log(metadata.music[0])
108
+ return metadata.music[0];
109
+ } else {
110
+ throw new Error('Error: only audio/video files are supported');
111
+ }
112
  }
113
 
 
114
  // MEDIAFIRE DL
115
  async function mediafire(url) {
116
+ return new Promise(async (resolve, reject) => {
117
+ var a, b;
118
+ if (!/https?:\/\/(www\.)?mediafire.com/.test(url)) return resolve();
119
+ try {
120
+ const data = await axios.get(url, {
121
+ headers: {
122
+ 'User-Agent': generateRandomUserAgent(),
123
+ 'X-Forwarded-For': generateRandomIP(),
124
+ }
125
+ });
126
+ if (!data) {
127
+ resolve();
128
+ } else {
129
+ const $ = cheerio.load(data.data);
130
+ const Url = ($('#downloadButton').attr('href') || '').trim();
131
+ const url2 = ($('#download_link > a.retry').attr('href') || '').trim();
132
+ const $intro = $('div.dl-info > div.intro');
133
+ const filename = $intro.find('div.filename').text().trim();
134
+ const filetype = $intro.find('div.filetype > span').eq(0).text().trim();
135
+ const ext = ((b = (a = /(.+?)\s*(?:\(|$)/.exec($intro.find('div.filetype > span').eq(1).text())) === null || a === void 0 ? void 0 : a[1]) === null || b === void 0 ? void 0 : b.trim()) || 'bin';
136
+ const $li = $('div.dl-info > ul.details > li');
137
+ const upload_date = $li.eq(1).find('span').text().trim();
138
+ const filesize = $li.eq(0).find('span').text().trim();
139
+ const filesizeB = formatSize(filesize);
140
+ const result = {
141
+ url: Url || url2,
142
+ url2,
143
+ filename,
144
+ filetype,
145
+ ext,
146
+ upload_date,
147
+ filesize,
148
+ filesizeB
149
+ };
150
+ resolve(result);
151
+ }
152
+ } catch (error) {
153
+ reject(error);
154
+ }
155
+ });
156
  }
157
 
158
 
 
160
  async function igdl(query) {
161
  url_dl = [];
162
  let headers = {
163
+ 'Accept': '/',
164
+ 'Accept-Language': 'en-US,en;q=0.9',
165
+ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
166
+ 'Referer': 'https://saveig.app/',
167
+ 'Referrer-Policy': 'strict-origin-when-cross-origin',
168
+ 'X-Requested-With': 'XMLHttpRequest'
169
+ }
170
  let options = {
171
  method: 'POST',
172
  uri: 'https://saveig.app/api/ajaxSearch',
 
183
  //FBDL
184
  async function fby2mate(url) {
185
  try {
186
+ let form = new FormData();
187
+ form.append('q', url);
188
+ form.append('vt', 'facebook');
189
+ let data = await fetch('https://y2mate.mx/api/ajaxSearch/facebook', {
190
+ method: 'POST',
191
+ body: form,
192
+ headers: {
193
+ 'User-Agent': generateRandomUserAgent(),
194
+ 'X-Forwarded-For': generateRandomIP(),
195
+ ...form.getHeaders()
196
+ }
197
+ });
198
+ data = await data.json();
199
+ return data;
200
  } catch (e) {
201
+ return e;
202
  }
203
  }
204
 
205
  //YTDL-CORE
206
  async function uploadBuffer(media) {
207
+ return new Promise(async (resolve, reject) => {
208
+ try {
209
+ let {fileTypeFromBuffer} = await (await import('file-type'))
210
+ let mime = await fileTypeFromBuffer(media);
211
+ let form = new FormData();
212
+ form.append("files[]", media, `file-${new Date().getTime()}.${mime.ext}`);
213
+
214
+ let response = await axios.post("https://pomf.lain.la/upload.php", form, {
215
+ headers: {
216
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0",
217
+ ...form.getHeaders()
218
+ }
219
+ });
220
+
221
+ resolve(response.data?.files[0]?.url || null);
222
+ } catch (error) {
223
+ console.error(error);
224
+ resolve(null); // Ensure null is returned if there's an error
225
+ }
226
+ });
227
  }
228
  async function streamToBuffer(stream) {
229
+ const chunks = [];
230
+ const captureChunks = new Writable({
231
+ write(chunk, encoding, callback) {
232
+ chunks.push(chunk);
233
+ callback();
234
+ }
235
+ });
 
 
236
 
237
+ await util.promisify(pipeline)(stream, captureChunks);
238
+
239
+ return Buffer.concat(chunks);
240
+ }
241
  function formatViews(viewCount) {
242
+ if (viewCount >= 1000000000) {
243
+ return (viewCount / 1000000000).toFixed(1) + 'B';
244
+ } else if (viewCount >= 1000000) {
245
+ return (viewCount / 1000000).toFixed(1) + 'M';
246
+ } else {
247
+ return viewCount >= 1000
248
+ ? (viewCount / 1000).toFixed(1) + 'K'
249
+ : viewCount.toString();
250
+ }
251
  }
252
 
253
  function formatDuration(durationInSeconds) {
254
+ const hours = Math.floor(durationInSeconds / 3600);
255
+ const minutes = Math.floor((durationInSeconds % 3600) / 60);
256
+ const seconds = durationInSeconds % 60;
257
+
258
+ return hours > 0
259
+ ? hours +
260
+ ':' +
261
+ minutes.toString().padStart(2, '0') +
262
+ ':' +
263
+ seconds.toString().padStart(2, '0')
264
+ : minutes + ':' + seconds.toString().padStart(2, '0');
265
  }
266
 
267
  function formatSize(bytes, si = false, dp = 2) {
268
+ const thresh = si ? 1000 : 1024;
 
 
 
 
269
 
270
+ if (Math.abs(bytes) < thresh) {
271
+ return `${bytes} B`;
272
+ }
 
 
273
 
274
+ const units = si
275
+ ? ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
276
+ : ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
277
+ let u = -1;
278
+ const r = 10 ** dp;
279
+
280
+ do {
281
+ bytes /= thresh;
282
+ ++u;
283
+ } while (
284
+ Math.round(Math.abs(bytes) * r) / r >= thresh &&
285
+ u < units.length - 1
286
+ );
287
+
288
+ return `${bytes.toFixed(dp)} ${units[u]}`;
289
+ }
290
 
291
+ async function ytmp4(url, quality = 'highestvideo') {
292
+ try {
293
+ const ID = ytdl.getVideoID(url),
294
+ data = await ytdl.getInfo('https://www.youtube.com/watch?v=' + ID);
295
+ const videoStream = await ytdl(ID, { filter: format => format.hasVideo && format.hasAudio, quality: quality });
296
+ let buffer = await streamToBuffer(videoStream);
297
+ let upload = await uploadBuffer(buffer);
298
+ let urel = upload != null ? { url_v2: upload } : null;
299
+ let format = ytdl.chooseFormat(data.formats, { filter: format => format.hasVideo && format.hasAudio, quality: quality });
300
+
301
+
302
+ if (format) {
303
+ return {
304
+ title: data.videoDetails.title,
305
+ description: data.videoDetails.description,
306
+ channel: data.videoDetails.ownerChannelName,
307
+ views: formatViews(data.videoDetails.viewCount),
308
+ publish: data.videoDetails.publishDate,
309
+ duration: formatDuration(data.videoDetails.lengthSeconds),
310
+ size: format.contentLength ? formatSize(format.contentLength) : 0,
311
+ quality: format.qualityLabel,
312
+ thumb: data.videoDetails.thumbnails[0].url,
313
+ dl_url: format.url,
314
+ ...urel,
315
+ };
316
+ } else {
317
+ throw new Error('No suitable format found');
318
+ }
319
+ } catch (error) {
320
+ console.error('Error occurred:', error);
321
+ return error;
322
+ }
323
  }
324
 
325
+ async function ytmp3(url, bitrate = 'lowestaudio') {
326
+ try {
327
+ const ID = ytdl.getVideoID(url),
328
+ data = await ytdl.getInfo('https://www.youtube.com/watch?v=' + ID);
329
+ const audioStream = await ytdl(ID, { filter: 'audioonly', quality: bitrate });
330
+ let buffer = await streamToBuffer(audioStream);
 
331
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332
 
333
+ async function convertToAudio(buffer, ext) {
334
  try {
335
+ const tmp = path.join(os.tmpdir(), `${+new Date()}.${ext}`);
336
+ const out = `${tmp}.mp3`;
337
+ await fs.promises.writeFile(tmp, buffer);
338
+
339
+ const ffmpegProcess = cp.spawn('ffmpeg', [
340
+ '-y',
341
+ '-i', tmp,
342
+ '-vn',
343
+ '-ac', '2',
344
+ '-b:a', '128k',
345
+ '-ar', '44100',
346
+ '-f', 'mp3',
347
+ out
348
+ ]);
349
+
350
+ await new Promise((resolve, reject) => {
351
+ ffmpegProcess.on('error', (err) => {
352
+ console.error(err);
353
+ reject(err);
354
+ });
355
+ ffmpegProcess.on('close', (code) => {
356
+ if (code !== 0) {
357
+ reject(`ffmpeg process closed with code: ${code}`);
358
+ } else {
359
+ resolve();
360
+ }
361
+ });
362
  });
363
 
364
+ const result = await fs.promises.readFile(out);
365
+ await fs.promises.unlink(tmp);
366
+ await fs.promises.unlink(out);
367
+ return result;
368
+ } catch (e) {
369
+ console.error(e);
370
+ throw e;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
  }
372
  }
373
 
374
+ let konver = await convertToAudio(buffer, "mp4");
375
+ let upload = await uploadBuffer(konver);
376
+ let urel = upload != null ? { url_v2: upload } : null;
377
+ let format = ytdl.chooseFormat(data.formats, { filter: 'audioonly', quality: bitrate });
378
+
379
+ if (format) {
380
+ return {
381
+ title: data.videoDetails.title,
382
+ description: data.videoDetails.description,
383
+ channel: data.videoDetails.ownerChannelName,
384
+ views: formatViews(data.videoDetails.viewCount),
385
+ publish: data.videoDetails.publishDate,
386
+ duration: formatDuration(data.videoDetails.lengthSeconds),
387
+ size: format.contentLength ? formatSize(format.contentLength) : 0,
388
+ quality: format.audioQuality,
389
+ thumb: data.videoDetails.thumbnails[0].url,
390
+ dl_url: format.url,
391
+ ...urel,
392
+ };
393
+ } else {
394
+ throw new Error('No suitable format found');
395
+ }
396
+ } catch (error) {
397
+ console.error('Error occurred:', error);
398
+ return error;
399
+ }
400
+ }
401
 
402
  // Fungsi untuk mengkonversi video dari YouTube
403
  const convert = async (url, v_id, ftype, fquality, fname, token, timeExpire) => {
404
+ let params = {
405
+ v_id,
406
+ ftype,
407
+ fquality,
408
+ fname,
409
+ token,
410
+ timeExpire,
411
+ client: 'yt5s.com'
412
+ };
413
+
414
+ // Mengirim permintaan konversi
415
+ let resServer = await (await post(url, params, { 'x-requested-key': 'de0cfuirtgf67a' })).json();
416
+ let server = resServer.c_server;
417
+
418
+ // Jika tidak ada server dan tipe file adalah mp3, kembalikan null
419
+ if (!server && ftype === 'mp3') return server || resServer.d_url || '';
420
+
421
+ // Mengambil data hasil konversi
422
+ let data = await (await post(`${server}/api/json/convert`, params)).json();
423
+ let result;
424
+
425
+ // Memeriksa status kode hasil konversi
426
+ if (data.statusCode === 200) result = data.result;
427
+ while (!result) {
428
+ let json = await (await post(`${server}/api/json/convert`, params)).json();
429
+ if (json.statusCode === 200) {
430
+ result = json.result;
431
+ break;
 
 
432
  }
433
+ await new Promise(resolve => setTimeout(resolve, 2000));
434
+ }
435
+ return result;
436
  };
437
 
438
  // Fungsi untuk mendownload video dari YouTube
439
+ const youtubedl = async (url) => {
440
+ let html = await (await fetch('https://yt5s.com/en32', {headers: {
441
+ 'User-Agent': generateRandomUserAgent(),
442
+ 'X-Forwarded-For': generateRandomIP(),
443
  }})).text();
444
+ let urlAjax = (html.match(/k_url_search="(.?)"/) || [])[1];
445
+ let urlConvert = (html.match(/k_url_convert="(.?)"/) || [])[1];
446
+ let json = await (await post(urlAjax, { q: url, vt: 'home' })).json();
447
+ let video = {}, audio = {};
448
+ if (!json?.links) throw json.mess;
449
+ Object.values(json.links.mp4).map(({ k, size }) => video[k] = {
450
+ quality: k,
451
+ fileSizeH: size,
452
+ fileSize: parseFloat(size) * (/MB$/.test(size) ? 1000 : 1),
453
+ download: convert.bind(null, urlConvert, json.vid, 'mp4', k, json.fn, json.token, parseInt(json.timeExpires))
454
+ });
455
 
456
+ Object.values(json.links.mp3).map(({ key, size }) => audio[key] = {
457
+ quality: key,
458
+ fileSizeH: size,
459
+ fileSize: parseFloat(size) * (/MB$/.test(size) ? 1000 : 1),
460
+ download: convert.bind(null, urlConvert, json.vid, 'mp3', key.replace(/kbps/i, ''), json.fn, json.token, parseInt(json.timeExpires))
461
+ });
462
 
463
+ return {
464
+ id: json.vid,
465
+ title: json.title,
466
+ thumbnail: `https://i.ytimg.com/vi/${json.vid}/0.jpg`,
467
+ video,
468
+ audio
469
+ };
470
  };
471
 
472
  //TWITTER API
473
  async function twitterDL(url) {
474
+ try {
475
+ let form = new FormData();
476
+ form.append('q', url);
477
+ form.append('lang', 'en');
478
+ let response = await fetch('https://x2twitter.com/api/ajaxSearch', {
479
+ method: 'POST',
480
+ body: form,
481
+ headers: {
482
+ 'User-Agent': generateRandomUserAgent(),
483
+ 'X-Forwarded-For': generateRandomIP(),
484
+ ...form.getHeaders()
485
+ }
486
+ });
487
 
488
+ let data = await response.json();
489
+ const $ = cheerio.load(data?.data);
490
+ let downloads = [];
 
 
 
 
 
 
491
 
492
+ $('.dl-action a').each((index, element) => {
493
+ const format = $(element).text().trim();
494
+ const url = $(element).attr('href');
495
+ if (url !== '#') {
496
+ downloads.push({ format, url });
497
+ }
498
+ });
499
 
500
+ // Jika tidak ada unduhan dari load pertama, coba load kedua
501
+ if (downloads.length === 0) {
502
+ $('a').each((index, element) => {
503
+ const href = $(element).attr('href');
504
+ if (href && href !== '/' && href !== '#') {
505
+ downloads.push(href);
506
  }
507
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
508
  }
 
509
 
510
+ return { downloads };
511
+ } catch (error) {
512
+ return error;
513
+ }
514
+ }
515
 
516
  const app = express();
517
  app.set('json spaces', 4);
 
520
 
521
  const v8 = require('v8');
522
 
523
+ app.all('/', async (req, res) => {
524
+ const status = {}
525
+ status['diskUsage'] = cp.execSync('du -sh').toString().split('M')[0] + ' MB'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
 
527
+ const used = process.memoryUsage()
528
+ for (let x in used) status[x] = formatSize(used[x])
529
 
530
+ const totalmem = os.totalmem()
531
+ const freemem = os.freemem()
532
+ status['memoryUsage'] = `${formatSize(totalmem - freemem)} / ${formatSize(totalmem)}`
533
 
534
+ // Menambahkan statistik heap V8
535
+ const heapStats = v8.getHeapStatistics();
536
+ for (let x in heapStats) status[x] = formatSize(heapStats[x])
537
+
538
+ // Menambahkan semua properti dan metode dari v8
539
+ for (let x in v8) {
540
+ if (typeof v8[x] !== 'function') {
541
+ status[x] = v8[x]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
542
  }
543
  }
544
+
545
+ const host = 'https://' + req.get('host');
546
+
547
+ res.json({
548
+ creator: `@${process.env['SPACE_AUTHOR_NAME'] || 'ALOK FF'}`,
549
+ message: 'Hello World!',
550
+ uptime: new Date(process.uptime() * 1000).toUTCString().split(' ')[4],
551
+ status, // Menambahkan latency ke JSON
552
+ list: [
553
+ {
554
+ title: "BING AI",
555
+ method: "GET",
556
+ example: `${host}/bing?q=`
557
+ },
558
+ {
559
+ title: "Facebook Downloader",
560
+ method: "GET",
561
+ example: `${host}/fb?url=`
562
+ },
563
+ {
564
+ title: "Instagram Downloader",
565
+ method: "GET",
566
+ example: `${host}/ig?url=`
567
+ },
568
+ {
569
+ title: "Mediafire Downloader",
570
+ method: "GET",
571
+ example: `${host}/mediafire?url=`
572
+ },
573
+ {
574
+ title: "Mega Downloader",
575
+ method: "GET",
576
+ example: `${host}/mega?url=${encodeURIComponent('url')}`
577
+ },
578
+ {
579
+ title: "Pinterest Downloader",
580
+ method: "GET",
581
+ example: `${host}/pindl?url=`
582
+ },
583
+ {
584
+ title: "Tiktok Downloader",
585
+ method: "GET",
586
+ example: `${host}/tt?url=`
587
+ },
588
+ {
589
+ title: "Twitter/X Downloader",
590
+ method: "GET",
591
+ example: `${host}/twitter?url=`
592
+ },
593
+ {
594
+ title: "Whatmusic Search",
595
+ method: "GET",
596
+ example: `${host}/whatmusic?url=`
597
+ },
598
+ {
599
+ title: "Youtube Downloader",
600
+ method: "GET",
601
+ example: `${host}/ytdl?url=`
602
+ },
603
+ {
604
+ title: "Youtube Search",
605
+ method: "GET",
606
+ example: `${host}/ytsearch?q=`
607
+ }
608
+ ]
609
+ });
610
+
611
+
612
+ app.get('/yt', async (req, res) => {
613
+ const host = 'https://' + req.get('host');
614
+ try {
615
+ let { url, type, quality, json } = req.query;
616
+ if (!ytIdRegex.test(url)) return res.json({ message: 'Invalid URL' });
617
+ if (!!json) {
618
+ let ytId = ytIdRegex.exec(url)?.[1];
619
+ if (!ytId) return res.json({ message: 'No video id found' });
620
+ let data = await yts({ videoId: ytId });
621
+ const downloadUrls = {
622
+ audio: `${host}/yt?url=${url}&type=audio&quality=128kbps`,
623
+ video: `${host}/yt?url=${url}&type=video&quality=`,
624
+ };
625
+ return res.json({
626
+ ...data,
627
+ download: downloadUrls
628
  });
629
+ }
630
+ if (!type || !/audio|video/i.test(type)) type = 'video';
631
+ let data = await youtubedl(url).catch(e => console.log(e));
632
+ if (!data) return res.json({ message: 'Error: link download not found' });
633
+ type = type.toLowerCase();
634
+ let result = quality ? Object.values(data[type]).find(x => x.quality == quality) : Object.values(data[type])[0];
635
+ if (quality && !result) return res.json({ message: `Invalid quality: ${quality}, available quality (${Object.keys(data[type]).join('/')})` });
636
+ if (!result) return res.json({ message: 'Error: can\'t download' });
637
+ res.redirect(await result.download());
638
+ } catch (e) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
639
  console.log(e);
640
  return res.json({ message: e.message });
641
  }
642
  });
643
+ app.get('/ig', async (req,res) => {
644
+ try {
645
+ let {url} = req.query
646
+ let regex = /https?:\/\/(www\.)?instagram\.com\/(p|reel|tv)\/[a-zA-Z0-9_-]+\/?/;
647
+ if (!regex.test(url)) return res.json({ message: 'Invalid URL' });
648
+ let data = await igdl(url)
649
+ return res.json(data)
650
+ } catch (e) {
651
+ console.log(e);
652
+ return res.json({ message: e.message });
653
+ }
654
+ });
655
+ app.get('/tt', async (req, res) => {
656
+ try {
657
+ let { url } = req.query
658
+ let regex = /https?:\/\/(www\.)?(tiktok\.com|vt\.tiktok\.com|v\.tiktok\.com|t\.tiktok\.com)/;
659
+ if (!regex.test(url)) return res.json({ message: 'Invalid URL' });
660
+ let data = await fetch(`https://tikwm.com/api/?url=${url}`, {
661
+ headers: {
662
+ 'User-Agent': generateRandomUserAgent(),
663
+ 'X-Forwarded-For': generateRandomIP(),
664
+ }
665
+ });
666
+ data = await data.json();
667
+ if (!data) return res.json({ message: 'API TO API KOID' });
668
+ return res.json(data);
669
+ } catch (e) {
670
+ console.log(e);
671
+ return res.json({ message: e.message });
672
+ }
673
+ });
674
 
675
+ app.get('/pindl', async (req, res) => {
676
+ try {
677
+ let { url } = req.query
678
+ let regex = /https:\/\/pin\.it\/\w+|https:\/\/[a-z]{2}\.pinterest\.com\/pin\/\d+/;
679
+ if (!regex.test(url)) return res.json({ message: 'Invalid URL' });
680
+ let data = await fetch(`https://pinterestdownloader.io/id/frontendService/DownloaderService?url=${url}`, {
681
+ headers: {
682
+ 'User-Agent': generateRandomUserAgent(),
683
+ 'X-Forwarded-For': generateRandomIP(),
684
+ }
685
+ });
686
+ data = await data.json();
687
+ if (!data) return res.json({ message: 'API TO API KOID' });
688
+ return res.json(data);
689
+ } catch (e) {
690
+ console.log(e);
691
+ return res.json({ message: e.message });
692
+ }
693
+ });
694
+
695
+ app.get('/fb', async (req, res) => {
696
+ try {
697
+ let {url} = req.query
698
+ let regex = /https?:\/\/(fb\.watch|(www\.|web\.|m\.)?facebook\.com)/;
699
+ if (!regex.test(url)) return res.json({ message: 'Invalid URL' });
700
+ let data = await fby2mate(url)
701
+ return res.json(data)
702
+ } catch (e) {
703
+ console.log(e);
704
+ return res.json({ message: e.message });
705
+ }
706
+ });
707
+ app.get('/bimg', async (req, res) => {
708
+ try {
709
+ let q = req.query.q || req.query.query;
710
+ if (!q) return res.json({ message: 'Input parameter q' });
711
+ let data = await bimg(q)
712
+ return res.json({query: q, data: data})
713
+ } catch (e) {
714
+ console.log(e);
715
+ return res.json({ message: e.message });
716
+ }
717
+ });
718
+ app.get('/bing', async (req, res) => {
719
+ try {
720
+ let q = req.query.q || req.query.query;
721
+ if (!q) return res.json({ message: 'Input parameter q' });
722
+ let data = await bingChat(q)
723
+ if (data.length === 0) {
724
+ async function gpt4o(prompt) {
725
+ let session_hash = Math.random().toString(36).substring(2);
726
+
727
  try {
728
+ let resPrompt = await axios.post('https://kingnish-opengpt-4o.hf.space/run/predict?__theme=light', {
729
+ "data": [{
730
+ "text": prompt,
731
+ "files": []
732
+ }],
733
+ "event_data": null,
734
+ "fn_index": 3,
735
+ "trigger_id": 34,
736
+ "session_hash": session_hash
737
+ });
738
+
739
+ let res = await axios.post('https://kingnish-opengpt-4o.hf.space/queue/join?__theme=light', {
740
+ "data": [
741
+ null,
742
+ null,
743
+ "idefics2-8b-chatty",
744
+ "Top P Sampling",
745
+ 0.5,
746
+ 4096,
747
+ 1,
748
+ 0.9,
749
+ true
750
+ ],
751
+ "event_data": null,
752
+ "fn_index": 5,
753
+ "trigger_id": 34,
754
+ "session_hash": session_hash
755
+ });
756
+
757
+ let event_ID = res.data.event_id;
758
+
759
+ let anu = await axios.get('https://kingnish-opengpt-4o.hf.space/queue/data?session_hash=' + session_hash);
760
+ const lines = anu.data.split('\n');
761
+ const processStartsLine = lines.find(line => line.includes('process_completed'));
762
+
763
+ if (processStartsLine) {
764
+ const processStartsData = JSON.parse(processStartsLine.replace('data: ', ''));
765
+ let ress = processStartsData.output.data;
766
+ let result = ress[0][0][1];
767
+ return result;
768
+ } else {
769
+ return 'error kang!';
770
  }
771
+ } catch (error) {
772
+ console.error(error);
773
+ return 'error kang!';
 
 
 
 
 
 
 
 
774
  }
775
+ }
776
+
777
+ data = await gpt4o(q)
778
+ //return res.json({message: 'Terkena Chaptcha BOT!!!'})
779
+ }
780
+ return res.json({result
781
+ })
782
+ } catch (e) {
783
+ console.log(e);
784
+ return res.json({ message: e.message });
785
+ }
786
+ })
787
+ app.get('/whatmusic', async (req, res) => {
788
+ try {
789
+ let { url } = req.query
790
+ async function downloadBuffer(url) {
791
+ try {
792
+ const response = await axios({
793
+ method: 'get',
794
+ url: url,
795
+ responseType: 'arraybuffer'
796
+ });
797
+ return Buffer.from(response.data, 'binary');
798
+ } catch (error) {
799
+ throw new Error(`Failed to download the file: ${error.message}`);
800
+ }
801
+ }
802
+ if (!url) return res.json({ message: 'Input parameter url' });
803
+ if (!isUrl(url)) return res.json({ message: 'Invalit Input Link' })
804
+ let data = await acrCloud(await downloadBuffer(isUrl(url)[0]))
805
+ if (!data) return res.json({ error: 'Error'});
806
+ return res.json(data);
807
+ } catch (e) {
808
+ console.log(e);
809
+ return res.json({ message: e.message });
810
+ }
811
+ })
812
+ app.get('/ytsearch', async (req, res) => {
813
+ try {
814
+ let q = req.query.q || req.query.query;
815
+ if (!q) return res.json({ message: 'Input parameter q' });
816
+ let data = await yts(q);
817
+ if (!data.all[0]) return res.json({ message: 'Not found' });
818
+ return res.json(data.all);
819
+ } catch (e) {
820
+ console.log(e);
821
+ return res.json({ message: e.message });
822
+ }
823
+ });
824
+ app.get('/mediafire', async (req, res) => {
825
+ try {
826
+ let { url } = req.query
827
+ //console.log(url)
828
+ if (!/https?:\/\/(www\.)?mediafire\.com\/(file|download)/i.test(url)) {
829
+ return res.json({ message: 'Invalid URL' });
830
+ }
831
+ let data = await mediafire(url)
832
+ return res.json(data)
833
+ } catch (e) {
834
+ console.log(e);
835
+ return res.json({ message: e.message });
836
+ }
837
+ });
838
+ app.get('/ytdl', async (req, res) => {
839
+ try {
840
+ let { url } = req.query
841
+ if (!ytIdRegex.test(url)) return res.json({ message: 'Invalid URL' });
842
+ let video = await ytmp4(url)
843
+ let audio = await ytmp3(url)
844
+ return res.json({
845
+ video: video,
846
+ audio: audio
847
+ })
848
+ } catch (e) {
849
+ console.log(e);
850
+ return res.json({ message: e.message });
851
+ }
852
+ });
853
+ app.get('/twitter', async (req, res) => {
854
+ try {
855
+ let { url } = req.query;
856
+ url = url.replace('x.com', 'twitter.com'); // Mengganti x.com dengan twitter.com dalam URL
857
+ if (!/(https?:\/\/(www\.)?(twitter|x)\.com\/.*\/status\/.*)/.test(url)) {
858
+ return res.json({ message: 'Invalid URL' });
859
+ }
860
+ let data = await twitterDL(url);
861
+ return res.json(data);
862
+ } catch (e) {
863
+ console.log(e);
864
+ return res.json({ message: e.message });
865
+ }
866
+ });
867
+
868
+
869
+ app.get('/mega', async (req, res) => {
870
+ try {
871
+ let { url } = req.query;
872
+ if (!/https:\/\/mega\.nz\/file\/[a-zA-Z0-9]{8}#[a-zA-Z0-9-_]{43}/.test(url)) {
873
+ return res.json({ message: 'Invalid URL' });
874
+ }
875
+ const file = File.fromURL(url);
876
+ await file.loadAttributes();
877
+ let data = await file.downloadBuffer();
878
+ return res.json({
879
+ title: file.name,
880
+ size: formatSize(file.size),
881
+ base64: data.toString('base64')
882
+ })
883
+ } catch (e) {
884
+ console.log(e);
885
+ return res.json({ message: e.message });
886
+ }
887
  });
888
+ app.listen(7860, () => console.log('App running on port 7860'));