Greasy Fork

Greasy Fork is available in English.

Licensed (in English)

Show if manga is licensed in English.

当前为 2023-11-26 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Licensed (in English)
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Show if manga is licensed in English.
// @author       Santeri Hetekivi
// @match        https://mangadex.org/title/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=mangadex.org
// @grant        GM.xmlHttpRequest
// ==/UserScript==

(function() {
    'use strict';
    // ID for result element.
    const ID_RESULT = "licensedInEnglishResult"

    // Colors for different results.
    const COLOR_ERROR = "yellow"
    const COLOR_LICENSED = "red"
    const COLOR_UNLICENSED = "green"

    // Milliseconds to sleep multiplied by try counter.
    const MS_SLEEP = 1000

    // Start for Manga Updates series url.
    const URL_START_MANGAUPDATES = "https://www.mangaupdates.com/series.html?id="

    // Querys for elements.
    // Parent to store result element in.
    const QUERY_PARENT = ".title"
    // Query for getting link for Manga Updates.
    const QUERY_LINK_MANGAUPDATES = "a[href^='"+URL_START_MANGAUPDATES+"']"
    // Query for getting elements that can contain TEXT_LICENSED_IN_ENGLISH text.
    const QUERY_MANGAUPDATES_LICENSED_IN_ENGLISH = ".sCat b"

    // Texts.
    const TEXT_LICENSED_IN_ENGLISH = "Licensed (in English)"
    const TEXT_LICENSED_POSITIVE = "Yes"
    const TEXT_LICENSED_NEGATIVE = "No"

    // Update result element.
    const updateLicensedInEnglishText = (_elementResult, _text, _color = "yellow") => {
        _elementResult.style.color = _color
        _elementResult.textContent = _text;
    }

    // Select node list with given _query.
    const selectNodeList = (_query, _document = document) => {
        const nodeList = _document.querySelectorAll(_query);
        if(!(nodeList instanceof NodeList))
        {
            throw "nodeList for query '"+_query+"' was not instance of NodeList!"
        }
        return nodeList
    }

    // Select single element.
    const selectElement = (_query) => {
        // Get node list.
        const nodeList = selectNodeList(_query);

        // Check that got only single result.
        const lengthNodeList = nodeList.length
        if(lengthNodeList !== 1)
        {
            throw "Found "+lengthNodeList+" nodes for '"+_query+"'!"
        }

        // Check that single element is instance of Element.
        const element = nodeList[0]
        if(!(element instanceof Element))
        {
            throw "Element for query "+_query+" was not instance of Element!"
        }

        // Return gotten element.
        return element
    }

    // Get element for result.
    const getElementResult = () => {
        return document.getElementById(ID_RESULT)
    }

    // Output given _error to console.
    const consoleError = (_error) => {
        console.error("Licensed (in English)", _error)
    }

    // Handle given _error.
    const handleError = (_error) => {
        // Output to console.
        consoleError(_error)

        // Get element for result.
        const elementResult = getElementResult()

        // If element result found.
        if(elementResult instanceof Element)
        {
            // Update error to result element.
            updateLicensedInEnglishText(
                elementResult,
                _error,
                COLOR_ERROR
            )
        }
    }

    // Check that given _element is instance of Element.
    const checkIsElement = (_element, _name) => {
        if(!(_element instanceof Element))
        {
            throw _name+" was not instance of Element!"
        }
        return _element
    }

    // Get element with TEXT_LICENSED_IN_ENGLISH text.
    const getElementLicensedInEnglish = (_document) => {
        // Loop node list.
        const nodeList = selectNodeList(QUERY_MANGAUPDATES_LICENSED_IN_ENGLISH, _document)
        let element = null
        for (let i = 0; i < nodeList.length; i++)
        {
            // Get element.
            element = checkIsElement(nodeList[i], "nodeList["+i+"]")
            // If text matches
            if (element.textContent == TEXT_LICENSED_IN_ENGLISH)
            {
                // return element.
                return element
            }
        }

        // No element found.
        throw "No element with text '"+TEXT_LICENSED_IN_ENGLISH+"' found!"
    }

    // Get text answer for lisenced in english.
    const getTextLisencedInEnglish = (_document) => {
        // Get text.
        const text = checkIsElement(
            checkIsElement(
                getElementLicensedInEnglish(_document).parentElement ?? null,
                "getElementLicensedInEnglish.parentElement"
            ).nextElementSibling ?? null,
            "getElementLicensedInEnglish.parentElement.nextElementSibling"
        ).textContent.trim()

        // Check gotten text.
        if(
            text !== TEXT_LICENSED_POSITIVE
            &&
            text !== TEXT_LICENSED_NEGATIVE
        )
        {
            throw "Invalid text: "+text
        }

        // Return text.
        return text
    }

    // Handle response.
    const handleResponse = (_response) => {
        // Get answer for lisenced in english.
        const lisencedInEnglish = getTextLisencedInEnglish(
            (
                new DOMParser()
            ).parseFromString(
                _response.responseText,
                'text/html'
            )
        )

        // Update result element.
        updateLicensedInEnglishText(
            checkIsElement(
                getElementResult(),
                "getElementResult"
            ),
            lisencedInEnglish,
            (
                (lisencedInEnglish === TEXT_LICENSED_NEGATIVE) ?
                    COLOR_UNLICENSED :
                    (
                        (lisencedInEnglish === TEXT_LICENSED_POSITIVE) ?
                            COLOR_LICENSED :
                            COLOR_ERROR
                    )
            )
        )
    }

    // Run logic.
    const run = (_counter = 0) => {
        // Get parent elements.
        const parentElementsLength = selectNodeList(QUERY_PARENT).length

        // If
        if(
            // no parent values found
            parentElementsLength === 0
            &&
            // and call counter is under 10.
            _counter < 10
        )
        {
            // Increment counter.
            _counter++

            // Call after timeout.
            setTimeout(
                () => {
                    try
                    {
                        run(_counter)
                    }
                    catch(_error)
                    {
                        handleError(_error)
                    }
                },
                MS_SLEEP*_counter
            );

            // Return.
            return
        }
        // Throw error if found other than 0 or 1 elements.
        else if(parentElementsLength !== 1)
        {
            throw "Found "+parentElementsLength+" nodes for '"+QUERY_PARENT+"'!"
        }

        // Get result element.
        let elementResult = getElementResult(ID_RESULT)

        // If no result element found.
        if(!(elementResult instanceof Element))
        {
            // Create result element.
            elementResult = document.createElement("p")
            elementResult.id = ID_RESULT
            selectElement(QUERY_PARENT).appendChild(elementResult);
        }

        // Update result to unknown.
        updateLicensedInEnglishText(
            elementResult,
            "Unknown",
            COLOR_ERROR
        )

        // Get url for Manga Updates.
        const urlMangaUpdates = selectElement(QUERY_LINK_MANGAUPDATES).href ?? null
        if(typeof urlMangaUpdates !== "string" || !urlMangaUpdates)
        {
            throw "Got invalid URL for MangaUpdates: "+urlMangaUpdates
        }

        // Get Manga Updates page.
        GM.xmlHttpRequest(
            {
                method: "GET",
                url: urlMangaUpdates,
                headers: {
                    "Accept": "text/html"
                },
                onload: function(_response) {
                    // Handle response.
                    try
                    {
                        handleResponse(_response)
                    }
                    catch(_error)
                    {
                        handleError(_error)
                    }
                },
                onerror: (_response) => {
                    consoleError(_response)
                    handleError(_response.error ?? "Unknown error!")
                },
                ontimeout: (_response) => {
                    consoleError(_response)
                    handleError(_response.error ?? "Unknown timeout!")
                },
                onabort: (_response) => {
                    consoleError(_response)
                    handleError(_response.error ?? "Unknown timeout!")
                }
            }
        );
    }

    // Try to start running.
    try
    {
        // Make sure that document is instance of HTMLDocument.
        if(!(document instanceof HTMLDocument))
        {
            throw "document was not instance of HTMLDocument!"
        }
        run()
    }
    catch(_error)
    {
        handleError(_error)
    }
})();