Greasy Fork

Greasy Fork is available in English.

New MangaDex Follows

Manage your follows

当前为 2021-10-03 提交的版本,查看 最新版本

// ==UserScript==
// @name         New MangaDex Follows
// @namespace    http://greasyfork.icu/scripts/430295-new-mangadex-follows
// @version      1.0.4
// @description  Manage your follows
// @author       Australis
// @match        https://mangadex.org/*
// @icon         https://www.google.com/s2/favicons?domain=mangadex.org
// @grant        none
// ==/UserScript==
if(localStorage.getItem("seriesdex") == null) seriesdex = []
else seriesdex = JSON.parse(localStorage.getItem("seriesdex"))

function FS(array, number){//FindSeries
    return array.findIndex(q => q.id == number)
}

button_reload = 0
disURL = ""

function NextNext(array,pointer,next){
    if(next[0] < array[pointer].nextc*1 && array[pointer].last < next[0]) {
        array[pointer].nextc = next[0]
        array[pointer].nextl = next[1]
    }
}

function Reload1(){
    elem_no = follows.length
    if(before < elem_no) button_reload = setTimeout(Reload1,4000)
    else repeat = setTimeout(FollowsFeed,2000)
    before = follows.length
}

function Reload(){
    if(lista.length == 0) button_reload = setTimeout(Reload,1000)
    else repeat = setTimeout(FollowsFeed,2000)
}

