UNPKG

autosung

Version:

A library to fetch insults and get eBay autosuggestions.

137 lines (115 loc) 4.7 kB
// insult-autosug.mjs // Node >= 18 (sử dụng global fetch) // Exports functions to fetch insults and call eBay autosug import puppeteer from 'puppeteer-extra'; import StealthPlugin from 'puppeteer-extra-plugin-stealth'; pupeteer.use(StealthPlugin()); const EVIL_URL = 'https://evilinsult.com/generate_insult.php?lang=vi&type=txt'; const AUTOSUG_BASE = 'https://autosug.ebaystatic.com/autosug'; const defaultConfig = { insultCount: 20, delayBetweenCallsMs: [300, 900], autosugTimeoutMs: 8000, maxAutosugResultsPerInsult: 20, userAgentUrl: 'https://raw.githubusercontent.com/shop360000/cookie/refs/heads/main/ua', }; const rand = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; const sleep = ms => new Promise(r => setTimeout(r, ms)); /** fetch a list of user agents */ export async function fetchUserAgents(url) { if (!url) return []; try { const res = await fetch(url); if (!res.ok) return []; const text = await res.text(); return text.split('\n').map(ua => ua.trim()).filter(Boolean); } catch (e) { return []; } } /** fetch one insult (text/plain) using Puppeteer */ export async function fetchInsult(page, userAgent) { try { if (userAgent) { await page.setUserAgent(userAgent); } await page.goto(EVIL_URL, { waitUntil: 'networkidle2' }); const insult = await page.evaluate(() => document.body.textContent); return insult.trim(); } catch (e) { console.error(`Error fetching insult with Puppeteer: ${e.message}`); return null; } } /** call eBay autosug for a keyword, return suggestions array + raw */ export async function fetchAutosug(keyword, cfg = {}, userAgent) { const c = { ...defaultConfig, ...cfg }; try { const url = new URL(AUTOSUG_BASE); url.searchParams.set('kwd', keyword); url.searchParams.set('sId', '0'); url.searchParams.set('_rs', '1'); url.searchParams.set('_richres', '1'); const controller = new AbortController(); const id = setTimeout(() => controller.abort(), c.autosugTimeoutMs); const headers = { 'Accept': 'application/json, text/javascript, */*;q=0.01' }; if (userAgent) { headers['User-Agent'] = userAgent; } const res = await fetch(url.toString(), { signal: controller.signal, headers }); clearTimeout(id); if (!res.ok) return { keyword, suggestions: [], raw: null, status: res.status }; const j = await res.json().catch(() => null); const suggestions = []; if (j && j.res) { if (Array.isArray(j.res.q)) j.res.q.forEach(o => o.kwd && suggestions.push(o.kwd)); if (Array.isArray(j.res.s)) j.res.s.forEach(o => o.kwd && suggestions.push(o.kwd)); } return { keyword, suggestions: suggestions.slice(0, c.maxAutosugResultsPerInsult), raw: j, status: 200 }; } catch (e) { return { keyword, suggestions: [], raw: null, error: e.message }; } } /** * Build list from insults: * - fetch `insultCount` insults * - for each insult call autosug (if autosugPerKeyword true) * - return array of { insult, autosug } */ export async function buildFromInsults(options = {}) { const cfg = { ...defaultConfig, ...options }; const userAgents = await fetchUserAgents(cfg.userAgentUrl); console.log(`Fetched ${userAgents.length} User-Agents.`); const browser = await puppeteer.launch({ headless: true }); const page = await browser.newPage(); const set = new Set(); const results = []; let attempts = 0; while (results.length < cfg.insultCount && attempts < cfg.insultCount * 4) { attempts++; const userAgent = userAgents.length > 0 ? userAgents[rand(0, userAgents.length - 1)] : undefined; if (userAgent) console.log(`[Insult] Using UA: ${userAgent}`); const ins = await fetchInsult(page, userAgent); // polite delay await sleep(rand(...cfg.delayBetweenCallsMs)); if (!ins) continue; const norm = ins.replace(/\s+/g, ' ').trim(); if (set.has(norm)) continue; set.add(norm); const entry = { insult: norm, autosug: null }; if (cfg.autosugPerKeyword !== false) { const autosugUserAgent = userAgents.length > 0 ? userAgents[rand(0, userAgents.length - 1)] : undefined; if (autosugUserAgent) console.log(`[Autosug] Using UA: ${autosugUserAgent}`); entry.autosug = await fetchAutosug(norm, cfg, autosugUserAgent); // short polite delay await sleep(rand(...cfg.delayBetweenCallsMs)); } results.push(entry); } await browser.close(); return results; } /** convenience: extract plain keyword list (insults) from results */ export function extractKeywords(results, limit = 100) { return results.map(r => r.insult).filter(Boolean).slice(0, limit); }