Greasy Fork

Greasy Fork is available in English.

Crunchyroll VF images pour les titres depuis Crunchyroll

Ajoute automatiquement une image d'affiche ou un texte alternatif à partir du lien de l'anime sur Crunchyroll.

目前为 2024-10-28 提交的版本,查看 最新版本

// ==UserScript==
// @name         Crunchyroll VF images pour les titres depuis Crunchyroll
// @namespace    http://greasyfork.icu/scripts/489193
// @version      2.1
// @description  Ajoute automatiquement une image d'affiche ou un texte alternatif à partir du lien de l'anime sur Crunchyroll.
// @author       MASTERD
// @match        https://www.crunchyroll.com/fr/news/guides/2022/3/4/crunchyroll-vf-anime
// @grant        GM_xmlhttpRequest
// @require      https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js
// ==/UserScript==

(async function() {
    'use strict';

    const fetchAnimeImage = async (animeUrl) => {
        return new Promise((resolve, reject) => {
            // Ignorer l'URL spécifique
            if (animeUrl === "https://www.crunchyroll.com/fr/news/seasonal-lineup/2023/12/13/vf-crunchyroll-hiver-2024?utm_source=news_cr&utm_medium=editorial_cr&utm_campaign=q1-2024_fr&referrer=news_cr_editorial_cr_q1-2024_fr" ||
                animeUrl === "https://www.crunchyroll.com/fr/news/seasonal-lineup/2023/12/13/lineup-anime-hiver-2024?utm_source=news_cr&utm_medium=editorial_cr&utm_campaign=q1-2024_fr&referrer=news_cr_editorial_cr_q1-2024_fr") {
                console.log("seasonal-lineup, passage à l'URL suivante.");
                resolve(null); // Passer à l'URL suivante
                return;
            }

            // Créer un iframe
            const iframe = document.createElement('iframe');
            iframe.style.display = 'none'; // Rendre l'iframe invisible
            document.body.appendChild(iframe);

            // Écouter l'événement de chargement de l'iframe
            iframe.onload = () => {
                const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
                // Observer les changements dans le document de l'iframe
                const observer = new MutationObserver(() => {
                    // Vérifier la présence d'une erreur 404
                    if (iframeDoc.body && iframeDoc.body.innerText.includes("404")) {
                        console.log("Erreur 404 détectée, passage à l'URL suivante.");
                        const yuzuImage = iframeDoc.querySelector('.exception-artwork');
                        if (yuzuImage) {
                            resolve(yuzuImage.src); // Utilise l'URL de l'image Yuzu
                        } else {
                            resolve("404"); // Si l'image n'est pas trouvée, retourner un code d'erreur
                        }
                        observer.disconnect(); // Déconnecter l'observateur
                        document.body.removeChild(iframe);
                        return;
                    }
                    const images = Array.from(iframeDoc.querySelectorAll('img[alt="Series background blurred"][data-t="original-image"]'));
                    if (images.length > 0) {
                        console.log("Images trouvées : ", images);
                        resolve(images[0].src); // Renvoie la première image trouvée
                        observer.disconnect(); // Déconnecter l'observateur
                        document.body.removeChild(iframe);
                    }
                });

                // Commencer à observer les changements
                observer.observe(iframeDoc, { childList: true, subtree: true });
            };

            // Gérer les erreurs de chargement de l'iframe
            iframe.onerror = () => {
                reject(new Error('Erreur de chargement de l\'iframe'));
                document.body.removeChild(iframe);
            };

            // Charger l'URL dans l'iframe
            iframe.src = animeUrl;
        });
    };

    // Fonction pour convertir une image en données base64
    const getBase64Image = async function(url) {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: "GET",
                url: url,
                responseType: "blob",
                onload: function(response) {
                    const reader = new FileReader();
                    reader.onloadend = function() {
                        resolve(reader.result);
                    };
                    reader.onerror = function(error) {
                        reject(new Error(error));
                    };
                    reader.readAsDataURL(response.response);
                },
                onerror: function(error) {
                    reject(new Error(error));
                }
            });
        });
    };

    // Fonction pour afficher l'affiche de l'anime ou un texte alternatif si l'image n'est pas disponible
    const displayMoviePoster = async function(posterUrl, titleElement) {
        // Vérifier que titleElement existe avant d’insérer l'image
        if (!titleElement) {
            console.warn("Élément de titre introuvable pour l'affichage de l'affiche.");
            return;
        }

        const posterParagraph = document.createElement('p');

        if (posterUrl && posterUrl != "404") {
            const base64Image = await getBase64Image(posterUrl);

            // Créer l'image et lui attribuer les données base64
            const posterImg = document.createElement('img');
            posterImg.src = base64Image;
            posterImg.style.maxHeight = '200px';

            // Ajouter l'image au paragraphe
            posterParagraph.appendChild(posterImg);
        }

        if (posterUrl === "404") {
            const placeholderText = document.createElement('i');
            placeholderText.textContent = '[404]';
            posterParagraph.appendChild(placeholderText);
        }

        // Insérer le paragraphe après le titre
        titleElement.parentNode.insertBefore(posterParagraph, titleElement.nextSibling);
    };

    // Attente jusqu'à ce que des éléments de titre soient disponibles
    let titleElements = [];
    while (titleElements.length === 0) {
        titleElements = $('b > i');
        await new Promise(resolve => setTimeout(resolve, 1000)); // Attente de 1 seconde avant de vérifier à nouveau
    }

    // Récupérer tous les liens d'anime dans la page et afficher les images ou le texte alternatif
    const animeLinks = document.querySelectorAll('li > p > a');
    for (const link of animeLinks) {
        const titleElement = link.querySelector('b > i') || link.querySelector('b');
        const animeUrl = link.href;
        console.log("Url du titre pour l'image :", animeUrl);
        const posterUrl = await fetchAnimeImage(animeUrl);
        await displayMoviePoster(posterUrl, titleElement);
    }

    alert("Tous les titres d'anime ont été traités.");

})();