import express from 'express'; import cors from 'cors'; import dotenv from 'dotenv'; import request from 'node-superfetch'; import { decode as decodeHTML } from 'html-entities'; dotenv.config(); const app = express(); app.use(express.json()); app.use(cors()); app.get('/', async (req, res) => { return res.status(200).json({ success: true, message: 'Game' }); }); const regions = ['en', 'ar', 'cn', 'de', 'es', 'fr', 'il', 'it', 'jp', 'kr', 'nl', 'pt', 'ru', 'tr', 'id']; const answersMap = { A: 'Yes', B: 'No', C: 'Don\'t know', D: 'Probably', E: 'Probably not' }; class Akinator { constructor(region, childMode = false) { if (!regions.includes(region.toLowerCase())) throw new TypeError('Invalid region.'); this.region = region.toLowerCase(); this.childMode = Boolean(childMode); this.currentStep = 0; this.stepLastProposition = ''; this.progress = '0.00000'; this.answers = Object.keys(answersMap); this.question = null; this.session = null; this.signature = null; this.guessed = null; this.akiWin = null; } async start() { try { console.log(`[Akinator] Memulai game di region: ${this.region}`); const { text } = await request .post(`https://${this.region}.akinator.com/game`) .send({ sid: '1', cm: this.childMode }); this.question = text.match(/

(.+)<\/p>/)[1]; this.session = text.match(/session: '(.+)'/)[1]; this.signature = text.match(/signature: '(.+)'/)[1]; this.answers = { A: decodeHTML(text.match(/(.+)<\/a>/)[1]), B: decodeHTML(text.match(/(.+)<\/a>/)[1]), C: decodeHTML(text.match(/(.+)<\/a>/)[1]), D: decodeHTML(text.match(/(.+)<\/a>/)[1]), E: decodeHTML(text.match(/(.+)<\/a>/)[1]) }; console.log(`[Akinator] Game dimulai! Pertanyaan pertama: ${this.question}`); return this; } catch (error) { console.error('[Akinator] Gagal memulai game:', error); throw error; } } async step(inputAnswer) { try { const answerText = answersMap[inputAnswer] ?? answersMap.C; console.log(`[Akinator] Jawaban: ${inputAnswer} -> ${answerText}`); const { body } = await request .post(`https://${this.region}.akinator.com/answer`) .send({ step: this.currentStep.toString(), progression: this.progress, sid: '1', cm: this.childMode, answer: answerText, step_last_proposition: this.stepLastProposition, session: this.session, signature: this.signature }); if (body.id_proposition) { this.guessed = { id: body.id_proposition, name: body.name_proposition, description: body.description_proposition, photo: body.photo }; console.log(`[Akinator] Tebakan: ${this.guessed.name}`); return this; } this.currentStep++; this.progress = body.progression; this.question = body.question; console.log(`[Akinator] Langkah: ${this.currentStep}, Pertanyaan: ${this.question}`); return this; } catch (error) { console.error('[Akinator] Gagal mengirim jawaban:', error); throw error; } } async back() { try { console.log(`[Akinator] Kembali ke langkah sebelumnya (${this.currentStep - 1})`); const { body } = await request .post(`https://${this.region}.akinator.com/cancel_answer`) .send({ step: this.currentStep.toString(), progression: this.progress, sid: '1', cm: this.childMode, session: this.session, signature: this.signature }); this.currentStep--; this.progress = body.progression; this.question = body.question; console.log(`[Akinator] Kembali ke langkah ${this.currentStep}, Pertanyaan: ${this.question}`); return this; } catch (error) { console.error('[Akinator] Gagal kembali ke langkah sebelumnya:', error); throw error; } } async guess(correct, keepGoing) { try { if (correct) { this.akiWin = true; console.log('[Akinator] Tebakan benar!'); return this; } if (!correct && keepGoing) { console.log('[Akinator] Tebakan salah, lanjut mencari...'); const { body } = await request .post(`https://${this.region}.akinator.com/exclude`) .send({ step: this.currentStep.toString(), sid: '1', cm: this.childMode, progression: this.progress, session: this.session, signature: this.signature }); this.guessed = null; this.stepLastProposition = body.step; this.progress = body.progression; this.question = body.question; console.log(`[Akinator] Lanjut ke pertanyaan berikutnya: ${this.question}`); return this; } this.akiWin = false; console.log('[Akinator] Tebakan salah, permainan selesai.'); return this; } catch (error) { console.error('[Akinator] Gagal menebak:', error); throw error; } } } const games = new Map(); // Simpan sesi permainan berdasarkan ID pengguna // Cek daftar region yang tersedia app.get('/regions', (req, res) => res.json({ regions })); // Mulai permainan app.get('/start', async (req, res) => { const userId = req.query.userId || 'default'; const region = regions.includes(req.query.region) ? req.query.region : 'id'; try { const akinator = new Akinator(region); await akinator.start(); games.set(userId, akinator); res.json({ question: akinator.question, answers: akinator.answers }); } catch (error) { res.status(500).json({ error: 'Gagal memulai permainan.', details: error.message }); } }); // Jawab pertanyaan app.get('/step', async (req, res) => { const userId = req.query.userId || 'default'; const answer = ['A', 'B', 'C', 'D', 'E'].includes(req.query.answer) ? req.query.answer : 'C'; const akinator = games.get(userId); if (!akinator) return res.status(404).json({ error: 'Permainan tidak ditemukan.' }); try { await akinator.step(answer); res.json({ question: akinator.question, answers: akinator.answers, progress: akinator.progress }); } catch (error) { res.status(500).json({ error: 'Gagal melanjutkan permainan.', details: error.message }); } }); // Kembali ke pertanyaan sebelumnya app.get('/back', async (req, res) => { const userId = req.query.userId || 'default'; const akinator = games.get(userId); if (!akinator) return res.status(404).json({ error: 'Permainan tidak ditemukan.' }); try { await akinator.back(); res.json({ question: akinator.question, answers: akinator.answers, progress: akinator.progress }); } catch (error) { res.status(500).json({ error: 'Gagal kembali ke pertanyaan sebelumnya.', details: error.message }); } }); // Menebak jawaban app.get('/guess', async (req, res) => { const userId = req.query.userId || 'default'; const correct = req.query.correct === 'true' ? true : false; const keepGoing = req.query.keepGoing === 'true' ? true : false; const akinator = games.get(userId); if (!akinator) return res.status(404).json({ error: 'Permainan tidak ditemukan.' }); try { await akinator.guess(correct, keepGoing); res.json( akinator.akiWin ? { result: 'Akinator menang!', guessed: akinator.guessed } : keepGoing ? { question: akinator.question, answers: akinator.answers, progress: akinator.progress } : { result: 'Akinator kalah!' } ); } catch (error) { res.status(500).json({ error: 'Gagal menebak.', details: error.message }); } }); const PORT = process.env.PORT || 7860; app.listen(PORT, async () => { console.log(`Server running on port ${PORT}`); }); process.on('SIGINT', async () => { process.exit(0); });