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.1.2
// @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"))
var classChapter = "flex chapter" //class of the elements containing the chapters
var classFeed = "chapter-feed__chapters-list" //class containing the chapter cluster
var grouptagclass = "group-tag line-clamp-1 -my-1"
var newStyle = newInner("style","text/css",".hideme {\ndisplay: none;\n}")
document.querySelector("head").append(newStyle)
var filter = JSON.parse(localStorage.getItem("filter"))
if(filter == undefined || filter == null) {
console.log("filter: "+JSON.stringify(filter))
filter = true
localStorage.setItem("filter",JSON.stringify(filter))
}
whitelist = []
blacklist = []
function GetNumero(text){
for(let t of text.split(" ")){
console.log(t)
if((t*1)>0) return t*1
}
return NaN
}
function ScriptForm(){
if(document.URL.includes("https://mangadex.org/titles/feed") && !document.getElementById("script_btn")){
console.log("executing ScriptForm")
var options_loc = "flex items-center mb-4"
if(/*!document.getElementById("script_btn") && */document.getElementsByClassName(options_loc).length){
var newButton = newInner("div","",'<button id="script_btn" onclick="NMDF()" style="right: 2rem;position: absolute;">SCRIPT OPTIONS</button><popup id="script_body" style="position: fixed;right: 2rem;top: 5.5rem;width: 75%;background-color: var(--bg-color);z-index: 5;padding: 2rem;display: none;"><h2>New MangaDex Follows Script Options</h2><label><input type="checkbox" id="filter" value="filter"> Filter by groups</label><p>You can filter chapters by adding certain groups to a blacklist (so it\'s hidden) or whitelist (so it only shows that group releases). This only applies to 1 series at a time.</p><button class="menu__item--active-highlight" id="nmdf_save" onclick="SC()" style="background-color: orangered;padding: 0.5rem;margin: 0.5rem;">Save Changes</button><button id="nmdf_exit" onclick="EXIT()">Exit</button></popup>')
document.getElementsByClassName(options_loc)[0].append(newButton.children[0])
document.getElementsByClassName(options_loc)[0].append(newButton.children[0])
console.log("form added")
}
else setTimeout(ScriptForm,500)
}
}
window.NMDF = function(){
var daBody = document.getElementById("script_body")
document.getElementById("filter").checked = filter
if(daBody.style.display == "none"){
//including event listener
daBody.style.display = "block"
}
else{
daBody.style.display = "none"
//removing listener
}
}
window.SC = function(){
filter = document.getElementById("filter").checked
localStorage.setItem("filter",JSON.stringify(filter))
document.getElementById("script_body").style.display = "none"
}
window.EXIT = function(){
document.getElementById("script_body").style.display = "none"
}
function FS(array, number){//FindSeries
return array.findIndex(q => q.id == number)
}
function HideThis(array,series,group){
if(array.findIndex(q => q[0] == series && q[1] == group) >= 0) return true
return false
}
function OnlyThis(array,series,group){
if(array.findIndex(q => q[0] == series && q[1] == group) < 0) return 0 //it's not there
if(array.findIndex(q => q[0] == series && q[1] != group) >= 0) return 1 //the series is listed but not this group
if(array.findIndex(q => q[0] == series && q[1] == group) >= 0) return 2 //the series is listed with this group
return 3 //series is not listed
}
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 newInner(tag,classN,inner){
var temp = document.createElement(tag)
if(classN == "text/css") temp.type = classN
else temp.className = classN
temp.innerHTML = inner
return temp
}
function cloneDOM(tag,nodo){
var temp = document.createElement(tag)
temp = nodo.cloneNode(true)
return temp
}
function newDOM(tag,classN,style){
var temp = document.createElement(tag)
temp.className = classN
temp.style.display = style
return temp
}
function HasBeenRead(nodo){
if(!nodo.getElementsByTagName("svg")[0].className.baseVal.includes(" feather ")) return true
else return false
}
function ChangeToBL(nodo){
if(nodo.parentElement.getElementsByClassName("showme").length) console.log("still blacklisted?")//InverseIt(nodo.parentElement)//HideItAgain
else {
var parche = newInner("a","font-bold truncate showme blacklisted","BLACKLISTED")
nodo.parentElement.append(parche)//removeAttribute("href")
nodo.className += " hideme"
}
}
function InverseIt(nodo){//ShowItgain
let hideme = nodo.getElementsByClassName("hideme")[0]
let showme = nodo.getElementsByClassName("showme")[0]
if(!!hideme && !!showme){
console.log("inversing in process")
hideme.className = nodo.children[2].className.replace("hideme","showme")
showme.className = nodo.children[3].className.replace("showme","hideme")
}
}
function HideItAgain(nodo){
console.log("Hide It Again in process")
let hideme = nodo.getElementsByClassName("hideme")[0]
let showme = nodo.getElementsByClassName("showme")[0]
hideme.className = nodo.children[2].className.replace("hideme","showme")
showme.className = nodo.children[3].className.replace("showme","hideme")
}
function getID(nodo){
return nodo.getElementsByTagName("a")[0].href.split("/")[4]
}
function getID2(nodo){
return nodo.getElementsByTagName("a")[1].href.split("/")[4]
}
function ProcessGroups(process,batch,i,id_series){//todo: fix syntaxis to consider every scenario
if(filter){
var repeated = false
var icono,newdiv
var groupclass = "md:col-span-2"
var externals = "flex items-center"
var groupflex = batch[i].getElementsByClassName(groupclass)[0] //get the groups of this chapters
if(!groupflex) groupflex = batch[i].getElementsByClassName(externals)[1] //external chapters
if(batch[i].getElementsByClassName("nmf-single").length) {
groupflex = batch[i].getElementsByClassName("group-tag") //already processed
repeated = true
}
else{
if(groupflex.getElementsByTagName("svg").length) icono = cloneDOM("svg",groupflex.getElementsByTagName("svg")[0])
else icono = newInner("div","",'<svg data-v-9117f4b0="" data-v-d4f823fe="" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="small text-icon-black dark:text-icon-white icon"><path data-v-9117f4b0="" d="M17 21V19C17 17.9391 16.5786 16.9217 15.8284 16.1716C15.0783 15.4214 14.0609 15 13 15H5C3.93913 15 2.92172 15.4214 2.17157 16.1716C1.42143 16.9217 1 17.9391 1 19V21" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path data-v-9117f4b0="" d="M9 11C11.2091 11 13 9.20914 13 7C13 4.79086 11.2091 3 9 3C6.79086 3 5 4.79086 5 7C5 9.20914 6.79086 11 9 11Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path data-v-9117f4b0="" d="M23 20.9999V18.9999C22.9993 18.1136 22.7044 17.2527 22.1614 16.5522C21.6184 15.8517 20.8581 15.3515 20 15.1299" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path data-v-9117f4b0="" d="M16 3.12988C16.8604 3.35018 17.623 3.85058 18.1676 4.55219C18.7122 5.2538 19.0078 6.11671 19.0078 7.00488C19.0078 7.89305 18.7122 8.75596 18.1676 9.45757C17.623 10.1592 16.8604 10.6596 16 10.8799" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>').firstChild
newdiv = newDOM("div",groupclass+" nmf-groups","inline-grid")
}
function GFP(groupflex,z,process,batch,i,id_series){
let wl = false
let bl = false
var gid = 0
if(groupflex.innerText == "No Group") gid = 0
else {
if(groupflex.children[z].href) gid = groupflex.children[z].href.split("/")[4]
else if(groupflex.children[z].parentElement.href) gid = groupflex.children[z].parentElement.href.split("/")[4] //external links
else {
groupflex = groupflex.getElementsByClassName("nmf-single")[z].children[1]
}//console.log(groupflex.children[z])
}
//check if should be shown
if(HideThis(blacklist,id_series,gid)) {
console.log("blacklisted! hidethis")
process += false
bl = true
//ChangeToBL(batch[i].getElementsByTagName("a")[0])
}
else if(OnlyThis(whitelist,id_series,gid) == 1) {
console.log("not in whitelist!")
process += false
}
else if(OnlyThis(whitelist,id_series,gid) == 2) {
console.log("whitelisted!")
process += true
wl = true
}
else{
process += true
}
//add buttons
if(!groupflex.getElementsByClassName("nmf-single").length){
var single = newDOM("div","nmf-single","flex")
var newicono
if(!!icono) {
newicono= cloneDOM("svg",icono)
single.append(newicono)
}
var dagroup = document.createElement("a")
dagroup = groupflex.children[z].cloneNode(true)
if(dagroup.tagName != "A") {
dagroup = newInner("a",grouptagclass,groupflex.children[z].innerText)
if(!!groupflex.children[z].parentElement.href) dagroup.href = groupflex.children[z].parentElement.href //for external
}
dagroup.style.maxWidth = "80%"
dagroup.title = groupflex.children[z].innerText
single.append(dagroup)
var executor
if(wl) executor = newInner("div","list-options","<button title=\"Remove from Whitelist\" onclick=\"WL('"+id_series+"','"+gid+"')\">✅</button><button title=\"Add to Blacklist\" onclick=\"BL('"+id_series+"','"+gid+"')\">❌</button>")
else if(bl) executor = newInner("div","list-options","<button title=\"Add to Whitelist\" onclick=\"WL('"+id_series+"','"+gid+"')\">✅</button><button title=\"Remove from Blacklist\" onclick=\"BL('"+id_series+"','"+gid+"')\">❌</button>")
else executor = newInner("div","list-options","<button title=\"Add to Whitelist\" onclick=\"WL('"+id_series+"','"+gid+"')\">✅</button><button title=\"Add to Blacklist\" onclick=\"BL('"+id_series+"','"+gid+"')\">❌</button>")
single.append(executor)
newdiv.append(single)
}
return process
}
try{
if(!repeated){
for(let z=1; z<groupflex.children.length; z++){
process = GFP(groupflex,z,process,batch,i,id_series)
}
if(!batch[i].getElementsByClassName(groupclass+" nmf-groups").length) groupflex.parentElement.replaceChild(newdiv,groupflex)
else return true
return process
}
else{//has been repeated
for(let g of groupflex){
var gid = getID(g.parentElement)
//check if should be shown
if(HideThis(blacklist,id_series,gid)) {
console.log("blacklisted! processgroups")
process += false
ChangeToBL(batch[i].getElementsByTagName("a")[0])
}
else if(OnlyThis(whitelist,id_series,gid) == 1) {
console.log("not in whitelist!")
process += false
}
else if(OnlyThis(whitelist,id_series,gid) == 2) {
console.log("whitelisted!")
process += true
}
else{
process += true
}
}
return process
}
}
catch(e){
console.log("groupflex error")
console.log(e)
console.log(batch[i])
return true
}
}
}
function DecideNext(pseries,nextc,nextl,last,link,id_series,l){
if(pseries >= 0) NextNext(seriesdex,pseries,[nextc,nextl])
else seriesdex.push({id:id_series, name:l.firstChild.innerText, last:last, nextc:nextc, nextl:nextl})
let 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{
follows.push({id:id_series, ch:last, url:link, nextc:nextc, nextl:nextl, pointer:l})
}
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
}
}
var feedone = "mb-4"
function FollowsFeed(){
if(JSON.parse(localStorage.getItem("whitelist"))) whitelist = JSON.parse(localStorage.getItem("whitelist"))
if(JSON.parse(localStorage.getItem("blacklist"))) blacklist = JSON.parse(localStorage.getItem("blacklist"))
if(document.URL.includes("titles/feed")) {
var feedwhole = "mb-12"
if(document.getElementsByClassName(feedwhole).length){//if page is loaded
console.log("FollowsFeed")
lista = document.getElementsByClassName(feedwhole)[0].getElementsByClassName(feedone)
console.log("lista loaded")
for(let i = seriesdex.length-1; i>=0; i--){//to correct a previous bug
if(seriesdex[i].id.includes("/")) seriesdex.splice(i,1)
}
for(let l of lista){//check the list
try{
var id_series = getID(l)//.getElementsByTagName("a")[0].href.split("/")[4]
var batch = l.getElementsByClassName(classChapter)
var chap, link, read, nextc, nextl, last
nextc = 10000
nextl = ""
let pseries = FS(seriesdex,id_series)
if(pseries < 0) last = -10
else last = seriesdex[pseries].last
if(batch.length){//if there's chapters
for(let i=0; i<batch.length; i++){
var name = batch[i].getElementsByTagName("a")[0].innerText.replace("\n"," ")
var current = name.split(" ")[1]*1
var process = false
batch[i].getElementsByTagName("a")[0].setAttribute("title",name)
try{//for external links
JSON.parse(current)
}
catch(e){
current = batch[i].getElementsByTagName("a")[0].innerText.replace("\n"," ").split(" ")[2]*1
if(Number.isNaN(current)) current = 0
}
if(filter) process = ProcessGroups(process,batch,i,id_series)
else process = true
if(process){//should be shown
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(filter) InverseIt(batch[i].getElementsByTagName("a")[0].parentElement)
}
else{//has to be hidden
if(filter) ChangeToBL(batch[i].getElementsByTagName("a")[0])
}
}
}
DecideNext(pseries,nextc,nextl,last,link,id_series,l)
}
catch(e){
console.log("error processing lista")
console.log(e)
}
}
for(let f of follows){//consider chapters that aren't together
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 elem = a.getElementsByTagName("a")[0]
let disONE = elem.innerText.replace("\n"," ").split(" ")[1]*1
try{
JSON.parse(disONE)//for external links
}
catch(e){
console.log("external link")
disONE = elem.innerText.replace("\n"," ").split(" ")[2]*1
if(Number.isNaN(disONE)) disONE = 0
}
let unread = (!HasBeenRead(a))
if(disONE > lastest && !unread) lastest = disONE
if(unread && newest > disONE && disONE > lastest) {
newest = disONE
link = elem.href.split("chapter/")[1]
}
}
}
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
}
else{
if(seriesdex[current].nextc != f.nextc){
seriesdex[current].nextc = f.nextc
seriesdex[current].nextl = f.nextl
}
}
}
for(let l of lista){//add the continue link if necessary
let elem = l.getElementsByTagName("a")[0]
if(elem){ //l.firstChild.getElementsByTagName("a")[0]
let daONE = seriesdex[FS(seriesdex,elem.href.split("/")[4])]
let extrainfo = ""
if(l.getElementsByClassName(classFeed).length == 0) l.style.display = "none"
else if(daONE.nextc > daONE.last && daONE.nextl){
if(daONE.last != -10 && (daONE.nextc - daONE.last >= 1.2)) extrainfo = " (WARNING: skipped chapters)"
let newbutton = newInner("div",classFeed,"<button class=\"continue\"><a href=\"/chapter/"+daONE.nextl+"\">CONTINUE to Chapter "+daONE.nextc+extrainfo+"</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--){//put unread series on top of the list
if(follows[n].pointer.getElementsByClassName("continue")[0] != undefined) lista[0].parentElement.insertBefore(follows[n].pointer,lista[0])
}
localStorage.setItem("seriesdex",JSON.stringify(seriesdex))
}
else 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 = getID(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 != "<!---->"){
let status = t.firstChild.firstChild.firstChild.innerText
if(status == "Reading") reading = Llenar(t)
if(status == "On Hold") onhold = Llenar(t)
if(status == "Plan To Read") planto = Llenar(t)
if(status == "Dropped") dropped = Llenar(t)
if(status == "Completed") completed = Llenar(t)
}
}
let oldr = JSON.parse(localStorage.getItem("reading"))
let oldo = JSON.parse(localStorage.getItem("onhold"))
let oldp = JSON.parse(localStorage.getItem("planto"))
let oldd = JSON.parse(localStorage.getItem("dropped"))
let oldc = JSON.parse(localStorage.getItem("completed"))
for(let r of reading){
if(FS(seriesdex,r.id) == -1) seriesdex.push(r)
}
function Copiar(arrA,argB){
if(FS(arrA, argB.id) >= 0){
let indice = FS(arrA, argB.id)
arrA[indice].last = argB.last
arrA[indice].nextc = argB.nextc
arrA[indice].nextl = argB.nextl
}
}
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])
}
function UpdateArrays(old,array){
for(let a of array){
let indice = FS(old,a.id)
if(old[indice].last > a.last) {
a.last = old[indice].last
a.nextc = old[indice].nextc
a.nextl = old[indice].nextl
}
}
return array
}
reading = UpdateArrays(oldr,reading)
//planto = UpdateArrays(oldp,planto)
onhold = UpdateArrays(oldo,onhold)
dropped = UpdateArrays(oldd,dropped)
completed = UpdateArrays(oldc,completed)
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("error filling titles")
console.log(e)
}
}
function main(){
if(document.getElementsByClassName("ml-4 cursor-pointer rounded-full overflow-hidden bg-accent flex items-center justify-center")[0].firstChild.tagName == "IMG"){//is logged
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("select__tab select__tab-active")[0].innerText == "Follows"){
NewButton()
}
}
if(document.URL.includes("https://mangadex.org/titles/feed")){
console.log("checking feed")
follows = []
ScriptForm()
if(document.getElementsByClassName(feedone).length) FollowsFeed()
else setTimeout(main,2000)
}
if(document.URL.includes("https://mangadex.org/title/")){
console.log("Checking a series")
var fstatus
if(JSON.parse(localStorage.getItem("whitelist"))) whitelist = JSON.parse(localStorage.getItem("whitelist"))
if(JSON.parse(localStorage.getItem("blacklist"))) blacklist = JSON.parse(localStorage.getItem("blacklist"))
function UpdatingSeriesData(){
var loadedp = "flex gap-2 sm:mb-0 mb-2"
if(document.getElementsByClassName(loadedp).length){//if page is loaded
console.log("loaded")
var toProcess = false
var id_series = document.URL.split("/")[4]
var daLast = -110
var daNext = 10000
var daNLink = null
var tags = document.getElementsByClassName("tag bg-accent")
var volChange = document.getElementsByClassName("col-span-4")
var sus = false
fstatus = document.getElementsByClassName(loadedp)[0].firstChild.innerText //following status
console.log("fstatus: "+fstatus)
var toConsider = ["Reading","Completed","On Hold","Dropped","Added To Library"]
var lastup = document.getElementsByClassName("chapter-grid")[0].innerText.split(" ")[1]*1
if(Number.isNaN(lastup) || HideThis(blacklist,id_series,getID(document.getElementsByClassName(grouptagclass)[0].parentElement))) lastup = 100000
for(let t of tags){
//console.log(t.innerText)
if(t.innerText.toLowerCase().includes("4-koma")) {
sus = true
console.log("SUS!!")
}
}
function Apoo(){
if(toConsider.includes(fstatus)){//(fstatus == "Reading"){
console.log("reading series")
toProcess = true
daVolumes = document.getElementsByClassName("rounded flex flex-col gap-2")
for(let dv of daVolumes){
//console.log("checking volumes")
daChapters = dv.getElementsByClassName("chapter-grid")
for(let dc of daChapters){
//console.log("checking chapters")
let current
if(dc.innerText.includes("Oneshot")) current = 0
else current = GetNumero(dc.innerText.split("\n")[0])
if(Number.isNaN(current)) current = GetNumero(dc.parentElement.parentElement.parentElement.innerText.split("\n")[0])
if(current <= daLast) break
//console.log("checking "+current)
// console.log(dc.innerText)
if(sus){
console.log("sus checking "+current)
if(current < lastup) lastup = current
else {
console.log("break")
return
}
}
if(current <= daLast) break
if((!HideThis(blacklist,id_series,getID2(dc)) || HideThis(whitelist,id_series,getID2(dc))) && !HasBeenRead(dc) && daNext > current && daNext > daLast){
daNext = current
console.log("daNext: "+daNext)
daNLink = getID(dc)//.getElementsByTagName("a")[0].href.split("/")[4]
console.log("daNLink: "+daNLink)
}//todo: multiple groups
if((HideThis(blacklist,id_series,getID2(dc)) || OnlyThis(whitelist,id_series,getID2(dc))==1) && !HasBeenRead(dc) && daNext > current && daNext > daLast){//not consider if it's blacklisted
daNext = 10000
daNLink = null
}
if(HasBeenRead(dc) && daLast < current) {
daLast = current
if(daNext <= daLast) {
daNext = 10000
daNLink = null
}
console.log("found a last one")
break
}
}
}
}
}
Apoo()
let daIndex = FS(seriesdex,id_series)
if(daIndex >= 0){
if(seriesdex[daIndex].name != document.title.replace(" - MangaDex","")) seriesdex[daIndex].name = document.title.replace(" - MangaDex","")
console.log("previous last: "+seriesdex[daIndex].last)
if(sus){
seriesdex[daIndex].last = daLast
seriesdex[daIndex].nextc = daNext
seriesdex[daIndex].nextl = daNLink
}else if(seriesdex[daIndex].last <= daLast) {
seriesdex[daIndex].last = daLast
seriesdex[daIndex].nextc = daNext
seriesdex[daIndex].nextl = daNLink
}
console.log("new last: "+seriesdex[daIndex].last)
}
else {
if(toProcess){//not registered
console.log("new series!")
seriesdex.push({id:id_series, name:document.title.replace(" - MangaDex",""), last:daLast, nextc:daNext, nextl:daNLink})
}
else{//fixes bug that adds everything
if(fstatus != "Plan to Read") seriesdex.splice(daIndex,1)
}
}
if(FS(seriesdex,id_series) >= 0) console.log(seriesdex[FS(seriesdex,id_series)])
localStorage.setItem("seriesdex",JSON.stringify(seriesdex))
}
else setTimeout(UpdatingSeriesData,500)
}
UpdatingSeriesData()
}
}
else setTimeout(main,5000)
}
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"
if(a.last*1 < 0 || 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() {
if(document.URL.includes("titles/feed")) {
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
}
}
}
document.WL = function(id,gid){
if(OnlyThis(whitelist,id,gid) < 2 ) {//it's not included
whitelist.push([id,gid])
alert("This group has been added to the whitelist for this series. Click the botton again to undo it.")
}
if(HideThis(whitelist,id,gid)){
whitelist.splice(whitelist.findIndex(q => q[0] == id && q[1] == gid),1)
alert("This group has been removed from the whitelist for this series.")
}
UpdateShown()
localStorage.setItem("whitelist",JSON.stringify(whitelist))
}
document.BL = function(id,gid){
if(!HideThis(blacklist,id,gid)){
blacklist.push([id,gid])
alert("This group has been added to the blacklist for this series. Click the botton again to undo it.")
}
else{
blacklist.splice(blacklist.findIndex(q => q[0] == id && q[1] == gid),1)
alert("This group has been removed from the blacklist for this series.")
}
UpdateShown()
localStorage.setItem("blacklist",JSON.stringify(blacklist))
}
//to do: check conflicts between wl & bl
function UpdateShown(){
let hidden = document.getElementsByClassName("hideme")
if(hidden.length){ //document.getElementsByClassName("hideme")[0].parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement == l
for(let h of hidden) {//document.getElementsByClassName("hideme")[0].parentElement.parentElement.parentElement == batch[i]
let batch = h.parentElement.parentElement.parentElement
let l = batch.parentElement.parentElement.parentElement.parentElement
let id = getID(l)//.getElementsByTagName("a")[0].href.split("/")[4]
let gel = h.parentElement.parentElement.children[1]
let gid = 0
if(gel.getElementsByTagName("a").length) gid = getID(gel)//.getElementsByTagName("a")[0].href.split("/")[4]
else if(gel.getElementsByTagName("span").length) gid = gel.getElementsByTagName("span")[0].parentElement.href.split("/")[4]
if(!HideThis(blacklist,id,gid)) InverseIt(h.parentElement)
//else InverseIt(h.parentElement)
}
}
}