function FollowsFeed(){
    var classChapter = "flex chapter"
    var classFeed = "chapter-feed__chapters-list"
    if(document.URL.includes("titles/feed")) {
        try{
            console.log("FollowsFeed")
            lista = document.getElementsByClassName("mb-12")[0].getElementsByClassName("mb-4")
            console.log("lista loaded")

            for(let i = seriesdex.length-1; i>=0; i--){//to correct latest bug
                if(seriesdex[i].id.includes("/")) seriesdex.splice(i,1)
            }

            try{
                clearInterval(button_reload)
            }
            catch(e){
                console.log("no reload")
            }
            try{
                clearInterval(repeat)
            }
            catch(e){
                console.log("no repeat")
            }

            for(let l of lista){
                //if(!l.className.includes("my-6") && l.style.display != "none") {
                try{
                    var id_series = l.getElementsByTagName("a")[0].href.split("/")[4]
                    var batch = l.getElementsByClassName(classChapter)
                    var chap, link, read, nextc, nextl, last
                    nextc = 10000
                    nextl = ""
                    pseries = FS(seriesdex,id_series)
                    if(pseries < 0) last = -10
                    else last = seriesdex[pseries].last

                    function HasBeenRead(nodo){
                        if(!nodo.getElementsByTagName("svg")[0].className.baseVal.includes(" feather ")) return true
                        else return false
                    }

                    if(batch.length){
                        for(let i=0; i<batch.length; i++){
                            var current = batch[i].getElementsByTagName("a")[0].innerText.replace("\n"," ").split(" ")[1]*1
                            try{//for external links
                                JSON.parse(current)
                            }
                            catch(e){
                                current = batch[i].getElementsByTagName("a")[0].innerText.replace("\n"," ").split(" ")[2]*1
                            }
                            if(!HasBeenRead(batch[i])){
                                if(last < current && nextc > last && nextc > current){
                                    nextc = current
                                    nextl = batch[i].getElementsByTagName("a")[0].href.split("chapter/")[1]
                                }
                            }
                            else if(HasBeenRead(batch[i])){
                                if(last < current) last = current
                            }
                        }
                    }

                    if(pseries >= 0) NextNext(seriesdex,pseries,[nextc,nextl])
                    else seriesdex.push({id:id_series, name:l.firstChild.innerText, last:last, nextc:nextc, nextl:nextl})

                    index = FS(follows,id_series)
                    if(index >= 0){
                        if(seriesdex[pseries].last < last || seriesdex[pseries].last == null) seriesdex[pseries].last = last
                        if(nextc > last){
                            NextNext(follows,index,[nextc,nextl])
                            NextNext(seriesdex,pseries,[nextc,nextl])
                        }
                        if(l != follows[index].pointer) {
                            while(l.getElementsByClassName(classChapter)[0] != undefined) follows[index].pointer.getElementsByClassName(classChapter)[0].append(l.getElementsByClassName(classChapter)[0])
                        }
                        //else console.log("new?")
                    }
                    else{
                        follows.push({id:id_series, ch:last, url:link, nextc:nextc, nextl:nextl, pointer:l})
                    }

                    // if(pseries >= 0){
                    if(pseries == -1) pseries = FS(seriesdex,id_series)
                    if(seriesdex[pseries].nextc == 0 || seriesdex[pseries].nextc == null || seriesdex[pseries].nextc == 10000 || (seriesdex[pseries].nextc > nextc && seriesdex[pseries].last < nextc)){
                        seriesdex[pseries].nextc = nextc
                        seriesdex[pseries].nextl = nextl
                    }
                    // }
                }
                catch(e){
                    console.log(e)
                    //  console.log(l)
                }
                //}
            }
            for(let f of follows){
                let avail = f.pointer.getElementsByClassName(classChapter)
                let lastest = -10
                let newest = 10000
                let link = null
                let current = FS(seriesdex,f.id)
                if(current >= 0){
                    lastest = seriesdex[current].last
                    newest = seriesdex[current].nextc
                }
                for(let a of avail){
                    if(!a.getElementsByClassName("continue").length){
                        let disONE = a.getElementsByTagName("a")[0].innerText.replace("\n"," ").split(" ")[1]*1
                        try{
                            JSON.parse(disONE)//for external links
                        }
                        catch(e){
                            disONE = a.getElementsByTagName("a")[0].innerText.replace("\n"," ").split(" ")[2]*1
                        }
                        let unread = (!HasBeenRead(a))
                        if(disONE > lastest && !unread) lastest = disONE
                        if(unread && newest > disONE && disONE > lastest) {
                            newest = disONE
                            link = a.getElementsByTagName("a")[0].href.split("chapter/")[1]
                        }
                    }
                }
                // console.log(f.pointer.getElementsByTagName("h6")[0].innerText+" last: "+lastest+" nextc: "+newest)
                f.ch = lastest
                if(newest > lastest) {
                    f.nextc = newest
                    f.nextl = link
                }
                else{
                    f.nextc = 10000
                    f.nextl = null
                }
                if(lastest > seriesdex[current].last) {
                    seriesdex[current].last = lastest
                    // seriesdex[current].nextc = f.nextc
                    // seriesdex[current].nextl = f.nextl
                }
                else{//lastest <= seriesdex[current].last
                    if(seriesdex[current].nextc != f.nextc){
                        seriesdex[current].nextc = f.nextc
                        seriesdex[current].nextl = f.nextl
                    }
                }
            }
            for(let l of lista){
                if(l.getElementsByTagName("a")[0]){ //l.firstChild.getElementsByTagName("a")[0]
                    let daONE = seriesdex[FS(seriesdex,l.getElementsByTagName("a")[0].href.split("/")[4])]
                    if(l.getElementsByClassName(classFeed).length == 0) l.style.display = "none"
                    else if(daONE.nextc > daONE.last && daONE.nextl){
                        let newbutton = document.createElement("div")
                        newbutton.className = classFeed
                        newbutton.innerHTML = "<button class=\"continue\"><a href=\"/chapter/"+daONE.nextl+"\">CONTINUE to Chapter "+daONE.nextc+"</button>"
                        if(l.getElementsByClassName("continue").length == 0) l.getElementsByClassName("chapter-feed__chapters")[0].insertBefore(newbutton,l.getElementsByClassName(classFeed)[0])
                        else l.getElementsByClassName("continue")[0].parentElement.innerHTML = newbutton.innerHTML
                    }
                    if((daONE.nextl == null || daONE.nextl == "") && l.getElementsByClassName("continue")[0] != undefined) l.getElementsByClassName("continue")[0].parentElement.remove()
                }
            }

            for(let n=follows.length-1; n >= 0; n--){
                if(follows[n].pointer.getElementsByClassName("continue")[0] != undefined) lista[0].parentElement.insertBefore(follows[n].pointer,lista[0])
            }
            localStorage.setItem("seriesdex",JSON.stringify(seriesdex))
            //interval = setInterval(FollowsFeed,120000)
        }
        catch(e){
            console.log("error FollowsFeed")
            console.log(e)
            repeat = setTimeout(FollowsFeed,5000)
        }
    }
}

function Clickear(){
    hola = document.getElementsByClassName("follows__content mb-12")[0].firstChild.children
    state = true
    try{
        for(let h of hola){
            if(h.innerHTML != "<!---->"){
                if(h.firstChild.firstChild.lastChild.tagName == "BUTTON") {
                    h.firstChild.firstChild.lastChild.click()
                }
                else state = false
            }
        }
        if(state) setTimeout(Clickear,2500)
        else FillTitles()
    }
    catch(e){
        setTimeout(Clickear,2500)
    }
}

