ShaDream / Anime OP/ED

// ==UserScript==
// @name         Anime OP/ED
// @version      0.10.6
// @description  Get OP/ED by MAL
// @author       ShaDream
// @match        https://shikimori.org/*
// @match        https://shikimori.one/*
// @match        http://shikimori.one/*
// @match        http://shikimori.org/*
// @connect      myanimelist.net
// @updateURL    https://openuserjs.org/meta/ShaDream/Anime_OPED.meta.js
// @copyright    2018, ShaDream (https://openuserjs.org/users/ShaDream)
// @downloadURL  https://openuserjs.org/install/ShaDream/Anime_OPED.user.js
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==
var debug = !1, showMalCount = !1;

function log(message) {
    debug && console.log(message)
}
const insertAfter = (elem, refElem) => refElem.parentNode.insertBefore(elem, refElem.nextSibling);

function get_anime_id() {
    let full_url = window.location.href,
        start = full_url.lastIndexOf('/') + 1;
    for (; isNaN(parseInt(full_url[start]));) start++;
    let number = "";
    for (; !isNaN(parseInt(full_url[start]));) number += full_url[start], start++;
    return number
}

function createMusic(elements, placeToAppend) {
    elements.forEach(element => {
        var sound = document.createElement("span");
        sound.innerText = element, sound.className = "value sound", placeToAppend.appendChild(sound)
    })
}

function musicConstructor(main, text, items) {
    var container = document.createElement("div"),
        addedClassName = "OP'S" === text ? " op" : " ed";
    container.className = "sound-container" + addedClassName, main.appendChild(container);
    var title = document.createElement("div");
    title.innerText = text, title.className = "subheadline m5", container.appendChild(title), createMusic(items, container)
}

function createOPEDList(op, ed) {
    if (0 != op.length || 0 != ed.length) {
        // Create main div and paste in in a right place
        var main = document.createElement("div"),
            paste_after = document.getElementsByClassName("b-db_entry")[0];
        //Create open button if needed
        if (main.className = "main-sound-container", insertAfter(main, paste_after),
            //Create content
            musicConstructor(main, "OP'S", op), musicConstructor(main, "ED'S", ed), op.length > 4 || ed.length > 4) {
            main.style.maxHeight = '150px';
            var expand_container = document.createElement("div");
            insertAfter(expand_container, main), expand_container.className = "b-height_shortener open-music";
            var shade = document.createElement("div");
            shade.className = "shade", expand_container.appendChild(shade);
            var expander = document.createElement("div");
            expander.className = "expand", expand_container.appendChild(expander);
            var span = document.createElement('span');
            span.innerText = "Развернуть", expander.appendChild(span), expand_container.onclick = function () {
                expand_container.parentNode.removeChild(expand_container), main.style.animation = 'height 15s cubic-bezier(.19,1,.22,1) forwards'
            }
        }
        //apply styles
        createStyle()
    }
}

function createStyle() {
    // Here you can change style of all new elements
    GM_addStyle(".main-sound-container{margin-bottom:15px; overflow:hidden}.sound-container{display:inline-block; vertical-align:top; width: 48%;}.op{margin-right:3%;}.sound{padding-top:5px; margin:5px; display: block;}.open-music{margin-bottom:15px;}@keyframes height {from{max-height:150px;} to {max-height: 5000px;}}")
}

function getMusic(doc, class_name) {
    let music = Array.from(doc.querySelectorAll('.theme-songs.js-theme-songs.' + class_name + ' > table > tbody tr > td:nth-child(2)'));
    return music.map(function(tr, index){
        let songName = tr.querySelector('.theme-song-title')?.innerText;
        if (!songName){
            return tr.innerText.trim();
        }
        let songAuthor = tr.querySelector('.theme-song-artist').innerText;
        let episodes = tr.querySelector('.theme-song-episode')?.innerText;
        return `${index+1}. ${songName}${songAuthor} ${episodes?episodes:""}`;
    });
}

function CreateUserScoresCount(doc) {
    if (document.getElementById("shiki-score"), null !== document.getElementById("shiki-score") && showMalCount) {
        var shikiRating = document.getElementsByClassName('score-source'),
            count = doc.querySelector("#content > table > tbody > tr > td:nth-child(2) > div.js-scrollfix-bottom-rel > table > tbody > tr:nth-child(1) > td > div.pb16 > div.di-t.w100.mt12 > div.anime-detail-header-stats.di-tc.va-t > div.stats-block.po-r.clearfix > div.fl-l.score").getAttribute("data-user");
        if (count = count.substring(0, count.length - 6), 0 != shikiRating.length) shikiRating[0].innerText = "На основе " + count + " оценок mal";
        else {
            var score = document.querySelector("#animes_show > section > div > div.menu-slide-outer.x199 > div > div > div.block > div.b-db_entry > div.c-about > div > div.c-info-right > div:nth-child(1) > div.scores > div"),
                scoreCount = document.createElement('p');
            scoreCount.className = 'score - source', scoreCount.style = "margin-bottom: 15px; text-align: center; color: rgb(123, 128, 132);", scoreCount.innerText = "На основе " + count + " оценок mal", insertAfter(scoreCount, score)
        }
    }
}

function loadMal() {
    "use strict";
    if (!isAnimePage() || isAdded()) return;
    let url = "https://myanimelist.net/anime/" + get_anime_id();
    log("Finding OP/ED."), GM_xmlhttpRequest({
        method: "GET",
        url: url,
        onload: function (response) {
            let doc = (new DOMParser).parseFromString(response.responseText, 'text/html');
            createOPEDList(getMusic(doc, "opnening"), getMusic(doc, "ending")), CreateUserScoresCount(doc), log("OP/ED finded!");
        }
    })
}

function isAnimePage() {
    return 0 === window.location.href.replace(/http.?:\/\/shikimori\..*\/animes\/[^\/]*/, "").length
}

function isAdded() {
    return document.getElementsByClassName("main-sound-container").length > 0
}

function ready(fn) {
    document.addEventListener('page:load', fn), document.addEventListener('turbolinks:load', fn), (document.attachEvent ? "complete" === document.readyState : "loading" !== document.readyState) ? fn() : document.addEventListener('DOMContentLoaded', fn)
}
ready(loadMal);