Skip to content

Repository files navigation

WhatsApp BOT @caioagiani

WhatsApp Bot

A powerful, extensible WhatsApp bot built with TypeScript β€” with a REST API, command system and in-memory cache

GitHub language count GitHub top language GitHub repo size GitHub last commit License


πŸ“‹ Overview

This application is a WhatsApp client that connects to WhatsApp Web using Puppeteer, enabling real-time automation, command execution and programmatic control via a built-in HTTP REST API. Built with TypeScript and following modern software architecture principles.

✨ Key Features

  • πŸ€– Command-based Architecture - Extensible command system with interface-based design
  • 🌐 HTTP REST API - Control the bot and query data programmatically
  • ⚑ In-memory Cache - Contacts and chats cached with configurable TTL
  • πŸ”„ Alias Support - Multiple names for the same command
  • πŸ›‘οΈ Error Handling - Robust error handling with user-friendly messages
  • πŸ“ Type Safety - Full TypeScript implementation
  • 🎯 Easy to Extend - Add new commands in minutes
  • πŸ” Group Validation - Built-in group-only command support
  • πŸ’¬ Real-time Responses - Typing indicators and instant feedback
  • πŸ”’ Graceful Shutdown - Clean SIGTERM/SIGINT handling

πŸš€ Available Commands

Command Aliases Description
!help !ajuda, !comandos, !commands Shows all available commands with descriptions
!cotacao !moeda, !dolar, !bitcoin Get current currency exchange rates (USD, BTC, EUR)
!cep <code> - Search Brazilian postal code information
!perfil @user !foto, !avatar, !pic Get user's profile picture
!mencionar !everyone, !all, !todos Mention all group members (admin only)
!sms @user - Send SMS to mentioned user

Note: All commands start with ! prefix


🌐 HTTP REST API

The bot exposes a REST API on port 3000 (configurable) for programmatic control.

Authentication

Set API_KEY in .env to enable Bearer token authentication. If not set, the API is open.

Authorization: Bearer <your-api-key>

Endpoints

Method Endpoint Description
GET /api/status Bot connection status + QR code when pending
GET /api/contacts List all contacts (paginated)
GET /api/contacts/search?q= Search contacts by name or number
GET /api/groups List all groups (paginated)
GET /api/groups/:id Group details + participants with admin flags
POST /api/messages/send Send a message to a contact or group

Pagination

/api/contacts and /api/groups support ?page=1&limit=20 (max limit: 100).

{
  "contacts": [...],
  "pagination": {
    "total": 120,
    "page": 1,
    "limit": 20,
    "pages": 6
  }
}

Examples

Get bot status:

curl http://localhost:3000/api/status
# {"status":"ready","name":"MyBot","qr":null}

List groups:

curl http://localhost:3000/api/groups?page=1&limit=10

Send a message:

curl -X POST http://localhost:3000/api/messages/send \
  -H "Content-Type: application/json" \
  -d '{"to": "5511999999999", "text": "Hello!"}'

Tip: Import insomnia.json from the project root into Insomnia for a ready-to-use collection.


πŸ“¦ Installation

Prerequisites

  • Node.js 16+
  • npm
  • WhatsApp account

Setup

# Clone the repository
git clone git@github.com:caioagiani/whatsapp-bot.git
cd whatsapp-bot

# Install dependencies
npm install

# Configure environment variables
cp .env.example .env
# Edit .env with your settings

# Start the bot
npm run dev

First Run

  1. When you start the bot for the first time, a QR code will appear in your terminal
  2. Open WhatsApp on your phone
  3. Go to Settings β†’ Linked Devices β†’ Link a Device
  4. Scan the QR code displayed in your terminal
  5. Wait for the authentication to complete

βœ… Your bot is now connected. The HTTP API is available at http://localhost:3000.


πŸ—οΈ Architecture

Project Structure

