const express = require('express'); const axios = require('axios'); const crypto = require('crypto'); const app = express(); const PORT = process.env.PORT || 5000; app.use(express.static('public')); app.use(express.json()); const CACHE = {}; // simple in-memory store function shuffle(arr) { for (let i = arr.length - 1; i > 0; i--) { const j = Math.floor(crypto.randomInt(0, i + 1)); [arr[i], arr[j]] = [arr[j], arr[i]]; } return arr; } async function getImages() { const catCount = crypto.randomInt(2, 5); // 2 to 4 cats const dogCount = 9 - catCount; const [cats, dogs] = await Promise.all([ axios.get(`https://api.thecatapi.com/v1/images/search?limit=${catCount}`), axios.get(`https://dog.ceo/api/breeds/image/random/${dogCount}`) ]); const images = [ ...cats.data.map(img => ({ url: img.url, type: 'cat' })), ...dogs.data.message.map(url => ({ url, type: 'dog' })) ]; return shuffle(images); } app.get('/captcha', async (req, res) => { try { const images = await getImages(); const id = crypto.randomUUID(); CACHE[id] = images.filter(i => i.type === 'cat').map(i => i.url); setTimeout(() => delete CACHE[id], 3 * 60 * 1000); res.json({ id, images: images.map(i => i.url) }); } catch (err) { res.status(500).json({ error: 'Image fetch failed' }); } }); app.post('/verify', (req, res) => { const { id, selections } = req.body; if (!CACHE[id]) return res.json({ success: false, reason: 'expired' }); const correct = CACHE[id]; delete CACHE[id]; const matched = selections.every(sel => correct.includes(sel)) && selections.length === correct.length; res.json({ success: matched }); }); app.listen(PORT, () => console.log(`Server running at http://localhost:${PORT}`));