new format and marketplace
This commit is contained in:
174
book/mangapark.js
Normal file
174
book/mangapark.js
Normal file
@@ -0,0 +1,174 @@
|
||||
class mangapark {
|
||||
constructor() {
|
||||
this.baseUrl = "https://mangapark.net/apo";
|
||||
this.type = "book-board";
|
||||
this.mediaType = "manga";
|
||||
}
|
||||
|
||||
async search(queryObj) {
|
||||
const query = queryObj.query;
|
||||
|
||||
const res = await fetch(`${this.baseUrl}/`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"accept": "*/*",
|
||||
"content-type": "application/json",
|
||||
"x-apollo-operation-name": "get_searchComic",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: "query get_searchComic($select: SearchComic_Select) { get_searchComic(select: $select) { reqPage reqSize reqSort reqWord newPage paging { total pages page init size skip limit prev next } items { id data { id dbStatus name origLang tranLang urlPath urlCover600 urlCoverOri genres altNames authors artists is_hot is_new sfw_result score_val follows reviews comments_total max_chapterNode { id data { id dateCreate dbStatus isFinal sfw_result dname urlPath is_new userId userNode { id data { id name uniq avatarUrl urlPath } } } } } sser_follow sser_lastReadChap { date chapterNode { id data { id dbStatus isFinal sfw_result dname urlPath is_new userId userNode { id data { id name uniq avatarUrl urlPath } } } } } } } }",
|
||||
variables: {
|
||||
select: { word: query, size: 10, page: 1, sortby: "field_score" }
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
if (!data.data || !data.data.get_searchComic || !data.data.get_searchComic.items) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return data.data.get_searchComic.items.map(m => ({
|
||||
id: m.data.urlPath.split('/title/')[1]?.split('-')[0] || mangaId.split('/comic/')[1]?.split('-')[0], // This identifies the book
|
||||
title: m.data.name,
|
||||
image: `https://mangapark.net/${m.data.urlCoverOri}`,
|
||||
rating: m.data.score_val ? Math.round(m.data.score_val * 10) : null,
|
||||
type: "book",
|
||||
headers: {
|
||||
referer: "https://mangapark.net"
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
async getMetadata(id) {
|
||||
const res = await fetch(`https://mangapark.net/title/${id}`);
|
||||
const html = await res.text();
|
||||
|
||||
const match = html.match(
|
||||
/<script type="qwik\/json">([\s\S]*?)<\/script>/
|
||||
);
|
||||
if (!match) throw new Error("qwik json not found");
|
||||
|
||||
function decodeQwik(obj) {
|
||||
const refs = obj.refs || {};
|
||||
function walk(v) {
|
||||
if (typeof v === "string" && refs[v] !== undefined) {
|
||||
return walk(refs[v]);
|
||||
}
|
||||
if (Array.isArray(v)) {
|
||||
return v.map(walk);
|
||||
}
|
||||
if (v && typeof v === "object") {
|
||||
const out = {};
|
||||
for (const k in v) out[k] = walk(v[k]);
|
||||
return out;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
return walk(obj);
|
||||
}
|
||||
|
||||
const raw = JSON.parse(match[1]);
|
||||
const data = decodeQwik(raw);
|
||||
|
||||
const comic =
|
||||
data?.objs?.find(o => o && o.name && o.summary) ||
|
||||
data?.state?.comic;
|
||||
|
||||
if (!comic) throw new Error("comic not found");
|
||||
|
||||
const score100 = comic.score_avg
|
||||
? Math.round((Number(comic.score_avg) / 10) * 100)
|
||||
: 0;
|
||||
|
||||
return {
|
||||
id,
|
||||
title: comic.name || "",
|
||||
format: "Manga",
|
||||
score: score100,
|
||||
genres: comic.genres || [],
|
||||
status: comic.originalStatus || comic.status || "",
|
||||
published: comic.originalPubFrom
|
||||
? String(comic.originalPubFrom)
|
||||
: "???",
|
||||
summary: comic.summary || "",
|
||||
chapters: comic.chaps_normal || comic.chapters_count || 0,
|
||||
image: comic.urlCoverOri
|
||||
? `https://mangapark.net${comic.urlCoverOri}`
|
||||
: ""
|
||||
};
|
||||
}
|
||||
|
||||
async findChapters(mangaId) {
|
||||
const comicId = mangaId
|
||||
if (!comicId) {
|
||||
console.error("[MangaPark] Invalid ID format:", mangaId);
|
||||
return [];
|
||||
}
|
||||
|
||||
const res = await fetch(this.baseUrl + "/", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"accept": "*/*",
|
||||
"content-type": "application/json",
|
||||
"x-apollo-operation-name": "get_comicChapterList",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: "query get_comicChapterList($comicId: ID!) { get_comicChapterList(comicId: $comicId){ id data { id comicId isFinal volume serial dname title urlPath sfw_result } } }\n",
|
||||
variables: { comicId }
|
||||
})
|
||||
});
|
||||
|
||||
const json = await res.json();
|
||||
|
||||
if (!json.data || !json.data.get_comicChapterList) return [];
|
||||
|
||||
let list = json.data.get_comicChapterList;
|
||||
|
||||
list.sort((a, b) => a.data.serial - b.data.serial);
|
||||
|
||||
return list.map((c, i) => ({
|
||||
id: `https://mangapark.net${c.data.urlPath}`,
|
||||
title: c.data.dname || c.data.title || `Chapter ${c.data.serial}`,
|
||||
number: Number(c.data.serial),
|
||||
releaseDate: null,
|
||||
index: i
|
||||
}));
|
||||
}
|
||||
|
||||
async findChapterPages(chapterUrl) {
|
||||
const res = await fetch(chapterUrl, {
|
||||
headers: {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
||||
}
|
||||
});
|
||||
const html = await res.text();
|
||||
|
||||
const scripts = html.match(/<script\b[^>]*>[\s\S]*?<\/script>/gi) || [];
|
||||
let found = [];
|
||||
|
||||
for (const s of scripts) {
|
||||
const matches = s.match(/https?:\/\/[^"' ]+\.(?:jpg|jpeg|png|webp)/gi);
|
||||
if (matches) found.push(...matches);
|
||||
}
|
||||
|
||||
const urls = [...new Set(found)];
|
||||
const clean = urls.filter(u =>
|
||||
!u.includes("icon") &&
|
||||
!u.includes("logo") &&
|
||||
!u.includes("banner") &&
|
||||
!u.includes("thumb")
|
||||
);
|
||||
|
||||
return clean.map((url, index) => ({
|
||||
url,
|
||||
index,
|
||||
headers: { referer: 'https://mangapark.net' }
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = mangapark;
|
||||
Reference in New Issue
Block a user