// ==UserScript== // @name Crunchyroll VF affiche depuis Crunchyroll // @namespace https://greasyfork.org/scripts/489193 // @version 2.0 // @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 // @downloadURL none // ==/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."); })();