Spaces:
Paused
Paused
| 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}`); | |
| }); |