const express = require('express'); const axios = require('axios'); const cheerio = require('cheerio'); const puppeteer = require('puppeteer-core'); const app = express(); const PORT = 7860; // Enable CORS const cors = require('cors'); app.use(cors()); app.get('/anime/:title/:episode', async (req, res) => { const animeTitle = req.params.title; const episodeNumber = req.params.episode; console.log(`Requested: ${animeTitle} Episode ${episodeNumber}`); try { const episodeData = await searchGogoanime(animeTitle, episodeNumber); res.json(episodeData); } catch (error) { res.status(500).json({ error: "Failed to fetch episode data", details: error.message }); } }); async function searchGogoanime(animeTitle, episodeNumber) { try { console.log(`Searching for: ${animeTitle} Episode ${episodeNumber}`); // Search Gogoanime const searchUrl = `https://ww24.gogoanimes.fi/search.html?keyword=${encodeURIComponent(animeTitle)}`; const searchResponse = await axios.get(searchUrl); const $ = cheerio.load(searchResponse.data); // Find first result const firstResult = $('.items li a').first(); const animeSlug = firstResult.attr('href')?.split('/')[2]; const foundTitle = firstResult.text().trim(); if (!animeSlug) throw new Error("Anime not found"); console.log(`Anime Found: ${foundTitle} (${animeSlug})`); // Episode page URL const episodeUrl = `https://ww24.gogoanimes.fi/${animeSlug}-episode-${episodeNumber}`; console.log(`Episode URL: ${episodeUrl}`); return await getEpisodeInfo(episodeUrl, foundTitle, episodeNumber); } catch (error) { throw new Error("Error searching Gogoanime: " + error.message); } } async function getEpisodeInfo(episodeUrl, animeTitle, episodeNumber) { try { console.log(`Fetching: ${episodeUrl}`); const response = await axios.get(episodeUrl); const $ = cheerio.load(response.data); // Extract anime details const thumbnail = $('.anime_info_body_bg img').attr('src'); const summary = $('.anime_info_body_bg p.type').last().text().trim(); // Find download link page const downloadPageUrl = $('.dowloads a').attr('href'); if (!downloadPageUrl) throw new Error("Download page not found"); console.log(`S3embtaku Download Page Found: ${downloadPageUrl}`); const downloadLinks = await getVideoLinks(downloadPageUrl); return { anime: animeTitle, episode: episodeNumber, thumbnail, summary, owner: "Reiker", downloads: downloadLinks }; } catch (error) { throw new Error("Error fetching episode info: " + error.message); } } async function getVideoLinks(downloadPageUrl) { console.log(`Opening Puppeteer: ${downloadPageUrl}`); const browser = await puppeteer.launch({ executablePath: "/usr/bin/chromium", args: ["--no-sandbox", "--disable-setuid-sandbox"] }); const page = await browser.newPage(); try { await page.goto(downloadPageUrl, { waitUntil: 'networkidle2' }); // Wait for the download buttons to load await page.waitForSelector('a[href*="ggredi.info/download.php"]', { timeout: 10000 }); // Get all quality links const videoLinks = await page.evaluate(() => { const links = Array.from(document.querySelectorAll('a[href*="ggredi.info/download.php"]')); return links.map(link => ({ quality: link.innerText.trim(), url: link.href })); }); await browser.close(); return videoLinks; } catch (error) { console.error("Error extracting video links:", error.message); await browser.close(); return []; } } async function getFinalMp4Link(redirectLink) { try { console.log(`Following redirect: ${redirectLink}`); // Step 1: Follow Redirect and Get Final Video URL const response = await axios.get(redirectLink, { maxRedirects: 5 }); if (response.request.res.responseUrl) { console.log(`Final MP4 Link: ${response.request.res.responseUrl}`); return response.request.res.responseUrl; } else { console.log("No final MP4 link found."); return null; } } catch (error) { console.error("Error fetching final MP4 link:", error.message); return null; } } // Start API Server app.listen(PORT, () => console.log(`Server running on http://localhost:${PORT}`));