// ==UserScript== // @name Mangadex API v5 reader // @namespace Violentmonkey Scripts // @match https://mangadex.org/index.html // @grant none // @version 1.0 // @author UnnamedMinecrafter // @description (shitty) frontend for the v5 mangadex api // @downloadURL none // ==/UserScript== let cache = new Map(); let fetchJSON = async(url)=>{ let cached = cache.get(url); if(cached) return cached; let response = await fetch(url); let data = await response.json(); cache.set(url,data); return data; }; let getImageUrlsFromChapterID = async(chapterID)=>{ let chapter = await fetchJSON(`https://api.mangadex.org/chapter/${chapterID}`); let server = await fetchJSON(`https://api.mangadex.org/at-home/server/${chapterID}`); console.log(chapter) let urls = chapter.data.attributes.dataSaver.map(s=>`${server.baseUrl}/data-saver/${chapter.data.attributes.hash}/${s}`) return urls; }; let getChaptersFromMangaID = async(mangaID)=>{ let chapters = await fetchJSON(`https://api.mangadex.org/manga/${mangaID}/feed`); return chapters.results; }; let getGroupNamesFromChapter = async(chapter)=>{ let groupIDs = chapter.relationships.filter(e=>e.type==="scanlation_group").map(e=>e.id); let groups = await Promise.all(groupIDs.map(id=>fetchJSON(`https://api.mangadex.org/group/${id}`))); console.log(...groups) return groups.map(g=>g.data.attributes.name); }; let search = async(title)=>{ let url = new URL("https://api.mangadex.org/manga"); url.search = new URLSearchParams({ title }); let result = await fetchJSON(url); return result; }; let div = document.createElement("div"); div.innerHTML = `
`; document.body.insertBefore(div,document.body.childNodes[0]) let searchResults = document.querySelector("#search-results"); document.querySelector("#search").addEventListener("input",async(e)=>{ console.log(e.target.value); let query = e.target.value; let result = await search(query); searchResults.innerHTML = ""; for(let e of result.results) { console.log(e); let id = e.data.id; let title = e.data.attributes.title.en; let manga = document.createElement("div"); manga.innerText = title; manga.addEventListener("click",()=>{ displayManga(id); }); searchResults.appendChild(manga); } //document.querySelector("#search-results").innerText = JSON.stringify(result); }); const displayManga = async(id)=>{ let chapters = await getChaptersFromMangaID(id); searchResults.innerHTML = ""; for(let e of chapters) { let chapter = document.createElement("div"); console.log(e) let names = await getGroupNamesFromChapter(e); chapter.innerText = `${e.data.attributes.volume||0}.${e.data.attributes.chapter} ${e.data.attributes.title} by ${names.join(" ")}`; chapter.addEventListener("click",()=>{ displayChapter(e.data.id); }); searchResults.appendChild(chapter); } }; const displayChapter = async(id)=>{ let imageIDs = await getImageUrlsFromChapterID(id); searchResults.innerHTML = ""; for(let e of imageIDs) { let image = document.createElement("img"); image.src = e; searchResults.appendChild(image); } };