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

xnxx-bail-pro

v2.4.1

Published

WhatsApp Web API client with interactive messages, product catalogs, carousels, events, payments, and polls. Forked from WhiskeySockets/Baileys.

Downloads

492

Readme

XNXX Bail Pro


What this package actually gives you

This package is not just a renamed socket export.

It currently gives you:

  • standard Baileys-style socket exports
  • a modular runtime at sock.mod
  • command registration
  • plugin registration
  • menu routing for list and button replies
  • queue and retry helpers
  • anti-spam, rate limiting, and rule execution
  • analytics and session helpers
  • UI helpers for buttons, lists, carousel, flow steps, and progress updates
  • starter plugins and battle foundations

If you want a README that behaves like a feature index, start here:


Visual map


Install

npm install xnxx-bail-pro

Or alias it as Baileys:

{
  "dependencies": {
    "@whiskeysockets/baileys": "npm:xnxx-bail-pro"
  }
}

Quick Start

import makeModularWASocket, { useMultiFileAuthState } from 'xnxx-bail-pro'

async function connect() {
  const { state, saveCreds } = await useMultiFileAuthState('auth_session')

  const sock = makeModularWASocket({
    auth: state,
    printQRInTerminal: true
  }, {
    prefix: '.',
    queue: {
      global: { concurrency: 1, minIntervalMs: 100 },
      user: { concurrency: 1, minIntervalMs: 250 },
      group: { concurrency: 1, minIntervalMs: 150 }
    },
    antiSpam: {
      floodWindowMs: 7000,
      floodThreshold: 6,
      cooldownMs: 15000,
      autoMuteMs: 60000
    }
  })

  sock.ev.on('creds.update', saveCreds)
  return sock
}

connect()

Command Runtime

The command runtime is the main feature layer. It parses a prefix, resolves commands, checks permissions, applies cooldowns, and executes a handler with a rich context.

sock.mod.registerCommand({
  name: 'owner',
  aliases: ['adminpanel'],
  permission: 'admin.command',
  cooldownMs: 2000,
  execute: async ({ reply, chatId, userId, args }) => {
    await reply(`owner panel for ${userId} in ${chatId}`)
  }
})
execute: async (ctx) => {
  console.log(ctx.chatId)
  console.log(ctx.userId)
  console.log(ctx.args)
  console.log(ctx.text)
  console.log(ctx.actionId)

  await ctx.reply('done')
}

Runtime context includes:

  • chatId
  • userId
  • participant
  • message
  • text
  • actionId
  • reply()
  • warn()
  • deleteMessage()
  • forward()
  • mute()

Plugin System

Plugins let you register commands, rules, and role mappings in one place.

const ownerPlugin = {
  name: 'owner-tools',
  roles: {
    '923001234567': 'admin'
  },
  commands: [
    {
      name: 'panel',
      permission: 'admin.command',
      execute: async ({ reply }) => reply('owner panel')
    }
  ],
  rules: [
    {
      id: 'warn-links',
      when: {
        type: 'condition',
        left: 'text',
        operator: 'contains',
        right: 'https://'
      },
      then: [
        { type: 'warn', payload: { text: 'Links are restricted.' } }
      ]
    }
  ]
}

sock.mod.use(ownerPlugin)

Menu Routing

The menu system stores a menu definition, then resolves button or list replies back into commands.

const menu = sock.mod.menus.buildListMenu({
  id: 'main',
  title: 'Main Menu',
  text: 'Choose a system',
  sections: [
    {
      title: 'Core',
      rows: [
        { id: 'ping', label: 'Ping', description: 'Check status', command: 'ping' },
        { id: 'stats', label: 'Stats', description: 'View analytics', command: 'stats' }
      ]
    }
  ]
})

await sock.mod.menus.register(jid, menu)
await sock.mod.sendList(jid, menu.payload)
const menu = sock.mod.menus.buildButtonsMenu({
  id: 'quick',
  title: 'Quick Actions',
  text: 'Pick one',
  footer: 'Command router',
  items: [
    { id: 'ping', label: 'Ping', command: 'ping' },
    { id: 'battle', label: 'Battle', command: 'battle' }
  ]
})

await sock.mod.menus.register(jid, menu)
await sock.mod.sendButtons(jid, menu.payload)

The runtime resolves IDs like menu:main:ping and runs the mapped command automatically.


Buttons

This package now builds outbound buttonsMessage correctly.

