您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Manage your follows
当前为
// ==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() }