function Llenar(X){
    let temp = []
    console.log("now filling "+X.firstChild.firstChild.firstChild.innerText)
    for(let t of X.getElementsByClassName("manga-card")){
        var id = t.getElementsByTagName("a")[0].href.split("/")[4]
        var name = t.getElementsByTagName("a")[0].innerText.replaceAll("\n    ","").replaceAll("\n  ","")
        temp.push({id:id, name:name, last:null, nextc:null, nextl:null })
        if(temp.length == 0) temp = [{id:id, name:name, last:null, nextc:null, nextl:null}]
    }
    console.log("Done Filling!!")
    return temp
}

function NewButton(){
    try{
        newb = document.createElement("button")
        newb.innerHTML = "<button id=\"fill-btn\" data-v-621772ff=\"\" type=\"button\" class=\"v-btn v-btn--is-elevated v-btn--has-bg theme--dark v-size--default\"><span class=\"v-btn__content\"><span data-v-621772ff=\"\" aria-hidden=\"true\" class=\"v-icon notranslate theme--dark\" onclick=\"Fill()\"><a>FILL</a></span></span></button>"
        if(!document.getElementById("fill-btn")) document.getElementsByClassName("controls mb-auto ml-auto")[0].appendChild(newb)

        dl = document.createElement("div")
        dl.innerHTML="<button class=\"rounded relative md-btn flex items-center px-3 my-6 justify-center text-white bg-primary hover:bg-primary-darken active:bg-primary-darken2 glow px-4 px-6\" onclick=\"DownloadCSV()\">Download CSV</button><button class=\"rounded relative md-btn flex items-center px-3 my-6 justify-center text-white bg-primary hover:bg-primary-darken active:bg-primary-darken2 glow px-4 px-6\" onclick=\"DownloadJSON()\">Download JSON<button>"
        document.getElementsByClassName("follows__display")[0].parentElement.insertBefore(dl,document.getElementsByClassName("follows__display")[0])
    }
    catch(e){
        setTimeout(NewButton,500)
    }
}

function FillTitles(){
    try{
        titles = document.getElementsByClassName("follows__content")[0].firstChild.children
        if(titles != undefined){
            console.log("Filling Titles")
            for(t of titles){
                if(t.innerHTML != "<!---->"){
                    if(t.firstChild.firstChild.firstChild.innerText == "Reading") reading = Llenar(t)
                    if(t.firstChild.firstChild.firstChild.innerText == "On Hold") onhold = Llenar(t)
                    if(t.firstChild.firstChild.firstChild.innerText == "Plan To Read") planto = Llenar(t)
                    if(t.firstChild.firstChild.firstChild.innerText == "Dropped") dropped = Llenar(t)
                    if(t.firstChild.firstChild.firstChild.innerText == "Completed") completed = Llenar(t)
                }
            }
            for(let r of reading){
                if(FS(seriesdex,r.id) == -1) seriesdex.push(r)
            }

            function Copiar(arrA,argB){
                if(FS(arrA, argB.id) >= 0){
                    arrA[FS(arrA, argB.id)].last = argB.last
                }
            }

            for(let i = seriesdex.length-1; i >= 0; i--){
                Copiar(completed, seriesdex[i])
                Copiar(onhold, seriesdex[i])
                Copiar(reading, seriesdex[i])
                Copiar(dropped, seriesdex[i])
                //Copiar(planto, seriesdex[i])
            }
            localStorage.setItem("reading",JSON.stringify(reading))
            localStorage.setItem("planto",JSON.stringify(planto))
            localStorage.setItem("onhold",JSON.stringify(onhold))
            localStorage.setItem("dropped",JSON.stringify(dropped))
            localStorage.setItem("completed",JSON.stringify(completed))
            alert("Done!")
        }
    }
    catch(e){
        console.log(e)
        // setTimeout(FillTitles, 5500)
    }
}

