Nexchan commited on
Commit
66100df
1 Parent(s): c4af20f

Upload 2 files

Browse files
Files changed (2) hide show
  1. index.js +516 -0
  2. package.json +29 -0
index.js ADDED
@@ -0,0 +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
+ });
package.json ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "scrape",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "type": "module",
6
+ "main": "index.js",
7
+ "scripts": {
8
+ "test": "echo \"Error: no test specified\" && exit 1"
9
+ },
10
+ "keywords": [],
11
+ "author": "",
12
+ "license": "ISC",
13
+ "dependencies": {
14
+ "axios": "^1.6.8",
15
+ "chalk": "^5.3.0",
16
+ "cheerio": "^1.0.0-rc.12",
17
+ "jsdom": "^24.0.0",
18
+ "node-fetch": "^3.3.2"
19
+ },
20
+ "devDependencies": {
21
+ "express": "^4.19.2",
22
+ "file-type": "^19.0.0",
23
+ "fluent-ffmpeg": "^2.1.2",
24
+ "googleapis": "^136.0.0",
25
+ "node-id3": "^0.2.6",
26
+ "youtubei": "^1.4.0",
27
+ "ytdl-core": "^4.11.5"
28
+ }
29
+ }