Nexchan commited on
Commit
10176a6
·
verified ·
1 Parent(s): 1081c21

Create server.js

Browse files
Files changed (1) hide show
  1. server.js +249 -0
server.js ADDED
@@ -0,0 +1,249 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ import fetch from 'node-fetch';
13
+
14
+ const require = createRequire(import.meta.url);
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+ const { google } = require('googleapis');
18
+ const puppeteer = require('puppeteer');
19
+
20
+ const PORT = process.env.PORT || 7860;
21
+ const app = express();
22
+ const readFileAsync = promisify(fs.readFile);
23
+
24
+ const tempDir = path.join(os.tmpdir(), "temp");
25
+ const fss = fs.promises;
26
+
27
+ // Membuat direktori sementara jika belum ada
28
+ (async () => {
29
+ if (!fs.existsSync(tempDir)) {
30
+ await fss.mkdir(tempDir, { recursive: true });
31
+ }
32
+ })();
33
+
34
+ const youtube = google.youtube({ version: 'v3', auth: 'AIzaSyBPkpdJEGtAHebbaP3_CcA1_urfMFfeLLg' });
35
+
36
+ app.use('/temp', express.static(tempDir));
37
+ app.use(express.json());
38
+
39
+ app.get("/", (req, res) => {
40
+ res.type("json");
41
+ const keluaran = {
42
+ success: true,
43
+ author: "Nex",
44
+ data: {
45
+ igdl: "/igdl",
46
+ twdl: "/twdl"
47
+ },
48
+ };
49
+ res.send(keluaran);
50
+ });
51
+
52
+ // Fungsi untuk menghasilkan IP acak
53
+ const generateRandomIP = () => {
54
+ const octet = () => Math.floor(Math.random() * 256);
55
+ return `${octet()}.${octet()}.${octet()}.${octet()}`;
56
+ };
57
+
58
+ // Fungsi untuk upload file
59
+ async function uploader(buffer) {
60
+ const { ext } = await fileTypeFromBuffer(buffer);
61
+ const bodyForm = new FormData();
62
+ bodyForm.append('file', buffer, `file.${ext}`);
63
+
64
+ const response = await fetch('https://aemt.me/api/upload.php', {
65
+ method: 'POST',
66
+ body: bodyForm,
67
+ });
68
+
69
+ return {
70
+ status: response.status,
71
+ creator: 'Nex',
72
+ result: await response.json(),
73
+ };
74
+ }
75
+
76
+ // Fungsi untuk mendapatkan URL thumbnail HD
77
+ async function getHDThumbnailUrl(videoId) {
78
+ try {
79
+ const response = await youtube.videos.list({ part: 'snippet', id: videoId });
80
+ return response.data.items[0].snippet.thumbnails.maxres.url;
81
+ } catch (error) {
82
+ console.error('Error fetching HD thumbnail URL:', error.message);
83
+ return null;
84
+ }
85
+ }
86
+
87
+ // Fungsi untuk mendapatkan ID video dari URL
88
+ async function GetId(data) {
89
+ 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})/;
90
+ const res = regex.exec(data);
91
+ if (res && res[1]) return res[1];
92
+ throw new Error("Please check the URL you have entered");
93
+ }
94
+
95
+ // Fungsi untuk menambahkan tag ID3 ke file audio
96
+ async function addAudioTags(media, title, artist, year, imagecover) {
97
+ try {
98
+ let audioBuffer;
99
+ if (typeof media === 'string') {
100
+ const response = await axios.get(media, { responseType: 'arraybuffer', maxContentLength: -1 });
101
+ audioBuffer = Buffer.from(response.data);
102
+ } else if (media instanceof Buffer) {
103
+ audioBuffer = media;
104
+ } else {
105
+ throw new Error('Media harus berupa URL string atau Buffer.');
106
+ }
107
+
108
+ const randomFilename = generateRandomName(10) + '.mp3';
109
+ const tmpFilePath = path.join(tempDir, randomFilename);
110
+ fs.writeFileSync(tmpFilePath, audioBuffer);
111
+
112
+ const tags = { title, artist, year };
113
+ if (typeof imagecover === 'string') {
114
+ const response = await axios.get(imagecover, { responseType: 'arraybuffer' });
115
+ const coverBuffer = Buffer.from(response.data);
116
+ tags.image = {
117
+ mime: 'image/jpeg',
118
+ type: { id: 3, name: 'Front Cover' },
119
+ description: 'Cover',
120
+ imageBuffer: coverBuffer
121
+ };
122
+ } else if (imagecover instanceof Buffer) {
123
+ tags.image = {
124
+ mime: 'image/jpeg',
125
+ type: { id: 3, name: 'Front Cover' },
126
+ description: 'Cover',
127
+ imageBuffer: imagecover
128
+ };
129
+ }
130
+
131
+ const success = nodeID3.write(tags, tmpFilePath);
132
+ console[success ? 'log' : 'error'](success ? 'Tag ID3 berhasil diubah!' : 'Gagal mengubah tag ID3.');
133
+
134
+ return { msg: `Audio berhasil diubah.`, path: `${tmpFilePath}` };
135
+ } catch (error) {
136
+ console.error('Terjadi kesalahan:', error);
137
+ throw new Error('Terjadi kesalahan saat mengubah audio.');
138
+ }
139
+ }
140
+
141
+ // Fungsi untuk menghasilkan nama acak
142
+ function generateRandomName(length) {
143
+ const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
144
+ let randomName = '';
145
+ for (let i = 0; i < length; i++) {
146
+ randomName += characters.charAt(Math.floor(Math.random() * characters.length));
147
+ }
148
+ return randomName;
149
+ }
150
+
151
+ // Fungsi untuk mendapatkan URL audio MP3 dari video YouTube
152
+ async function getAudioMP3Url(videoUrl) {
153
+ try {
154
+ const info = await ytdl.getInfo(videoUrl);
155
+ const audioFormat = ytdl.chooseFormat(info.formats, { filter: 'audioonly', quality: 'highestaudio' });
156
+ const path_audio = path.join(tempDir, generateRandomName(10) + '.mp3');
157
+ let uploadResult;
158
+
159
+ await new Promise((resolve, reject) => {
160
+ ffmpeg()
161
+ .input(audioFormat.url)
162
+ .outputOptions('-f mp3')
163
+ .outputOptions('-acodec libmp3lame')
164
+ .outputOptions('-ab 128k')
165
+ .outputOptions('-ar 44100')
166
+ .on('end', async () => {
167
+ const buffer = fs.readFileSync(path_audio);
168
+ const id_video = await GetId(videoUrl);
169
+ const hd_thumbnail = await getHDThumbnailUrl(id_video);
170
+ const convert = await addAudioTags(buffer, info.videoDetails.title, info.videoDetails.ownerChannelName, 2024, hd_thumbnail);
171
+ const buffer2 = fs.readFileSync(convert.path);
172
+
173
+ fs.unlinkSync(path_audio);
174
+
175
+ resolve();
176
+ })
177
+ .on('error', (err) => {
178
+ console.error('FFmpeg conversion error:', err);
179
+ reject(err);
180
+ })
181
+ .save(path_audio);
182
+ });
183
+
184
+ return {
185
+ status: 200,
186
+ title: info.videoDetails.title,
187
+ result: {
188
+ url_path: `${process.env.SPACE_HOST}/temp/${path.basename(convert.path)}`,
189
+ path: convert.path
190
+ }
191
+ };
192
+ } catch (error) {
193
+ console.error('Error:', error);
194
+ throw new Error('Failed to process audio URL');
195
+ }
196
+ }
197
+
198
+ // Endpoint untuk mengunduh audio MP3 dari YouTube
199
+ app.get('/ytmp3', async (req, res) => {
200
+ try {
201
+ const { url } = req.query;
202
+ if (!url) return res.status(400).json({ error: 'Parameter url is required' });
203
+
204
+ let result = await getAudioMP3Url(url);
205
+ res.json(result);
206
+
207
+ // Menghapus file setelah 10 menit
208
+ try {
209
+ await new Promise(resolve => setTimeout(resolve, 10 * 60 * 1000)); // 10 minutes
210
+ await fss.unlink(result.result.path);
211
+ console.log(`File ${result.result.path} deleted.`);
212
+ } catch (error) {
213
+ console.error(`Error deleting file ${result.result.path}:`, error);
214
+ }
215
+ } catch (error) {
216
+ console.error('Error processing request:', error);
217
+ res.status(500).json({
218
+ error: 'Failed to process request\n' + error
219
+ });
220
+ }
221
+ });
222
+
223
+ // Fungsi untuk ping website
224
+ async function pingWebsite() {
225
+ const browser = await puppeteer.launch({
226
+ headless: true,
227
+ args: ['--no-sandbox', '--disable-setuid-sandbox']
228
+ });
229
+ const page = await browser.newPage();
230
+ await page.setUserAgent("Mozilla/5.0 (Linux; Android 10; SM-G965U Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.141 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/420.0.0.32.61;]");
231
+ await page.goto('https://huggingface.co/spaces/ArashiCode/api');
232
+ console.log("Ping");
233
+ await browser.close();
234
+ }
235
+
236
+ // Ping website setiap 5 jam
237
+ async function pingEvery5Hours() {
238
+ await pingWebsite();
239
+ setInterval(async () => {
240
+ await pingWebsite();
241
+ }, 5 * 60 * 60 * 1000); // 5 hours in milliseconds
242
+ }
243
+
244
+ // Mulai ping
245
+ pingEvery5Hours();
246
+
247
+ app.listen(PORT, () => {
248
+ console.log(`Server is running on port ${PORT}`);
249
+ });