| const puppeteer = require('puppeteer'); | |
| const scrapeFlixer = async (searchQuery) => { | |
| const browser = await puppeteer.launch({ | |
| headless: true, | |
| args: [ | |
| '--no-sandbox', | |
| '--disable-setuid-sandbox', | |
| '--disable-dev-shm-usage', | |
| '--disable-gpu' | |
| ] | |
| }); | |
| const page = await browser.newPage(); | |
| await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'); | |
| const searchUrl = `https://flixer.sh/search?q=${encodeURIComponent(searchQuery)}`; | |
| await page.goto(searchUrl, { waitUntil: 'networkidle0', timeout: 30000 }); | |
| await new Promise(resolve => setTimeout(resolve, 2000)); | |
| const searchResults = await page.evaluate(() => { | |
| const results = []; | |
| const images = document.querySelectorAll('img[alt]'); | |
| images.forEach(img => { | |
| const link = img.closest('a'); | |
| if (link && img.alt) { | |
| results.push({ | |
| title: img.alt, | |
| image: img.src, | |
| url: link.href | |
| }); | |
| } | |
| }); | |
| return results; | |
| }); | |
| if (searchResults.length === 0) { | |
| await browser.close(); | |
| throw new Error('No results found'); | |
| } | |
| const movieUrl = searchResults[0].url; | |
| await page.goto(movieUrl, { waitUntil: 'networkidle0', timeout: 30000 }); | |
| await new Promise(resolve => setTimeout(resolve, 3000)); | |
| const servers = await page.evaluate(() => { | |
| const serverList = []; | |
| const buttons = document.querySelectorAll('button'); | |
| buttons.forEach(btn => { | |
| const nameEl = btn.querySelector('.font-medium'); | |
| const statusEl = btn.querySelector('.text-green-400'); | |
| if (nameEl && statusEl && statusEl.textContent.includes('AVAILABLE')) { | |
| serverList.push({ | |
| name: nameEl.textContent.trim(), | |
| available: true | |
| }); | |
| } | |
| }); | |
| return serverList; | |
| }); | |
| let videoUrl = null; | |
| page.on('response', async response => { | |
| const url = response.url(); | |
| if (url.includes('.m3u8') || url.includes('.mp4') || url.includes('stream')) { | |
| videoUrl = url; | |
| } | |
| }); | |
| for (const server of servers) { | |
| try { | |
| await page.evaluate((serverName) => { | |
| const buttons = Array.from(document.querySelectorAll('button')); | |
| const btn = buttons.find(b => { | |
| const nameEl = b.querySelector('.font-medium'); | |
| return nameEl && nameEl.textContent.trim() === serverName; | |
| }); | |
| if (btn) btn.click(); | |
| }, server.name); | |
| await new Promise(resolve => setTimeout(resolve, 5000)); | |
| const currentVideoUrl = await page.evaluate(() => { | |
| const video = document.querySelector('video'); | |
| return video ? video.src : null; | |
| }); | |
| if (currentVideoUrl && !currentVideoUrl.startsWith('blob:')) { | |
| videoUrl = currentVideoUrl; | |
| break; | |
| } | |
| if (videoUrl && !videoUrl.startsWith('blob:')) { | |
| break; | |
| } | |
| } catch (e) { | |
| continue; | |
| } | |
| } | |
| await browser.close(); | |
| return { | |
| title: searchResults[0].title, | |
| image: searchResults[0].image, | |
| movieUrl: movieUrl, | |
| servers: servers, | |
| videoUrl: videoUrl, | |
| allResults: searchResults | |
| }; | |
| }; | |
| const handler = async (req, res) => { | |
| try { | |
| const { q } = req.query; | |
| if (!q) { | |
| return res.status(400).json({ | |
| success: false, | |
| error: 'Missing required parameter: q' | |
| }); | |
| } | |
| const result = await scrapeFlixer(q); | |
| res.json({ | |
| author: "Herza", | |
| success: true, | |
| msg: result | |
| }); | |
| } catch (error) { | |
| res.status(500).json({ | |
| success: false, | |
| error: error.message | |
| }); | |
| } | |
| }; | |
| module.exports = { | |
| name: 'Flixer Search', | |
| description: 'Search and get video from Flixer', | |
| type: 'GET', | |
| routes: ['api/search/flixer'], | |
| tags: ['search', 'movie', 'tools'], | |
| parameters: ['q', 'key'], | |
| enabled: true, | |
| main: ['Downloader', 'Search'], | |
| handler | |
| }; |