const { PornHub } = require('pornhub.js'); const fs = require('fs'); const { exec } = require('child_process'); class Ph { constructor() { this.client = new PornHub(); } search = async function (query) { try { const results = await this.client.searchVideo(query); if (!results.data || results.data.length === 0) return []; return results.data.sort(() => Math.random() - 0.5); } catch (error) { throw new Error(error.message); } } download = async function (url) { return new Promise(async (resolve, reject) => { try { const videoData = await this.client.video(url); const resolution = videoData.mediaDefinitions.find((f) => f.format === 'hls' && (f.quality === 480 || f.quality === 720)); if (!resolution) return reject(new Error('Video resolution not found')); const m3u8Url = resolution.videoUrl; const outputPath = `./video_${Date.now()}.mp4`; exec(`ffmpeg -i "${m3u8Url}" -c copy -bsf:a aac_adtstoasc "${outputPath}"`, (error, stdout, stderr) => { if (error) { console.error(`FFmpeg Error: ${error.message}`); return reject(error); } console.log(`FFmpeg Output: ${stdout || stderr}`); fs.readFile(outputPath, async (err, buffer) => { if (err) return reject(err); fs.unlink(outputPath, (unlinkErr) => { if (unlinkErr) console.error(`Failed to delete file: ${unlinkErr.message}`); }); resolve({ title: videoData.title, duration: videoData.durationFormatted, rating: videoData.vote.rating, uploader: videoData.provider.username, tags: videoData.tags, category: videoData.categories, videoBuffer: buffer }); }); }); } catch (error) { throw new Error(error.message); } }); } } // Usage: const ph = new Ph(); const resp = await ph.search('girl'); console.log(resp);