class Tenor { baseUrl = "https://tenor.com"; constructor() { this.type = "image-board"; this.lastQuery = null; this.seenIds = new Set(); this.version = "1.0" } async search(query, page = 1, perPage = 48) { query = query?.trim() || "thighs"; if (query !== this.lastQuery) { this.lastQuery = query; this.seenIds.clear(); } const url = `${this.baseUrl}/search/${query.replaceAll(" ", "-")}-gifs`; const { result } = await this.scrape( url, async (page) => { return page.evaluate(() => { const items = document.querySelectorAll('div.GifList figure, figure'); const results = []; items.forEach(fig => { const link = fig.querySelector('a'); const img = fig.querySelector('img'); if (!link || !img) return; const href = link.getAttribute('href') || ""; const idMatch = href.match(/-(\d+)(?:$|\/?$)/); const id = idMatch ? idMatch[1] : null; const imgUrl = img.getAttribute('src') || img.getAttribute('data-src'); const tagsRaw = img.getAttribute('alt') || ""; const tags = tagsRaw.trim().split(/\s+/).filter(Boolean); if (id && imgUrl && !imgUrl.includes("placeholder")) { results.push({ id, image: imgUrl, sampleImageUrl: imgUrl, tags, type: "preview" }); } }); const uniqueResults = Array.from( new Map(results.map(r => [r.id, r])).values() ); return {results: uniqueResults, hasNextPage: true}; }); }, { waitSelector: "figure", timeout: 30000, scrollToBottom: true, renderWaitTime: 3000, loadImages: true } ); const newResults = result.results.filter(r => !this.seenIds.has(r.id)); newResults.forEach(r => this.seenIds.add(r.id)); return { results: newResults.map(r => ({ id: r.id, image: r.image, tags: r.tags, })), hasNextPage: result.hasNextPage, page }; } async getInfo(id) { const url = `${this.baseUrl}/view/gif-${id}`; const { result } = await this.scrape( url, async (page) => { return page.evaluate(() => { const img = document.querySelector(".Gif img"); const fullImage = img?.src || null; const tags = [...document.querySelectorAll(".tag-list li a .RelatedTag")] .map(t => t.textContent.trim()) .filter(Boolean); return { fullImage, tags }; }); }, { waitSelector: ".Gif img", timeout: 15000 } ); return { id, image: result.fullImage, tags: result.tags, title: result.tags?.join(" ") || `Tenor GIF ${id}`, headers: "" }; } } module.exports = Tenor;