返回首頁 

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.


Install this script?
// ==UserScript==// @name         Crunchyroll VF images pour les titres depuis Crunchyroll// @namespace    https://greasyfork.org/scripts/489193// @version      2.2// @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// @icon         https://www.google.com/s2/favicons?sz=64&domain=crunchyroll.com// @grant        GM_xmlhttpRequest// @require      https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js// ==/UserScript==(async function() {'use strict';const startTime = Date.now(); // Enregistrer l'heure de débutconst fetchAnimeImage = async (animeUrl) => {return new Promise((resolve, reject) => {// Ignorer l'URL spécifiqueif (animeUrl.includes("seasonal-lineup")) {console.log("seasonal-lineup, passage à l'URL suivante.");resolve({ url: null, is404: false });return;}// Créer un iframeconst iframe = document.createElement('iframe');iframe.style.display = 'none'; // Rendre l'iframe invisibledocument.body.appendChild(iframe);// Écouter l'événement de chargement de l'iframeiframe.onload = () => {const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;// Observer les changements dans le document de l'iframeconst observer = new MutationObserver(() => {// Vérifier la présence d'une erreur 404if (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({ url: yuzuImage.src, is404: true });} else {resolve({ url: "404", is404: true });}observer.disconnect(); // Déconnecter l'observateurdocument.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({ url: images[0].src, is404: false }); // Renvoie la première image trouvéeobserver.disconnect(); // Déconnecter l'observateurdocument.body.removeChild(iframe);}});// Commencer à observer les changementsobserver.observe(iframeDoc, { childList: true, subtree: true });};// Gérer les erreurs de chargement de l'iframeiframe.onerror = () => {reject(new Error('Erreur de chargement de l\'iframe'));document.body.removeChild(iframe);};// Charger l'URL dans l'iframeiframe.src = animeUrl;});};// Fonction pour convertir une image en données base64const 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.r###lt);};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 disponibleconst displayMoviePoster = async function(posterUrl, titleElement) {// Vérifier que titleElement existe avant d’insérer l'imageif (!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 base64const posterImg = document.createElement('img');posterImg.src = base64Image;posterImg.style.maxHeight = '200px';// Ajouter l'image au paragrapheposterParagraph.appendChild(posterImg);}if (posterUrl === "404") {const placeholderText = document.createElement('i');placeholderText.textContent = '[404]';posterParagraph.appendChild(placeholderText);}// Insérer le paragraphe après le titretitleElement.parentNode.insertBefore(posterParagraph, titleElement.nextSibling);};const getStoredPosterUrl = (title) => {const storedData = JSON.parse(localStorage.getItem("animePosterUrls") || "{}");return storedData[title] || null;};const storePosterUrl = (title, url) => {const storedData = JSON.parse(localStorage.getItem("animePosterUrls") || "{}");storedData[title] = url;localStorage.setItem("animePosterUrls", JSON.stringify(storedData));console.log("animePosterUrls :", url);};// Attente jusqu'à ce que des éléments de titre soient disponibleslet 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 alternatifconst 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 titleText = titleElement ? titleElement.textContent : "";let posterUrl = getStoredPosterUrl(titleText);if (posterUrl) {console.log("Affiche trouvée dans localStorage :", posterUrl);} else {posterUrl = await fetchAnimeImage(animeUrl);if (posterUrl.url && !posterUrl.is404) {storePosterUrl(titleText, posterUrl.url);}posterUrl = posterUrl.url;}await displayMoviePoster(posterUrl, titleElement);}// Calculer le temps écoulé et afficher une alerteconst endTime = Date.now();const duration = ((endTime - startTime) / 1000).toFixed(2); // Durée en secondes avec deux décimalesalert(`Tous les titres d'anime ont été traités en ${duration} secondes.`);})();