class Rule34 { baseUrl = "https://rule34.xxx"; headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' }; constructor() { this.type = "image-board"; } async search(query = "alisa_mikhailovna_kujou", page = 1, perPage = 42) { const offset = (page - 1) * perPage; const url = `${this.baseUrl}/index.php?page=post&s=list&tags=${query}&pid=${offset}`; const response = await fetch(url, { headers: this.headers }); const data = await response.text(); const $ = this.cheerio.load(data); const results = []; $('.image-list span').each((_, e) => { const $e = $(e); const id = $e.attr('id')?.replace('s', ''); let image = $e.find('img').attr('src'); if (image && !image.startsWith('http')) { image = `https:${image}`; } const tags = $e.find('img') .attr('alt') ?.trim() .split(' ') .filter(Boolean); if (id && image) { results.push({ id, image, tags }); } }); const pagination = $('#paginator .pagination'); const lastPageLink = pagination.find('a[alt="last page"]'); let totalPages = 1; if (lastPageLink.length) { const pid = Number(lastPageLink.attr('href')?.split('pid=')[1] ?? 0); totalPages = Math.ceil(pid / perPage) + 1; } return { page, hasNextPage: page < totalPages, results }; } async getInfo(id) { const url = `${this.baseUrl}/index.php?page=post&s=view&id=${id}`; const resizeCookies = { 'resize-notification': 1, 'resize-original': 1 }; const cookieString = Object.entries(resizeCookies).map(([key, value]) => `${key}=${value}`).join('; '); const fetchHeaders = { ...this.headers }; const resizeHeaders = { ...this.headers, 'cookie': cookieString }; const [resizedResponse, nonResizedResponse] = await Promise.all([ fetch(url, { headers: resizeHeaders }), fetch(url, { headers: fetchHeaders }) ]); const [resized, original] = await Promise.all([resizedResponse.text(), nonResizedResponse.text()]); const $ = this.cheerio.load(original); let fullImage = $('#image').attr('src'); if (fullImage && !fullImage.startsWith('http')) { fullImage = `https:${fullImage}`; } const tags = $('#image').attr('alt')?.trim()?.split(' ').filter(tag => tag !== ""); return { id, image: fullImage, tags }; } } module.exports = Rule34;