130 lines
3.9 KiB
JavaScript
130 lines
3.9 KiB
JavaScript
class asmhentai {
|
|
constructor() {
|
|
this.baseUrl = "https://asmhentai.com";
|
|
this.type = "book-board";
|
|
this.version = "1.1"
|
|
this.mediaType = "manga";
|
|
}
|
|
|
|
async search(queryObj) {
|
|
const q = (queryObj.query || "").trim().replace(/\s+/g, "+");
|
|
const html = await fetch(`${this.baseUrl}/search/?q=${q}&page=1`).then(r => r.text());
|
|
const $ = this.cheerio.load(html);
|
|
|
|
const results = [];
|
|
|
|
$(".preview_item").each((_, el) => {
|
|
const href = $(el).find(".image a").attr("href");
|
|
const id = href?.match(/\/g\/(\d+)\//)?.[1];
|
|
if (!id) return;
|
|
|
|
let img = $(el).find(".image img").attr("data-src") || $(el).find(".image img").attr("src") || "";
|
|
if (img.startsWith("//")) img = "https:" + img;
|
|
|
|
const image = img.replace("thumb.jpg", "1.jpg");
|
|
const title = $(el).find("h2.caption").text().trim();
|
|
|
|
results.push({
|
|
id,
|
|
image,
|
|
title,
|
|
rating: null,
|
|
type: "book"
|
|
});
|
|
});
|
|
|
|
return results;
|
|
}
|
|
|
|
async getMetadata(id) {
|
|
const html = await fetch(`${this.baseUrl}/g/${id}/`).then(r => r.text());
|
|
const $ = this.cheerio.load(html);
|
|
|
|
let image =
|
|
$('a[href^="/gallery/"] img').attr("data-src") ||
|
|
$('a[href^="/gallery/"] img').attr("src") ||
|
|
"";
|
|
|
|
if (image.startsWith("//")) image = "https:" + image;
|
|
|
|
const genres = $(".tags a.tag")
|
|
.map((_, el) => $(el).text().trim())
|
|
.get()
|
|
|
|
return {
|
|
id,
|
|
title: $("h1").first().text().trim(),
|
|
format: "MANGA",
|
|
score: 0,
|
|
genres,
|
|
status: "unknown",
|
|
published: "???",
|
|
summary: "",
|
|
chapters: 1,
|
|
image
|
|
};
|
|
}
|
|
|
|
async findChapters(mangaId) {
|
|
return [{
|
|
id: mangaId.toString(),
|
|
title: "Chapter",
|
|
number: 1,
|
|
index: 0
|
|
}];
|
|
}
|
|
|
|
async findChapterPages(chapterId) {
|
|
const html = await fetch(`${this.baseUrl}/g/${chapterId}/`).then(r => r.text());
|
|
const $ = this.cheerio.load(html);
|
|
|
|
const token = $('meta[name="csrf-token"]').attr("content") || "";
|
|
const loadId = $("#load_id").val();
|
|
const loadDir = $("#load_dir").val();
|
|
const totalPages = $("#t_pages").val() || "0";
|
|
|
|
const body = new URLSearchParams({
|
|
id: loadId,
|
|
dir: loadDir,
|
|
visible_pages: "0",
|
|
t_pages: totalPages,
|
|
type: "2",
|
|
});
|
|
|
|
if (token) body.append("_token", token);
|
|
|
|
const res = await fetch(`${this.baseUrl}/gallery/`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
"Referer": `${this.baseUrl}/g/${chapterId}/`,
|
|
},
|
|
body
|
|
}).then(r => r.text());
|
|
|
|
const $$ = this.cheerio.load(res);
|
|
|
|
return $$("img[data-src], img[src]").get()
|
|
.map((el) => {
|
|
let url = $$(el).attr("data-src") || $$(el).attr("src");
|
|
if (url?.startsWith("//")) url = "https:" + url;
|
|
return url;
|
|
})
|
|
.filter(url => {
|
|
// Mantenemos el filtro que te funcionó
|
|
return url && url.includes("images.") && !url.includes("/images/");
|
|
})
|
|
.map((url, i) => {
|
|
// Reemplazamos "thumb" por el número del índice + 1
|
|
// Ejemplo: .../thumb.jpg -> .../1.jpg
|
|
const newUrl = url.replace("thumb", (i + 1).toString());
|
|
|
|
return {
|
|
index: i,
|
|
url: newUrl
|
|
};
|
|
});
|
|
}
|
|
}
|
|
|
|
module.exports = asmhentai; |