class ZeroChan { baseUrl = "https://zerochan.net"; constructor() { this.type = "image-board"; this.version = "1.0" } async search(query = "thighs", page = 1, perPage = 48) { const url = `${this.baseUrl}/${query.trim().replace(/\s+/g, "+")}?p=${page}`; const { result } = await this.scrape( url, async (page) => { return page.evaluate(() => { const list = document.querySelectorAll("#thumbs2 li"); if (list.length === 0) { return {results: [], hasNextPage: false}; } const results = []; list.forEach(li => { const id = li.getAttribute("data-id"); if (!id) return; const img = li.querySelector("img"); const imgUrl = img?.getAttribute("data-src") || img?.getAttribute("src") || null; if (!imgUrl) return; const tagLinks = li.querySelectorAll("p a"); const tags = [...tagLinks] .map(a => a.textContent.trim()) .filter(Boolean); results.push({ id, image: imgUrl, tags, }); }); const hasNextPage = document.querySelector('nav.pagination a[rel="next"]') !== null; return {results, hasNextPage}; }); }, { waitSelector: "#thumbs2 li", timeout: 15000, renderWaitTime: 3000, loadImages: true } ); return { results: result.results.map(r => ({ id: r.id, image: r.image, tags: r.tags })), hasNextPage: result.hasNextPage, page }; } async getInfo(id) { const url = `${this.baseUrl}/${id}`; const { result } = await this.scrape( url, async (page) => { return page.evaluate(() => { const preview = document.querySelector("a.preview"); if (!preview) { return { fullImage: null, tags: [], createdAt: Date.now() }; } const fullImage = preview.getAttribute("href") || null; const img = preview.querySelector("img"); const alt = img?.getAttribute("alt") || ""; let tags = []; if (alt.startsWith("Tags:")) { tags = alt .replace("Tags:", "") .split(",") .map(t => t.trim()) .filter(Boolean); } return { fullImage, tags, createdAt: Date.now() }; }); }, { waitSelector: "a.preview img", timeout: 15000 } ); return { id, image: result.fullImage, tags: result.tags }; } } module.exports = ZeroChan;