await sock.mod.sendButtons(jid, {
  text: 'Choose an action',
  footer: 'Main control panel',
  buttons: [
    { id: 'battle:start', text: 'Start Battle' },
    { id: 'stats:view', text: 'View Stats' }
  ]
})
await sock.mod.sendButtons(jid, {
  header: 'XNXX Bail Pro',
  text: 'Select one option',
  footer: 'Runtime demo',
  buttons: [
    { id: 'menu:open', text: 'Open Menu' },
    { id: 'owner:panel', text: 'Owner Panel' }
  ]
})

Lists

Lists work through the same high-level sock.mod API.

await sock.mod.sendList(jid, {
  title: 'Main Menu',
  text: 'Pick one module',
  buttonText: 'Open',
  sections: [
    {
      title: 'Systems',
      rows: [
        { id: 'analytics', title: 'Analytics', description: 'See activity data' },
        { id: 'games', title: 'Games', description: 'Play PvP and story mode' }
      ]
    }
  ]
})

Hybrid Carousel

The helper builds a paged carousel-style payload from cards. This is a wrapper layer on top of the interactive support already in the fork.

await sock.mod.sendHybridCarousel(jid, {
  body: 'Carousel demo',
  footer: 'Page 1',
  cards: [
    {
      title: 'Control Runtime',
      text: 'Commands, cooldowns, anti-spam, permissions',
      buttons: [{ name: 'quick_reply', params: { display_text: 'Open', id: 'runtime:open' } }]
    },
    {
      title: 'Game Layer',
      text: 'PvP, story mode, detective state, loot',
      buttons: [{ name: 'quick_reply', params: { display_text: 'Play', id: 'game:play' } }]
    }
  ]
})

Queue System

The queue system serializes work globally, per user, or per group. The main high-level helper is sendQueued().

await sock.mod.sendQueued(jid, { text: 'queued message' })
const sock = makeModularWASocket(config, {
  queue: {
    global: { concurrency: 1, minIntervalMs: 100 },
    user: { concurrency: 1, minIntervalMs: 250 },
    group: { concurrency: 1, minIntervalMs: 150 }
  }
})

Retry Engine

Retries are applied automatically by sendQueued(), and the RetryEngine is exported if you want custom retry flows.

const sock = makeModularWASocket(config, {
  retry: {
    maxRetries: 3,
    baseDelayMs: 1000,
    maxDelayMs: 10000
  }
})

Permission System

Permissions are role-based, with extension points for custom rules.

Default role behavior:

  • admin can do everything
  • mod can do most non-admin actions
  • vip can do non-admin actions
  • user is limited to public.* actions unless you extend the system
const sock = makeModularWASocket(config, {
  permissions: {
    roles: {
      '923001234567': 'admin',
      '923009999999': 'mod',
      '923008888888': 'vip'
    }
  }
})
sock.mod.registerCommand({
  name: 'shutdown',
  permission: 'admin.command',
  execute: async ({ reply }) => reply('restricted action')
})

Anti-Spam and Rate Limiting

These run before command execution and before generic rules.

const sock = makeModularWASocket(config, {
  antiSpam: {
    floodWindowMs: 7000,
    floodThreshold: 6,
    cooldownMs: 15000,
    autoMuteMs: 60000
  }
})
const sock = makeModularWASocket(config, {
  rateLimiter: {
    perUser: { windowMs: 10000, limit: 8 },
    perGroup: { windowMs: 10000, limit: 20 },
    perCommand: { windowMs: 10000, limit: 5 }
  }
})

Rule Engine

Rules are node-based. They are not meant to be handwritten nested if/else blocks everywhere in your bot.

Supported comparators:

  • contains
  • equals
  • startsWith
  • regex
  • gt
  • lt

Supported built-in actions:

  • reply
  • warn
  • delete
  • mute
  • forward
const modConfig = {
  rules: [
    {
      id: 'link-warning',
      when: {
        type: 'group',
        operator: 'AND',
        children: [
          { type: 'condition', left: 'isGroup', operator: 'equals', right: true },
          { type: 'condition', left: 'text', operator: 'contains', right: 'https://' }
        ]
      },
      then: [
        { type: 'warn', payload: { text: 'Links are restricted in this chat.' } }
      ]
    }
  ]
}
const modConfig = {
  rules: [
    {
      id: 'phone-filter',
      when: {
        type: 'condition',
        left: 'text',
        operator: 'regex',
        right: '\\\\b\\d{11,14}\\\\b'
      },
      then: [
        { type: 'warn', payload: { text: 'Phone numbers are blocked.' } }
      ]
    }
  ]
}

