// ==UserScript== // @name Anime list total time - MAL // @namespace https://greasyfork.org/en/users/670188-hacker09?sort=daily_installs // @version 1 // @description Shows the total amount of time you will take to watch all entries on your anime list. // @author hacker09 // @match https://myanimelist.net/profile/* // @icon https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://myanimelist.net&size=64 // @run-at document-end // @grant none // @downloadURL none // ==/UserScript== (async function() { 'use strict'; document.head.insertAdjacentHTML('beforeend', ''); //Make each status total entry number look clickable document.querySelectorAll(".di-ib.fl-r.lh10").forEach(async function(el, i) { //ForEach status total entry number el.onclick = async function() //When the user clicks on the status total entry number { //Starts the onclick event listener var stats; //Set a global variable var EntryIds = []; //Create a new array var TotalHrMins = []; //Create a new array var nextpagenum = 0; //Create a variable to hold the page number var Counter = 0; //Create a variable to hold the Total Entries Number var increaseby = 300; //Create a variable to Increase the list page number switch (i) { //Detect the user choice case 0: //If the user clicked on Watching stats = 1; //Change the variable value document.querySelector("h5").style.backgroundColor = '#2db039'; //Change the bg color to match the selected status alert(`This process will take about ${(el.innerText.match(/\d+/g)[0] * 2 / 60).toFixed(2)} minutes to complete\n\nPlease avoid opening any MAL links during that time!`); //Let the user know how log it will take break; //Stop executing the switch statement case 1: //If the user clicked on Completed stats = 2; //Change the variable value document.querySelector("h5").style.backgroundColor = '#26448f'; //Change the bg color to match the selected status alert(`This process will take about ${(el.innerText.match(/\d+/g)[0] * 2 / 60).toFixed(2)} minutes to complete\n\nPlease avoid opening any MAL links during that time!`); //Let the user know how log it will take break; //Stop executing the switch statement case 2: //If the user clicked on On-Hold stats = 3; //Change the variable value document.querySelector("h5").style.backgroundColor = '#f9d457'; //Change the bg color to match the selected status alert(`This process will take about ${(el.innerText.match(/\d+/g)[0] * 2 / 60).toFixed(2)} minutes to complete\n\nPlease avoid opening any MAL links during that time!`); //Let the user know how log it will take break; //Stop executing the switch statement case 3: //If the user clicked on Dropped stats = 4; //Change the variable value document.querySelector("h5").style.backgroundColor = '#a12f31'; //Change the bg color to match the selected status alert(`This process will take about ${(el.innerText.match(/\d+/g)[0] * 2 / 60).toFixed(2)} minutes to complete\n\nPlease avoid opening any MAL links during that time!`); //Let the user know how log it will take break; //Stop executing the switch statement case 4: //If the user clicked on Plan to Watch stats = 6; //Change the variable value document.querySelector("h5").style.backgroundColor = '#c3c3c3'; //Change the bg color to match the selected status alert(`This process will take about ${(el.innerText.match(/\d+/g)[0] * 2 / 60).toFixed(2)} minutes to complete\n\nPlease avoid opening any MAL links during that time!`); //Let the user know how log it will take break; //Stop executing the switch statement } //Finishes the switch statement while (true) { //Starts the while condition to get the Total Number of Entries on the user list const entries = await (await fetch(`https://myanimelist.net/animelist/${location.href.split('/')[4]}/load.json?status=${stats}&offset=${nextpagenum}`)).json(); //Fetches the user list nextpagenum += increaseby; //Increase the next page number var TotalEntries = entries.length; //Save the Total Entries Number Counter += TotalEntries; //Sum the Total Entries Number to TotalEntries entries.forEach(el => EntryIds.push(el.anime_id)); //Save all entry ids if (TotalEntries !== 300) //If the next page has less than 300 entries stop looping the while condition { //Starts the if condition console.log('Finished Getting the Total Entries Number!'); //Shows a console message EntryIds.forEach(async function(id, index) { //For each entry id setTimeout(async function() { //Starts the settimeout const response = await (await fetch("https://myanimelist.net/includes/ajax-no-auth.inc.php?t=6", { //Fetch "headers": { "content-type": "application/x-www-form-urlencoded; charset=UTF-8" }, "body": `color=1&id=${id}&memId=${document.querySelector("input[name*=profileMemId]").value}&type=anime&csrf_token=${document.querySelector("meta[name=csrf_token]").content}`, "method": "POST", "mode": "cors" })).text(); //Get each entry individual episode duration times const newDocument = new DOMParser().parseFromString(response, 'text/html'); //Parses the fetch response const json = await (await fetch(`https://api.jikan.moe/v4/anime/${id}/full`)).json(); //Fetch to get the eps var TotalEpisodes = json.data.episodes; //Get the amount of eps var TotalMins = TotalEpisodes * newDocument.querySelectorAll("td > div > a:nth-child(2) > small")[0].childNodes[0].data.match(/\d+/g)[1]; //Multiply Extracted Eps By Mins var TotalHrs = TotalEpisodes * newDocument.querySelectorAll("td > div > a:nth-child(2) > small")[0].childNodes[0].data.match(/\d+/g)[0] * 60; //Multiply Eps By Hrs TotalHrMins.push(TotalHrs, TotalMins); //Add Hrs And Mins To The Array var TotalMinsResult = TotalHrMins.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b); //Sum Hrs in Mins + Total Mins var days = Math.floor(TotalMinsResult / 1440); //Get total days amount var hours = Math.floor((TotalMinsResult % 1440) / 60); //Get total hours amount var minutes = (TotalMinsResult % 1440) % 60; //Get total minutes amount document.querySelector("h5").innerText = 'Anime Stats (' + days + ' Days ' + hours + ' Hours ' + minutes + ' Minutes)'; //Show the total time if (EntryIds.length - 1 === index) //If it's the last loop { //Starts the if condition document.querySelector("h5").innerText += ' ✔️'; //Shows a console message } //Finishes the if condition }, index * 2000); //Finishes the settimeout function }); //Finishes the for each condition return; //Stop the script if fetched page has less than 300 entries and run the EntryIds.forEach loop } //Finishes the if condition } //Finishes the while condition }; //Finishes the onclick event listener }); //Finishes the foreach loop })();