src/
β”œβ”€β”€ api/
β”‚   β”œβ”€β”€ middleware/
β”‚   β”‚   └── auth.ts             # Bearer token auth
β”‚   β”œβ”€β”€ routes/
β”‚   β”‚   β”œβ”€β”€ contacts.ts         # GET /api/contacts
β”‚   β”‚   β”œβ”€β”€ groups.ts           # GET /api/groups
β”‚   β”‚   β”œβ”€β”€ messages.ts         # POST /api/messages/send
β”‚   β”‚   └── status.ts           # GET /api/status
β”‚   β”œβ”€β”€ utils/
β”‚   β”‚   β”œβ”€β”€ cache.ts            # In-memory TTL cache
β”‚   β”‚   └── paginate.ts         # Pagination helper
β”‚   β”œβ”€β”€ server.ts               # Express setup
β”‚   └── state.ts                # Bot state tracker
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ commands/               # Command implementations
β”‚   β”‚   β”œβ”€β”€ CepCommand.ts
β”‚   β”‚   β”œβ”€β”€ EconomyCommand.ts
β”‚   β”‚   β”œβ”€β”€ HelpCommand.ts
β”‚   β”‚   β”œβ”€β”€ ProfileCommand.ts
β”‚   β”‚   β”œβ”€β”€ QuoteCommand.ts
β”‚   β”‚   β”œβ”€β”€ SmsCommand.ts
β”‚   β”‚   └── index.ts
β”‚   β”œβ”€β”€ interfaces/
β”‚   β”‚   β”œβ”€β”€ ICommand.ts
β”‚   β”‚   └── Cep.ts
β”‚   └── utils/
β”‚       β”œβ”€β”€ BaseCommand.ts
β”‚       └── CommandDispatcher.ts
β”œβ”€β”€ config/
β”‚   └── integrantes.json        # Admin users (gitignored)
β”œβ”€β”€ data/                       # WhatsApp session data (gitignored)
β”œβ”€β”€ services/
β”‚   β”œβ”€β”€ mobizon.ts              # SMS service
β”‚   β”œβ”€β”€ shutdown.ts             # Graceful shutdown
β”‚   └── whatsapp.ts             # WhatsApp client
└── index.ts

Cache

getContacts() and getChats() are expensive Puppeteer calls (~500ms). Results are cached in memory for 30 seconds (configurable via CACHE_TTL_MS). Cache is cleared automatically on disconnect.


πŸ”§ Configuration

Environment Variables

# HTTP API
API_PORT=3000
API_KEY=                        # Bearer token (leave empty to disable auth)

# Bot owner β€” receives a message when the bot connects
# Falls back to the first admin in integrantes.json if not set
BOT_OWNER_PHONE=

# Cache TTL in milliseconds (default: 30000)
CACHE_TTL_MS=30000

# Mobizon SMS (optional β€” required for !sms command)
MOBIZON_URL_SRV=https://api.mobizon.com.br
MOBIZON_API_KEY=

Admin Configuration

For admin-only commands (like !mencionar), configure authorized users in src/config/integrantes.json (gitignored):

{
  "company": [
    {
      "numero": "5511999999999",
      "admin": true,
      "nome": "Your Name",
      "cargo": "Admin"
    }
  ]
}

πŸ”§ Adding New Commands

// src/app/commands/HelloCommand.ts
import { BaseCommand } from '../utils/BaseCommand';
import type { Message } from 'whatsapp-web.js';

export class HelloCommand extends BaseCommand {
  name = 'hello';
  description = 'Responds with a greeting';
  aliases = ['hi', 'ola'];

  async execute(message: Message, args: string[]): Promise<Message> {
    await this.sendTyping(message);
    const name = args.join(' ') || 'friend';
    return message.reply(`πŸ‘‹ Hello, ${name}!`);
  }
}

Then register in src/app/commands/index.ts:

commandDispatcher.register(new HelloCommand());

πŸ§ͺ Testing

# Run tests
npm test

# Run linter
npm run lint

# Development mode with auto-reload
npm run dev

Tests use Jest + Supertest and cover all API endpoints, pagination, authentication and error paths (46 tests).


🀝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes using Conventional Commits
  4. Push to the branch and open a Pull Request

πŸ“ License

Copyright Β© 2022-2026 Caio Agiani

This project is licensed under the GNU AGPL License.


⚠️ Disclaimer

This project is not affiliated, associated, authorized, endorsed by, or in any way officially connected with WhatsApp or any of its subsidiaries or affiliates.

Use this bot responsibly and in accordance with WhatsApp's Terms of Service.


πŸ‘₯ Contributors

πŸ™ Acknowledgments

  • @pedroslopez - whatsapp-web.js library
  • All contributors who have helped improve this project

πŸ“ž Contact


Made with ❀️ by Caio Agiani