Analytics

The analytics system tracks per-user and per-group message activity.

const stats = sock.mod.analytics.getGroupStats(jid)

console.log(stats.messageCount)
console.log(stats.activeUsers)
console.log(stats.heatmap)
console.log(stats.lastActiveAt)
const stats = sock.mod.analytics.getUserStats('923001234567')
console.log(stats.messageCount)
console.log(stats.lastActiveAt)

Multi-Session

The package exports a session manager that can create isolated modular sockets.

import { createSessionManager } from 'xnxx-bail-pro'

const sessions = createSessionManager()
await sessions.createSession('bot-1', {
  config: {
    auth: state,
    printQRInTerminal: true
  },
  modConfig: {
    prefix: '.'
  }
})
console.log(sessions.listSessions())
await sessions.closeSession('bot-1')

Store Adapters

The exported store system supports:

  • memory adapter
  • Redis adapter pattern
  • Mongo adapter pattern
import { StoreSystem, MemoryStoreAdapter } from 'xnxx-bail-pro'

const store = new StoreSystem(new MemoryStoreAdapter())
await store.set('test', 'key1', { ok: true }, 60000)
const value = await store.get('test', 'key1')
import { StoreSystem, RedisStoreAdapter } from 'xnxx-bail-pro'

const redisAdapter = new RedisStoreAdapter(redisClient)
const store = new StoreSystem(redisAdapter)
import { StoreSystem, MongoStoreAdapter } from 'xnxx-bail-pro'

const mongoAdapter = new MongoStoreAdapter(collection)
const store = new StoreSystem(mongoAdapter)

Game Foundations

These are foundation systems. They give you state and helper logic, not a finished game.

await sock.mod.games.createBattle(`battle-${jid}`, [
  { id: 'player1', name: 'Player 1' },
  { id: 'enemy', name: 'Enemy' }
])

const update = await sock.mod.games.performBattleAction(`battle-${jid}`, 'player1', 'attack')
console.log(update.log)
console.log(update.players)
const loot = sock.mod.games.rollLoot([
  { name: 'Common Box', weight: 70 },
  { name: 'Rare Box', weight: 25 },
  { name: 'Legendary Box', weight: 5 }
])
const story = {
  id: 'case-1',
  startNodeId: 'intro',
  nodes: [
    { id: 'intro', choices: [{ id: 'go-left', nextNodeId: 'left' }] },
    { id: 'left', choices: [] }
  ]
}

let state = sock.mod.games.createStoryState(story)
state = sock.mod.games.advanceStory(story, state, 'go-left')
const detectiveCase = sock.mod.games.createDetectiveCase({
  id: 'detective-1',
  suspects: ['A', 'B', 'C'],
  clues: ['ticket', 'photo']
})

Starter Commands

Starter plugins are loaded by default unless you set loadStarterPlugins: false.

Included starter commands:

  • .ping
  • .menu
  • .help
  • .stats
  • .battle
  • .attack
  • .defend
const sock = makeModularWASocket(config, {
  loadStarterPlugins: false
})

Main Exports

import makeModularWASocket, {
  createModFramework,
  createSessionManager,
  CommandRegistry,
  CommandRuntime,
  CooldownManager,
  MenuSystem,
  PluginManager,
  QueueSystem,
  RetryEngine,
  RuleEngine,
  StoreSystem,
  MemoryStoreAdapter,
  RedisStoreAdapter,
  MongoStoreAdapter,
  createCorePlugin,
  createModerationPlugin
} from 'xnxx-bail-pro'

Example file

There is a runnable example in:

  • example.mod.js

It shows:

  • modular socket boot
  • queue and anti-spam config
  • starter command visibility
  • button/list/carousel sending

Project layout

lib/
  Mod/
    analytics-system.js
    command-system.js
    control-system.js
    game-system.js
    menu-system.js
    permissions.js
    plugin-system.js
    queue-system.js
    retry-engine.js
    rule-engine.js
    session-system.js
    starter-plugins.js
    store-system.js
    ui-system.js

Upstream note

This package still sits on top of a forked Baileys build. That means upstream protocol and transport changes still matter.

Recommended strategy:

  1. keep low-level socket changes small
  2. keep new product features in lib/Mod
  3. build advanced bot behavior through commands and plugins

Upstream references:


Local development

npm install
node example.mod.js

If you want the startup banner:

set XNXX_BAIL_PRO_SHOW_BANNER=1

Disclaimer

This project is not affiliated with WhatsApp. Use it responsibly.