Nexchan commited on
Commit
8bb3cd6
1 Parent(s): f73e0fd

Update index.js

Browse files
Files changed (1) hide show
  1. index.js +516 -516
index.js CHANGED
@@ -1,516 +1,516 @@
1
- import axios from 'axios';
2
- import cheerio from 'cheerio';
3
- import { createRequire } from 'module';
4
- import os from 'os';
5
- import express from 'express';
6
- import { promisify } from 'util';
7
- import { fileTypeFromBuffer } from 'file-type';
8
- import ffmpeg from 'fluent-ffmpeg';
9
- import nodeID3 from 'node-id3';
10
- import ytdl from 'ytdl-core';
11
- import FormData from 'form-data';
12
- const require = createRequire(import.meta.url);
13
- const fs = require('fs');
14
- const path = require('path');
15
- const { google } = require('googleapis');
16
- const PORT = process.env.PORT || 5000;
17
- const app = express();
18
- const readFileAsync = promisify(fs.readFile);
19
- import fetch from 'node-fetch';
20
-
21
- const tempDir = path.join(os.tmpdir(), "temp");
22
- const fss = fs.promises;
23
-
24
- (async () => {
25
- if (!fs.existsSync(tempDir)) {
26
- await fss.mkdir(tempDir, { recursive: true });
27
- }
28
- })();
29
-
30
- const youtube = google.youtube({ version: 'v3', auth: 'AIzaSyBPkpdJEGtAHebbaP3_CcA1_urfMFfeLLg' });
31
-
32
- app.use('/temp', express.static(tempDir));
33
- app.use(express.json());
34
- app.get("/", (req, res) => {
35
- res.type("json");
36
- const keluaran = {
37
- success: true,
38
- author: "Nex",
39
- data: {
40
- igdl: "/igdl",
41
- twdl: "/twdl"
42
- },
43
- };
44
- res.send(keluaran);
45
- });
46
-
47
- const generateRandomIP = () => {
48
- const octet = () => Math.floor(Math.random() * 256);
49
- return `${octet()}.${octet()}.${octet()}.${octet()}`;
50
- };
51
-
52
- async function igdl1(url) {
53
- const apiEndpoint = 'https://v3.igdownloader.app/api/ajaxSearch';
54
- const requestOptions = {
55
- headers: {
56
- 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
57
- 'Accept': '*/*',
58
- 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; SM-S908B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.58 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/357.0.0.23.115;]',
59
- 'Referer': 'https://igdownloader.app/en',
60
- 'X-Forwarded-For': generateRandomIP()
61
- },
62
- };
63
- const postData = `recaptchaToken=&q=${encodeURIComponent(url)}&t=media&lang=en`;
64
- try {
65
- const response = await axios.post(apiEndpoint, postData, requestOptions);
66
- const $ = cheerio.load(response.data.data);
67
- const downloadLinks = $('div.download-items__btn > a');
68
- return await Promise.all(downloadLinks.map(async (index, element) => $(element).attr('href')));
69
- } catch (error) {
70
- console.error('Instagram Downloader 1 - Error:', error.message);
71
- return null;
72
- }
73
- }
74
-
75
- async function igdl2(url) {
76
- try {
77
- const response = await axios.post('https://fastdl.app/c/', {
78
- url: url,
79
- lang_code: 'en',
80
- token: ''
81
- }, {
82
- headers: {
83
- 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
84
- 'Accept': '*/*',
85
- 'X-Requested-With': 'XMLHttpRequest',
86
- 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36',
87
- 'Referer': 'https://fastdl.app/'
88
- },
89
- responseType: 'arraybuffer'
90
- });
91
- const html = response.data.toString('utf-8');
92
- const $ = cheerio.load(html);
93
- $('img').remove();
94
- const links = [];
95
- $('a').each((index, element) => links.push($(element).attr('href')));
96
- return links;
97
- } catch (error) {
98
- console.error('Error downloading Instagram post:', error);
99
- return null;
100
- }
101
- }
102
-
103
- async function igdl3(url) {
104
- const apiEndpoint = 'https://co.wuk.sh/api/json';
105
- const requestData = { url, aFormat: 'mp3', filenamePattern: 'classic', dubLang: false, vQuality: '720' };
106
- const headers = {
107
- 'Accept': 'application/json',
108
- 'Content-Type': 'application/json',
109
- 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36',
110
- 'Referer': 'https://cobalt.tools/',
111
- };
112
- try {
113
- const response = await axios.post(apiEndpoint, requestData, { headers });
114
- const array_res = [];
115
- if (response.data.status === 'redirect') {
116
- array_res.push(response.data.url);
117
- } else if (response.data.status === 'picker') {
118
- response.data.picker.forEach(item => array_res.push(item.url));
119
- }
120
- return array_res;
121
- } catch (error) {
122
- console.error('Instagram Downloader 3 - Error:', error.message);
123
- return null;
124
- }
125
- }
126
-
127
- async function igdl4(url) {
128
- try {
129
- const apiEndpoint = 'https://v3.saveig.app/api/ajaxSearch';
130
- const requestOptions = {
131
- headers: {
132
- 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
133
- 'Accept': '*/*',
134
- 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; SM-S908B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.58 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/357.0.0.23.115;]',
135
- 'Referer': 'https://saveig.app/en',
136
- },
137
- };
138
- const postData = `recaptchaToken=&q=${encodeURIComponent(url)}&t=media&lang=en`;
139
- const response = await axios.post(apiEndpoint, postData, requestOptions);
140
- const $ = cheerio.load(response.data.data);
141
- const downloadLinks = $('div.download-items__btn > a');
142
- return await Promise.all(downloadLinks.map(async (index, element) => $(element).attr('href')));
143
- } catch (error) {
144
- console.error('Instagram Downloader 4 - Error:', error.message);
145
- return null;
146
- }
147
- }
148
-
149
- async function twdl1(url) {
150
- const apiUrl = 'https://savetwitter.net/api/ajaxSearch';
151
- const headers = {
152
- 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
153
- 'Accept': '*/*',
154
- 'X-Requested-With': 'XMLHttpRequest',
155
- 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; SM-S908B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.58 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/357.0.0.23.115;]',
156
- 'Referer': 'https://x2twitter.com/id',
157
- 'X-Forwarded-For': generateRandomIP(),
158
- };
159
- const data = `q=${encodeURIComponent(url)}&lang=id`;
160
-
161
- try {
162
- const response = await axios.post(apiUrl, data, {
163
- headers
164
- });
165
- if (!response.data.hasOwnProperty('data')) {
166
- throw new Error('Data tidak ditemukan di response');
167
- }
168
- const $ = cheerio.load(response.data.data);
169
-
170
- $('a[onclick="showAd()"][href="#"]').remove();
171
- $('a[href="/"]').remove();
172
- $('a[href="#"]').remove();
173
-
174
- const hrefs = [];
175
- $('.dl-action').each((index, element) => {
176
- const firstAnchor = $(element).find('a').first();
177
- hrefs.push(firstAnchor.attr('href'));
178
- });
179
-
180
- return hrefs;
181
-
182
- } catch (error) {
183
- throw new Error('Failed to fetch Twitter image: ' + error);
184
- }
185
- }
186
-
187
-
188
-
189
- async function twdl2(url) {
190
- const apiUrl = 'https://x2twitter.com/api/ajaxSearch';
191
- const headers = {
192
- 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
193
- 'Accept': '*/*',
194
- 'X-Requested-With': 'XMLHttpRequest',
195
- 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; SM-S908B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.58 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/357.0.0.23.115;]',
196
- 'Referer': 'https://x2twitter.com/id',
197
- 'X-Forwarded-For': generateRandomIP(),
198
- };
199
- const data = `q=${encodeURIComponent(url)}&lang=id`;
200
-
201
- try {
202
- const response = await axios.post(apiUrl, data, {
203
- headers
204
- });
205
- if (!response.data.hasOwnProperty('data')) {
206
- throw new Error('Data tidak ditemukan di response');
207
- }
208
- const $ = cheerio.load(response.data.data);
209
-
210
- $('a[onclick="showAd()"][href="#"]').remove();
211
- $('a[href="/"]').remove();
212
-
213
- const hrefs = [];
214
- $('.dl-action').each((index, element) => {
215
- const firstAnchor = $(element).find('a').first();
216
- hrefs.push(firstAnchor.attr('href'));
217
- });
218
-
219
- return hrefs;
220
-
221
- } catch (error) {
222
- throw new Error('Failed to fetch Twitter image: ' + error);
223
- }
224
- }
225
-
226
-
227
-
228
- async function twdl3(url) {
229
- const apiUrl = 'https://twtube.app/en/download?url=';
230
-
231
- const headers = {
232
- 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
233
- 'Accept': '*/*',
234
- 'X-Requested-With': 'XMLHttpRequest',
235
- 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; SM-S908B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.58 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/357.0.0.23.115;]',
236
- 'Referer': 'https://savetwitter.net/id/twitter-image-downloader',
237
- 'X-Forwarded-For': generateRandomIP(),
238
- };
239
- try {
240
- const response = await axios.get(apiUrl + url, {
241
- headers
242
- });
243
- const $ = cheerio.load(response.data);
244
- // Mendapatkan semua href dari elemen a dalam div dengan kelas 'square-box-btn'
245
- const allHrefs = [];
246
- // Menggunakan map untuk mengambil href dan mengembalikan array promise
247
- const promises = $('.square-box-btn a').map(async (index, element) => {
248
- let link = $(element).attr('href');
249
- return link;
250
- }).get();
251
- // Menunggu semua promise selesai dan mengumpulkan hasilnya
252
- return Promise.all(promises);
253
- } catch (error) {
254
- throw new Error('Failed to fetch Twitter image: ' + error);
255
- }
256
- }
257
-
258
- async function DownloadFile(url) {
259
- try {
260
- const response = await axios.get(url, { responseType: 'arraybuffer' });
261
- const mimeType = response.headers['content-type'];
262
- const buffer = response.data;
263
- const fileExtension = (await fileTypeFromBuffer(buffer)).ext;
264
- const filename = `downloaded_file_${Date.now()}.${fileExtension}`;
265
- const filePath = path.join(tempDir, filename);
266
- await fss.writeFile(filePath, buffer);
267
- console.log(`File berhasil diunduh dan disimpan sebagai: ${filePath}`);
268
- return { mimeType, filePath };
269
- } catch (error) {
270
- console.error('Error saat mengunduh file:', error);
271
- return null;
272
- }
273
- }
274
-
275
-
276
-
277
- const getInstagramDownloadLinks = async (url) => {
278
- let result = await igdl1(url);
279
- if (!result || result.length === 0) {
280
- result = await igdl2(url);
281
- }
282
- if (!result || result.length === 0) {
283
- result = await igdl3(url);
284
- }
285
- if (!result || result.length === 0) {
286
- result = await igdl4(url);
287
- }
288
- if (!result || result.length === 0) {
289
- result = {
290
- message: "all server error"
291
- };
292
- }
293
- return result;
294
- };
295
-
296
- const Twitter = async (url) => {
297
- let result = await twdl3(url);
298
- if (!result || result.length === 0) {
299
- result = await twdl2(url);
300
- }
301
- if (!result || result.length === 0) {
302
- result = await twdl1(url);
303
- }
304
- if (!result || result.length === 0) {
305
- result = {
306
- message: "all server error"
307
- };
308
- }
309
- return result;
310
- };
311
-
312
- app.get('/igdl', async (req, res) => {
313
- try {
314
- const { url } = req.query;
315
- if (!url) return res.status(400).json({ error: 'Parameter url is required' });
316
- if (!/https?:\/\/(www\.)?instagram\.com\/(p|reel|tv)/.test(url)) return res.status(400).json({ error: "Example: https://www.instagram.com/p/Cz1fTwMJFpx/?igsh=MXRrY2g4eWNucGoyZg==" });
317
- let result = await getInstagramDownloadLinks(url);
318
- let result_upload = {
319
- media: []
320
- }
321
-
322
- for (let item of result) {
323
- let unduh = await DownloadFile(item);
324
- result_upload.media.push({
325
- type: unduh.mimeType,
326
- path: unduh.filePath,
327
- url_path: `https://downloader-nex.vercel.app/temp/${path.basename(unduh.filePath)}`
328
- });
329
- }
330
-
331
- res.json(result_upload);
332
-
333
- for (let item of result_upload.media) {
334
- try {
335
- await new Promise(resolve => setTimeout(resolve, 10 * 60 * 1000)); // 10 minutes
336
- await fss.unlink(item.path);
337
- console.log(`File ${item.path} deleted.`);
338
- } catch (error) {
339
- console.error(`Error deleting file ${item.path}:`, error);
340
- }
341
- }
342
- } catch (error) {
343
- console.error('Error processing request:', error);
344
- res.status(500).json({
345
- error: 'Failed to process request\n' + error
346
- });
347
- }
348
- });
349
-
350
- app.get('/twdl', async (req, res) => {
351
- try {
352
- const { url } = req.query;
353
- if (!url) return res.status(400).json({ error: 'Parameter url is required' });
354
- let result = await Twitter(url);
355
-
356
- let result_upload = {
357
- media: []
358
- }
359
-
360
- for (let item of result) {
361
- let unduh = await DownloadFile(item);
362
- result_upload.media.push({
363
- type: unduh.mimeType,
364
- path: unduh.filePath,
365
- url_path: `https://downloader-nex.vercel.app/temp/${path.basename(unduh.filePath)}`,
366
- url_path2: `http://${os.hostname()}:${PORT}/temp/${path.basename(unduh.filePath)}`
367
- });
368
- }
369
-
370
- res.json(result_upload);
371
-
372
- for (let item of result_upload.media) {
373
- try {
374
- await new Promise(resolve => setTimeout(resolve, 10 * 60 * 1000)); // 10 minutes
375
- await fss.unlink(item.path);
376
- console.log(`File ${item.path} deleted.`);
377
- } catch (error) {
378
- console.error(`Error deleting file ${item.path}:`, error);
379
- }
380
- }
381
-
382
- } catch (error) {
383
- console.error('Error processing request:', error);
384
- res.status(500).json({
385
- error: 'Failed to process request\n' + error
386
- });
387
- }
388
- });
389
-
390
- /****
391
- YTMP3
392
- YTMP3
393
- YTMP3
394
- YTMP3
395
- *****/
396
- async function uploader(buffer) {
397
- const { ext } = await fileTypeFromBuffer(buffer);
398
- const bodyForm = new FormData();
399
- bodyForm.append('file', buffer, `file.${ext}`);
400
-
401
- const response = await fetch('https://aemt.me/api/upload.php', {
402
- method: 'POST',
403
- body: bodyForm,
404
- });
405
-
406
- return {
407
- status: response.status,
408
- creator: 'Nex',
409
- result: await response.json(),
410
- };
411
- }
412
-
413
- async function getHDThumbnailUrl(videoId) {
414
- try {
415
- const response = await youtube.videos.list({ part: 'snippet', id: videoId });
416
- return response.data.items[0].snippet.thumbnails.maxres.url;
417
- } catch (error) {
418
- console.error('Error fetching HD thumbnail URL:', error.message);
419
- return null;
420
- }
421
- }
422
-
423
- async function GetId(data) {
424
- const regex = /(?:https?:\/\/)?(?:www\.)?(?:youtu(?:be\.com\/(?:watch\?(?:v=|vi=)|v\/|vi\/)|\.be\/|be\.com\/embed\/|be\.com\/shorts\/)|youtube\.com\/\?(?:v=|vi=))([\w-]{11})/;
425
- const res = regex.exec(data);
426
- if (res && res[1]) return res[1];
427
- throw new Error("Please check the URL you have entered");
428
- }
429
-
430
- async function addAudioTags(media, title, artist, year, imagecover) {
431
- try {
432
- let audioBuffer = (typeof media === 'string') ? Buffer.from((await axios.get(media, { responseType: 'arraybuffer', maxContentLength: -1 })).data) : (media instanceof Buffer) ? media : (() => { throw new Error('Media harus berupa URL string atau Buffer.'); })();
433
- const randomFilename = title.replace(/[^\w\s\#\$\&\-\+\(\)\/\[\]\`\×\{\}\\\\\~\•]/g, '') + '.mp3';
434
- const tmpFilePath = path.join(tempDir, randomFilename);
435
- fs.writeFileSync(tmpFilePath, audioBuffer);
436
- const tags = { title, artist, year };
437
- if (typeof imagecover === 'string') {
438
- const coverBuffer = Buffer.from((await axios.get(imagecover, { responseType: 'arraybuffer' })).data);
439
- tags.image = { mime: 'image/jpeg', type: { id: 3, name: 'Front Cover' }, description: 'Cover', imageBuffer: coverBuffer };
440
- } else if (imagecover instanceof Buffer) {
441
- tags.image = { mime: 'image/jpeg', type: { id: 3, name: 'Front Cover' }, description: 'Cover', imageBuffer: imagecover };
442
- }
443
- const success = nodeID3.write(tags, tmpFilePath);
444
- console[success ? 'log' : 'error'](success ? 'Tag ID3 berhasil diubah!' : 'Gagal mengubah tag ID3.');
445
- return { msg: `Audio berhasil diubah.`, path: `${tmpFilePath}` };
446
- } catch (error) {
447
- console.error('Terjadi kesalahan:', error);
448
- throw new Error('Terjadi kesalahan saat mengubah audio.');
449
- }
450
- }
451
-
452
- function generateRandomName(length) {
453
- const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
454
- let randomName = '';
455
- for (let i = 0; i < length; i++) {
456
- randomName += characters.charAt(Math.floor(Math.random() * characters.length));
457
- }
458
- return randomName;
459
- }
460
-
461
- async function getAudioMP3Url(videoUrl) {
462
- try {
463
- const info = await ytdl.getInfo(videoUrl);
464
- const audioFormat = ytdl.chooseFormat(info.formats, { filter: 'audioonly', quality: 'highestaudio' });
465
- const path_audio = path.join(tempDir, generateRandomName(10) + '.mp3');
466
- let uploadResult;
467
- await new Promise((resolve, reject) => {
468
- ffmpeg()
469
- .input(audioFormat.url)
470
- .outputOptions('-f mp3')
471
- .outputOptions('-acodec libmp3lame')
472
- .outputOptions('-ab 128k')
473
- .outputOptions('-ar 44100')
474
- .on('end', async () => {
475
- const buffer = fs.readFileSync(path_audio);
476
- const id_video = await GetId(videoUrl);
477
- const hd_thumbnail = await getHDThumbnailUrl(id_video);
478
- const convert = await addAudioTags(buffer, info.videoDetails.title, info.videoDetails.ownerChannelName, 2024, hd_thumbnail);
479
- const buffer2 = fs.readFileSync(convert.path);
480
- uploadResult = await uploader(buffer2);
481
- console.log('Upload result:', uploadResult);
482
- fs.unlinkSync(path_audio);
483
- fs.unlinkSync(convert.path);
484
- resolve(uploadResult);
485
- })
486
- .on('error', (err) => {
487
- console.error('FFmpeg conversion error:', err);
488
- reject(err);
489
- })
490
- .save(path_audio);
491
- });
492
- return uploadResult;
493
- } catch (error) {
494
- console.error('Error:', error);
495
- throw new Error('Failed to process audio URL');
496
- }
497
- }
498
-
499
- app.get('/ytmp3', async (req, res) => {
500
- try {
501
- const { url } = req.query;
502
- if (!url) return res.status(400).json({ error: 'Parameter url is required' });
503
- let result = await getAudioMP3Url(url);
504
- res.json(result);
505
- } catch (error) {
506
- console.error('Error processing request:', error);
507
- res.status(500).json({
508
- error: 'Failed to process request\n' + error
509
- });
510
- }
511
- });
512
-
513
-
514
- app.listen(PORT, () => {
515
- console.log(`Server is running on port https://localhost:${PORT}`);
516
- });
 
1
+ import axios from 'axios';
2
+ import cheerio from 'cheerio';
3
+ import { createRequire } from 'module';
4
+ import os from 'os';
5
+ import express from 'express';
6
+ import { promisify } from 'util';
7
+ import { fileTypeFromBuffer } from 'file-type';
8
+ import ffmpeg from 'fluent-ffmpeg';
9
+ import nodeID3 from 'node-id3';
10
+ import ytdl from 'ytdl-core';
11
+ import FormData from 'form-data';
12
+ const require = createRequire(import.meta.url);
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+ const { google } = require('googleapis');
16
+ const PORT = process.env.PORT || 7860;
17
+ const app = express();
18
+ const readFileAsync = promisify(fs.readFile);
19
+ import fetch from 'node-fetch';
20
+
21
+ const tempDir = path.join(os.tmpdir(), "temp");
22
+ const fss = fs.promises;
23
+
24
+ (async () => {
25
+ if (!fs.existsSync(tempDir)) {
26
+ await fss.mkdir(tempDir, { recursive: true });
27
+ }
28
+ })();
29
+
30
+ const youtube = google.youtube({ version: 'v3', auth: 'AIzaSyBPkpdJEGtAHebbaP3_CcA1_urfMFfeLLg' });
31
+
32
+ app.use('/temp', express.static(tempDir));
33
+ app.use(express.json());
34
+ app.get("/", (req, res) => {
35
+ res.type("json");
36
+ const keluaran = {
37
+ success: true,
38
+ author: "Nex",
39
+ data: {
40
+ igdl: "/igdl",
41
+ twdl: "/twdl"
42
+ },
43
+ };
44
+ res.send(keluaran);
45
+ });
46
+
47
+ const generateRandomIP = () => {
48
+ const octet = () => Math.floor(Math.random() * 256);
49
+ return `${octet()}.${octet()}.${octet()}.${octet()}`;
50
+ };
51
+
52
+ async function igdl1(url) {
53
+ const apiEndpoint = 'https://v3.igdownloader.app/api/ajaxSearch';
54
+ const requestOptions = {
55
+ headers: {
56
+ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
57
+ 'Accept': '*/*',
58
+ 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; SM-S908B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.58 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/357.0.0.23.115;]',
59
+ 'Referer': 'https://igdownloader.app/en',
60
+ 'X-Forwarded-For': generateRandomIP()
61
+ },
62
+ };
63
+ const postData = `recaptchaToken=&q=${encodeURIComponent(url)}&t=media&lang=en`;
64
+ try {
65
+ const response = await axios.post(apiEndpoint, postData, requestOptions);
66
+ const $ = cheerio.load(response.data.data);
67
+ const downloadLinks = $('div.download-items__btn > a');
68
+ return await Promise.all(downloadLinks.map(async (index, element) => $(element).attr('href')));
69
+ } catch (error) {
70
+ console.error('Instagram Downloader 1 - Error:', error.message);
71
+ return null;
72
+ }
73
+ }
74
+
75
+ async function igdl2(url) {
76
+ try {
77
+ const response = await axios.post('https://fastdl.app/c/', {
78
+ url: url,
79
+ lang_code: 'en',
80
+ token: ''
81
+ }, {
82
+ headers: {
83
+ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
84
+ 'Accept': '*/*',
85
+ 'X-Requested-With': 'XMLHttpRequest',
86
+ 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36',
87
+ 'Referer': 'https://fastdl.app/'
88
+ },
89
+ responseType: 'arraybuffer'
90
+ });
91
+ const html = response.data.toString('utf-8');
92
+ const $ = cheerio.load(html);
93
+ $('img').remove();
94
+ const links = [];
95
+ $('a').each((index, element) => links.push($(element).attr('href')));
96
+ return links;
97
+ } catch (error) {
98
+ console.error('Error downloading Instagram post:', error);
99
+ return null;
100
+ }
101
+ }
102
+
103
+ async function igdl3(url) {
104
+ const apiEndpoint = 'https://co.wuk.sh/api/json';
105
+ const requestData = { url, aFormat: 'mp3', filenamePattern: 'classic', dubLang: false, vQuality: '720' };
106
+ const headers = {
107
+ 'Accept': 'application/json',
108
+ 'Content-Type': 'application/json',
109
+ 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36',
110
+ 'Referer': 'https://cobalt.tools/',
111
+ };
112
+ try {
113
+ const response = await axios.post(apiEndpoint, requestData, { headers });
114
+ const array_res = [];
115
+ if (response.data.status === 'redirect') {
116
+ array_res.push(response.data.url);
117
+ } else if (response.data.status === 'picker') {
118
+ response.data.picker.forEach(item => array_res.push(item.url));
119
+ }
120
+ return array_res;
121
+ } catch (error) {
122
+ console.error('Instagram Downloader 3 - Error:', error.message);
123
+ return null;
124
+ }
125
+ }
126
+
127
+ async function igdl4(url) {
128
+ try {
129
+ const apiEndpoint = 'https://v3.saveig.app/api/ajaxSearch';
130
+ const requestOptions = {
131
+ headers: {
132
+ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
133
+ 'Accept': '*/*',
134
+ 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; SM-S908B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.58 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/357.0.0.23.115;]',
135
+ 'Referer': 'https://saveig.app/en',
136
+ },
137
+ };
138
+ const postData = `recaptchaToken=&q=${encodeURIComponent(url)}&t=media&lang=en`;
139
+ const response = await axios.post(apiEndpoint, postData, requestOptions);
140
+ const $ = cheerio.load(response.data.data);
141
+ const downloadLinks = $('div.download-items__btn > a');
142
+ return await Promise.all(downloadLinks.map(async (index, element) => $(element).attr('href')));
143
+ } catch (error) {
144
+ console.error('Instagram Downloader 4 - Error:', error.message);
145
+ return null;
146
+ }
147
+ }
148
+
149
+ async function twdl1(url) {
150
+ const apiUrl = 'https://savetwitter.net/api/ajaxSearch';
151
+ const headers = {
152
+ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
153
+ 'Accept': '*/*',
154
+ 'X-Requested-With': 'XMLHttpRequest',
155
+ 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; SM-S908B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.58 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/357.0.0.23.115;]',
156
+ 'Referer': 'https://x2twitter.com/id',
157
+ 'X-Forwarded-For': generateRandomIP(),
158
+ };
159
+ const data = `q=${encodeURIComponent(url)}&lang=id`;
160
+
161
+ try {
162
+ const response = await axios.post(apiUrl, data, {
163
+ headers
164
+ });
165
+ if (!response.data.hasOwnProperty('data')) {
166
+ throw new Error('Data tidak ditemukan di response');
167
+ }
168
+ const $ = cheerio.load(response.data.data);
169
+
170
+ $('a[onclick="showAd()"][href="#"]').remove();
171
+ $('a[href="/"]').remove();
172
+ $('a[href="#"]').remove();
173
+
174
+ const hrefs = [];
175
+ $('.dl-action').each((index, element) => {
176
+ const firstAnchor = $(element).find('a').first();
177
+ hrefs.push(firstAnchor.attr('href'));
178
+ });
179
+
180
+ return hrefs;
181
+
182
+ } catch (error) {
183
+ throw new Error('Failed to fetch Twitter image: ' + error);
184
+ }
185
+ }
186
+
187
+
188
+
189
+ async function twdl2(url) {
190
+ const apiUrl = 'https://x2twitter.com/api/ajaxSearch';
191
+ const headers = {
192
+ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
193
+ 'Accept': '*/*',
194
+ 'X-Requested-With': 'XMLHttpRequest',
195
+ 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; SM-S908B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.58 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/357.0.0.23.115;]',
196
+ 'Referer': 'https://x2twitter.com/id',
197
+ 'X-Forwarded-For': generateRandomIP(),
198
+ };
199
+ const data = `q=${encodeURIComponent(url)}&lang=id`;
200
+
201
+ try {
202
+ const response = await axios.post(apiUrl, data, {
203
+ headers
204
+ });
205
+ if (!response.data.hasOwnProperty('data')) {
206
+ throw new Error('Data tidak ditemukan di response');
207
+ }
208
+ const $ = cheerio.load(response.data.data);
209
+
210
+ $('a[onclick="showAd()"][href="#"]').remove();
211
+ $('a[href="/"]').remove();
212
+
213
+ const hrefs = [];
214
+ $('.dl-action').each((index, element) => {
215
+ const firstAnchor = $(element).find('a').first();
216
+ hrefs.push(firstAnchor.attr('href'));
217
+ });
218
+
219
+ return hrefs;
220
+
221
+ } catch (error) {
222
+ throw new Error('Failed to fetch Twitter image: ' + error);
223
+ }
224
+ }
225
+
226
+
227
+
228
+ async function twdl3(url) {
229
+ const apiUrl = 'https://twtube.app/en/download?url=';
230
+
231
+ const headers = {
232
+ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
233
+ 'Accept': '*/*',
234
+ 'X-Requested-With': 'XMLHttpRequest',
235
+ 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; SM-S908B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.58 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/357.0.0.23.115;]',
236
+ 'Referer': 'https://savetwitter.net/id/twitter-image-downloader',
237
+ 'X-Forwarded-For': generateRandomIP(),
238
+ };
239
+ try {
240
+ const response = await axios.get(apiUrl + url, {
241
+ headers
242
+ });
243
+ const $ = cheerio.load(response.data);
244
+ // Mendapatkan semua href dari elemen a dalam div dengan kelas 'square-box-btn'
245
+ const allHrefs = [];
246
+ // Menggunakan map untuk mengambil href dan mengembalikan array promise
247
+ const promises = $('.square-box-btn a').map(async (index, element) => {
248
+ let link = $(element).attr('href');
249
+ return link;
250
+ }).get();
251
+ // Menunggu semua promise selesai dan mengumpulkan hasilnya
252
+ return Promise.all(promises);
253
+ } catch (error) {
254
+ throw new Error('Failed to fetch Twitter image: ' + error);
255
+ }
256
+ }
257
+
258
+ async function DownloadFile(url) {
259
+ try {
260
+ const response = await axios.get(url, { responseType: 'arraybuffer' });
261
+ const mimeType = response.headers['content-type'];
262
+ const buffer = response.data;
263
+ const fileExtension = (await fileTypeFromBuffer(buffer)).ext;
264
+ const filename = `downloaded_file_${Date.now()}.${fileExtension}`;
265
+ const filePath = path.join(tempDir, filename);
266
+ await fss.writeFile(filePath, buffer);
267
+ console.log(`File berhasil diunduh dan disimpan sebagai: ${filePath}`);
268
+ return { mimeType, filePath };
269
+ } catch (error) {
270
+ console.error('Error saat mengunduh file:', error);
271
+ return null;
272
+ }
273
+ }
274
+
275
+
276
+
277
+ const getInstagramDownloadLinks = async (url) => {
278
+ let result = await igdl1(url);
279
+ if (!result || result.length === 0) {
280
+ result = await igdl2(url);
281
+ }
282
+ if (!result || result.length === 0) {
283
+ result = await igdl3(url);
284
+ }
285
+ if (!result || result.length === 0) {
286
+ result = await igdl4(url);
287
+ }
288
+ if (!result || result.length === 0) {
289
+ result = {
290
+ message: "all server error"
291
+ };
292
+ }
293
+ return result;
294
+ };
295
+
296
+ const Twitter = async (url) => {
297
+ let result = await twdl3(url);
298
+ if (!result || result.length === 0) {
299
+ result = await twdl2(url);
300
+ }
301
+ if (!result || result.length === 0) {
302
+ result = await twdl1(url);
303
+ }
304
+ if (!result || result.length === 0) {
305
+ result = {
306
+ message: "all server error"
307
+ };
308
+ }
309
+ return result;
310
+ };
311
+
312
+ app.get('/igdl', async (req, res) => {
313
+ try {
314
+ const { url } = req.query;
315
+ if (!url) return res.status(400).json({ error: 'Parameter url is required' });
316
+ if (!/https?:\/\/(www\.)?instagram\.com\/(p|reel|tv)/.test(url)) return res.status(400).json({ error: "Example: https://www.instagram.com/p/Cz1fTwMJFpx/?igsh=MXRrY2g4eWNucGoyZg==" });
317
+ let result = await getInstagramDownloadLinks(url);
318
+ let result_upload = {
319
+ media: []
320
+ }
321
+
322
+ for (let item of result) {
323
+ let unduh = await DownloadFile(item);
324
+ result_upload.media.push({
325
+ type: unduh.mimeType,
326
+ path: unduh.filePath,
327
+ url_path: `https://arashicode-api.hf.space/temp/${path.basename(unduh.filePath)}`
328
+ });
329
+ }
330
+
331
+ res.json(result_upload);
332
+
333
+ for (let item of result_upload.media) {
334
+ try {
335
+ await new Promise(resolve => setTimeout(resolve, 10 * 60 * 1000)); // 10 minutes
336
+ await fss.unlink(item.path);
337
+ console.log(`File ${item.path} deleted.`);
338
+ } catch (error) {
339
+ console.error(`Error deleting file ${item.path}:`, error);
340
+ }
341
+ }
342
+ } catch (error) {
343
+ console.error('Error processing request:', error);
344
+ res.status(500).json({
345
+ error: 'Failed to process request\n' + error
346
+ });
347
+ }
348
+ });
349
+
350
+ app.get('/twdl', async (req, res) => {
351
+ try {
352
+ const { url } = req.query;
353
+ if (!url) return res.status(400).json({ error: 'Parameter url is required' });
354
+ let result = await Twitter(url);
355
+
356
+ let result_upload = {
357
+ media: []
358
+ }
359
+
360
+ for (let item of result) {
361
+ let unduh = await DownloadFile(item);
362
+ result_upload.media.push({
363
+ type: unduh.mimeType,
364
+ path: unduh.filePath,
365
+ url_path: `https://arashicode-api.hf.space/temp/${path.basename(unduh.filePath)}`,
366
+ url_path2: `http://${os.hostname()}:${PORT}/temp/${path.basename(unduh.filePath)}`
367
+ });
368
+ }
369
+
370
+ res.json(result_upload);
371
+
372
+ for (let item of result_upload.media) {
373
+ try {
374
+ await new Promise(resolve => setTimeout(resolve, 10 * 60 * 1000)); // 10 minutes
375
+ await fss.unlink(item.path);
376
+ console.log(`File ${item.path} deleted.`);
377
+ } catch (error) {
378
+ console.error(`Error deleting file ${item.path}:`, error);
379
+ }
380
+ }
381
+
382
+ } catch (error) {
383
+ console.error('Error processing request:', error);
384
+ res.status(500).json({
385
+ error: 'Failed to process request\n' + error
386
+ });
387
+ }
388
+ });
389
+
390
+ /****
391
+ YTMP3
392
+ YTMP3
393
+ YTMP3
394
+ YTMP3
395
+ *****/
396
+ async function uploader(buffer) {
397
+ const { ext } = await fileTypeFromBuffer(buffer);
398
+ const bodyForm = new FormData();
399
+ bodyForm.append('file', buffer, `file.${ext}`);
400
+
401
+ const response = await fetch('https://aemt.me/api/upload.php', {
402
+ method: 'POST',
403
+ body: bodyForm,
404
+ });
405
+
406
+ return {
407
+ status: response.status,
408
+ creator: 'Nex',
409
+ result: await response.json(),
410
+ };
411
+ }
412
+
413
+ async function getHDThumbnailUrl(videoId) {
414
+ try {
415
+ const response = await youtube.videos.list({ part: 'snippet', id: videoId });
416
+ return response.data.items[0].snippet.thumbnails.maxres.url;
417
+ } catch (error) {
418
+ console.error('Error fetching HD thumbnail URL:', error.message);
419
+ return null;
420
+ }
421
+ }
422
+
423
+ async function GetId(data) {
424
+ const regex = /(?:https?:\/\/)?(?:www\.)?(?:youtu(?:be\.com\/(?:watch\?(?:v=|vi=)|v\/|vi\/)|\.be\/|be\.com\/embed\/|be\.com\/shorts\/)|youtube\.com\/\?(?:v=|vi=))([\w-]{11})/;
425
+ const res = regex.exec(data);
426
+ if (res && res[1]) return res[1];
427
+ throw new Error("Please check the URL you have entered");
428
+ }
429
+
430
+ async function addAudioTags(media, title, artist, year, imagecover) {
431
+ try {
432
+ let audioBuffer = (typeof media === 'string') ? Buffer.from((await axios.get(media, { responseType: 'arraybuffer', maxContentLength: -1 })).data) : (media instanceof Buffer) ? media : (() => { throw new Error('Media harus berupa URL string atau Buffer.'); })();
433
+ const randomFilename = title.replace(/[^\w\s\#\$\&\-\+\(\)\/\[\]\`\×\{\}\\\\\~\•]/g, '') + '.mp3';
434
+ const tmpFilePath = path.join(tempDir, randomFilename);
435
+ fs.writeFileSync(tmpFilePath, audioBuffer);
436
+ const tags = { title, artist, year };
437
+ if (typeof imagecover === 'string') {
438
+ const coverBuffer = Buffer.from((await axios.get(imagecover, { responseType: 'arraybuffer' })).data);
439
+ tags.image = { mime: 'image/jpeg', type: { id: 3, name: 'Front Cover' }, description: 'Cover', imageBuffer: coverBuffer };
440
+ } else if (imagecover instanceof Buffer) {
441
+ tags.image = { mime: 'image/jpeg', type: { id: 3, name: 'Front Cover' }, description: 'Cover', imageBuffer: imagecover };
442
+ }
443
+ const success = nodeID3.write(tags, tmpFilePath);
444
+ console[success ? 'log' : 'error'](success ? 'Tag ID3 berhasil diubah!' : 'Gagal mengubah tag ID3.');
445
+ return { msg: `Audio berhasil diubah.`, path: `${tmpFilePath}` };
446
+ } catch (error) {
447
+ console.error('Terjadi kesalahan:', error);
448
+ throw new Error('Terjadi kesalahan saat mengubah audio.');
449
+ }
450
+ }
451
+
452
+ function generateRandomName(length) {
453
+ const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
454
+ let randomName = '';
455
+ for (let i = 0; i < length; i++) {
456
+ randomName += characters.charAt(Math.floor(Math.random() * characters.length));
457
+ }
458
+ return randomName;
459
+ }
460
+
461
+ async function getAudioMP3Url(videoUrl) {
462
+ try {
463
+ const info = await ytdl.getInfo(videoUrl);
464
+ const audioFormat = ytdl.chooseFormat(info.formats, { filter: 'audioonly', quality: 'highestaudio' });
465
+ const path_audio = path.join(tempDir, generateRandomName(10) + '.mp3');
466
+ let uploadResult;
467
+ await new Promise((resolve, reject) => {
468
+ ffmpeg()
469
+ .input(audioFormat.url)
470
+ .outputOptions('-f mp3')
471
+ .outputOptions('-acodec libmp3lame')
472
+ .outputOptions('-ab 128k')
473
+ .outputOptions('-ar 44100')
474
+ .on('end', async () => {
475
+ const buffer = fs.readFileSync(path_audio);
476
+ const id_video = await GetId(videoUrl);
477
+ const hd_thumbnail = await getHDThumbnailUrl(id_video);
478
+ const convert = await addAudioTags(buffer, info.videoDetails.title, info.videoDetails.ownerChannelName, 2024, hd_thumbnail);
479
+ const buffer2 = fs.readFileSync(convert.path);
480
+ uploadResult = await uploader(buffer2);
481
+ console.log('Upload result:', uploadResult);
482
+ fs.unlinkSync(path_audio);
483
+ fs.unlinkSync(convert.path);
484
+ resolve(uploadResult);
485
+ })
486
+ .on('error', (err) => {
487
+ console.error('FFmpeg conversion error:', err);
488
+ reject(err);
489
+ })
490
+ .save(path_audio);
491
+ });
492
+ return uploadResult;
493
+ } catch (error) {
494
+ console.error('Error:', error);
495
+ throw new Error('Failed to process audio URL');
496
+ }
497
+ }
498
+
499
+ app.get('/ytmp3', async (req, res) => {
500
+ try {
501
+ const { url } = req.query;
502
+ if (!url) return res.status(400).json({ error: 'Parameter url is required' });
503
+ let result = await getAudioMP3Url(url);
504
+ res.json(result);
505
+ } catch (error) {
506
+ console.error('Error processing request:', error);
507
+ res.status(500).json({
508
+ error: 'Failed to process request\n' + error
509
+ });
510
+ }
511
+ });
512
+
513
+
514
+ app.listen(PORT, () => {
515
+ console.log(`Server is running on port https://localhost:${PORT}`);
516
+ });