Greasy Fork is available in English.
This Script allows You to play Openings and Endings directly on AniList
Вам также может понравится AniList - Activity Assistant.
// ==UserScript==// @name Anime Songs - AniList Player// @namespace Openings and Endings Player// @version 2.2.1// @description This Script allows You to play Openings and Endings directly on AniList// @author NurarihyonMaou// @match https://anilist.co/*// @icon https://www.google.com/s2/favicons?sz=64&domain=anilist.co// @grant GM_xmlhttpRequest// @grant GM_setValue// @grant GM_getValue// @grant GM_addStyle// @require http://code.jquery.com/jquery-3.5.1.min.js// ==/UserScript==const $ = window.jQuery;let r###lt;let openings, endings;let audioUrls = ['https://animethemes.moe/audio/', 'https://a.animethemes.moe/', 'https://beta.animethemes.moe/audio/'];let videoUrls = ['https://animethemes.moe/video/', 'https://v.animethemes.moe/', 'https://beta.animethemes.moe/video/'];let urlsIndex = GM_getValue("urlsIndex") ?? 1;//let audioURLAddon = "-NCBD1080";let url = "https://graphql.anilist.co";let AnimeID;let AniID = { id: parseInt(window.location.pathname.split("/")[2]) };const VideoIcon = `<svg class="svg-inline--fa fa-solid fa-video"aria-hidden="true" data-fa-processed="" data-prefix="fa" data-icon="video" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M0 128C0 92.7 28.7 64 64 64H320c35.3 0 64 28.7 64 64V384c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V128zM559.1 99.8c10.4 5.6 16.9 16.4 16.9 28.2V384c0 11.8-6.5 22.6-16.9 28.2s-23 5-32.9-1.6l-96-64L416 337.1V320 192 174.9l14.2-9.5 96-64c9.8-6.5 22.4-7.2 32.9-1.6z"/></svg>`;const MusicIcon = `<svg class="svg-inline--fa fa-solid fa-music"aria-hidden="true" data-fa-processed="" data-prefix="fa" data-icon="music" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M499.1 6.3c8.1 6 12.9 15.6 12.9 25.7v72V368c0 44.2-43 80-96 80s-96-35.8-96-80s43-80 96-80c11.2 0 22 1.6 32 4.6V147L192 223.8V432c0 44.2-43 80-96 80s-96-35.8-96-80s43-80 96-80c11.2 0 22 1.6 32 4.6V200 128c0-14.1 9.3-26.6 22.8-30.7l320-96c9.7-2.9 20.2-1.1 28.3 5z"/></svg>`;const ToggleStyle = `.AudioMode {width:45px;height:15px;background-color: grey;position: relative;transition: ease-in-out 0.5s;display: flex;justify-content: center;align-items: center;}.circle {border-radius:50%;width: 30px;max-height: 30px;color:red;z-index: 9999;position: absolute;left:0;transition: ease-in-out 0.5s;}.circle svg {transition: ease-in-out 0.5s;color:red;}.active{left:50%;}`;GM_addStyle(ToggleStyle);let AudioMode = GM_getValue("AudioMode") ?? false;async function getAID() {AniID = { id: parseInt(window.location.pathname.split("/")[2]) };let query = `query ($id: Int) {Media (id: $id, type: ANIME) {idMal}}`;let options = {method: "POST",headers: {"Content-Type": "application/json",Accept: "application/json",},body: JSON.stringify({query: query,variables: AniID,}),};await fetch(url, options).then(handleResponse).then(handleData).catch(handleError);function handleResponse(response) {return response.json().then(function (json) {return response.ok ? json : Promise.reject(json);});}function handleData(data) {AnimeID = data.data.Media.idMal;}function handleError(error) {console.error(error);}}async function returnThemes() {await getAID();let response = $.ajax({url: `https://api.jikan.moe/v4/anime/${AnimeID}/themes`,method: "GET",success: function (data) {return data;},error: function (error) {alert("Something went wrong.\n" + error.errorMessage);},});return response;}function appendThemes() {if ($("body").find("div.openings").length == 0)$("body div.characters").after("<div class='openings'><h2>Openings</h2></div>");else {$("body div.characters").after($("body").find("div.openings"));$("body").find("div.openings").html("<h2>Openings</h2>");}if ($("body").find("div.endings").length == 0)$("body div.openings").after("<div class='endings'><h2>Endings</h2></div>");else {$("body div.openings").after($("body").find("div.endings"));$("body").find("div.endings").html("<h2>Endings</h2>");}themes.data.openings.forEach((opening) => {$("body").find("div.openings").append(`<ul class='tag'>${opening}</ul>`);});themes.data.endings.forEach((ending) => {$("body").find("div.endings").append(`<ul class='tag'>${ending}</ul>`);});if (parseInt(AniID.id) != 112323) {if ($("body").find("div.AudioMode").length == 0)$("body div.openings").before(`<input id="urlsIndex" type="range" value="${urlsIndex}" min="0" max="2"/> URL Slider - use this when the Player(s) don't work<div class="AudioMode"><button class="${!AudioMode ? "circle" : "circle active"}">${AudioMode ? MusicIcon : VideoIcon}</button></div></br>`);else $("body div.openings").before($("body").find("div.AudioMode"));}}$("body").on("click", "div.AudioMode", function () {AudioMode = !AudioMode;if (AudioMode) {$(this).children().addClass("active");$(this).children().html(MusicIcon);} else {$(this).children().removeClass("active");$(this).children().html(VideoIcon);}GM_setValue("AudioMode", AudioMode);$("body").find(".AnimeThemesPlayer").remove();loadVideos();});$("body").on("change", "input#urlsIndex", function () {urlsIndex = document.getElementById('urlsIndex').value;GM_setValue("urlsIndex", urlsIndex);$("body").find(".AnimeThemesPlayer").remove();loadVideos();});function loadVideos() {let Song = 0;(function init() {openings = document.getElementsByClassName("openings");endings = document.getElementsByClassName("endings");if (openings.length > 0 || endings.length > 0) {GM_xmlhttpRequest({method: "GET",url:"https://api.animethemes.moe/anime?filter[has]=resources&filter[site]=MyAnimeList&filter[external_id]=" +AnimeID +"&include=animethemes.animethemeentries.videos,animethemes.song.artists",data: AnimeID,headers: { "Content-Type": "application/json" },onload: function (response) {r###lt = JSON.parse(response.responseText);openings = openings.length > 0 ? openings : endings;if ($("body .AnimeThemesPlayer").length == 0) {$(openings).append(AudioMode? "<audio style='display: none' class='AnimeThemesPlayer' width='500px' height='300' src=''controls autoplay/>": "<video style='display: none' class='AnimeThemesPlayer' width='500px' height='300' src='' allowfullscreen controls autoplay/>");}$("body div.IMOE").remove();if ($("body").find("a#AnimeThemesLink").length == 0)$("body").find("div.openings").before(`<a id="AnimeThemesLink" href="https://animethemes.moe/anime/${r###lt.anime[0].slug}">AnimeThemes - Videos Source</a></br></br>`);for (Song; Song < r###lt.anime[0].animethemes.length; Song++) {let CurrSongMatch = false;$("div.openings, div.endings").children(".tag").filter(function (x) {let entriesCount = $("div.openings, div.endings").children(".tag").length;let currSong = $(this);let safetyIndicator = r###lt.anime[0].animethemes[Song].animethemeentries[0].nsfw? "NSFW": "";safetyIndicator +=safetyIndicator == "NSFW"? r###lt.anime[0].animethemes[Song].animethemeentries[0].spoiler? " && Spoilers ": " ": r###lt.anime[0].animethemes[Song].animethemeentries[0].spoiler? "Spoilers ": " ";if ($(currSong).text().toLowerCase().split(" by ")[0].replace(/\(([^)]+)\)/, "").replace(/[“"”]+/g, "").replace(/\#\d*:/g, "").replace(/\d*\:/g, "").replace(/[^\w\s]/gi, " ").replace(/ /g, "").trim() ==r###lt.anime[0].animethemes[Song].song.title.toLowerCase().replace(/\(([^)]+)\)/, "").replace(/\#\d*:/g, "").replace(/[^\w\s]/gi, " ").replace(/^0+/, "").replace(/ /g, "").trim()) {CurrSongMatch = true;$(currSong).html(AudioMode? "<span style='color: red;'>" +safetyIndicator +"</span><a href='"+audioUrls[urlsIndex]+r###lt.anime[0].animethemes[Song].animethemeentries[0].videos[0].filename +".ogg'>" +$(currSong).text() +"</a>": "<span style='color: red;'>" +safetyIndicator +"</span><a href='"+videoUrls[urlsIndex]+r###lt.anime[0].animethemes[Song].animethemeentries[0].videos[0].basename +"'>" +$(currSong).text() +"</a>");}if (x == entriesCount - 1 && CurrSongMatch == false) {if ($("div.IMOE").length == 0) {if ($("div.endings").length > 0) {$("div.endings").after('<div class="IMOE" style="margin-bottom: 30px;"><h2>Additional OPs and EDs</h2></div>');} else if ("div.openings".length > 0) {$("div.endings").after('<div class="IMOE" style="margin-bottom: 30px;"><h2>Additional OPs and EDs</h2></div>');} else {$("div.characters").after('<div class="IMOE" style="margin-bottom: 30px;"><h2>Additional OPs and EDs</h2></div>');}}let CurrentSongArtists = "";for (let Artists = 0;Artists <r###lt.anime[0].animethemes[Song].song.artists.length;Artists++) {CurrentSongArtists +=r###lt.anime[0].animethemes[Song].song.artists[Artists].name + " ";}if (CurrentSongArtists == "") CurrentSongArtists = "???";$("div.IMOE").append(AudioMode? "<span style='color: red;'>" +safetyIndicator +"</span><ul class='tag'><a href='"+audioUrls[urlsIndex]+r###lt.anime[0].animethemes[Song].animethemeentries[0].videos[0].filename +".ogg'>" +r###lt.anime[0].animethemes[Song].song.title +" by " +CurrentSongArtists +"</a></ul>": "<span style='color: red;'>" +safetyIndicator +"</span><ul class='tag'><a href='"+videoUrls[urlsIndex]+r###lt.anime[0].animethemes[Song].animethemeentries[0].videos[0].basename +"'>" +r###lt.anime[0].animethemes[Song].song.title +" by " +CurrentSongArtists +"</a></ul>");CurrentSongArtists = "";}});}},onerror: function (error) {console.log(error);},});} else {setTimeout(init, 0);}})();}function SetArifureta() {$("body").find(".AudioMode").remove();$("body").find("#AnimeThemesLink").remove();if ($("body iframe.AnimeThemesPlayer").length == 0) {$("body").find("div.openings").append("<iframe style='display: none' class='AnimeThemesPlayer' width='500px' height='300' src='' allowfullscreen/>");}if ($("body").find("a#MyYTChannel").length == 0)$("body").find("div.openings").before(`<a id="MyYTChannel" href="https://www.youtube.com/c/NurarihyonMaou">My YT Channel</a></br></br>`);$("div.openings").children(".tag").html('<a href="https://www.youtube.com/embed/s0vm9JVjexY?autoplay=1">"Daylight" by MindaRyn</a>');$("div.endings").children(".tag").html('<a href="https://www.youtube.com/embed/5aJWWk9B78E?autoplay=1">"Gedou Sanka (外道讃歌)" by FantasticYouth</a>');}let themes;async function loadThemesAndVideos() {themes = await returnThemes();appendThemes();if (parseInt(AniID.id) == 112323) SetArifureta();else loadVideos();}$(window).on("load", async function () {if (window.location.pathname.split("/")[1] === "anime") {await loadThemesAndVideos();$("body").on("click", ".tag", function (e) {e.preventDefault();if ($(this).children().length == 0) {alert("Sadly, this OP/ED is Missing or there's a bug in the Script (Check Instruction)");} else if ($("body .AnimeThemesPlayer").css("display") == "none" ||$(this).children("a").attr("href") !=$("body .AnimeThemesPlayer").attr("src")) {$("body .AnimeThemesPlayer").css("display", "block");$("body .AnimeThemesPlayer").attr("src",$(this).children("a").attr("href"));} else if ($(this).children("a").attr("href") ==$("body .AnimeThemesPlayer").attr("src")) {$("body .AnimeThemesPlayer").css("display", "none");$("body .AnimeThemesPlayer").attr("src", "");}});}});let oldURL;(function () {let pushState = history.pushState;let replaceState = history.replaceState;history.pushState = function () {pushState.apply(history, arguments);window.dispatchEvent(new Event("pushstate"));window.dispatchEvent(new Event("locationchange"));};history.replaceState = function () {replaceState.apply(history, arguments);window.dispatchEvent(new Event("replacestate"));window.dispatchEvent(new Event("locationchange"));};window.addEventListener("popstate", function () {window.dispatchEvent(new Event("locationchange"));});$(window).on("load", function () {GM_setValue("oldURL", $(location).attr("pathname").split("/")[1]);});window.addEventListener("locationchange", function () {oldURL = GM_getValue("oldURL");if (oldURL != "anime" &&$(location).attr("pathname").split("/")[1] == "anime") {GM_setValue("oldURL", $(location).attr("pathname").split("/")[1]);location.reload();} else if (oldURL == "anime" &&$(location).attr("pathname").split("/")[1] == "anime") {loadThemesAndVideos();} else {GM_setValue("oldURL", $(location).attr("pathname").split("/")[1]);}});})();