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.

Nainstalovat skript?
Skript doporučený autorem

Mohlo by se vám také líbit MALFunction - "Fix" ERRORS on MAL + Text AutoSaver.

Nainstalovat skript
  1. // ==UserScript==
  2. // @name Total Duration Time + Total Episodes Of Any Animes Franchises
  3. // @namespace DurationByFranchise
  4. // @version 47
  5. // @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.
  6. // @author hacker09
  7. // @match https://chiaki.site/?/
  8. // @match https://chiaki.site/?/auth
  9. // @match https://myanimelist.net/dialog/authorization
  10. // @match https://chiaki.site/?/tools/watch_order/id/*
  11. // @match https://chiaki.site/?/tools/watch_order/group_id/*
  12. // @include /^https:\/\/myanimelist\.net\/(anime|manga)\/[\d]+(\/.*)?/
  13. // @icon https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://myanimelist.net&size=64
  14. // @require https://greatest.deepsurf.us/scripts/446666-jquery-core-minified/code/jQuery%20Core%20minified.js
  15. // @run-at document-end
  16. // @connect chiaki.site
  17. // @grant GM.xmlHttpRequest
  18. // @grant GM_deleteValue
  19. // @grant GM_listValues
  20. // @grant GM_getValue
  21. // @grant GM_setValue
  22. // ==/UserScript==
  23.  
  24. (async function() {
  25. 'use strict';
  26. const SecondsFromNow = 0; //Creates a new const
  27. var TotalHrMins = []; //Creates a new blank array
  28. var TotalEpsResult = []; //Creates a new blank array
  29. var TotalEpisodesTypeTV = ['0']; //Creates a new array
  30. var TotalEpisodesTypeOVA = ['0']; //Creates a new array
  31. var TotalEpisodesTypeONA = ['0']; //Creates a new array
  32. var TotalCompletedMins = []; //Creates a new blank array
  33. var TotalEpisodesTypeMusic = ['0']; //Creates a new array
  34. var TotalEpisodesTypeMovie = ['0']; //Creates a new array
  35. var TotalEpisodesTypeSpecial = ['0']; //Creates a new array
  36. var CompletedAnimeIdsArray = []; //Creates a new blank array
  37. const $ = window.jQuery; //Defines That The Symbol $ Is A jQuery
  38. var Remaining = '', newDocument, TextElement, date, date2, EpsSeen, EntryTotalHours, EntryTotalMinutes; //Creates new global variables
  39.  
  40. if (location.href.match('chiaki') !== null && document.querySelector('a.uk-button.uk-button-text.uk-text-danger').innerText === 'SIGN IN' && location.href !== 'https://chiaki.site/?/') //If the user is on the chiaki.site and if the user isn't signed in on chiaki.site, and if the user wasn't returned to the chiaki.site home page
  41. { //Starts the if condition
  42. document.querySelector('a.uk-button.uk-button-text.uk-text-danger').click(); //Click on the sign-in btn
  43. if (location.href.match('auth') !== null) //If the user is on the auth chiaki.site page
  44. { //Starts the if condition
  45. document.querySelectorAll('.uk-button-large')[1].click(); //Click on the SIGN IN WITH MYANIMELIST btn
  46. } //Finishes the if condition
  47. } //Finishes the if condition
  48.  
  49. if (location.href.match('authorization') !== null) //If the user is on the MAL auth website
  50. { //Starts the if condition
  51. window.onload = function() { //When the page finishes loading
  52. document.querySelectorAll("form > input")[1].id = 'clicked'; //Add an id to the btn
  53. document.querySelectorAll("form > input")[1].click(); //Click on the Allow btn
  54. }; //Finishes the onload event listener
  55. } //Finishes the if condition
  56. if (location.href === 'https://chiaki.site/?/') //When the user gets returned to the chiaki.site home page
  57. { //Starts the if condition
  58. window.history.go(-3); //Return to the franchise page
  59. } //Finishes the if condition
  60.  
  61. if (GM_listValues().length >= 100 && top.location.host === 'myanimelist.net') //If there are 100 completed anime IDs stored on tampermonkey and if the user is on mal
  62. { //Starts the if condition
  63. $("h2:contains('Statistics')")[0].style.cursor = 'pointer'; //Make the text look like it's clickable
  64. $("h2:contains('Statistics')")[0].innerText = 'Click to Erase Franchise Script Cache'; //Change the Statistics text to another text
  65.  
  66. $("h2:contains('Click to Erase Franchise Script Cache')")[0].onclick = function() //When the script text is clicked
  67. { //Starts the onclick event listener
  68. GM_listValues().forEach(a => GM_deleteValue(a)); //Erase all the 100 stored completed anime IDs stored on tampermonkey
  69. $("h2:contains('Click to Erase Franchise Script Cache')")[0].innerText = 'Statistics'; //Change the 'Click to Erase Franchise Script Cache' text to 'Statistics'
  70. }; //Finishes the onclick event listener
  71. } //Finishes the if condition
  72.  
  73. if (top.location.host === 'myanimelist.net') { //Starts the user is on mal
  74. var animeid = location.pathname.match(/\d+/) === null ? location.search.match(/\d+/)[0] : location.pathname.match(/\d+/)[0]; //Detect the anime id
  75. GM_listValues().forEach(a => CompletedAnimeIdsArray.push('^' + a)); //Add all anime IDs on tampermonkey to the array
  76. var CompletedAnimeIdsRegex = new RegExp(CompletedAnimeIdsArray.join('$|')); //Create a new variable and regex containing all the values saved on tampermonkey and replace the , separator with the or $| regex symbols
  77.  
  78. if (document.querySelector("#myinfo_status.btn-user-status-add-list.js-form-user-status.js-form-user-status-btn.myinfo_addtolist") === null && document.querySelectorAll("#myinfo_status").length == 2) { //If the anime is on the user list and the middle page status btn exists
  79. document.querySelectorAll("#myinfo_status")[1].addEventListener('change', function() { //Listen for the anime entry status changes
  80. if (this.value !== '6' && this.value !== '1') { //If any status besides Plan To Watch and Watching is selected
  81. GM_setValue(animeid, 'Completed Anime Id'); //Get and save the anime id as a variable
  82. } //Finishes the if condition
  83. if (this.value === '6') //If Plan To Watch is selected
  84. { //Starts the if condition
  85. GM_deleteValue(animeid); //Remove the anime if of the completed script anime IDs storage
  86. } //Finishes the if condition
  87. }, false); //Finishes the change advent listener
  88. } //Finishes the if condition
  89.  
  90. if (document.querySelector("#myinfo_status.btn-user-status-add-list.js-form-user-status.js-form-user-status-btn.myinfo_addtolist") === null && document.querySelectorAll("i.fa-solid.fa-circle-plus").length == 2) { //If the entry is on the user list and the middle page + btn exists
  91. document.querySelectorAll("i.fa-solid.fa-circle-plus")[1].addEventListener('click', function() { //Listen for clicks on the plus button
  92. setTimeout(function() { //Starts the function settimeout
  93. if (document.querySelector("#myinfo_watchedeps").value === document.querySelector("#curEps").innerText) //If the number of watched eps is = the total entry eps
  94. { //Starts the if condition
  95. GM_setValue(animeid, 'Completed Anime Id'); //Get and save the anime id as a variable
  96. } //Finishes the if condition
  97. }, 800); //Finishes the function settimeout
  98. }, false); //Finishes the click advent listener
  99. } //Finishes the if condition
  100.  
  101. } //Finishes the if condition
  102.  
  103. if (top.location.host === 'myanimelist.net') //If The User Is On The https://myanimelist.net/ Website Fetch Chiaki
  104. { //Starts the if condition
  105. var IsUserOnMAL = true;
  106. GM.xmlHttpRequest({ //Starts the xmlHttpRequest
  107. method: "GET",
  108. url: `https://chiaki.site/?/tools/watch_order/id/${animeid}`,
  109. onload: async function(response) { //Starts the onload event listener
  110. newDocument = new DOMParser().parseFromString(response.responseText, 'text/html'); //Parses the fetch response
  111. TextElement = newDocument.querySelectorAll("span.uk-text-muted.uk-text-small"); //Creates a variable to loop through the elements after
  112. await Calc(); //Call the Calc function
  113. } //Finishes the onload event listener
  114. }); //Finishes the xmlHttpRequest
  115. } //Finishes the if condition
  116. else //If The User Is On The https://chiaki.site/ Website Start Processing The Content
  117. { //Starts the else condition
  118. IsUserOnMAL = false;
  119. TextElement = document.querySelectorAll("span.uk-text-muted.uk-text-small"); //Creates a variable to loop through the elements after
  120. await Calc(); //Call the Calc function
  121. } //Finishes the else condition
  122.  
  123. async function Calc() //Creates a new function to calculate the time
  124. { //Starts the function
  125. for (var i = 0; i < TextElement.length; i++) { //Starts the for condition
  126. const TotalRawDurationHasSecs = TextElement[i].textContent.split("× ")[1].match('sec'); //Creates a variable to check later if there's an entry that has secs
  127. var TotalRawDuration = TextElement[i].textContent.split("× ")[1].split(' |')[0].match(/\d+|\?/g); //Creates a variable to hold the total unprocessed times
  128. const TotalEpisodes = TextElement[i].textContent.split("× ")[0].split(' |')[2].match(/\d+|\?/g); //Creates a variable to hold the total episodes
  129. const EpisodeType = TextElement[i].textContent.split("× ")[0].split(' |')[1]; //Creates a variable to check the episode types
  130. TotalEpsResult.push(TotalEpisodes); //Add The Eps To The Array
  131. if (IsUserOnMAL === true) //If The User Is On The https://myanimelist.net/ Website
  132. { //Starts the if condition
  133. if (TextElement[i].children[0].href.match(/\d+/)[0].match(CompletedAnimeIdsRegex) !== null && CompletedAnimeIdsRegex.toLocaleString() !== '/(?:)/') //If the current URL anime id matches an anime entry that was already completed, and if the Regex contains 1 or more anime ids
  134. { //Starts the if condition
  135. const CompletedMins = TotalRawDuration; //Creates a new variable
  136. TotalRawDuration = '?'; //Remove the Total Raw Duration value of this anime to not count it later
  137. Remaining = 'Remaining '; //Adds the text "Remaining" to the variable
  138.  
  139. if (CompletedMins.length !== 1 && TotalRawDurationHasSecs === null) //If has Hrs and Mins and not secs
  140. { //Starts the if condition
  141. var ExtractHrs = CompletedMins[0] * 60; //Extract Hrs And Convert To Mins
  142. var TotalHrs = TotalEpisodes * ExtractHrs; //Multiply Eps By Hrs
  143. var TotalMins = TotalEpisodes * CompletedMins[1]; //Multiply Extracted Eps By Mins
  144. TotalCompletedMins.push(TotalHrs, TotalMins); //Add Hrs And Mins To The Array
  145. } //Finishes the if condition
  146. else if (TotalRawDurationHasSecs === null) //Extract only Mins and not secs
  147. { //Starts the else condition
  148. TotalMins = TotalEpisodes * CompletedMins[0]; //Multiply Extracted Eps By Mins
  149. TotalCompletedMins.push(TotalMins); //Add Mins To The Array
  150. } //Finishes the else condition
  151.  
  152. } //Finishes the if condition
  153. } //Finishes the if condition
  154. if (TotalRawDuration.length !== 1 && TotalRawDurationHasSecs === null) //If has Hrs and Mins and not secs
  155. { //Starts the if condition
  156. ExtractHrs = TotalRawDuration[0] * 60; //Extract Hrs And Convert To Mins
  157. TotalHrs = TotalEpisodes * ExtractHrs; //Multiply Eps By Hrs
  158. TotalMins = TotalEpisodes * TotalRawDuration[1]; //Multiply Extracted Eps By Mins
  159. TotalHrMins.push(TotalHrs, TotalMins); //Add Hrs And Mins To The Array
  160. } //Finishes the if condition
  161. else if (TotalRawDurationHasSecs === null) //Extract only Mins and not secs
  162. { //Starts the else condition
  163. TotalMins = TotalEpisodes * TotalRawDuration[0]; //Multiply Extracted Eps By Mins
  164. TotalHrMins.push(TotalMins); //Add Mins To The Array
  165. } //Finishes the else condition
  166.  
  167. if (EpisodeType.match('Music') !== null) //If it's Music
  168. { //Starts the if condition
  169. TotalEpisodesTypeMusic.push(TotalEpisodes); //Add The Eps To The Array
  170. } //Finishes the if condition
  171. if (EpisodeType.match('TV') !== null) //If it's TV
  172. { //Starts the if condition
  173. TotalEpisodesTypeTV.push(TotalEpisodes); //Add The Eps To The Array
  174. } //Finishes the if condition
  175. if (EpisodeType.match('OVA') !== null) //If it's OVA
  176. { //Starts the if condition
  177. TotalEpisodesTypeOVA.push(TotalEpisodes); //Add The Eps To The Array
  178. } //Finishes the if condition
  179. if (EpisodeType.match('Special') !== null) //If it's Special
  180. { //Starts the if condition
  181. TotalEpisodesTypeSpecial.push(TotalEpisodes); //Add The Eps To The Array
  182. } //Finishes the if condition
  183. if (EpisodeType.match('ONA') !== null) //If it's ONA
  184. { //Starts the if condition
  185. TotalEpisodesTypeONA.push(TotalEpisodes); //Add The Eps To The Array
  186. } //Finishes the if condition
  187. if (EpisodeType.match('Movie') !== null) //If it's Movie
  188. { //Starts the if condition
  189. TotalEpisodesTypeMovie.push(TotalEpisodes); //Add The Eps To The Array
  190. } //Finishes the if condition
  191. } //Finishes the for condition
  192.  
  193. const TotalEpsFinal = TotalEpsResult.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b); //Sum The Total Eps
  194. const TotalMinsResult = TotalHrMins.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b); //Sum Hrs in Mins + Total Mins
  195. const ONAEpisodesResult = TotalEpisodesTypeONA.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b) + ' ONA(s)'; //Sum The Total Eps
  196. const OVAEpisodesResult = TotalEpisodesTypeOVA.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b) + ' OVA(s)'; //Sum The Total Eps
  197. const TVEpisodesResult = TotalEpisodesTypeTV.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b) + ' TV Episode(s)'; //Sum The Total Eps
  198. const MusicEpisodesResult = TotalEpisodesTypeMusic.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b) + ' Music(s)'; //Sum The Total Eps
  199. const MovieEpisodesResult = TotalEpisodesTypeMovie.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b) + ' Movie(s)'; //Sum The Total Eps
  200. const SpecialEpisodesResult = TotalEpisodesTypeSpecial.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b) + ' Special(s)'; //Sum The Total Eps
  201. //The Code Below Converts The Total Franchise Time To Precise Days, Hours And Minutes
  202. var days = Math.floor(TotalMinsResult / 1440);
  203. var hours = Math.floor((TotalMinsResult % 1440) / 60);
  204. var minutes = (TotalMinsResult % 1440) % 60;
  205.  
  206. var CompletedPercentage = '0%'; //Set the default Completed % as 0%
  207. if (TotalCompletedMins.length !== 0) //If at least one entry of the franchise was marked as completed/dropped/on-hold or watching/reading
  208. { //Starts the if condition
  209. const TotalCompletedMinsResult = TotalCompletedMins.filter(Boolean).map(i => Number(i)).reduce((a, b) => a + b); //Sum Hrs in Mins + Total Mins
  210. var TotalFranchiseMins = TotalCompletedMinsResult + TotalMinsResult; //Sum and save the total franchise duration in minutes
  211. var TotalFranchiseLeftMins = TotalFranchiseMins - TotalMinsResult; //Subtract and save the total franchise left duration in minutes
  212. CompletedPercentage = (TotalFranchiseLeftMins / TotalFranchiseMins).toLocaleString("en", { //Divide the franchise left duration mins by the franchise duration mins and show the result
  213. style: 'percent', //Show the result as %
  214. minimumFractionDigits: 2 //Show the % with 2 decimals
  215. }); //Finishes the toLocaleString
  216. } //Finishes the if condition
  217.  
  218. //Start the function to correctly format the date and time from now
  219. function formatDateTime(date) { //Starts the function
  220. var year = date.getFullYear();
  221. var month = date.getMonth() + 1;
  222. var day = date.getDate();
  223. var hh = date.getHours();
  224. var m = date.getMinutes();
  225. var s = date.getSeconds();
  226. var dd = "AM";
  227. var h = hh;
  228.  
  229. if (h >= 12) {
  230. h = hh - 12;
  231. dd = "PM";
  232. }
  233. if (h == 0) {
  234. h = 12;
  235. }
  236.  
  237. month = month < 10 ? "0" + month : month;
  238. day = day < 10 ? "0" + day : day;
  239. m = m < 10 ? "0" + m : m;
  240. s = s < 10 ? "0" + s : s;
  241. h = h < 10 ? "0" + h : h;
  242.  
  243. var display = month + "/" + day + "/" + year + " " + h + ":" + m;
  244. display += ":" + s;
  245. display += " " + dd;
  246.  
  247. return display;
  248. } //Finishes the function
  249.  
  250. function UpdateFinishTime() { //Starts the function UpdateFinishTime
  251. const DisplayedFranchiseDays = $('div.spaceit_pad:contains("Franchise Duration") > span')[0].nextSibling.textContent.match(/(?:(\d+) day\(s\) )?(?:(\d+) hr\(s\) )?(\d+) min\(s\)/)[1]; //Gets the actual displayed franchise days and save the days number to a variable
  252. const DisplayedFranchiseHours = $('div.spaceit_pad:contains("Franchise Duration") > span')[0].nextSibling.textContent.match(/(?:(\d+) day\(s\) )?(?:(\d+) hr\(s\) )?(\d+) min\(s\)/)[2]; //Gets the actual displayed franchise hour and save the hour number to a variable
  253. const DisplayedFranchiseMinutes = $('div.spaceit_pad:contains("Franchise Duration") > span')[0].nextSibling.textContent.match(/(?:(\d+) day\(s\) )?(?:(\d+) hr\(s\) )?(\d+) min\(s\)/)[3]; //Gets the actual displayed franchise minutes and save the minutes number to a variable
  254.  
  255. date = new Date(); //Creates a new date
  256. const secondsToAdd = DisplayedFranchiseDays * 60 * 60 * 24 + DisplayedFranchiseHours * 60 * 60 + DisplayedFranchiseMinutes * 60 + SecondsFromNow; //Convert the actual Total/Remaining Franchise Duration days, hours and minutes to seconds
  257. date.setSeconds(date.getSeconds() + secondsToAdd);
  258.  
  259. if (document.querySelector("td.borderClass").innerText.search("Remaining time:") > -1) //If the text "Remaining time:" exists
  260. { //Starts the if condition
  261. var RemainingEntryHours = parseInt($('div.spaceit_pad:contains("Remaining time") > span')[0].nextSibling.textContent.match(/(?: ?((\d+) hr\. ))?/)[1]); //Get and save the entry remaining hours
  262. if ($('div.spaceit_pad:contains("Remaining time") > span')[0].nextSibling.textContent.match(/\d+(?= min)/) !== null) //If the entry has remaining minutes
  263. { //Starts the if condition
  264. var RemainingEntryMinutes = parseInt($('div.spaceit_pad:contains("Remaining time") > span')[0].nextSibling.textContent.match(/\d+(?= min)/)[0]); //Get and save the entry remaining minutes
  265. } //Finishes the if condition
  266. else //If the entry has no remaining minutes
  267. { //Starts the else condition
  268. RemainingEntryMinutes = 0; //Save the entry remaining minutes as 0 instead of NaN
  269. } //Finishes the else condition
  270.  
  271. if (isNaN(RemainingEntryHours) === true) //If the entry has no remaining hours
  272. { //Starts the if condition
  273. RemainingEntryHours = 0; //Save the entry remaining hours as 0 instead of NaN
  274. } //Finishes the if condition
  275.  
  276. date2 = new Date(); //Creates a new date
  277. const secondsToAdd2 = 0 * 60 * 60 * 24 + RemainingEntryHours * 60 * 60 + RemainingEntryMinutes * 60 + SecondsFromNow; //Convert the actual "Remaining time" entry Duration hours and minutes to seconds
  278. date2.setSeconds(date2.getSeconds() + secondsToAdd2);
  279. } //Finishes the if condition
  280.  
  281. } //Finishes the function UpdateFinishTime
  282.  
  283. const title = 'title="' + OVAEpisodesResult + '&#13;' + ONAEpisodesResult + '&#13;' + MusicEpisodesResult + '&#13;' + SpecialEpisodesResult + '&#13;' + MovieEpisodesResult + '&#13;' + TVEpisodesResult + '"'; //Content that will be shown on mouse hover
  284.  
  285. if (TextElement.length === 1) //If there's only 1 entry on chiaki.site for the whole franchise
  286. { //Starts the if condition
  287. var html; //Creates a blank variable
  288. IsUserOnMAL === true && 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
  289. var HasMoreThan1Entry = false; //Create a variable to confirm that the Franchise has less than 1 entry
  290. } //Finishes the if condition
  291. else //If there's more than 1 entry on chiaki.site for the whole franchise
  292. { //Starts the else condition
  293. html = Remaining + ' Franchise Duration: </span>' + days + ' day(s) ' + hours + ' hr(s) ' + minutes + ' min(s)'; //Shows the real HTML on MAL
  294. HasMoreThan1Entry = true; //Create a variable to confirm that the Franchise has more than 1 entry
  295.  
  296. if (IsUserOnMAL === true) //If The User Is On The https://myanimelist.net/ Website
  297. { //Starts the if condition
  298. function GetWatchedEps() { //Starts the function GetWatchedEps()
  299. EpsSeen = parseInt(document.querySelector("#myinfo_watchedeps").value); //Get the total number of eps seen and convert the value to int
  300. EntryTotalHours = $('div.spaceit_pad:contains("Duration") > span')[0].nextSibling.textContent.match(/(?:(\d+) hr\. )?(\d+) min\./)[1] * EpsSeen * 60; //Get the Entry Total Hours of seen episodes and convert from hrs to mins
  301. EntryTotalMinutes = parseInt($('div.spaceit_pad:contains("Duration") > span')[0].nextSibling.textContent.match(/(?:(\d+) hr\. )?(\d+) min\./)[2] * EpsSeen); //Get the Entry Total Minutes of seen episodes
  302.  
  303. if ($('div.spaceit_pad:contains("Duration") > span')[0].nextSibling.textContent.match(/(?:(\d+) hr\. )?(\d+) min\./)[1] === undefined) { //Starts the if condition
  304. EntryTotalHours = 0; //Set the Entry Total Hours as 0
  305. } //Finishes the if condition
  306. } //Finishes the function
  307.  
  308. if (document.querySelectorAll("i.fa-solid.fa-circle-plus").length === 2) //If the anime is already on the user list
  309. { //Starts the if condition
  310. document.querySelectorAll("i.fa-solid.fa-circle-plus")[1].addEventListener("click", function() { //Adds an advent listener to the plus button
  311.  
  312. setTimeout(async function() { //Creates and starts the settimout function
  313. await GetWatchedEps(); //Starts the function GetWatchedEps()
  314.  
  315. days = Math.floor((TotalMinsResult - EntryTotalHours - EntryTotalMinutes) / 1440); //Sum again the total Franchise days duration - the total watched eps duration time
  316. hours = Math.floor(((TotalMinsResult - EntryTotalHours - EntryTotalMinutes) % 1440) / 60); //Sum again the total Franchise hours duration - the total watched EPS duration time
  317. minutes = ((TotalMinsResult - EntryTotalHours - EntryTotalMinutes) % 1440) % 60; //Sum again the total Franchise minutes duration - the duration total watched eps time
  318.  
  319. $('div.spaceit_pad:contains("Franchise Duration") > span')[0].textContent = 'Remaining Franchise Duration: '; //Add "Remaining" in front of the Franchise Duration text
  320. $('div.spaceit_pad:contains("Franchise Duration") > span')[0].nextSibling.textContent = days + ' day(s) ' + hours + ' hr(s) ' + minutes + ' min(s)'; //Update the Franchise Duration Time
  321.  
  322. if ($('div.spaceit_pad:contains("Remaining time") > span')[0] !== undefined) //If the "Remaining time" text exists
  323. { //Starts the if condition
  324. const TotalEntryHours = (parseInt($('div.spaceit_pad:contains("Total Duration") > span')[0].nextSibling.textContent.match(/(?:(\d+) hr\. )?(\d+) min\./)[1] * 60)); //Get and save the entry remaining hours, and convert to minutes
  325. const TotalEntryMinutes = (parseInt($('div.spaceit_pad:contains("Total Duration") > span')[0].nextSibling.textContent.match(/(?:(\d+) hr\. )?(\d+) min\./)[2])); //Get and save the entry remaining minutes
  326.  
  327. const RemainingTimeHours = Math.floor((TotalEntryMinutes + TotalEntryHours - EntryTotalHours - EntryTotalMinutes % 1440) / 60); //Sum the total remaining Franchise hours duration - the total watched eps duration time
  328. const RemainingTimeMinutes = (TotalEntryMinutes + TotalEntryHours - EntryTotalHours - EntryTotalMinutes % 1440) % 60; //Sum again the total remaining Franchise minutes duration - the duration total watched eps time
  329.  
  330. $('div.spaceit_pad:contains("Remaining time") > span')[0].nextSibling.textContent = ' ' + RemainingTimeHours + ' hr. ' + RemainingTimeMinutes + ' min.'; //Update the "Remaining time" Duration
  331. } //Finishes the if condition
  332. }, 800); //Finishes the settimeout function
  333. }); //Finishes the onclick advent listener
  334. } //Finishes the if condition
  335.  
  336. if (document.querySelector("#myinfo_watchedeps").value !== '0' && document.querySelector("#myinfo_watchedeps").value !== '' && parseInt(document.querySelector("#curEps").innerText) >= 1 && document.querySelector(".po-r > #myinfo_status > option:checked").value === '1') //If there's at least 1 watched episode, and if the entry has 1 or more episodes, and if the anime has a Watching status
  337. { //Starts the if condition
  338. GetWatchedEps(); //Starts the function GetWatchedEps()
  339.  
  340. days = Math.floor((TotalMinsResult - EntryTotalHours - EntryTotalMinutes) / 1440); //Sum again the total Franchise days duration - the total watched eps duration time
  341. hours = Math.floor(((TotalMinsResult - EntryTotalHours - EntryTotalMinutes) % 1440) / 60); //Sum again the total Franchise hours duration - the total watched eps duration time
  342. minutes = ((TotalMinsResult - EntryTotalHours - EntryTotalMinutes) % 1440) % 60; //Sum again the total Franchise minutes duration - the duration total watched eps time
  343. html = 'Remaining Franchise Duration: </span>' + days + ' day(s) ' + hours + ' hr(s) ' + minutes + ' min(s)'; //Shows the real HTML on MAL
  344.  
  345. } //Finishes the if condition
  346. } //Finishes the if condition
  347.  
  348. } //Finishes the else condition
  349.  
  350. if (IsUserOnMAL === true) //If The User Is On The https://myanimelist.net/ Website
  351. { //Starts the if condition
  352. [...[...document.querySelectorAll("h2")].find(h2 => h2.textContent === "Information").parentNode.querySelectorAll("div")].find(info => info.innerText.includes("Rating")).insertAdjacentHTML('afterend', '<div class="TotalFranchise"></div>'); //Show The Total Duration inside the Rating text that's inside the information h2 element
  353.  
  354. document.querySelector(".TotalFranchise").insertAdjacentHTML('afterend', `<div class="spaceit_pad" title="Time left to complete: ${days + ' day(s) ' + hours + ' hr(s) ' + minutes + ' min(s)'}"><span class="dark_text">Watched: ${CompletedPercentage}</a></li></div>`); //Show The Completed %
  355. document.querySelector(".TotalFranchise").insertAdjacentHTML('afterend', '<div class="spaceit_pad" ' + title + '><span class="dark_text">Franchise Entries: ' + TextElement.length + '</a></li></div>'); //Show The Total Entries
  356. if (HasMoreThan1Entry === true) //If the Franchise has more than 1 Entry
  357. { //Starts the if condition
  358. document.querySelector(".TotalFranchise").insertAdjacentHTML('afterend', '<div class="spaceit_pad" ' + title + '><span class="dark_text">Franchise Episodes: ' + TotalEpsFinal + '</a></li></div>'); //Show The Total Episodes
  359. } //Finishes the if condition
  360. document.querySelector(".TotalFranchise").insertAdjacentHTML('afterend', '<div class="spaceit_pad" ' + title + '><span class="dark_text">' + html + '</div>'); //Show The Total Duration
  361. } //Finishes the if condition
  362. else //If The User Is On The https://chiaki.site/ Website
  363. { //Starts the else condition
  364. 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
  365. if (HasMoreThan1Entry === true) //If the Franchise has more than 1 Entry
  366. { //Starts the if condition
  367. document.querySelector("ul.uk-flex-center.noborder.uk-tab").insertAdjacentHTML('beforeend', '<li><a href="#" ' + title + '>Total Episodes: ' + TotalEpsFinal + '</a></li>'); //Show The Total Episodes
  368. 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
  369. } //Finishes the if condition
  370. } //Finishes the else condition
  371.  
  372. if (IsUserOnMAL === true) //If The User Is On The https://myanimelist.net/ Website
  373. { //Starts the if condition
  374. $('span.dark_text:contains("Franchise Duration")').css("cursor", "pointer"); //Make the "Franchise Duration" text look like it's clickable
  375.  
  376. $('span.dark_text:contains("Franchise Duration")')[0].onclick = function() { //When the Franchise Duration text is clicked
  377. UpdateFinishTime(); //Starts the function UpdateFinishTime
  378.  
  379. if (document.querySelector("td.borderClass").innerText.search("Remaining time:") > -1) //If the text "Remaining time:" exists
  380. { //Starts the if condition
  381.  
  382. if ($('div.spaceit_pad:contains("Remaining time") > span')[0].nextSibling.textContent !== ' ') //If the text "Remaining time:" has text
  383. { //Starts the if condition
  384. alert('You will finish watching this 🡳: (Without stopping)\nEntry on: ' + formatDateTime(date2) + '\nFranchise on: ' + formatDateTime(date)); //Display a message showing the days and hours from now
  385. } //Finishes the if condition
  386. else //If the text "Remaining time:" does NOT exist
  387. { //Starts the else condition
  388. alert('You will finish watching this franchise without stopping on ' + formatDateTime(date)); //Display a message showing the days and hours from now
  389. } //Finishes the else condition
  390. } //Finishes the if condition
  391.  
  392. else //If the text "Remaining time:" does NOT exist
  393. { //Starts the else condition
  394. alert('You will finish watching this franchise without stopping on ' + formatDateTime(date)); //Display a message showing the days and hours from now
  395. } //Finishes the else condition
  396.  
  397. }; //Finishes the onclick advent listener
  398. } //Finishes the if condition
  399.  
  400. } //Finishes the async function
  401. })();