npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@irithell-js/akinator

v1.0.0

Published

Akinator game engine

Readme

@irithell-js/akinator

npm version Node.js Version License: MIT Termux Supported

Puppeteer-based programmatic wrapper for the Akinator web game. It extracts game states via DOM evaluation, bypasses mandatory modals, and manages concurrent sessions.

Designed with explicit support for Termux/Android environments using custom bindings for Chromium and SQLite.

Termux & Android Compatibility

Standard Node.js packages relying on pre-compiled binaries (puppeteer, better-sqlite3) fail in Termux due to missing glibc and non-standard filesystem hierarchies.

This module natively resolves these environment constraints:

  • Uses @irithell-js/puppeteer-termux to automatically locate the Android Chromium binary and disable incompatible sandbox flags.
  • Uses @irithell-js/better-sqlite3-termux to provide N-API bindings compiled specifically for Termux architectures.

On standard Linux/Windows hosts, it defaults to standard execution paths.

Installation

npm install @irithell-js/akinator

Multi-Language / Region Support

The engine natively supports 17 regions/languages by routing the Puppeteer instance to the respective localized Akinator subdomains. The initial loading state is automatically translated based on the selected region.

const engine = new AkinatorEngine(storage, {
  region: "en", // Initializes the session in English
  headless: "new",
});

Usage Examples

The package supports both ECMAScript Modules (ESM) and CommonJS (CJS).

TypeScript / ESM

import { AkinatorEngine, SQLiteStorage } from "@irithell-js/akinator";

const storage = new SQLiteStorage("akinator_sessions.db");
const engine = new AkinatorEngine(storage, { region: "pt", headless: "new" });

async function play(sessionId: string) {
  const startRes = await engine.start(sessionId);
  if (!startRes.ok) throw new Error(startRes.reason);

  console.log(`[Step ${startRes.step}] ${startRes.question}`);

  // Answer: 0 (Yes), 1 (No), 2 (Don't Know), 3 (Probably), 4 (Probably Not)
  const answerRes = await engine.answer(sessionId, 0);
  if (!answerRes.ok) throw new Error(answerRes.reason);

  if (answerRes.isWin) {
    console.log("Result:", answerRes.result?.name);
    await engine.end(sessionId);
  }
}

play("session-uuid-1");

CommonJS

const { AkinatorEngine, JSONStorage } = require("@irithell-js/akinator");

const storage = new JSONStorage("./sessions-dir");
const engine = new AkinatorEngine(storage, { maxSessions: 10 });

async function play(sessionId) {
  const startRes = await engine.start(sessionId);
  if (startRes.ok) {
    console.log(startRes.question);
  }
}

play("session-uuid-2");

Architecture & API

AkinatorEngine

The primary facade class. It orchestrates the flow between the storage provider and the Puppeteer scraper. It implements a MutexMap internally, ensuring that multiple async calls for the same sessionId are queued and processed sequentially to prevent Puppeteer context crashes.

  • start(sessionId: string): Initializes a new page or resumes an existing session from storage. Injects localStorage overrides to bypass the theme selection screen.
  • answer(sessionId: string, answer: AkiAnswer): Submits an answer and polls the DOM until the new question renders or the proposal block becomes visible.
  • end(sessionId: string): Closes the specific Puppeteer page and updates the database status to ENDED.
  • destroyAll(): Closes the browser instance and clears the session map.

Storage Implementations

Storage classes implement the StorageProvider interface, allowing developers to write custom adapters (e.g., MongoDB, Redis).

SQLiteStorage

  • Standard relational implementation using better-sqlite3.
  • Creates akinator_games and akinator_answers tables.
  • Best suited for multi-process or high-load environments.

JSONStorage

  • File-based implementation using fs/promises.
  • Stores one .json file per sessionId.
  • I/O Optimization: Implements an in-memory cache with a 2000ms flush debounce. Concurrent writes within the 2-second window mutate the memory state and trigger a single disk write, preventing race conditions and I/O locking.

Types & Interfaces

EngineOptions

Passed to the AkinatorEngine constructor to configure the underlying browser and constraints.

type Region =
  | "en"
  | "ar"
  | "cn"
  | "de"
  | "es"
  | "fr"
  | "il"
  | "it"
  | "jp"
  | "kr"
  | "nl"
  | "pl"
  | "pt"
  | "ru"
  | "tr"
  | "id"
  | "vi";

interface EngineOptions {
  executablePath?: string; // Overrides Chromium path manually
  profileDir?: string; // Persistent directory for browser cache/cookies
  headless?: boolean | "new" | "shell"; // Puppeteer visibility state
  timeoutMs?: number; // TTL for inactive sessions (defaults to 300000ms)
  maxSessions?: number; // Hard limit for concurrent pages (defaults to 6)
  region?: Region; // Game language/region subdomain (defaults to 'pt')
}

AkiAnswer

Numeric mapping for the Akinator DOM inputs.

type AkiAnswer = 0 | 1 | 2 | 3 | 4;
// 0: Yes
// 1: No
// 2: Don't know
// 3: Probably yes
// 4: Probably no

AkiResult

Extracted when the engine detects the #proposeGameBlock element.

interface AkiResult {
  name?: string;
  description?: string;
  photoUrl?: string;
}

AkiState

The standard return payload for a successful engine operation.

interface AkiState {
  question: string;
  isWin: boolean;
  result?: AkiResult; // Populated only if isWin is true
}

Debugging

The module includes an internal logger and a DOM state dumper for debugging navigation failures.

To enable execution logs and force the scraper to save .html and .png dumps when a timeout or DOM error occurs, set the environment variable:

AKINATOR_DEBUG=1 node app.js

Dumps are written to [cwd]/data/akinator-debug/.