Total Duration Time + Total Episodes Of Any Animes Franchises

This is a tool to easily and quickly see how long it will take for you to finish watching the whole anime Franchise, and you can also see how many episodes and entries the Franchise has.

目前為 2021-02-05 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Total Duration Time + Total Episodes Of Any Animes Franchises
// @namespace    DurationByFranchise
// @version      1.0.0.3
// @description  This is a tool to easily and quickly see how long it will take for you to finish watching the whole anime Franchise, and you can also see how many episodes and entries the Franchise has.
// @author       hacker09
// @include      /^https:\/\/myanimelist\.net\/anime\/[\d]+(\/.*)?/
// @match        https://chiaki.site/?/tools/watch_order/id/*
// @match        https://chiaki.site/?/tools/watch_order/group_id/*
// @icon         https://www.google.com/s2/favicons?domain=myanimelist.net
// @run-at       document-end
// @grant        GM_deleteValue
// @grant        GM_listValues
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

(function() {
  'use strict';
  var Remaining = ''; //Creates a new blank variable
  var TotalHrMins = []; //Creates a new blank array
  var TotalEpsResult = []; //Creates a new blank array
  var TotalEpisodesTypeTV = ['0']; //Creates a new array
  var TotalEpisodesTypeOVA = ['0']; //Creates a new array
  var TotalEpisodesTypeONA = ['0']; //Creates a new array
  var TotalEpisodesTypeMusic = ['0']; //Creates a new array
  var TotalEpisodesTypeMovie = ['0']; //Creates a new array
  var TotalEpisodesTypeSpecial = ['0']; //Creates a new array

  if (top.location.host === 'myanimelist.net') { //Starts the if condition
    var animeid = location.pathname.match(/\d+/)[0]; //Detect the anime id
    var CompletedAnimeIds = GM_listValues(); //Add the new completed anime id to the variable
    var CompletedAnimeIdsRegex = new RegExp(CompletedAnimeIds.toLocaleString().replace(/,/gi, '|')); //Create a new variable and regex containing all the values saved on tampermonkey and replace the , separator with the or | regex symbol
    if (document.querySelector("#myinfo_status.btn-user-status-add-list.js-form-user-status.js-form-user-status-btn.myinfo_addtolist") === null) { //If the anime is on the user list
      document.querySelectorAll("#myinfo_status")[1].addEventListener('change', function() { //Listen for the anime entry status changes
        if (this.value !== '6') { //If any status besides Plant To Watch is selected
          GM_setValue(animeid, 'Completed Anime Id'); //Get and save the anime id as a variable
        } //Finishes the if condition
        else //If Plant To Watch is selected
        { //Starts the else condition
          GM_deleteValue(animeid); //Remove the anime if of the completed script anime ids storage
        } //Finishes the else condition
      }, false); //Finishes the change advent listener
    } //Finishes the if condition

  } //Finishes the if condition

  async function ProcessRawTextContent() //Creates a function to Process the RawTextContent
  { //Starts the function
    if (top.location.host === 'myanimelist.net') //If The User Is On The https://myanimelist.net/ Website Fetch Chiaki
    { //Starts the if condition
      var IsUserOnMAL = true;
      const response = await fetch('https://api.allorigins.win/raw?url=https://chiaki.site/?/tools/watch_order/id/' + animeid); //Fetch
      const html = await response.text(); //Gets the fetch response
      const newDocument = new DOMParser().parseFromString(html, 'text/html'); //Parses the fetch response
      var TextElement = newDocument.querySelectorAll("span.uk-text-muted.uk-text-small"); //Creates a variable to loop though the elements after
    } //Finishes the if condition
    else //If The User Is On The https://chiaki.site/ Website Start Processing The Content
    { //Starts the else condition
      var IsUserOnMAL = false;
      var TextElement = document.querySelectorAll("span.uk-text-muted.uk-text-small"); //Creates a variable to loop though the elements after
    } //Finishes the else condition

    for (var i = 0; i < TextElement.length; i++) { //Starts the for condition
      var TotalRawDurationHasSecs = TextElement[i].textContent.split("× ")[1].match('sec'); //Creates a variable to check later if there's an entry that has secs
      var TotalRawDuration = TextElement[i].textContent.split("× ")[1].split(' |')[0].match(/\d+|\?/g); //Creates a variable to hold the total unprocessed times
      var TotalEpisodes = TextElement[i].textContent.split("× ")[0].split(' |')[2].match(/\d+|\?/g); //Creates a variable to hold the total episodes
      var EpisodeType = TextElement[i].textContent.split("× ")[0].split(' |')[1]; //Creates a variable to check the episode types
      TotalEpsResult.push(TotalEpisodes); //Add The Eps To The Array
      if (IsUserOnMAL) //If The User Is On The https://myanimelist.net/ Website
      { //Starts the if condition
        if (TextElement[i].children[0].href.match(CompletedAnimeIdsRegex) !== null && CompletedAnimeIdsRegex.toLocaleString() !== '/(?:)/') //If the current url anime id matches an anime entry that was already completed, and if the Regex constains 1 or more anime ids
        { //Starts the if condition
          TotalRawDuration = '?'; //Remove the Total Raw Duration value of this anime to not count it later
          Remaining = 'Remaining '; //Adds the text "Remaining" to the variable
        } //Finishes the if condition
      } //Finishes the if condition
      if (TotalRawDuration.length !== 1 && TotalRawDurationHasSecs === null) //If has Hrs and Mins and not secs
      { //Starts the if condition
        var ExtractHrs = TotalRawDuration[0] * 60; //Extract Hrs And Convert To Mins
        var TotalHrs = TotalEpisodes * ExtractHrs; //Multiply Eps By Hrs
        var TotalMins = TotalEpisodes * TotalRawDuration[1]; //Multiply Extracted Eps By Mins
        TotalHrMins.push(TotalHrs, TotalMins); //Add Hrs And Mins To The Array
      } //Finishes the if condition
      else if (TotalRawDurationHasSecs === null) //Extract only Mins and not secs
      { //Starts the else condition
        var TotalMins = TotalEpisodes * TotalRawDuration[0]; //Multiply Extracted Eps By Mins
        TotalHrMins.push(TotalMins); //Add Mins To The Array
      } //Finishes the else condition
      if (EpisodeType.match('Music') !== null) //If it's Music
      { //Starts the if condition
        TotalEpisodesTypeMusic.push(TotalEpisodes); //Add The Eps To The Array
      } //Finishes the if condition
      if (EpisodeType.match('TV') !== null) //If it's TV
      { //Starts the if condition
        TotalEpisodesTypeTV.push(TotalEpisodes); //Add The Eps To The Array
      } //Finishes the if condition
      if (EpisodeType.match('OVA') !== null) //If it's OVA
      { //Starts the if condition
        TotalEpisodesTypeOVA.push(TotalEpisodes); //Add The Eps To The Array
      } //Finishes the if condition
      if (EpisodeType.match('Special') !== null) //If it's Special
      { //Starts the if condition
        TotalEpisodesTypeSpecial.push(TotalEpisodes); //Add The Eps To The Array
      } //Finishes the if condition
      if (EpisodeType.match('ONA') !== null) //If it's ONA
      { //Starts the if condition
        TotalEpisodesTypeONA.push(TotalEpisodes); //Add The Eps To The Array
      } //Finishes the if condition
      if (EpisodeType.match('Movie') !== null) //If it's Movie
      { //Starts the if condition
        TotalEpisodesTypeMovie.push(TotalEpisodes); //Add The Eps To The Array
      } //Finishes the if condition
    } //Finishes the for condition

    var TotalEpsFinal = TotalEpsResult.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b); //Sum The Total Eps
    //alert(TotalHrMins)
    //var TotalMinsResult = '0'
    var TotalMinsResult = TotalHrMins.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b); //Sum Hrs in Mins + Total Mins
    var ONAEpisodesResult = TotalEpisodesTypeONA.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b) + ' ONA(s)'; //Sum The Total Eps
    var OVAEpisodesResult = TotalEpisodesTypeOVA.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b) + ' OVA(s)'; //Sum The Total Eps
    var TVEpisodesResult = TotalEpisodesTypeTV.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b) + ' TV Episode(s)'; //Sum The Total Eps
    var MusicEpisodesResult = TotalEpisodesTypeMusic.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b) + ' Music(s)'; //Sum The Total Eps
    var MovieEpisodesResult = TotalEpisodesTypeMovie.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b) + ' Movie(s)'; //Sum The Total Eps
    var SpecialEpisodesResult = TotalEpisodesTypeSpecial.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b) + ' Special(s)'; //Sum The Total Eps
    //The Commands Below Converts The Total Franchise Time To Precise Hours And Minutes
    var days = Math.floor(TotalMinsResult / 1440);
    var hours = Math.floor((TotalMinsResult % 1440) / 60);
    var minutes = (TotalMinsResult % 1440) % 60;

    var title = 'title="' + OVAEpisodesResult + '&#13;' + ONAEpisodesResult + '&#13;' + MusicEpisodesResult + '&#13;' + SpecialEpisodesResult + '&#13;' + MovieEpisodesResult + '&#13;' + TVEpisodesResult + '"'; //Content that will be shown on mouse hover

    if (TextElement.length === 1) //If there's only 1 entry on chiaki.site for the whole franchise
    { //Starts the if condition
      var html; //Creates a blank variable
      IsUserOnMAL && document.querySelector("td.borderClass").innerText.search("Remaining time:") > -1 ? html = '' : html = 'Franchise Duration: </span>' + days + ' day(s) ' + hours + ' hr(s) ' + minutes + ' min(s)'; //If the text "Remaining time:" exists don't show the Franchise Duration text
      var HasMoreThan1Entry = false; //Create a varible to confirm that the Franchise thas more than 1 entry
    } //Finishes the if condition
    else //If there's more than 1 entry on chiaki.site for the whole franchise
    { //Starts the if condition
      var html = Remaining + 'Franchise Duration: </span>' + days + ' day(s) ' + hours + ' hr(s) ' + minutes + ' min(s)'; //Shows the real html on MAL
      var HasMoreThan1Entry = true; //Create a varible to confirm that the Franchise thas more than 1 entry
    } //Finishes the else condition

    if (IsUserOnMAL) //If The User Is On The https://myanimelist.net/ Website
    { //Starts the if condition
      function findTheInformationheader() {
        const headers = [...document.querySelectorAll("h2")]; //Select all h2 elements on MAL
        return headers.find(h2 => h2.textContent === "Information");
      } //Find the h2 element that has the text Information

      function findTheRatingText() {
        const allInfo = [...findTheInformationheader().parentNode.querySelectorAll("div")]; //Select all divs inside the Information h2 element
        return allInfo.find(info => info.innerText.includes("Rating"));
      } //Find the Rating text that's inside the information h2 element
      findTheRatingText().insertAdjacentHTML('beforeend', '<div class="spaceit" ' + title + '><span class="dark_text">' + html + '</div>'); //Show The Total Duration
      if (HasMoreThan1Entry === true) //If the Franchise has more than 1 Entry
      { //Starts the if condition
        findTheRatingText().insertAdjacentHTML('beforeend', '<div class="spaceit" ' + title + '><span class="dark_text">Franchise Episodes: ' + TotalEpsFinal + '</a></li></div>'); //Show The Total Episodes
      } //Finishes the if condition
      findTheRatingText().insertAdjacentHTML('beforeend', '<div class="spaceit" ' + title + '><span class="dark_text">Franchise Entries: ' + TextElement.length + '</a></li></div>'); //Show The Total Entries
    } //Finishes the if condition
    else //If The User Is On The https://chiaki.site/ Website
    { //Starts the else condition
      document.querySelector("ul.uk-flex-center.noborder.uk-tab").insertAdjacentHTML('beforeend', '<li><a href="#" ' + title + '>Total Duration: ' + days + ' day(s) ' + hours + ' hr(s) ' + minutes + ' min(s)</a></li>'); //Show The Total Duration
      if (HasMoreThan1Entry === true) //If the Franchise has more than 1 Entry
      { //Starts the if condition
        document.querySelector("ul.uk-flex-center.noborder.uk-tab").insertAdjacentHTML('beforeend', '<li><a href="#" ' + title + '>Total Episodes: ' + TotalEpsFinal + '</a></li>'); //Show The Total Episodes
        document.querySelector("ul.uk-flex-center.noborder.uk-tab").insertAdjacentHTML('beforeend', '<li><a href="#" ' + title + '>Total Entries: ' + TextElement.length + '</a></li>'); //Show The Total Entries
      } //Finishes the if condition
    } //Finishes the else condition
  } //Finishes the async function
  ProcessRawTextContent(); //Starts the function
})();