silent-akinator-pro 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +89 -10
  3. package/index.d.ts +26 -0
  4. package/index.js +234 -75
  5. package/package.json +62 -7
package/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) Silent Tech
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
package/README.md CHANGED
@@ -1,18 +1,97 @@
1
- # 🧞 SILENT-AKINATOR PRO 🧞
2
- ### BY SILENT TECH
1
+ # silent-akinator-pro
3
2
 
4
- The most reliable Akinator API for developers.
3
+ > 🧞 **The working Akinator API wrapper for Node.js** — fast, reliable, Cloudflare-safe. Modern Akinator client by **Silent Tech**.
5
4
 
6
- ## 🚀 INSTALL
7
- `npm install silent-akinator-pro`
5
+ [![npm](https://img.shields.io/npm/v/silent-akinator-pro.svg)](https://www.npmjs.com/package/silent-akinator-pro)
6
+ [![downloads](https://img.shields.io/npm/dm/silent-akinator-pro.svg)](https://www.npmjs.com/package/silent-akinator-pro)
7
+ [![license](https://img.shields.io/npm/l/silent-akinator-pro.svg)](LICENSE)
8
8
 
9
- ## đŸ’ģ USAGE
10
- ```javascript
9
+ The most up-to-date **Akinator** Node.js wrapper that actually works in 2026. Bypasses the Cloudflare `403` by using the official HTML form endpoints with realistic browser headers and a full cookie jar — no third-party proxies, no API keys.
10
+
11
+ ## Why silent-akinator-pro?
12
+
13
+ - ✅ **Working** — fixed the `403 Forbidden` / Cloudflare issue that broke every other akinator npm package
14
+ - ⚡ **Fast** — zero heavy dependencies (only `tough-cookie`)
15
+ - 🌍 **16 regions** — `en`, `fr`, `es`, `de`, `it`, `pt`, `ru`, `ar`, `jp`, `kr`, `cn`, `nl`, `pl`, `tr`, `il`, `id`
16
+ - 🧒 **Child mode** supported
17
+ - â†Šī¸ **Undo / back / continue / win** all supported
18
+ - 🤖 **Discord bot / Telegram bot / WhatsApp bot ready**
19
+ - 📘 **TypeScript types** included
20
+ - 🆓 **MIT** licensed
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ npm install silent-akinator-pro
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ```js
11
31
  const { Akinator } = require('silent-akinator-pro');
12
- const api = new Akinator({ region: 'en', childMode: false });
13
32
 
14
33
  (async () => {
15
- await api.start();
16
- console.log(api.question);
34
+ const aki = new Akinator({ region: 'en', childMode: false });
35
+ await aki.start();
36
+
37
+ console.log(aki.question);
38
+ await aki.answer('y'); // y / n / idk / p / pn (or 0-4)
39
+ console.log(aki.question);
40
+
41
+ while (!aki.guessed && aki.step < 80) {
42
+ await aki.answer('idk');
43
+ }
44
+
45
+ if (aki.guessed) {
46
+ console.log('Akinator thinks of:', aki.guess.name);
47
+ await aki.win();
48
+ }
17
49
  })();
18
50
  ```
51
+
52
+ ## API
53
+
54
+ ### `new Akinator({ region, childMode })`
55
+ - `region` — `en | fr | es | de | it | pt | ru | ar | jp | kr | cn | nl | pl | tr | il | id`
56
+ - `childMode` — `boolean`
57
+
58
+ ### Methods
59
+ | Method | Description |
60
+ |---------------|----------------------------------------------|
61
+ | `start()` | Begin a new game |
62
+ | `answer(a)` | `y` / `n` / `idk` / `p` / `pn` (or `0-4`) |
63
+ | `back()` | Undo the previous answer |
64
+ | `continue()` | Reject the current guess and keep playing |
65
+ | `win()` | Confirm the guess and end the game |
66
+
67
+ ### Properties
68
+ `question`, `step`, `progression`, `guess`, `guessed`, `finished`.
69
+
70
+ ## Discord bot example
71
+
72
+ ```js
73
+ const { Akinator } = require('silent-akinator-pro');
74
+ const games = new Map();
75
+
76
+ client.on('messageCreate', async (msg) => {
77
+ if (msg.content === '!aki') {
78
+ const aki = new Akinator({ region: 'en' });
79
+ await aki.start();
80
+ games.set(msg.author.id, aki);
81
+ msg.reply(aki.question);
82
+ } else if (['y','n','idk','p','pn'].includes(msg.content)) {
83
+ const aki = games.get(msg.author.id);
84
+ if (!aki) return;
85
+ await aki.answer(msg.content);
86
+ if (aki.guessed) msg.reply(`Is it **${aki.guess.name}**? (${aki.guess.description})`);
87
+ else msg.reply(aki.question);
88
+ }
89
+ });
90
+ ```
91
+
92
+ ## Keywords
93
+ akinator, akinator api, akinator nodejs, akinator wrapper, akinator client, akinator bot, akinator discord, akinator 2026, working akinator, akinator cloudflare, silent tech, silent-akinator, silent-akinator-pro, twenty questions, character guessing game, genie api.
94
+
95
+ ## License
96
+
97
+ MIT Š **Silent Tech**
package/index.d.ts ADDED
@@ -0,0 +1,26 @@
1
+
2
+ export interface AkinatorOptions {
3
+ region?: 'en'|'ar'|'cn'|'de'|'es'|'fr'|'il'|'it'|'jp'|'kr'|'nl'|'pl'|'pt'|'ru'|'tr'|'id';
4
+ childMode?: boolean;
5
+ }
6
+ export interface AkinatorGuess {
7
+ id?: string; name?: string; description?: string; photo?: string; pseudo?: string;
8
+ }
9
+ export class Akinator {
10
+ constructor(opts?: AkinatorOptions);
11
+ region: string;
12
+ childMode: boolean;
13
+ question: string | null;
14
+ step: number;
15
+ progression: string;
16
+ guess: AkinatorGuess | null;
17
+ guessed: boolean;
18
+ finished: boolean;
19
+ start(): Promise<this>;
20
+ answer(a: 'y'|'n'|'idk'|'p'|'pn'|0|1|2|3|4|string|number): Promise<this>;
21
+ back(): Promise<this>;
22
+ continue(): Promise<this>;
23
+ win(): Promise<AkinatorGuess>;
24
+ }
25
+ export const REGIONS: Record<string,string>;
26
+ export default Akinator;
package/index.js CHANGED
@@ -1,86 +1,245 @@
1
- const axios = require('axios');
1
+
2
+ 'use strict';
3
+ /*!
4
+ * silent-akinator-pro
5
+ * Working Akinator API wrapper (HTML-form endpoints, Cloudflare-safe).
6
+ * (c) Silent Tech — MIT
7
+ */
8
+ const { CookieJar } = require('tough-cookie');
9
+ const https = require('https');
10
+ const { URL, URLSearchParams } = require('url');
11
+
12
+ const REGIONS = {
13
+ en: 'en', ar: 'ar', cn: 'cn', de: 'de', es: 'es', fr: 'fr',
14
+ il: 'il', it: 'it', jp: 'jp', kr: 'kr', nl: 'nl', pl: 'pl',
15
+ pt: 'pt', ru: 'ru', tr: 'tr', id: 'id'
16
+ };
17
+
18
+ const ANSWER_MAP = {
19
+ y: 0, yes: 0, '0': 0,
20
+ n: 1, no: 1, '1': 1,
21
+ idk: 2, "don't know": 2, dk: 2, '2': 2,
22
+ p: 3, probably: 3, '3': 3,
23
+ pn: 4, 'probably not': 4, '4': 4
24
+ };
25
+
26
+ const UA =
27
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' +
28
+ '(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36';
29
+
30
+ function request(method, urlStr, { headers = {}, body = null, jar } = {}) {
31
+ return new Promise((resolve, reject) => {
32
+ const u = new URL(urlStr);
33
+ const cookieHeader = jar ? jar.getCookieStringSync(urlStr) : '';
34
+ const opts = {
35
+ method,
36
+ hostname: u.hostname,
37
+ path: u.pathname + u.search,
38
+ headers: {
39
+ 'User-Agent': UA,
40
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
41
+ 'Accept-Language': 'en-US,en;q=0.9',
42
+ 'Accept-Encoding': 'identity',
43
+ 'Referer': `https://${u.hostname}/`,
44
+ 'Origin': `https://${u.hostname}`,
45
+ ...(cookieHeader ? { Cookie: cookieHeader } : {}),
46
+ ...headers
47
+ }
48
+ };
49
+ if (body) {
50
+ opts.headers['Content-Type'] = 'application/x-www-form-urlencoded';
51
+ opts.headers['Content-Length'] = Buffer.byteLength(body);
52
+ opts.headers['X-Requested-With'] = 'XMLHttpRequest';
53
+ }
54
+ const req = https.request(opts, (res) => {
55
+ const chunks = [];
56
+ res.on('data', (c) => chunks.push(c));
57
+ res.on('end', () => {
58
+ const data = Buffer.concat(chunks).toString('utf8');
59
+ if (jar && res.headers['set-cookie']) {
60
+ for (const c of res.headers['set-cookie']) {
61
+ try { jar.setCookieSync(c, urlStr); } catch (_) {}
62
+ }
63
+ }
64
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
65
+ const next = new URL(res.headers.location, urlStr).toString();
66
+ return resolve(request('GET', next, { jar, headers }));
67
+ }
68
+ resolve({ status: res.statusCode, headers: res.headers, body: data });
69
+ });
70
+ });
71
+ req.on('error', reject);
72
+ if (body) req.write(body);
73
+ req.end();
74
+ });
75
+ }
76
+
77
+ function extract(html, re) {
78
+ const m = html.match(re);
79
+ return m ? m[1] : null;
80
+ }
2
81
 
