AnimeUnity fillers highlighter

highlight filler episodes

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         AnimeUnity fillers highlighter
// @namespace    http://tampermonkey.net/
// @version      2025-01-04
// @description  highlight filler episodes
// @author       bvuno
// @match        https://www.animeunity.so/anime/743-detective-conan*
// @icon         https://x-bv.uno/public/icon.svg
// @run-at       document-end
// @grant        GM.xmlHttpRequest
// @grant        GM_addStyle
// @license      https://creativecommons.org/licenses/by-nc/4.0/
// ==/UserScript==

/*
  Copyright (c) 2025 Bruno Cerra (https://x-bv.uno)
  This work is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License.
  You may not use this work for commercial purposes.
  https://creativecommons.org/licenses/by-nc/4.0/
*/

(function() {
    'use strict';

    GM_addStyle(`
        .episode.episode-item:has(.filler) {
            background-color: #8D2831;
        }

        .episode.episode-item.seen:has(.filler) {
            background-color: #FF057D;
        }


        .episode.episode-item.active:has(.filler) {
            background-color: #FF0000 !important;
        }

        .episode.episode-item:has(.mixed) {
            background-color: #65410B;
        }

        .episode.episode-item.seen:has(.mixed) {
            background-color: #FFD21E;
        }


        .episode.episode-item.active:has(.mixed) {
            background-color: #FF9C00 !important;
        }

    `);


     const FILLER_LIST_URL = "https://www.animefillerlist.com/shows/detective-conan"

     function from_div_to_list(elem) {
         let result = []
         for (const a of elem.querySelectorAll("a")) {
             const text = a.innerText
             if (text.includes("-")) {
                  const [start, end] = text.split("-").map(Number);
                  for (let i = start; i <= end; i++) {
                      result.push(i);
                  }
              } else {
                  result.push(Number(text));
              }
         }
         return result
     }

    const filler_list = []
    const mixed_list = []

    function highlight_eps(){
        const ep_elems = document.querySelectorAll("#anime > div.content.container > div.overview > div:nth-child(2) > div > div > div.mt-4.mb-4.episode-wrapper.text-center > div")
        for (const ep_elem of ep_elems) {
            const ep_elem_a = ep_elem.querySelector("a")

            for (const css_class of ['filler', 'mixed']) {
                if (ep_elem_a.classList.contains(css_class)) {
                    ep_elem_a.classList.remove(css_class);
                }
            }

            const text = ep_elem_a.innerText
            if (text.includes('-')) {
                const eps = text.split("-").map(Number);
                if (eps.every(x => filler_list.includes(x))) {
                    ep_elem_a.classList.add("filler");
                }
                else if (eps.some(x => filler_list.includes(x))) {
                    ep_elem_a.classList.add("mixed");
                }
            } else {
                const ep = Number(text)
                if (filler_list.includes(ep)) {
                    ep_elem_a.classList.add("filler");
                }
                if (mixed_list.includes(ep)) {
                    ep_elem_a.classList.add("mixed");
                }
            }
        }
    }

    function handleChange() {
        const first_ep = document.querySelector("#anime > div.content.container > div.overview > div:nth-child(2) > div > div > div.mt-4.mb-4.episode-wrapper.text-center > div")
        const text = first_ep.querySelector("a").innerText
        function waitChange() {
            if (text == first_ep.querySelector("a").innerText) {
                setTimeout(waitChange, 100)
            }
            else {
                highlight_eps()
            }
        }
        waitChange()
    }

     GM.xmlHttpRequest({
        method: "GET",
        url: FILLER_LIST_URL,
        onload: function(response) {
            const parser = new DOMParser();
            const doc = parser.parseFromString(response.responseText, "text/html");
            mixed_list.push(... from_div_to_list(doc.querySelector("#Condensed .mixed_canon\\/filler .Episodes")))
            filler_list.push(... from_div_to_list(doc.querySelector("#Condensed .filler .Episodes")))

            document.querySelector("#episode-nav").addEventListener('click', handleChange)
            setTimeout(highlight_eps, 100)
        }
    });
})();