autosung
Version:
A library to fetch insults and get eBay autosuggestions.
137 lines (115 loc) • 4.7 kB
JavaScript
// 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);
}