Spaces:
Paused
Paused
| 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}`)); |