Greasy Fork

来自缓存

Get label from Fernsehserien.de

Offer Fernsehserien.de label based on episode number or title as Wikidata label

目前为 2021-07-09 提交的版本。查看 最新版本

// ==UserScript==
// @name         Get label from Fernsehserien.de
// @namespace    https://greasyfork.org/users/21515
// @version      0.1.0
// @description  Offer Fernsehserien.de label based on episode number or title as Wikidata label
// @author       CennoxX
// @contact      [email protected]
// @homepage     https://twitter.com/CennoxX
// @match        https://www.wikidata.org/wiki/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=wikidata.org
// @grant        GM.xmlHttpRequest
// ==/UserScript==
/* jshint esversion: 6 */
/* eslint quotes: ["warn", "double", "avoid-escape"]*/
/* eslint curly: "off"*/

(function(){
    "use strict";
    var correct = false;
    function compareString(title){
        return title.trim().toLowerCase().replace(/\(?(?:part)? ?(\d+?)\)?$/i, "$1").replace(/&/i, "and").replace(/^the |^a |[\u200B-\u200D\uFEFF]| |\.|'|’|\(|\)|:|,|‚|\?|!|„|“|"|‘|…|\.|—|–|-/gi,"");
    }
    async function checkTitle(ep, oldTitle, tryByNumber){
        var titles = [...ep.querySelectorAll("div:nth-child(7)>span")].map(i => i.innerText);
        var german = titles[0].replace(/ \((\d+)\)$/," – Teil $1").replace(/, Teil (\d+)$/," – Teil $1").replace(/ \(Teil (\d+)\)$/," – Teil $1");
        var english = titles[1];
        var altLabel = null;
        return await new Promise(resolve => {
            var stopInterval = setInterval(()=>{
                if (altLabel != null){
                    var descr = altLabel.nextElementSibling;
                    descr.innerText = `(${english})`;
                    var titleA = compareString(oldTitle);
                    var titleB = compareString(english);
                    correct = titleA == titleB && german != "–";
                    if (!correct && !tryByNumber && german != "–" && (titleA==titleB.replace(/\d/g,"") || titleB==titleA.replace(/\d/g,""))){
                        german = german.split(" – Teil ")[0];
                        correct = true;
                    }
                    altLabel.innerText = german;
                    var color = "";
                    if (tryByNumber && correct)
                        color = "lightgreen";
                    else if (!tryByNumber && correct)
                        color = "lightyellow";
                    else
                        color = "lightpink";
                    descr.style.backgroundColor = color;
                    clearInterval(stopInterval);
                    resolve(correct);
                }
                altLabel = document.querySelector(".wb-item-altlabel");
            },500);
        });
    }
    function getByTitle(ep, oldTitle, html, tryByTitle){
        var originalTitle = [...html.querySelectorAll(".episodenliste-schmal")].filter(i => {
            var titleA = compareString(i.innerText);
            var titleB = compareString(oldTitle);
            if (tryByTitle)
                return titleA == titleB;
            else
                return titleA.replace(/\d/g,"") == titleB.replace(/\d/g,"");
        });
        if (originalTitle.length>0)
            ep = originalTitle[0].closest("a");
        return ep;
    }
    function getByLevenshteinDistance(ep, oldTitle, html){
        var distMap = [...html.querySelectorAll(".episodenliste-schmal")].map(i => {
            var titleA = compareString(i.innerText);
            var titleB = compareString(oldTitle);
            var dist = levenshteinDistance(titleA,titleB);
            return({ep:i,dist});
        });
        var minDist = distMap.reduce(function(prev, curr) {
            return prev.dist < curr.dist ? prev : curr;
        });
        console.log("levenshtein distance:",minDist.dist);
        return minDist.ep.closest("a");
    }
    function levenshteinDistance(str1, str2){
        var track = Array(str2.length + 1).fill(null).map(() => Array(str1.length + 1).fill(null));
        for (let i = 0; i <= str1.length; i += 1) {
            track[0][i] = i;
        }
        for (let j = 0; j <= str2.length; j += 1) {
            track[j][0] = j;
        }
        for (let j = 1; j <= str2.length; j += 1) {
            for (let i = 1; i <= str1.length; i += 1) {
                var indicator = str1[i - 1] === str2[j - 1] ? 0 : 1;
                track[j][i] = Math.min(
                    track[j][i - 1] + 1,
                    track[j - 1][i] + 1,
                    track[j - 1][i - 1] + indicator,
                );
            }
        }
        return track[str2.length][str1.length];
    }
    var mainLoop = setInterval(async()=>{
        if (document.querySelector(".wikibase-labelview-text").innerText=="Keine Bezeichnung vorhanden"){
            var oldTitle = document.querySelector(".wikibase-title-label span")?.innerText;
            if (oldTitle == null){
                oldTitle = document.querySelector(".wb-item-altlabel")?.innerText;
            }
            if (oldTitle != null){
                clearInterval(mainLoop);
                var season = document.querySelector('[data-property-id="P4908"] .wikibase-snakview-value')?.innerText.split("/Staffel ").pop();
                var episode = document.querySelector('[data-property-id="P4908"] [href="/wiki/Property:P1545"]')?.closest(".wikibase-snakview").querySelector(".wikibase-snakview-value").innerText;
                var episodeNumber = "";
                if (episode != null)
                    episodeNumber = season+"x"+(episode[1]?"":"0")+episode;
                var series = document.querySelector('[data-property-id="P179"] .wikibase-snakview-value a').href.split("/")[4];
                var response = await fetch(`https://query.wikidata.org/sparql?query=SELECT%20*%20WHERE%20%7B%0A%20%20wd%3A${series}%20wdt%3AP5327%20%3Fid.%0A%7D&format=json`);
                var data = await response.json();
                var fsid = data.results.bindings[0].id.value;
                var epGuide = `https://www.fernsehserien.de/${fsid}/episodenguide`;
                //console.clear();
                console.log(epGuide);
                var result = await GM.xmlHttpRequest({
                    method: "GET",
                    url: epGuide,
                    onload: function(response) {
                        return response;
                    }
                });
                var html=document.createElement("div");
                html.innerHTML = result.responseText;
                fsid = html.querySelector('meta[property="og:url"]').content.split("/")[3];
                var ep = null;
                if (episode){
                    console.log("try by episode number");
                    ep = html.querySelector(`a[href^='/${fsid}/folgen/${episodeNumber}']`);
                    if (ep)
                    {
                        correct = await checkTitle(ep, oldTitle, true);
                    }
                }
                if (!correct){
                    console.log("try by title, with matching numbers");
                    ep = getByTitle(ep, oldTitle, html, true);
                    if (ep)
                    {
                        correct = await checkTitle(ep, oldTitle, false);
                    }
                }
                if (!correct){
                    console.log("try by title, without matching numbers");
                    ep = getByTitle(ep, oldTitle, html, false);
                    if (ep){
                        correct = await checkTitle(ep, oldTitle, false)
                    }
                }
                if (!correct){
                    console.log("get episode by levenshtein distance of title")
                    ep = getByLevenshteinDistance(ep, oldTitle, html);
                    if (ep){
                        correct = await checkTitle(ep, oldTitle, false)
                    }
                }
            }
        }
    },100);
})();