puppeter-playground / server.js
Nexchan's picture
Update server.js
d98dd1b verified
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}`);
});