File size: 4,710 Bytes
d17a758
 
 
04d20e9
d17a758
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
04d20e9
 
 
 
 
 
d17a758
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
04d20e9
d17a758
 
 
04d20e9
d17a758
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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}`));