File size: 8,865 Bytes
10176a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1b5eea0
10176a6
 
 
 
 
 
 
 
 
1b5eea0
 
 
 
 
 
 
 
 
 
 
 
 
10176a6
 
 
 
 
 
 
 
 
 
 
 
1b5eea0
d98dd1b
10176a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1b5eea0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
import axios from 'axios';
import cheerio from 'cheerio';
import { createRequire } from 'module';
import os from 'os';
import express from 'express';
import { promisify } from 'util';
import { fileTypeFromBuffer } from 'file-type';
import ffmpeg from 'fluent-ffmpeg';
import nodeID3 from 'node-id3';
import ytdl from 'ytdl-core';
import FormData from 'form-data';
import fetch from 'node-fetch';

const require = createRequire(import.meta.url);
const fs = require('fs');
const path = require('path');
const { google } = require('googleapis');
const puppeteer = require('puppeteer');

const PORT = process.env.PORT || 7860;
const app = express();
const readFileAsync = promisify(fs.readFile);

const tempDir = path.join(os.tmpdir(), "temp");
const fss = fs.promises;

// Membuat direktori sementara jika belum ada
(async () => {
    if (!fs.existsSync(tempDir)) {
        await fss.mkdir(tempDir, { recursive: true });
    }
})();

const youtube = google.youtube({ version: 'v3', auth: 'AIzaSyBPkpdJEGtAHebbaP3_CcA1_urfMFfeLLg' });

app.use('/temp', express.static(tempDir));
app.use(express.json());

app.get("/", (req, res) => {
    res.type("json");
    const keluaran = {
        success: true,
        author: "Nex",
        data: {
            igdl: "/igdl",
            twdl: "/twdl"
        },
    };
    res.send(keluaran);
});

// Fungsi untuk menghasilkan IP acak
const generateRandomIP = () => {
    const octet = () => Math.floor(Math.random() * 256);
    return `${octet()}.${octet()}.${octet()}.${octet()}`;
};

// Fungsi untuk upload file
async function uploader(buffer) {
    const { ext } = await fileTypeFromBuffer(buffer);
    const bodyForm = new FormData();
    bodyForm.append('file', buffer, `file.${ext}`);

    const response = await fetch('https://aemt.me/api/upload.php', {
        method: 'POST',
        body: bodyForm,
    });

    return {
        status: response.status,
        creator: 'Nex',
        result: await response.json(),
    };
}

// Fungsi untuk mendapatkan URL thumbnail HD
async function getHDThumbnailUrl(videoId) {
    try {
        const response = await youtube.videos.list({ part: 'snippet', id: videoId });
        return response.data.items[0].snippet.thumbnails.maxres.url;
    } catch (error) {
        console.error('Error fetching HD thumbnail URL:', error.message);
        return null;
    }
}

// Fungsi untuk mendapatkan ID video dari URL
async function GetId(data) {
    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})/;
    const res = regex.exec(data);
    if (res && res[1]) return res[1];
    throw new Error("Please check the URL you have entered");
}

// Fungsi untuk menambahkan tag ID3 ke file audio
async function addAudioTags(media, title, artist, year, imagecover) {
    try {
        let audioBuffer;
        if (typeof media === 'string') {
            const response = await axios.get(media, { responseType: 'arraybuffer', maxContentLength: -1 });
            audioBuffer = Buffer.from(response.data);
        } else if (media instanceof Buffer) {
            audioBuffer = media;
        } else {
            throw new Error('Media harus berupa URL string atau Buffer.');
        }

        const randomFilename = generateRandomName(10) + '.mp3';
        const tmpFilePath = path.join(tempDir, randomFilename);
        fs.writeFileSync(tmpFilePath, audioBuffer);

        const tags = { title, artist, year };
        if (typeof imagecover === 'string') {
            const response = await axios.get(imagecover, { responseType: 'arraybuffer' });
            const coverBuffer = Buffer.from(response.data);
            tags.image = {
                mime: 'image/jpeg',
                type: { id: 3, name: 'Front Cover' },
                description: 'Cover',
                imageBuffer: coverBuffer
            };
        } else if (imagecover instanceof Buffer) {
            tags.image = {
                mime: 'image/jpeg',
                type: { id: 3, name: 'Front Cover' },
                description: 'Cover',
                imageBuffer: imagecover
            };
        }

        const success = nodeID3.write(tags, tmpFilePath);
        console[success ? 'log' : 'error'](success ? 'Tag ID3 berhasil diubah!' : 'Gagal mengubah tag ID3.');

        return { msg: `Audio berhasil diubah.`, path: `${tmpFilePath}` };
    } catch (error) {
        console.error('Terjadi kesalahan:', error);
        throw new Error('Terjadi kesalahan saat mengubah audio.');
    }
}