function main(){
    if(document.URL.includes("https://mangadex.org/user/me")){
        console.log("Script ready")

        function EsperaBotones(){
            try{
                botones = document.getElementsByClassName("follows__content mb-12")[0].getElementsByTagName("button")
            }
            catch(e){
                setTimeout(EsperaBotones,1000)
            }
        }

        EsperaBotones()

        function Repetir(){
            estado = true

            for(let b of botones){
                if(b.innerText.includes("Load More")) {
                    b.click()
                    estado = false
                }
            }

            if(estado) FillTitles()
            else setTimeout(Repetir,2500)
        }

        document.Fill = function(){
            console.log("Loading series...")
            alert("Please wait until the next alert, this can take several minutes depending of how many series you follow.")
            Repetir()
        }

        if(document.getElementsByClassName("user__tab-active")[0].innerText == "Follows"){
            NewButton()
        }
    }

    if(document.URL.includes("https://mangadex.org/titles/feed")){
        follows = []
        elem_no = 0
        before = 0

        function DoFollows(){
            FollowsFeed()
            //repeat = setTimeout(FollowsFeed,30000)
        }

        if(document.getElementsByClassName("mb-4").length) DoFollows()
        else setTimeout(main,2000)
    }

}

function Loop(){
    try{
        if(disURL != document.URL){
            console.log("loop")
            repeat = setTimeout(main,5000)
            disURL = document.URL
            trigger = false
        }
    }
    catch(e){
        console.log("error loop")
    }
    frutyloop = setTimeout(Loop,1000)
}

frutyloop = setTimeout(Loop,1000)

function exportToJsonFile(jsonData) {
    let dataStr = JSON.stringify(jsonData);
    let dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(dataStr);

    let exportFileDefaultName = 'seriesdex.json';

    let linkElement = document.createElement('a');
    linkElement.setAttribute('href', dataUri);
    linkElement.setAttribute('download', exportFileDefaultName);
    linkElement.click();
}

function parseJSONToCSVStr(jsonData) {
    if(jsonData.length == 0) {
        return '';
    }

    let keys = Object.keys(jsonData[0]);

    let columnDelimiter = '\t';
    let lineDelimiter = '\n';

    let csvColumnHeader = keys.join(columnDelimiter);
    let csvStr = csvColumnHeader + lineDelimiter;

    jsonData.forEach(item => {
        keys.forEach((key, index) => {
            if( (index > 0) && (index < keys.length) ) {
                csvStr += columnDelimiter;
            }
            csvStr += item[key];
        });
        csvStr += lineDelimiter;
    });

    return encodeURIComponent(csvStr);;
}

function exportToCsvFile(jsonData) {
    let csvStr = parseJSONToCSVStr(jsonData);
    let dataUri = 'data:text/csv;charset=utf-8,'+ csvStr;

    let exportFileDefaultName = 'MangaDexFollowFeed.csv';

    let linkElement = document.createElement('a');
    linkElement.setAttribute('href', dataUri);
    linkElement.setAttribute('download', exportFileDefaultName);
    linkElement.click();
}

function PrepareData(lala){
    var temp = []
    reading = JSON.parse(localStorage.getItem("reading"))
    planto = JSON.parse(localStorage.getItem("planto"))
    onhold = JSON.parse(localStorage.getItem("onhold"))
    dropped = JSON.parse(localStorage.getItem("dropped"))
    completed = JSON.parse(localStorage.getItem("completed"))

    function Processing(arrayy,naame){
        for(let a of arrayy){
            let last
            if(lala){
                if(a.last*1 < 0 || JSON.parse(a.last) == null) last = "unregistered"
                else last = a.last
            }
            else last = a.last
            temp.push({id:a.id,name:a.name,state:naame,last:last})
            if(temp.length == 0) temp = [{id:a.id,name:a.name,state:naame,last:last}]
        }
    }

    Processing(reading,"Reading")
    Processing(onhold,"On Hold")
    Processing(planto,"Plan to Read")
    Processing(dropped,"Dropped")
    Processing(completed,"Completed")

    return temp
}

window.FF = function(){//for debugging
    FollowsFeed()
}

window.DownloadCSV = function(){
    exportToCsvFile(PrepareData(true))
}

window.DownloadJSON = function(){
    exportToJsonFile(PrepareData(false))
}

document.onscroll = function() {
    // Detect webkit browser (Chrome, Safari)
    // console.log("scrolling")
    var w = document.documentElement.clientHeight;
    var over = document.documentElement.scrollTopMax;
    if(document.documentElement.scrollTop < over) trigger = true
    if(w < over && document.documentElement.scrollTop == over) {
        if(trigger) setTimeout(FollowsFeed,500)
        trigger = false
    }
    Reader()
}