all extensions to new format :P

This commit is contained in:
2025-12-15 19:40:07 +01:00
parent 9986b64ace
commit 9fe48f93fe
19 changed files with 1725 additions and 1375 deletions

View File

@@ -1,125 +1,104 @@
class asmhentai {
constructor(fetchPath, cheerioPath, browser) {
this.baseUrl = "https://asmhentai.com/";
this.fetch = require(fetchPath);
this.cheerio = require(cheerioPath);
this.browser = browser;
constructor() {
this.baseUrl = "https://asmhentai.com";
this.type = "book-board";
this.mediaType = "manga";
}
async fetchSearchResult(query = "", page = 1) {
const q = query.trim().replace(/\s+/g, "+");
const url = q ? `${this.baseUrl}/search/?q=${q}&page=${page}` : `${this.baseUrl}/?q=&page=${page}`;
const res = await this.fetch(url);
const html = await res.text();
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 items = $(".ov_item .preview_item");
const results = [];
items.each((_, el) => {
const $el = $(el);
$(".preview_item").each((_, el) => {
const href = $(el).find(".image a").attr("href");
const id = href?.match(/\/g\/(\d+)\//)?.[1];
if (!id) return;
const href = $el.find(".image a").attr("href") || "";
const id = href.match(/\d+/)?.[0] || null;
let img = $(el).find(".image img").attr("data-src") || $(el).find(".image img").attr("src") || "";
if (img.startsWith("//")) img = "https:" + img;
const img = $el.find(".image img");
const raw = img.attr("data-src") || img.attr("src") || "";
let image = raw.startsWith("//") ? "https:" + raw : raw;
const sampleImageUrl = image.replace("thumb", "cover");
image = image.replace(/[^\/]+$/, "1.jpg");
const title = ($el.find(".cpt h2.caption").text() || "").trim();
const tagsRaw = $el.attr("data-tags") || "";
const tags = tagsRaw.split(" ").filter(Boolean);
const image = img.replace("thumb.jpg", "1.jpg");
const title = $(el).find("h2.caption").text().trim();
results.push({
id,
image,
sampleImageUrl,
title,
tags,
rating: null,
type: "book"
});
});
const hasNextPage = $('ul.pagination a.page-link').filter((_, el) => $(el).text().trim().toLowerCase() === "next").length > 0;
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 .tag_list .badge.tag")
.map((_, el) => $(el).clone().children().remove().end().text().trim())
.get()
.join(", ");
return {
results,
hasNextPage,
page
id,
title: $("h1").first().text().trim(),
format: "MANGA",
score: 0,
genres,
status: "unknown",
published: "???",
summary: "",
chapters: 1,
image
};
}
async findChapters(mangaId) {
const res = await this.fetch(`${this.baseUrl}/g/${mangaId}/`);
const html = await res.text();
const html = await fetch(`${this.baseUrl}/g/${mangaId}/`).then(r => r.text());
const $ = this.cheerio.load(html);
const title = $(".right .info h1").first().text().trim() || "";
const title = $("h1").first().text().trim() || "Chapter 1";
let cover = $(".cover img").attr("data-src") || $(".cover img").attr("src") || "";
if (cover.startsWith("//")) cover = "https:" + cover;
let thumb = $(".gallery img").first().attr("data-src") || "";
if (thumb.startsWith("//")) thumb = "https:" + thumb;
const firstThumb = $('.gallery a img').first();
let t = firstThumb.attr("data-src") || "";
const base = thumb.match(/https:\/\/[^\/]+\/\d+\/\d+\//)?.[0];
const pages = parseInt($(".pages").text().match(/\d+/)?.[0] || "0");
const ext = thumb.match(/\.(jpg|png|jpeg|gif)/i)?.[1] || "jpg";
if (t.startsWith("//")) t = "https:" + t;
const chapterId = Buffer.from(JSON.stringify({ base, pages, ext })).toString("base64");
// ex: https://images.asmhentai.com/017/598614/8t.jpg
const baseMatch = t.match(/https:\/\/[^\/]+\/\d+\/\d+\//);
const basePath = baseMatch ? baseMatch[0] : null;
const pagesText = $(".pages h3").text(); // "Pages: 39"
const pagesMatch = pagesText.match(/(\d+)/);
const pages = pagesMatch ? parseInt(pagesMatch[1]) : 0;
let ext = "jpg";
const extMatch = t.match(/\.(jpg|png|jpeg|gif)/i);
if (extMatch) ext = extMatch[1];
let language = "unknown";
const langFlag = $('.info a[href^="/language/"] img').attr("src") || "";
if (langFlag.includes("en")) language = "english";
if (langFlag.includes("jp")) language = "japanese";
const encodedChapterId = Buffer.from(
JSON.stringify({
base: basePath,
pages,
ext
})
).toString("base64");
return {
chapters: [
{
id: encodedChapterId,
title,
chapter: 1,
index: 0,
language
}
],
cover
};
return [{
id: chapterId,
title,
number: 1,
releaseDate: null,
index: 0
}];
}
async findChapterPages(chapterId) {
const decoded = JSON.parse(
const { base, pages, ext } = JSON.parse(
Buffer.from(chapterId, "base64").toString("utf8")
);
const { base, pages, ext } = decoded;
return Array.from({ length: pages }, (_, i) => ({
url: `${base}${i + 1}.${ext}`,
index: i,
index: i
}));
}
}
module.exports = { asmhentai };
module.exports = asmhentai;