Greasy Fork is available in English.

Show Anime Duration With Seconds

Shows the Duration Time with seconds for all animes.

// ==UserScript==
// @name         Show Anime Duration With Seconds
// @namespace    DurationWithSeconds
// @version      19
// @description  Shows the Duration Time with seconds for all animes.
// @author       hacker09
// @include      /^https:\/\/myanimelist\.net\/(anime(id=)?(\.php\?id=)?)(\/)?([\d]+)/
// @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
// @connect      api.myanimelist.net
// @grant        GM.xmlHttpRequest
// @grant        GM_deleteValue
// @grant        GM_listValues
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

(async function() {
  'use strict';
  const animeid = location.pathname.match(/\d+/) === null ? location.search.match(/\d+/)[0] : location.pathname.match(/\d+/)[0]; //Detect the anime id
  var StoredAnimeIdsArray = []; //Creates a new blank array
  GM_listValues().forEach(a => StoredAnimeIdsArray.push('^' + a)); //Add all anime IDs on tampermonkey to the array
  const StoredAnimeIdsRegex = new RegExp(StoredAnimeIdsArray.join('$|')); //Create a new variable and regex containing all the values saved on tampermonkey and replace the , separator with the or $| regex symbols
  const findTheDurationText = [...[...document.querySelectorAll("h2")].find(h2 => h2.textContent === "Information").parentNode.querySelectorAll("div")].find(info => info.innerText.includes("Duration")).querySelector("span"); //Find the div that contains the Duration text

  if (GM_listValues().length >= 100) //If there's 100 anime ids and durations stored on tampermonkey
  { //Starts the if condition
    GM_listValues().forEach(a => GM_deleteValue(a)); //Erase all the 100 stored anime IDs and their durations stored on tampermonkey
  } //Finishes the if condition

  async function GetDurationWithSecs() { //Starts the if condition
    var API = await new Promise((resolve) => GM.xmlHttpRequest({ //Starts the xmlHttpRequest
      url: `https://api.myanimelist.net/v2/anime/${animeid}?fields=average_episode_duration`,
      headers: {
        "x-mal-client-id": "8ef0267fd86a187d479e6fcd7e1bb42a"
      },
      onload: r => resolve(r)
    })); //Finishes the xmlHttpRequest
    await new Promise(r => setTimeout(r, 500)); //Wait the xmlHttpRequest request to complete

    if (API.status !== 200) //If the API is being rated
    { //Starts the if condition
      throw ('The MAL API is being time rate limited!'); //Stop the script
    } //Finishes the if condition

    var Duration = new Date(JSON.parse(API.responseText).average_episode_duration * 1000).toISOString().slice(11, 19).split(':'); //Get each duration times
    Duration[0] = Duration[0] !== '00' ? Duration[0] + ' hr. ' : ''; //Erase the 00 hours amount if the entry has only minutes and seconds

    findTheDurationText.nextSibling.textContent = ' ' + Duration[0] + Duration[1] + ' min. ' + Duration[2] + ' sec. per ep.'; //Change the text content of the Duration: Element
    GM_setValue(animeid, ' ' + Duration[0] + Duration[1] + ' min. ' + Duration[2] + ' sec. per ep.'); //Get and save the anime id and Duration With Secs as a variable
  }; //Finishes the async function

  if (animeid.match(StoredAnimeIdsRegex) !== null && StoredAnimeIdsRegex.toLocaleString() !== '/(?:)/') //If the current url anime id matches an anime id that is stored on tampermonkey, and if the Regex contains 1 or more anime ids
  { //Starts the if condition

    findTheDurationText.nextSibling.textContent = GM_getValue(animeid); //Change the text content of the Duration: Element
    findTheDurationText.style.cursor = 'pointer'; //Make the bold Duration: text look like it's clickable
    findTheDurationText.onclick = GetDurationWithSecs

  } //Finishes the if condition
  else //If the current url anime id does NOT match any anime id that is stored on tampermonkey
  { //Starts the else condition
    var TimesExecuted = 0; //Creates a new variable

    window.onscroll = async function() { //Creates a new function to run when the page is scrolled
      TimesExecuted += 1; //Sum the amount of times that the page is scrolled
      if (TimesExecuted === 1) { //On the first time that the page is scrolled
        GetDurationWithSecs(); //Run the function to get the Duration With Secs
      } // //Finishes the if condition
    }; //Finishes the onscroll event listener

  } //Finishes the else condition
})();