Advertisement
Guest User

Untitled

a guest
Aug 4th, 2022
41
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name         MAL API Anime list total time - MAL
  3. // @namespace    https://greasyfork.org/en/users/670188-hacker09?sort=daily_installs
  4. // @version      2
  5. // @description  Shows the total amount of time you will take to watch all entries on your anime list.
  6. // @author       hacker09
  7. // @match        https://myanimelist.net/profile/*
  8. // @icon         https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://myanimelist.net&size=64
  9. // @grant        GM.xmlHttpRequest
  10. // @run-at       document-end
  11. // ==/UserScript==
  12.  
  13. (async function() {
  14.   'use strict';
  15.   document.head.insertAdjacentHTML('beforeend', '<style>.di-ib.fl-r.lh10 {cursor: pointer;}</style>'); //Make each status total entry number look clickable
  16.   document.querySelectorAll(".di-ib.fl-r.lh10").forEach(async function(el, i) { //ForEach status total entry number
  17.     el.onclick = async function() //When the user clicks on the status total entry number
  18.     { //Starts the onclick event listener
  19.       var stats; //Set a global variable
  20.       var EntryIds = []; //Create a new array
  21.       var TotalHrMins = ['0']; //Create a new array
  22.       var nextpagenum = 0; //Create a variable to hold the page number
  23.       var Counter = 0; //Create a variable to hold the Total Entries Number
  24.       var increaseby = 1000; //Create a variable to Increase the list page number
  25.  
  26.       alert(`This process will take about ${(Math.floor(el.innerText.match(/\d+,?\d+/g)[0].replace(',','') * 2 / 60))}:${el.innerText.match(/\d+,?\d+/g)[0].replace(',','') * 2 % 60} minutes to complete\n\nPlease avoid opening any MAL links during that time!`); //Let the user know how log it will take
  27.  
  28.       switch (i) { //Detect the user choice
  29.         case 0: //If the user clicked on Watching
  30.           stats = 'watching'; //Change the variable value
  31.           document.querySelector("h5,.pt16.pb12").style.backgroundColor = '#2db039'; //Change the bg color to match the selected status
  32.           break; //Stop executing the switch statement
  33.         case 1: //If the user clicked on Completed
  34.           stats = 'completed'; //Change the variable value
  35.           document.querySelector("h5,.pt16.pb12").style.backgroundColor = '#26448f'; //Change the bg color to match the selected status
  36.           break; //Stop executing the switch statement
  37.         case 2: //If the user clicked on On-Hold
  38.           stats = 'on_hold'; //Change the variable value
  39.           document.querySelector("h5,.pt16.pb12").style.backgroundColor = '#f9d457'; //Change the bg color to match the selected status
  40.           break; //Stop executing the switch statement
  41.         case 3: //If the user clicked on Dropped
  42.           stats = 'dropped'; //Change the variable value
  43.           document.querySelector("h5,.pt16.pb12").style.backgroundColor = '#a12f31'; //Change the bg color to match the selected status
  44.           break; //Stop executing the switch statement
  45.         case 4: //If the user clicked on Plan to Watch
  46.           stats = 'plan_to_watch'; //Change the variable value
  47.           document.querySelector("h5,.pt16.pb12").style.backgroundColor = '#c3c3c3'; //Change the bg color to match the selected status
  48.           break; //Stop executing the switch statement
  49.       } //Finishes the switch statement
  50.  
  51.       while (true) { //Starts the while condition to get the Total Number of Entries on the user list
  52.         var entries = await new Promise((resolve, reject) => GM.xmlHttpRequest({
  53.           responseType: 'json',
  54.           url: `https://api.myanimelist.net/v2/users/${location.href.split('/')[4]}/animelist?fields=list_status&status=${stats}&limit=${nextpagenum}`,
  55.           headers: {
  56.             "x-mal-client-id": "8ef0267fd86a187d479e6fcd7e1bb42a"
  57.           },
  58.           onload: r => resolve(r.response.data),
  59.           onerror: function () {
  60.             throw new Error(`Failed getting ${location.href.split('/')[4]} user list`); //Shows an error message
  61.           }
  62.         }));
  63.  
  64.         //console.log(response.response)
  65.         /*         if (entries.error !== undefined) //If the user has a private list
  66.         { //Starts the if condition
  67.           document.querySelector("h5,.pt16.pb12").style.backgroundColor = '#fff'; //Change the bg color to match the selected status
  68.           alert(location.href.split('/')[4] + ' has a private anime list!') //Show a message to the user
  69.           return; //Stop the script
  70.         } //Finishes the if condition */
  71.  
  72.         //return response.response.data;
  73.         //console.log( response.response.data.forEach(entry => console.log(entry.node.id)) );
  74.  
  75.         console.log(entries)
  76.         var TotalEntries = entries.length; //Save the Total Entries Number
  77.         Counter += TotalEntries; //Sum the Total Entries Number to TotalEntries
  78.         entries.forEach(el => EntryIds.push(el.anime_id)); //Save all entry ids
  79.         if (TotalEntries !== 1000) //If the next page has less than 1000 entries stop looping the while condition
  80.         { //Starts the if condition
  81.           console.log('Finished Getting the Total Entries Number!'); //Shows a console message
  82.           EntryIds.forEach(async function(id, index) { //For each entry id
  83.             setTimeout(async function() { //Starts the settimeout
  84.               const response = await (await fetch("https://myanimelist.net/includes/ajax-no-auth.inc.php?t=6", { //Fetch
  85.                 "headers": {
  86.                   "content-type": "application/x-www-form-urlencoded; charset=UTF-8"
  87.                 },
  88.                 "body": `color=1&id=${id}&memId=${document.querySelector("input[name*=profileMemId]") !== null ? document.querySelector("input[name*=profileMemId]").value : document.querySelector(".mr0").href.match(/\d+/g)[0]}&type=anime&csrf_token=${document.querySelector("meta[name=csrf_token]").content}`,
  89.                 "method": "POST",
  90.                 "mode": "cors"
  91.               })).text(); //Get each entry individual episode duration times
  92.               const newDocument = new DOMParser().parseFromString(response, 'text/html'); //Parses the fetch response
  93.               const json = await (await fetch(`https://api.jikan.moe/v4/anime/${id}/full`)).json(); //Fetch to get the eps
  94.  
  95.               if (newDocument.querySelector('td > div > a:nth-child(2) > small,td > div > strong > a > small') === null) //If an error occurs
  96.               { //Starts the if condition
  97.                 throw new Error('Failed getting total entry times for https://myanimelist.net/anime/' + id); //Shows an error message
  98.               } //Finishes the if condition
  99.  
  100.               var TotalEpisodes = json.data.episodes; //Get total entry amount of eps
  101.               var TotalMins = TotalEpisodes * newDocument.querySelector('td > div > a:nth-child(2) > small,td > div > strong > a > small').childNodes[0].data.match(/\d+/g)[1]; //Multiply Extracted Eps By total entry Mins
  102.               var TotalHrs = TotalEpisodes * newDocument.querySelector('td > div > a:nth-child(2) > small,td > div > strong > a > small').childNodes[0].data.match(/\d+/g)[0] * 60; //Multiply Eps By total entry Hrs
  103.               TotalHrMins.push(TotalHrs, TotalMins); //Add Hrs And Mins To The Array
  104.               var TotalMinsResult = TotalHrMins.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b); //Sum Hrs in Mins + Total Mins
  105.               var days = Math.floor(TotalMinsResult / 1440); //Get total days amount
  106.               var hours = Math.floor((TotalMinsResult % 1440) / 60); //Get total hours amount
  107.               var minutes = (TotalMinsResult % 1440) % 60; //Get total minutes amount
  108.               document.querySelector("h5,.pt16.pb12").innerText = 'Anime Stats (' + days + ' Days ' + hours + ' Hours ' + minutes + ' Minutes)'; //Show the total time
  109.  
  110.               if (EntryIds.length - 1 === index) //If it's the last loop
  111.               { //Starts the if condition
  112.                 document.querySelector("h5,.pt16.pb12").innerText += ' ✔️'; //Adds a checkmark after the total time
  113.               } //Finishes the if condition
  114.  
  115.             }, index * 2000); //Finishes the settimeout function
  116.           }); //Finishes the for each condition
  117.           return; //Stop the script if fetched page has less than 1000 entries and run the EntryIds.forEach loop
  118.         } //Finishes the if condition
  119.       } //Finishes the while condition
  120.     }; //Finishes the onclick event listener
  121.   }); //Finishes the foreach loop
  122. })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement