From 496fb67138ffacdaed551b7032f243544e81ac6e Mon Sep 17 00:00:00 2001 From: aka paul <50n50@noreply.localhost> Date: Sat, 29 Nov 2025 21:07:05 +0000 Subject: [PATCH] Add atsu/atsu.js --- atsu/atsu.js | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 atsu/atsu.js diff --git a/atsu/atsu.js b/atsu/atsu.js new file mode 100644 index 0000000..14e6867 --- /dev/null +++ b/atsu/atsu.js @@ -0,0 +1,108 @@ +async function searchContent(keyword, page=0) { + const results = []; + try { + const response = await fetch(`https://atsu.moe/collections/manga/documents/search?q=${encodeURIComponent(keyword)}&limit=250&query_by=title%2CenglishTitle%2CotherNames&query_by_weights=3%2C2%2C1&include_fields=id%2Ctitle%2CenglishTitle%2Cposter%2CposterSmall%2CposterMedium%2Ctype%2CisAdult&num_typos=4%2C3%2C2&highlight_full_fields=title%2CenglishTitle%2CotherNames`); + const data = await response.json(); + if (Array.isArray(data.hits)) { + for (const hit of data.hits) { + const doc = hit.document; + results.push({ + id: doc.id, + imageURL: "https://atsu.moe" + doc.poster, + title: doc.title || doc.englishTitle || "" + }); + } + } + return results; + } catch (err) { + return []; + } +} + +async function getContentData(ID) { + try { + const response = await fetch(`https://atsu.moe/manga/${ID}`); + const html = await response.text(); + const scriptRegex = /window\.mangaPage\s*=\s*(\{[\s\S]*?\});/; + const scriptMatch = scriptRegex.exec(html); + let description = ""; + let tags = []; + if (scriptMatch) { + try { + const mangaPageObj = JSON.parse(scriptMatch[1]); + const page = mangaPageObj.mangaPage; + description = page.synopsis || ""; + if (Array.isArray(page.tags)) { + tags = page.tags.map(tag => tag.name); + } + } catch (e) { + } + } + return { + description, + tags + }; + } catch (err) { + return { + description: "Error", + tags: [] + }; + } +} + +async function getChapters(ID) { + const results = []; + try { + const firstResponse = await fetch(`https://atsu.moe/api/manga/chapters?id=${ID}&filter=all&sort=desc&page=0`); + const firstData = await firstResponse.json(); + const totalPages = firstData.pages || 1; + let allChapters = firstData.chapters || []; + + const fetchPromises = []; + for (let p = 1; p < totalPages; p++) { + fetchPromises.push( + fetch(`https://atsu.moe/api/manga/chapters?id=${ID}&filter=all&sort=desc&page=${p}`).then(r => r.json()) + ); + } + const pageResults = await Promise.all(fetchPromises); + for (const pageData of pageResults) { + if (Array.isArray(pageData.chapters)) { + allChapters = allChapters.concat(pageData.chapters); + } + } + + const total = allChapters.length; + for (let i = 0; i < total; i++) { + const chapter = allChapters[i]; + results.push([ + String(total - i - 1), + [{ + id: "https://atsu.moe/api/read/chapter?mangaId=" + ID + "&chapterId=" + chapter.id, + title: chapter.title, + chapter: chapter.number, + scanlation_group: chapter.title + }] + ]); + } + return { en: results.reverse() }; + } catch (err) { + return { en: [] }; + } +} + +async function getChapterImages(url) { + const results = []; + try { + const response = await fetch(url); + const data = await response.json(); + if (data.readChapter && Array.isArray(data.readChapter.pages)) { + for (const page of data.readChapter.pages) { + results.push("https://atsu.moe" + page.image); + } + } + return results; + } catch (err) { + return []; + } +} +