3
82
  class Akinator {
4
- constructor(config = { region: 'en', childMode: false }) {
5
- this.region = config.region || 'en';
6
- this.childMode = config.childMode || false;
7
- this.baseUrl = `https://${this.region}.akinator.com`;
8
- this.session = null;
9
- this.signature = null;
10
- this.step = 0;
11
- this.progress = 0;
12
- this.question = null;
13
- this.isWin = false;
14
- this.sugestion_name = null;
15
- this.sugestion_desc = null;
16
- this.sugestion_photo = null;
17
-
18
- // 🚀 MOBILE SPOOFING HEADERS
19
- this.headers = {
20
- 'User-Agent': 'Akinator/1.2.3 (Android; 13; Scale/2.0)',
21
- 'X-Requested-With': 'com.digidust.akinator.freemium',
22
- 'Accept': 'application/json',
23
- 'Referer': `https://${this.region}.akinator.com/`
24
- };
83
+ constructor(opts = {}) {
84
+ this.region = REGIONS[(opts.region || 'en').toLowerCase()] || 'en';
85
+ this.childMode = !!opts.childMode;
86
+ this.host = `https://${this.region}.akinator.com`;
87
+ this.jar = new CookieJar();
88
+
89
+ this.session = null;
90
+ this.signature = null;
91
+ this.question = null;
92
+ this.step = 0;
93
+ this.progression = '0.00000';
94
+ this.guess = null;
95
+ this.guessed = false;
96
+ this.finished = false;
97
+ }
98
+
99
+ async start() {
100
+ // 1. warm-up to set Cloudflare cf_clearance / __cf_bm cookies
101
+ await request('GET', this.host + '/', { jar: this.jar });
102
+
103
+ // 2. fetch the game page (the HTML form gives us session + signature)
104
+ const url = `${this.host}/game?cm=${this.childMode ? 'true' : 'false'}`;
105
+ const r = await request('GET', url, { jar: this.jar });
106
+ if (r.status !== 200) {
107
+ throw new Error(`Akinator start failed (${r.status}). Region "${this.region}" may be blocked — try another region.`);
25
108
  }
26
109
 
27
- async start() {
28
- console.log("💀 SILENT TECH ENGINE v2.0: BOOTING...");
29
- try {
30
- const res = await axios.get(`${this.baseUrl}/new_session`, {
31
- params: { childMod: this.childMode, player: 'website-desktop' },
32
- headers: this.headers
33
- });
34
- const data = res.data.parameters;
35
- this.session = data.identification.session;
36
- this.signature = data.identification.signature;
37
- this.question = data.step_information.question;
38
- console.log("✅ SILENT TECH: Handshake Successful.");
39
- return this;
40
- } catch (e) {
41
- throw new Error("Cloudflare Block: Akinator rejected the connection.");
42
- }
110
+ this.session = extract(r.body, /#session['"]?\s*value=['"]([^'"]+)/i)
111
+ || extract(r.body, /name=['"]session['"][^>]*value=['"]([^'"]+)/i)
112
+ || extract(r.body, /var\s+session\s*=\s*['"]([^'"]+)/i);
113
+ this.signature = extract(r.body, /#signature['"]?\s*value=['"]([^'"]+)/i)
114
+ || extract(r.body, /name=['"]signature['"][^>]*value=['"]([^'"]+)/i)
115
+ || extract(r.body, /var\s+signature\s*=\s*['"]([^'"]+)/i);
116
+ this.question = extract(r.body, /<p[^>]*class=['"][^'"]*question-text[^'"]*['"][^>]*>([^<]+)<\/p>/i)
117
+ || extract(r.body, /id=['"]question-label['"][^>]*>([^<]+)</i);
118
+ this.step = 0;
119
+ this.progression = '0.00000';
120
+
121
+ if (!this.session || !this.signature) {
122
+ throw new Error('Could not parse session/signature from Akinator page. The site layout may have changed.');
43
123
  }
124
+ return this;
125
+ }
44
126
 
45
- async answer(ansId) {
46
- try {
47
- const res = await axios.get(`${this.baseUrl}/answer`, {
48
- params: {
49
- session: this.session,
50
- signature: this.signature,
51
- step: this.step,
52
- answer: ansId
53
- },
54
- headers: this.headers
55
- });
56
- const data = res.data.parameters;
57
- this.step++;
58
- this.progress = parseFloat(data.progression);
59
- this.question = data.question;
60
-
61
- if (this.progress >= 95) {
62
- await this.getWinner();
63
- }
64
- return this;
65
- } catch (e) {
66
- throw new Error("Lost connection to Akinator servers.");
67
- }
127
+ _answerCode(a) {
128
+ if (typeof a === 'number') a = String(a);
129
+ const code = ANSWER_MAP[String(a).toLowerCase().trim()];
130
+ if (code === undefined) throw new Error(`Invalid answer "${a}". Use y / n / idk / p / pn.`);
131
+ return code;
132
+ }
133
+
134
+ async answer(a) {
135
+ if (this.finished) throw new Error('Game already finished.');
136
+ const ans = this._answerCode(a);
137
+ const body = new URLSearchParams({
138
+ step: String(this.step),
139
+ progression: String(this.progression),
140
+ sid: '1',
141
+ cm: this.childMode ? 'true' : 'false',
142
+ answer: String(ans),
143
+ step_last_proposition: '',
144
+ session: this.session,
145
+ signature: this.signature
146
+ }).toString();
147
+
148
+ const r = await request('POST', this.host + '/answer', { jar: this.jar, body });
149
+ let data;
150
+ try { data = JSON.parse(r.body); }
151
+ catch { throw new Error(`Akinator answer failed (status ${r.status}). Response was not JSON.`); }
152
+
153
+ if (data.completion && data.completion !== 'OK' && data.completion !== 'KO - TIMEOUT') {
154
+ // proposal step (Akinator wants to guess)
155
+ if (data.id_proposition || data.name_proposition) {
156
+ this.guess = {
157
+ id: data.id_proposition,
158
+ name: data.name_proposition,
159
+ description: data.description_proposition,
160
+ photo: data.photo,
161
+ pseudo: data.pseudo
162
+ };
163
+ this.guessed = true;
164
+ return this;
165
+ }
68
166
  }
69
167
 
70
- async getWinner() {
71
- const res = await axios.get(`${this.baseUrl}/list`, {
72
- params: { session: this.session, signature: this.signature, step: this.step },
73
- headers: this.headers
74
- });
75
- const elements = res.data.parameters.elements;
76
- if (elements && elements.length > 0) {
77
- this.isWin = true;
78
- const char = elements[0].element;
79
- this.sugestion_name = char.name;
80
- this.sugestion_desc = char.description;
81
- this.sugestion_photo = char.absolute_picture_path;
82
- }
168
+ if (data.id_proposition || data.name_proposition) {
169
+ this.guess = {
170
+ id: data.id_proposition,
171
+ name: data.name_proposition,
172
+ description: data.description_proposition,
173
+ photo: data.photo,
174
+ pseudo: data.pseudo
175
+ };
176
+ this.guessed = true;
177
+ return this;
83
178
  }
179
+
180
+ this.question = data.question || this.question;
181
+ this.step = parseInt(data.step ?? this.step + 1, 10);
182
+ this.progression = data.progression || this.progression;
183
+ this.guessed = false;
184
+ this.guess = null;
185
+ return this;
186
+ }
187
+
188
+ async back() {
189
+ if (this.step <= 0) throw new Error('Cannot go back from step 0.');
190
+ const body = new URLSearchParams({
191
+ step: String(this.step),
192
+ progression: String(this.progression),
193
+ sid: '1',
194
+ cm: this.childMode ? 'true' : 'false',
195
+ session: this.session,
196
+ signature: this.signature
197
+ }).toString();
198
+ const r = await request('POST', this.host + '/cancel_answer', { jar: this.jar, body });
199
+ const data = JSON.parse(r.body);
200
+ this.question = data.question || this.question;
201
+ this.step = parseInt(data.step ?? Math.max(0, this.step - 1), 10);
202
+ this.progression = data.progression || this.progression;
203
+ this.guessed = false;
204
+ this.guess = null;
205
+ return this;
206
+ }
207
+
208
+ async continue() {
209
+ if (!this.guessed) throw new Error('No active guess to reject.');
210
+ const body = new URLSearchParams({
211
+ step: String(this.step),
212
+ progression: '10',
213
+ sid: '1',
214
+ cm: this.childMode ? 'true' : 'false',
215
+ session: this.session,
216
+ signature: this.signature
217
+ }).toString();
218
+ const r = await request('POST', this.host + '/exclude', { jar: this.jar, body });
219
+ const data = JSON.parse(r.body);
220
+ this.question = data.question || this.question;
221
+ this.step = parseInt(data.step ?? this.step + 1, 10);
222
+ this.progression = data.progression || this.progression;
223
+ this.guessed = false;
224
+ this.guess = null;
225
+ return this;
226
+ }
227
+
228
+ async win() {
229
+ if (!this.guessed) throw new Error('No guess to confirm.');
230
+ const body = new URLSearchParams({
231
+ sid: '1',
232
+ charac_name: this.guess.name || '',
233
+ charac_desc: this.guess.description || '',
234
+ session: this.session,
235
+ signature: this.signature,
236
+ pflag_photo: '0'
237
+ }).toString();
238
+ await request('POST', this.host + '/choice', { jar: this.jar, body });
239
+ this.finished = true;
240
+ return this.guess;
241
+ }
84
242
  }
85
243
 
86
- module.exports = { Akinator };
244
+ module.exports = { Akinator, REGIONS };
245
+ module.exports.default = Akinator;
package/package.json CHANGED
@@ -1,12 +1,67 @@
1
1
  {
2
2
  "name": "silent-akinator-pro",
3
- "version": "2.0.0",
4
- "description": "Standalone High-Speed Akinator SDK. Bypasses Cloudflare using Mobile-Handshake logic. No dependencies required.",
3
+ "version": "3.0.0",
4
+ "description": "Akinator API wrapper for Node.js \u2014 fast, working, Cloudflare-safe. The genie that guesses any character. Modern Akinator client with full region, child-mode, undo, and guess-confirm support. (silent-tech)",
5
5
  "main": "index.js",
6
- "keywords": ["akinator", "aki", "silent-tech", "baileys", "wa-bot", "cloudflare-bypass"],
7
- "author": "Silent Tech",
6
+ "types": "index.d.ts",
7
+ "type": "commonjs",
8
+ "scripts": {
9
+ "test": "node test.js"
10
+ },
11
+ "keywords": [
12
+ "akinator",
13
+ "akinator-api",
14
+ "akinator-wrapper",
15
+ "akinator-client",
16
+ "akinator-node",
17
+ "akinator-js",
18
+ "akinator-bot",
19
+ "akinator-game",
20
+ "silent",
21
+ "silent-tech",
22
+ "silent-akinator",
23
+ "silent-akinator-pro",
24
+ "genie",
25
+ "guess",
26
+ "guessing-game",
27
+ "20-questions",
28
+ "twenty-questions",
29
+ "character-guess",
30
+ "ai-guess",
31
+ "game",
32
+ "api",
33
+ "wrapper",
34
+ "client",
35
+ "cloudflare-bypass",
36
+ "working-akinator",
37
+ "akinator-2025",
38
+ "akinator-2026",
39
+ "discord-bot",
40
+ "telegram-bot",
41
+ "whatsapp-bot",
42
+ "chatbot",
43
+ "fun-api"
44
+ ],
45
+ "author": "Silent Tech <silent.tech.offc@gmail.com>",
8
46
  "license": "MIT",
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://github.com/silent-tech/silent-akinator-pro.git"
50
+ },
51
+ "homepage": "https://www.npmjs.com/package/silent-akinator-pro",
52
+ "bugs": {
53
+ "url": "https://github.com/silent-tech/silent-akinator-pro/issues"
54
+ },
55
+ "engines": {
56
+ "node": ">=14"
57
+ },
9
58
  "dependencies": {
10
- "axios": "^1.6.0"
11
- }
12
- }
59
+ "tough-cookie": "^4.1.4"
60
+ },
61
+ "files": [
62
+ "index.js",
63
+ "index.d.ts",
64
+ "README.md",
65
+ "LICENSE"
66
+ ]
67
+ }