class Gelbooru { baseUrl = "https://gelbooru.com"; constructor() { this.type = "image-board"; this.version = "1.0" } async search(query = "thighs", page = 1, perPage = 42) { const url = `${this.baseUrl}/index.php?page=post&s=list&tags=${encodeURIComponent(query)}&pid=${(page - 1) * perPage}`; const html = await fetch(url, { headers: { "User-Agent": "Mozilla/5.0" } }).then(r => r.text()); const $ = this.cheerio.load(html); const results = []; $("article.thumbnail-preview > a[id^='p']").each((_, el) => { const id = $(el).attr("id")?.slice(1); // p13123834 → 13123834 if (!id) return; const img = $(el).find("img"); const image = img.attr("src"); const tags = img.attr("alt") ?.replace(/^Rule 34 \|\s*/, "") ?.split(",") ?.map(t => t.trim()) ?.filter(Boolean) || []; results.push({ id, image, tags }); }); // pagination const totalPages = Math.max( page, ...$("a[href*='pid=']") .map((_, el) => Math.floor( parseInt($(el).attr("href")?.match(/pid=(\d+)/)?.[1] || 0) / perPage ) + 1 ) .get() ); return { results, page, hasNextPage: page < totalPages }; } async getInfo(id) { const html = await fetch( `${this.baseUrl}/index.php?page=post&s=view&id=${id}`, { headers: { "User-Agent": "Mozilla/5.0" } } ).then(r => r.text()); const $ = this.cheerio.load(html); const container = $("section.image-container"); let image = container.find("#image").attr("src") || container.attr("data-file-url") || container.attr("data-large-file-url") || null; // tags const tags = container .attr("data-tags") ?.trim() ?.split(/\s+/) ?.filter(Boolean) || []; return { id, image, tags }; } } module.exports = Gelbooru;