Aniworld Next Episode Button (Fixed v2)

Adds a Netflix-style "Next Episode" button to Aniworld

ही स्क्रिप्ट इंस्टॉल करा?
लेखकाने सुचवलेली स्क्रिप्ट

तुम्हाला कदाचित ही स्क्रिप्टदेखील आवडेल: 90 Second Skip Button with Auto-hide.

ही स्क्रिप्ट इंस्टॉल करा
// ==UserScript==
// @name         Aniworld Next Episode Button (Fixed v2)
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  Adds a Netflix-style "Next Episode" button to Aniworld
// @author       You
// @match        https://aniworld.to/anime/stream/*
// @license MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Configuration
    const BUTTON_TEXT = "Next Episode";
    const BUTTON_STYLE = `
        position: fixed;
        bottom: 20px;
        right: 20px;
        padding: 10px 20px;
        background-color: #040720;
        color: white;
        border: none;
        border-radius: 5px;
        font-weight: bold;
        cursor: pointer;
        z-index: 9999;
        opacity: 0.9;
        transition: opacity 0.3s ease;
        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
    `;

    // Function to add the Next Episode button
    function addNextEpisodeButton() {
        // Remove existing button if it exists
        const existingButton = document.getElementById('netflix-style-next-button');
        if (existingButton) {
            existingButton.remove();
        }

        // Create the button element
        const button = document.createElement('button');
        button.textContent = BUTTON_TEXT;
        button.style.cssText = BUTTON_STYLE;
        button.id = "netflix-style-next-button";

        // Hover effect
        button.addEventListener('mouseover', () => {
            button.style.opacity = '1';
        });
        button.addEventListener('mouseout', () => {
            button.style.opacity = '0.9';
        });

        // Add click event listener
        button.addEventListener('click', navigateToNextEpisode);

        // Add the button to the page
        document.body.appendChild(button);

        console.log("Added Next Episode button");
    }

    // Function to navigate to the next episode
    function navigateToNextEpisode() {
        console.log("Next Episode button clicked");

        // Instead of trying to determine the current episode in complex ways,
        // let's directly look at the episode numbers and find the one with different styling

        // First, get all the episode links from the episode section
        const episodeContainer = document.querySelector('.hosterSiteDirectNav') ||
                               document.querySelector('.episodenav');

        if (!episodeContainer) {
            console.error("Could not find episode container");
            return;
        }

        // Get all episode links
        const episodeLinks = Array.from(episodeContainer.querySelectorAll('a'));

        if (!episodeLinks || episodeLinks.length === 0) {
            console.error("Could not find episode links");
            return;
        }

        console.log("Found", episodeLinks.length, "episode links");

        // Find the currently active episode based on styling
        let activeLink = null;
        let activeIndex = -1;

        // Method 1: Look for any link with a blue/dark background color
        episodeLinks.forEach((link, index) => {
            const style = window.getComputedStyle(link);
            const bgColor = style.backgroundColor;

            // Check if background color is not transparent, white, or black
            if (bgColor !== 'transparent' &&
                bgColor !== 'rgba(0, 0, 0, 0)' &&
                bgColor !== 'rgb(255, 255, 255)' &&
                bgColor !== 'rgb(0, 0, 0)') {

                console.log("Found active episode with bg color:", bgColor, "at index:", index, "text:", link.textContent.trim());
                activeLink = link;
                activeIndex = index;
            }
        });

        // Method 2: If not found by background, check if any link has an 'active' class
        if (!activeLink) {
            episodeLinks.forEach((link, index) => {
                if (link.classList.contains('active') ||
                    link.parentElement.classList.contains('active')) {

                    console.log("Found active episode with active class at index:", index, "text:", link.textContent.trim());
                    activeLink = link;
                    activeIndex = index;
                }
            });
        }

        // Method 3: Direct comparison of the parent containers
        if (!activeLink) {
            // Get all number containers (parent elements of links)
            const episodeNumbers = Array.from(episodeContainer.children);

            episodeNumbers.forEach((numContainer, index) => {
                const link = numContainer.querySelector('a');
                if (!link) return;

                const style = window.getComputedStyle(numContainer);
                const bgColor = style.backgroundColor;

                if (bgColor !== 'transparent' &&
                    bgColor !== 'rgba(0, 0, 0, 0)' &&
                    bgColor !== 'rgb(255, 255, 255)' &&
                    bgColor !== 'rgb(0, 0, 0)') {

                    console.log("Found active container with bg color:", bgColor, "at index:", index, "text:", link.textContent.trim());
                    activeLink = link;
                    activeIndex = index;
                }
            });
        }

        // If still not found, try one more approach - find a link with text color different from others
        if (!activeLink) {
            const firstLinkColor = window.getComputedStyle(episodeLinks[0]).color;

            episodeLinks.forEach((link, index) => {
                const style = window.getComputedStyle(link);
                if (style.color !== firstLinkColor) {
                    console.log("Found active episode with different text color at index:", index, "text:", link.textContent.trim());
                    activeLink = link;
                    activeIndex = index;
                }
            });
        }

        // If still not found, try to directly get the current episode number from the URL
        if (!activeLink) {
            // Try to extract episode number from URL
            const urlMatch = window.location.href.match(/\/episode-(\d+)/);
            if (urlMatch && urlMatch[1]) {
                const currentEpisodeNum = parseInt(urlMatch[1], 10);
                console.log("Extracted episode number from URL:", currentEpisodeNum);

                // Find the link with this number
                episodeLinks.forEach((link, index) => {
                    if (link.textContent.trim() === currentEpisodeNum.toString()) {
                        console.log("Found active episode from URL at index:", index);
                        activeLink = link;
                        activeIndex = index;
                    }
                });
            }
        }

        // Finally, if we still haven't found an active link, just use the first link as a fallback
        if (!activeLink && episodeLinks.length > 0) {
            // Last resort: Just try to directly click the next number in sequence
            // Get all the episode numbers
            const episodeNumbers = episodeLinks.map(link => {
                const num = parseInt(link.textContent.trim(), 10);
                return isNaN(num) ? 0 : num;
            });

            // Find the highest visible episode number on the page
            const currentEpisodeNum = Math.max(...episodeNumbers.filter(num => num > 0));
            console.log("Current highest episode number found:", currentEpisodeNum);

            // Try to click the next episode number
            const nextEpisodeNum = currentEpisodeNum + 1;

            // Find link with the next episode number
            let nextLink = null;
            episodeLinks.forEach(link => {
                if (link.textContent.trim() === nextEpisodeNum.toString()) {
                    nextLink = link;
                }
            });

            if (nextLink) {
                console.log("Directly clicking next episode number:", nextEpisodeNum);
                nextLink.click();
                return;
            } else {
                console.error("Could not find next episode link");
                return;
            }
        }

        // Now that we have the active episode, get the next one
        if (activeLink && activeIndex !== -1 && activeIndex < episodeLinks.length - 1) {
            const nextEpisodeLink = episodeLinks[activeIndex + 1];
            console.log("Next episode found at index:", activeIndex + 1, "text:", nextEpisodeLink.textContent.trim());

            // Click the next episode link
            nextEpisodeLink.click();
        } else if (activeLink) {
            // We're at the last episode of this season, try to go to next season
            const seasonContainer = document.querySelector('.staffelWrapperLoop') ||
                                   document.querySelector('.seasonNav');

            if (seasonContainer) {
                const seasonLinks = Array.from(seasonContainer.querySelectorAll('a'));
                let activeSeasonLink = null;
                let activeSeasonIndex = -1;

                // Find active season
                seasonLinks.forEach((link, index) => {
                    const style = window.getComputedStyle(link);
                    const bgColor = style.backgroundColor;

                    if (bgColor !== 'transparent' &&
                        bgColor !== 'rgba(0, 0, 0, 0)' &&
                        bgColor !== 'rgb(255, 255, 255)' &&
                        bgColor !== 'rgb(0, 0, 0)') {

                        activeSeasonLink = link;
                        activeSeasonIndex = index;
                    }
                });

                if (activeSeasonLink && activeSeasonIndex < seasonLinks.length - 1) {
                    // Go to next season, first episode
                    const nextSeasonLink = seasonLinks[activeSeasonIndex + 1];
                    console.log("Going to next season");
                    nextSeasonLink.click();
                } else {
                    alert("You've reached the last episode of the final season!");
                }
            } else {
                // Directly try to find episode by number
                const currentEpisodeText = activeLink.textContent.trim();
                const currentEpisodeNum = parseInt(currentEpisodeText, 10);

                if (!isNaN(currentEpisodeNum)) {
                    const nextEpisodeNum = currentEpisodeNum + 1;

                    // Try to find the next episode number in all links on the page
                    const allLinks = Array.from(document.querySelectorAll('a'));
                    const nextLink = allLinks.find(link => link.textContent.trim() === nextEpisodeNum.toString());

                    if (nextLink) {
                        console.log("Found next episode by number:", nextEpisodeNum);
                        nextLink.click();
                    } else {
                        alert("Could not find the next episode!");
                    }
                } else {
                    alert("Could not determine the next episode!");
                }
            }
        } else {
            alert("Could not determine the current episode!");
        }
    }

    // Create and add the button when the page is fully loaded
    function initializeButton() {
        setTimeout(addNextEpisodeButton, 1000);
    }

    // Wait for the page to fully load
    window.addEventListener('load', initializeButton);

    // Also run when page content changes (for single-page apps)
    const observer = new MutationObserver(function(mutations) {
        // If major DOM changes were detected, reinitialize the button
        let significantChanges = false;

        mutations.forEach(function(mutation) {
            if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                // Check if significant elements were added
                for (let i = 0; i < mutation.addedNodes.length; i++) {
                    const node = mutation.addedNodes[i];
                    if (node.nodeType === 1) { // Element node
                        if (node.classList &&
                            (node.classList.contains('hosterSiteDirectNav') ||
                             node.classList.contains('episodenav'))) {
                            significantChanges = true;
                            break;
                        }
                    }
                }
            }
        });

        if (significantChanges) {
            initializeButton();
        }
    });

    // Start observing
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

    // Initialize immediately in case page is already loaded
    if (document.readyState === 'complete' || document.readyState === 'interactive') {
        initializeButton();
    }
})();