// Fungsi untuk menghasilkan nama acak
function generateRandomName(length) {
    const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    let randomName = '';
    for (let i = 0; i < length; i++) {
        randomName += characters.charAt(Math.floor(Math.random() * characters.length));
    }
    return randomName;
}

// Fungsi untuk mendapatkan URL audio MP3 dari video YouTube
async function getAudioMP3Url(videoUrl) {
    try {
        const info = await ytdl.getInfo(videoUrl);
        const audioFormat = ytdl.chooseFormat(info.formats, { filter: 'audioonly', quality: 'highestaudio' });
        const path_audio = path.join(tempDir, generateRandomName(10) + '.mp3');
        let uploadResult;
        let convert;

        await new Promise((resolve, reject) => {
            ffmpeg()
                .input(audioFormat.url)
                .outputOptions('-f mp3')
                .outputOptions('-acodec libmp3lame')
                .outputOptions('-ab 128k')
                .outputOptions('-ar 44100')
                .on('end', async () => {
                    try {
                        const buffer = fs.readFileSync(path_audio);
                        const id_video = await GetId(videoUrl);
                        const hd_thumbnail = await getHDThumbnailUrl(id_video);
                        convert = await addAudioTags(buffer, info.videoDetails.title, info.videoDetails.ownerChannelName, 2024, hd_thumbnail);
                        const buffer2 = fs.readFileSync(convert.path);

                        fs.unlinkSync(path_audio);

                        resolve();
                    } catch (error) {
                        reject(error);
                    }
                })
                .on('error', (err) => {
                    console.error('FFmpeg conversion error:', err);
                    reject(err);
                })
                .save(path_audio);
        });

        return {
            status: 200,
            title: info.videoDetails.title,
            result: {
                url_path: `https://${process.env.SPACE_HOST}/temp/${path.basename(convert.path)}`,
                curl_path: `https://${process.env.SPACE_HOST}/temp/${path.basename(convert.path)}?download=1&filename=${info.videoDetails.title}`,
                path: convert.path
            }
        };
    } catch (error) {
        console.error('Error:', error);
        throw new Error('Failed to process audio URL');
    }
}

// Endpoint untuk mengunduh audio MP3 dari YouTube
app.get('/ytmp3', async (req, res) => {
    try {
        const { url } = req.query;
        if (!url) return res.status(400).json({ error: 'Parameter url is required' });

        let result = await getAudioMP3Url(url);
        res.json(result);

        // Menghapus file setelah 10 menit
        try {
            await new Promise(resolve => setTimeout(resolve, 10 * 60 * 1000)); // 10 minutes
            await fss.unlink(result.result.path);
            console.log(`File ${result.result.path} deleted.`);
        } catch (error) {
            console.error(`Error deleting file ${result.result.path}:`, error);
        }
    } catch (error) {
        console.error('Error processing request:', error);
        res.status(500).json({
            error: 'Failed to process request\n' + error
        });
    }
});

// Fungsi untuk ping website
async function pingWebsite() {
    const browser = await puppeteer.launch({
        headless: true,
        args: ['--no-sandbox', '--disable-setuid-sandbox']
    });
    const page = await browser.newPage();
    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;]");
    await page.goto('https://huggingface.co/spaces/ArashiCode/api'); 
    console.log("Ping");
    await browser.close();
}

// Ping website setiap 5 jam
async function pingEvery5Hours() {
    await pingWebsite();
    setInterval(async () => {
        await pingWebsite();
    }, 5 * 60 * 60 * 1000); // 5 hours in milliseconds
}

// Mulai ping
pingEvery5Hours();

app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});