// ==UserScript== // @name Find The Correct Watch Order And All Related Entries+Live-Actions+Doramas + Copy Entry Title // @namespace Search for Live-Actions\Doramas\All Related Entries + Correct Watch Order + Copy Entry Title // @version 48 // @description Find the Correct Watch Order And All Related Entries. Also, find out if an anime has any Live-Action or Dorama adaptations, and Copy The entry Title. // @author hacker09 // @include https://myanimelist.net/forum/?topicid=1863965 // @include /^https:\/\/myanimelist\.net\/((anime|manga)(id=)?(\.php\?id=)?)(\/)?([\d]+)/ // @exclude https://myanimelist.net/anime/genre/* // @exclude https://myanimelist.net/anime/producer/* // @icon https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=https://myanimelist.net&size=64 // @run-at document-end // @connect chiaki.site // @connect mydramalist.com // @grant GM.xmlHttpRequest // @downloadURL none // ==/UserScript== (function() { 'use strict'; var hasRun = true; //Create a new variable async function Prog() { //Run the program if (document.hasFocus() && hasRun) //If the tab has focus and it's the first time the script runs { //Starts the if condition hasRun = false; //Change the var condition if (location.href === 'https://myanimelist.net/forum/?topicid=1863965') { //If the user is on the Official Guidex Index $("b:contains('Guides available:')")[0].innerHTML = '(Click on the letter you want to jump to.)
Guides available: A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z
'; //Adds a text and makes the letters clickable. Also adds a scroll to top button on the page for (let i = 'A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); ++i) { //For every charCode document.querySelector(`b#GoTo${String.fromCharCode(i)}`).onclick = () => document.querySelectorAll('b')[i - 36].scrollIntoView(); //Scroll the page until the letter can be seen } //Finishes the for condition } //Finishes the if condition else //If the user isn't on any Guide Index { //Starts the else condition const findButton = document.createElement("a"), copyButton = document.createElement("a"), chiakiButton = document.createElement("a"); //Creates an "a" element so the button will appear var ChiakiFranchiseTitle, ChiakiFranchiseTitleWithSymbols, MalClubText, ChiakiDocument, IMDBAsianWiki, hasAnime = '', ChiakiTextData = [], ChiakientryidSArray = [], MyDramaListText = ' and MyDramaList', MyDramaListCheck = '👍 Found on MyDramaList.'; //Create new global variables if (location.pathname.split('/')[1] === 'manga') { //If the user is in an manga entry const Relations = await (await fetch('https://api.jikan.moe/v4/' + location.href.split('/')[3] + '/' + location.pathname.match(/\d+/)[0] + '/relations')).json(); //Fetch hasAnime = Relations.data.flatMap(relation => relation.entry).find(entry => entry.type === "anime"); //Try getting 1 entry that is an anime } //Finishes the if condition var entryid = hasAnime !== undefined && hasAnime !== '' ? hasAnime.mal_id : location.pathname.match(/\d+/)[0]; //Get the anime id GM.xmlHttpRequest({ //Starts the xmlHttpRequest method: "GET", url: 'https://chiaki.site/?/tools/watch_order/id/' + entryid, onload: (response) => { //Starts the onload event listener ChiakiDocument = new DOMParser().parseFromString(response.responseText, 'text/html'); //Parses the fetch response if (ChiakiDocument.querySelector("h2") !== null) { //Starts the if condition ChiakiFranchiseTitle = ChiakiDocument.querySelector("h2").innerText.split(' Watch Order')[0].replace(/[^a-zA-Z0-9]+/g, " ").trim(); //Get the anime title on the h2 element and remove the Watch Order text, symbols, and whitespaces ChiakiFranchiseTitleWithSymbols = ChiakiDocument.querySelector("h2").innerText.split(' Watch Order')[0].trim(); //Get the anime title on the h2 element (with symbols) and remove the Watch Order text, and whitespaces } //Finishes the if condition ChiakiDocument.querySelectorAll("span.uk-text-muted.uk-text-small").forEach((TextElement, i) => { //Loop through the elements ChiakientryidSArray.push(ChiakiDocument.querySelectorAll("span.uk-text-muted.uk-text-small > a:nth-child(1)")[i].href.match(/\d+/)[0]); //Add All Anime Links on chiaki to an Array const TotalRawDuration = TextElement.textContent.split("×")[1].split("|")[0].trim(); //Creates a variable to hold the total unprocessed times const ALLChiakiTitles = ChiakiDocument.querySelectorAll("span.wo_title")[i].innerText; //Creates a variable to get all the anime titles on chiaki site const TotalEpisodes = TextElement.textContent.split("|")[2].match(/\d+|\?/g)[0]; //Creates a variable to hold the total episodes const EpisodeType = TextElement.textContent.split("|")[1].trim(); //Creates a variable to get the episode types var eps = ' eps'; //Create a variable called eps var Duration = ''; //Creates a blank variable var PerEp = ' per ep'; //Create a variable called PerEp if (TotalEpisodes === '1') { //If the entry has only 1 ep eps = ' ' + EpisodeType; //Change the variable called eps PerEp = ''; //Change the variable called PerEp } //Finishes the if condition if (EpisodeType !== 'TV') { //If the entry type isn't TV if (TotalEpisodes !== '1') { //If the entry doesn't have only 1 ep eps = ' ' + EpisodeType + 's'; //Change the variable called eps } //Finishes the if condition Duration = ' of ' + TotalRawDuration + PerEp; //Defines the Duration variable if the episode type isn't TV } //Finishes the if condition ChiakiTextData.push(ALLChiakiTitles + ',, ' + TotalEpisodes + eps + Duration + ',\n'); //Add Everything to an Array }); //Finishes the for condition } //Finishes the onload event listener }); //Finishes the xmlHttpRequest GM.xmlHttpRequest({ //Starts the xmlHttpRequest method: "GET", url: "https://mydramalist.com/search?q=" + (hasAnime !== undefined ? ChiakiFranchiseTitle : document.querySelector("[itemprop*='name']").innerText.split('\n')[0]) + '&adv=titles&ty=68,77,83,86', onload: (response) => { //Starts the onload event listener const MyDramaListDocument = new DOMParser().parseFromString(response.responseText, 'text/html'); //Parses the fetch response if (MyDramaListDocument.querySelector(".m-b-sm") === null) { //If MyDramaList did not return any results MyDramaListText = ''; //Display to the user that MyDramaList Won't be opened if OK is clicked MyDramaListCheck = '✖ NOT Found on MyDramaList.'; //Display the confirmation that the anime doesn't have any adaptations found on MyDramaList } //Finishes the if condition } //Finishes the onload event listener }); //Finishes the xmlHttpRequest copyButton.addEventListener("click", () => { navigator.clipboard.writeText(document.querySelector("[itemprop*='name']").innerText.split('\n')[0]); //Copy the entry title with symbols }); //Detect the single mouse click copyButton.addEventListener("dblclick", () => { navigator.clipboard.writeText(document.querySelector("[itemprop*='name']").innerText.split('\n')[0].replace(/[^a-zA-Z0-9]+/g, " ")); //Copy the entry title without symbols }); //Detect the double mouse click copyButton.addEventListener("contextmenu", (e) => { //Detect a mouse click hasAnime !== undefined ? navigator.clipboard.writeText(ChiakiTextData.join('').trim()) : ''; //Copy the array to the clipboard e.preventDefault(); //Don't show the right-click default context menu }); //Detect the mouse right click hasAnime !== undefined ? copyButton.setAttribute("title", "Click To Copy Entry Title (+ Symbols)\n2 Clicks To Copy Entry Title (Without Symbols)\n\nRight click to Copy ALL Anime Only Entry Titles on The Broadcast Order With EP Numbers, Entry Types and Duration Times") : copyButton.setAttribute("title", "1 Click To Copy Entry Title (+ Symbols)\n2 Clicks To Copy Entry Title (Without Symbols)"); //Detect a mouse hover on the button and shows an explanation text copyButton.setAttribute("style", "cursor: pointer;margin-left: 13px;height: 10px;width: 10px;background-size: cover;display: inline-block;transform: scale(1.8);vertical-align: top;margin-top: 7px;"); //The CSS for the copy button copyButton.style.backgroundImage = `url(${document.querySelector(".dark-mode") !== null ? 'https://i.imgur.com/hIfOM22.png' : 'https://i.imgur.com/vU0m0ye.png'})`; //The copy button image findButton.addEventListener("click", async () => { //Detect the mouse click and search for the anime title if (location.pathname.split('/')[1] === 'manga' || confirm('If you want to search using the Entry Title instead of the Franchise Title\nPress OK')) { //Show the confirmation alert box text ChiakiFranchiseTitle = document.querySelector("[itemprop*='name']").innerText.split('\n')[0]; //Change the Franchise title we got from Chiaki to the entry title (to search on mydramalist) ChiakiFranchiseTitleWithSymbols = document.querySelector("[itemprop*='name']").innerText.split('\n')[0]; //Change the Franchise title we got from Chiaki to the entry title (to search on the mal club) } //Finishes the if condition if ([...ChiakiDocument.querySelectorAll('span.uk-text-muted.uk-text-small')].find(el => el.innerText.includes('TV')) !== null) { //If the Franchise has at least 1 entry that the type is TV const response = await (await fetch('https://myanimelist.net/clubs.php?cid=5450')).text(); //Fetch new DOMParser().parseFromString(response, 'text/html').body.innerText.search(ChiakiFranchiseTitleWithSymbols) > -1 ? MalClubText = '👍 Found on the [[ Live Action Adaptations ]] MAL Club' : MalClubText = '✖ NOT found on the [[ Live Action Adaptations ]] MAL Club'; //If the title is found on the MALClub, display the confirmation whether or not the anime has adaptations found on the MALClub MyDramaListCheck.match('👍') !== null || MalClubText.match('👍') !== null ? IMDBAsianWiki = 'IMDB, AsianWiki' : IMDBAsianWiki = 'IMDB and AsianWiki'; //Change the IMDBAsianWiki variable depending on if mydramalist or the mal club returned any results or not if (confirm('Franchise Title: ' + ChiakiFranchiseTitle + '\n\n' + MyDramaListCheck + '\n' + MalClubText + '\n\nDo you want to open ' + IMDBAsianWiki + MyDramaListText + ' to confirm that information and get more detailed info?')) { //Show the confirmation alert box text open("https://www.imdb.com/find?s=tt&q=" + ChiakiFranchiseTitle + "&ref_=nv_sr_sm", "_blank"); //Open IMDB on a new tab open("https://asianwiki.com/index.php?title=Special%3ASearch&search=" + ChiakiFranchiseTitle, "_blank"); //Open AsianWiki on a new tab if (MyDramaListCheck.match('NOT') === null) { //If MyDramaList returned any results open("https://mydramalist.com/search?q=" + ChiakiFranchiseTitle + '&adv=titles&ty=68,77,83,86', "_blank"); //Open MyDramaList on a new tab } //Open MyDramaList on a new tab only if any results were found on the website } //Finishes the if condition } //Finishes the if condition else { //If the anime doesn't have any entry type = TV alert("This Franchise doesn't even have any TV type entries, it's very likely that there are adaptations of any kind for this Franchise, so there's no need to search."); //Show a message to the user } //Finishes the else condition }); //Finishes the event listener findButton.setAttribute("title", "Search for Live-Actions/Doramas"); //Detects a mouse hover on the button and show the text Find Live-Actions findButton.setAttribute("style", "cursor: pointer;margin-left: 15px;height: 10px;width: 10px;background-size: cover;display: inline-block;transform: scale(1.8);vertical-align: top;margin-top: 7px;"); //The CSS for the findButton findButton.style.backgroundImage = `url(${document.querySelector(".dark-mode") !== null ? 'https://i.imgur.com/TEPmlyF.png' : 'https://i.imgur.com/2XQm3qI.png'})`; //The find button image function Append(element) { //Creates a new Append function document.querySelector(".title-english") === null ? document.querySelector("[itemprop*='name']").append(element) : document.querySelector(".title-english").previousElementSibling.parentNode.insertBefore(element, document.querySelector(".title-english").previousElementSibling); //Append depending on if the entry has an English title or not } //Finishes the Append function chiakiButton.addEventListener('mousedown', async function(e) { //Detects when the user middle clicks on the chiakiButton if (e.button === 1 && hasAnime !== undefined) //If the middle mouse button was clicked { //Starts the if condition e.preventDefault(); //Prevent the default middle button action from executing const response = await (await fetch('https://myanimelist.net/forum/?topicid=1890672')).text(); //Fetch const GuideIndexnewDocument = new DOMParser().parseFromString(response, 'text/html'); //Parses the fetch response const GuideIndexLinkElement = [...GuideIndexnewDocument.querySelectorAll('b')].find(el => el.innerText.includes('|' + entryid + '|')); //Gets the topic element that probably has the link of the Franchise and adds that to a variable if (GuideIndexLinkElement !== undefined) { //If the anime id was found on the guide index if (GuideIndexLinkElement.previousElementSibling.innerText.match('あ') !== null) { //If the anime name has the あ symbol in it on the guide index alert('Recommended watch order:\nBroadcast order.'); //Shows an alert } //Finishes the if condition else { //If the anime name doesn't have the あ symbol in it on the guide index alert('Recommended watch order:\nAEGC Guide Order.'); //Shows a text } //Finishes the if condition open(GuideIndexLinkElement.previousElementSibling.href, "_blank"); //Opens the GuideIndexLink on a new tab, and specifies that the GuideIndexLink should be opened on a new tab } //Finishes the if condition else { //If the anime ID was NOT found on the guide index const NotFoundMessage = document.createElement("a"); //Creates an a element NotFoundMessage.innerHTML = "
Not found on the AEGC Club!
Only chiaki.site will be opened.
"; //Defines the element text NotFoundMessage.setAttribute("style", "font-size: 80%;text-decoration: none;"); //Set the CSS for the button Append(NotFoundMessage); //Append the NotFoundMessage close to the title element setTimeout(function() { open("https://chiaki.site/?/tools/watch_order/id/" + entryid, "_blank"); }, 1000); //Open chiaki.site on a new tab } //Finishes the else condition const FinalArray = ChiakientryidSArray.filter(d => !GuideIndexnewDocument.querySelector(".body.clearfix").innerText.match(/(?<=\|\b)\d+/gi).includes(d)); //Get the ids that chiaki.site has and the Guide is missing const GuideMissingIds = document.createElement("div"); //Creates a div element GuideMissingIds.setAttribute("style", "font-size: 80%;display: none;"); //Set the CSS for the button FinalArray.forEach(function(entryid) { //For every anime id that the guide index is missing GuideMissingIds.innerHTML += GuideMissingIds.innerHTML = `
https://myanimelist.net/anime/${entryid}`; //Add to the GuideMissingIds div a line break + the anime link with the link as text too }); //Finishes the foreach condition if (FinalArray.length !== 0 && FinalArray.length !== ChiakientryidSArray.length) { //If there's at least 1 missing id on the guide index and if the guide index is not missing the same amount of total links that Chiaki has for the franchise var LinksButton = document.createElement("button"); //Creates a button element LinksButton.innerHTML = 'Show AEGC Club Missing Links'; //Defines the element text LinksButton.setAttribute("style", "margin-left: 10px;"); //Set the CSS for the button LinksButton.onclick = function() { //Detects the mouse click on the Show Links Button if (GuideMissingIds.style.display === "none") { //If the Show missing links button is hidden GuideMissingIds.style.display = ''; //Show the missing links button LinksButton.innerHTML = 'Hide AEGC Club Missing Links'; //Defines the element text } else { //If the Show missing links button is being shown GuideMissingIds.style.display = "none"; //Hide the missing links button LinksButton.innerHTML = 'Show AEGC Club Missing Links'; //Defines the element text } //Finishes the else condition }; //FInishes the onclick event listener Append(LinksButton); //Display the button to show the IDs that chiaki.site has and the Guide is missing Append(GuideMissingIds); //Display the IDs that chiaki.site has and the Guide is missing } //Finishes the if condition if (GuideIndexLinkElement !== undefined && FinalArray.length === ChiakientryidSArray.length - 1) { //If the anime id was found on the guide index and the missing links are equal to all of the chiaki.site total links -1 LinksButton.remove(); //Remove the button that shows the missing links const TwoFranchises = document.createElement("a"); //Creates an a element TwoFranchises.innerHTML = "
It seems that this entry is related to 2 Anime Franchises.
Both chiaki.site and the AEGC Club will be opened."; //Defines the element text TwoFranchises.setAttribute("style", "font-size: 80%;text-decoration: none;"); //Set the CSS for the button Append(TwoFranchises); //Append the NotFoundMessage close to the title element open("https://chiaki.site/?/tools/watch_order/id/" + entryid, "_blank"); //Opens chiaki.site on a new tab to show all the related anime entries on MAL on the correct watch order for the anime franchise and specifies that chiaki.site should be opened on a new tab } //Finishes the if condition if (GuideIndexnewDocument.querySelector(".body.clearfix").innerText.match(new RegExp('(?:\\|' + entryid + '\\|)', 'gi')).length > 1) { //If 2 identical anime ids were found on the guide index const OtherFranchiseMessage = document.createElement("a"); //Creates an a element OtherFranchiseMessage.innerHTML = "
According to the AEGC club this entry also has another related entry that chiaki.site consider as being from another franchise."; //Defines the element text OtherFranchiseMessage.setAttribute("style", "font-size: 80%;text-decoration: none;"); //Set the CSS for the button Append(OtherFranchiseMessage); //Append the OtherFranchiseMessage close to the title element } //Finishes the if condition } //Finishes the if condition }); //Finishes the mousedown event listener chiakiButton.addEventListener("click", () => { //Detect the mouse click open(hasAnime !== undefined ? "https://chiaki.site/?/tools/watch_order/id/" + entryid : "https://relatedanime.com/manga/" + entryid, "_blank"); //Opens chiaki.site on a new tab to show all the related anime entries on MAL on the correct watch order for the anime franchise and specifies that chiaki.site should be opened on a new tab }); //Finishes the addEventListener click chiakiButton.addEventListener("contextmenu", (e) => { //Detect a mouse click open(hasAnime !== undefined ? "https://relatedanime.com/anime/" + entryid : "https://relatedanime.com/manga/" + entryid, "_blank"); //Open relatedanime.com on a new tab to show all the related anime entries on MAL on the correct watch order for the anime franchise, including reading material e.preventDefault(); //Don't show the right-click default context menu }); //Detect the mouse right click chiakiButton.setAttribute("style", "cursor: pointer;margin-left: 15px;height: 10px;width: 10px;background-size: cover;display: inline-block;transform: scale(1.8);vertical-align: top;margin-top: 7px;"); //The CSS for the chiakiButton chiakiButton.setAttribute("title", hasAnime !== undefined ? "Click to see all related anime entries only on the Broadcast Watch Order\nMiddle Click to see all related anime entries only on the Broadcast/Chronological Watch Order\nRight Click to see all related entries on the Broadcast Watch Order. (Including reading material)" : "This franchise has no anime adaptations!\nClick to open relatedanime.com to show all related entries on the Broadcast Watch Order. (Including reading material)"); //Detects a mouse hover on the button and shows some text info chiakiButton.style.backgroundImage = `url(${hasAnime !== undefined ? 'https://i.imgur.com/i635kBp.png' : 'https://i.imgur.com/7tUhvqf.png'})`; //The chiaki.site/relatedanime.com button favicon Append(copyButton); //Append the button next to the title element Append(findButton); //Append the button next to the title element Append(chiakiButton); //Append the button next to the title element } //Finishes the else condition } //Finishes the Prog function } //Finishes the if condition Prog(); //Run the program window.addEventListener('focus', () => { Prog(); }, { once: true }); //Run the program when the tab gets focus })(); //Finishes the whole function