cth / app.js
newservers's picture
Update app.js
8f5921b verified
Raw
History Blame Contribute Delete
1.77 kB
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}`));