update documentation and remove systemd support

This commit is contained in:
synt-xerror
2026-04-21 11:18:19 -03:00
parent f683496318
commit c12374f86c
18 changed files with 3441 additions and 248 deletions

277
docs/API (en).md Normal file
View File

@@ -0,0 +1,277 @@
# 🛠️ API Reference
Complete documentation of objects available in plugins.
---
## The `msg` Object
Contains information about the received message.
### Properties
| Property | Type | Description |
|----------|------|-------------|
| `msg.body` | `string` | Full text of the message |
| `msg.args` | `string[]` | Message tokens. E.g.: `"!video url"``["!video", "url"]` |
| `msg.type` | `string` | Message type: `chat`, `image`, `video`, `audio`, `sticker`, `ptt` (voice), `document`, `location` |
| `msg.sender` | `string` | Sender ID (format: `NUMBER@c.us` or `NUMBER@g.us`) |
| `msg.senderName` | `string` | Display name of the sender |
| `msg.fromMe` | `boolean` | `true` if the bot itself sent the message |
| `msg.hasMedia` | `boolean` | `true` if the message contains media |
| `msg.hasReply` | `boolean` | `true` if the message is a reply to another |
| `msg.isGif` | `boolean` | `true` if the media is a GIF |
| `msg.timestamp` | `number` | Unix timestamp of the message |
### Methods
#### `msg.is(cmd)`
Checks whether the message starts with the specified command.
```javascript
if (msg.is(CMD_PREFIX + "video")) {
// Execute command
}
```
**Returns:** `boolean`
---
#### `msg.reply(text)`
Replies to the current message with a quote (citation).
```javascript
await msg.reply("Reply with citation!");
```
**Parameters:**
- `text` (string): Text of the reply
**Returns:** `Promise<void>`
---
#### `msg.downloadMedia()`
Downloads the media from the message.
```javascript
const media = await msg.downloadMedia();
// Returns: { mimetype: "image/jpeg", data: "base64string..." }
```
**Returns:** `Promise<{ mimetype: string, data: string } | null>`
---
#### `msg.getReply()`
Returns the message that was quoted.
```javascript
const quotedMsg = msg.getReply();
if (quotedMsg) {
console.log(quotedMsg.body);
}
```
**Returns:** `msg object | null`
---
## The `api` Object
Contains methods for interacting with WhatsApp and other plugins.
### Properties
#### `api.chat`
Information about the current chat.
| Property | Type | Description |
|----------|------|-------------|
| `api.chat.id` | `string` | Chat ID |
| `api.chat.name` | `string` | Chat name |
| `api.chat.isGroup` | `boolean` | `true` if it is a group |
---
### Send Methods
#### `api.send(text)`
Sends a text message.
```javascript
await api.send("Message sent!");
```
**Parameters:**
- `text` (string): Text to send
**Returns:** `Promise<void>`
---
#### `api.sendVideo(filePath)`
Sends a video from the file system.
```javascript
await api.sendVideo("/path/to/video.mp4");
```
**Parameters:**
- `filePath` (string): Path to the file
**Returns:** `Promise<void>`
---
#### `api.sendAudio(filePath)`
Sends audio as a voice message (PTT).
```javascript
await api.sendAudio("/path/to/audio.mp3");
```
**Parameters:**
- `filePath` (string): Path to the file
**Returns:** `Promise<void>`
---
#### `api.sendImage(filePath, caption?)`
Sends an image.
```javascript
await api.sendImage("/path/to/image.jpg", "Optional caption");
```
**Parameters:**
- `filePath` (string): Path to the file
- `caption` (string, optional): Image caption
**Returns:** `Promise<void>`
---
#### `api.sendSticker(bufferOrPath)`
Sends a sticker. Accepts a `Buffer` or a file path.
```javascript
// With Buffer
const buffer = fs.readFileSync("image.png");
await api.sendSticker(buffer);
// With path
await api.sendSticker("/path/to/image.png");
```
**Parameters:**
- `bufferOrPath` (`Buffer` | `string`): Image data or file path
**Returns:** `Promise<void>`
---
### Plugin Methods
#### `api.getPlugin(name)`
Accesses the public API of another plugin.
```javascript
const utils = api.getPlugin("utilities");
const data = utils.formatDate(new Date());
```
**Parameters:**
- `name` (string): Plugin name
**Returns:** `object | undefined`
---
### Log Methods
#### `api.log.info(...args)`
Informational log.
```javascript
api.log.info("Message received:", msg.body);
```
#### `api.log.warn(...args)`
Warning log.
```javascript
api.log.warn("Missing config, using default");
```
#### `api.log.error(...args)`
Error log.
```javascript
api.log.error("Failed to process:", error);
```
---
## Configuration Object
Import settings from `manybot.conf`:
```javascript
import { CMD_PREFIX, CLIENT_ID, CHATS, PLUGINS } from "../../config.js";
// Custom configurations also work
import { MY_PREFIX } from "../../config.js";
```
---
## Full Example
```javascript
import { CMD_PREFIX } from "../../config.js";
import fs from "fs";
export default async function ({ msg, api }) {
// Ignore messages from the bot itself
if (msg.fromMe) return;
// Command: !echo
if (!msg.is(CMD_PREFIX + "echo")) return;
api.log.info("Echo command received from:", msg.senderName);
// If it has media, download and resend
if (msg.hasMedia) {
const media = await msg.downloadMedia();
await api.sendSticker(media.data);
return;
}
// If it's a reply, echo the quoted message
if (msg.hasReply) {
const quoted = msg.getReply();
await msg.reply(`You quoted: "${quoted.body}"`);
return;
}
// Default response
await msg.reply("Send media or reply to a message!");
}
```

277
docs/API.md Normal file
View File

@@ -0,0 +1,277 @@
# 🛠️ Referência da API
Documentação completa dos objetos disponíveis nos plugins.
---
## Objeto `msg`
Contém informações da mensagem recebida.
### Propriedades
| Propriedade | Tipo | Descrição |
|-------------|------|-----------|
| `msg.body` | `string` | Texto completo da mensagem |
| `msg.args` | `string[]` | Tokens da mensagem. Ex: `"!video url"``["!video", "url"]` |
| `msg.type` | `string` | Tipo da mensagem: `chat`, `image`, `video`, `audio`, `sticker`, `ptt` (voz), `document`, `location` |
| `msg.sender` | `string` | ID do remetente (formato: `NUMERO@c.us` ou `NUMERO@g.us`) |
| `msg.senderName` | `string` | Nome de exibição do remetente |
| `msg.fromMe` | `boolean` | `true` se o próprio bot enviou a mensagem |
| `msg.hasMedia` | `boolean` | `true` se a mensagem contém mídia |
| `msg.hasReply` | `boolean` | `true` se é uma resposta a outra mensagem |
| `msg.isGif` | `boolean` | `true` se a mídia é um GIF |
| `msg.timestamp` | `number` | Timestamp Unix da mensagem |
### Métodos
#### `msg.is(cmd)`
Verifica se a mensagem começa com o comando especificado.
```javascript
if (msg.is(CMD_PREFIX + "video")) {
// Executa comando
}
```
**Retorno:** `boolean`
---
#### `msg.reply(text)`
Responde à mensagem atual com quote (citação).
```javascript
await msg.reply("Resposta com citação!");
```
**Parâmetros:**
- `text` (string): Texto da resposta
**Retorno:** `Promise<void>`
---
#### `msg.downloadMedia()`
Baixa a mídia da mensagem.
```javascript
const media = await msg.downloadMedia();
// Retorna: { mimetype: "image/jpeg", data: "base64string..." }
```
**Retorno:** `Promise<{ mimetype: string, data: string } | null>`
---
#### `msg.getReply()`
Retorna a mensagem que foi citada.
```javascript
const mensagemCitada = msg.getReply();
if (mensagemCitada) {
console.log(mensagemCitada.body);
}
```
**Retorno:** `msg object | null`
---
## Objeto `api`
Contém métodos para interagir com o WhatsApp e outros plugins.
### Propriedades
#### `api.chat`
Informações do chat atual.
| Propriedade | Tipo | Descrição |
|-------------|------|-----------|
| `api.chat.id` | `string` | ID do chat |
| `api.chat.name` | `string` | Nome do chat |
| `api.chat.isGroup` | `boolean` | `true` se é grupo |
---
### Métodos de Envio
#### `api.send(text)`
Envia uma mensagem de texto.
```javascript
await api.send("Mensagem enviada!");
```
**Parâmetros:**
- `text` (string): Texto a enviar
**Retorno:** `Promise<void>`
---
#### `api.sendVideo(filePath)`
Envia um vídeo do sistema de arquivos.
```javascript
await api.sendVideo("/caminho/para/video.mp4");
```
**Parâmetros:**
- `filePath` (string): Caminho para o arquivo
**Retorno:** `Promise<void>`
---
#### `api.sendAudio(filePath)`
Envia um áudio como mensagem de voz (PTT).
```javascript
await api.sendAudio("/caminho/para/audio.mp3");
```
**Parâmetros:**
- `filePath` (string): Caminho para o arquivo
**Retorno:** `Promise<void>`
---
#### `api.sendImage(filePath, caption?)`
Envia uma imagem.
```javascript
await api.sendImage("/caminho/para/imagem.jpg", "Legenda opcional");
```
**Parâmetros:**
- `filePath` (string): Caminho para o arquivo
- `caption` (string, opcional): Legenda da imagem
**Retorno:** `Promise<void>`
---
#### `api.sendSticker(bufferOuPath)`
Envia uma figurinha. Aceita `Buffer` ou caminho para arquivo.
```javascript
// Com Buffer
const buffer = fs.readFileSync("imagem.png");
await api.sendSticker(buffer);
// Com caminho
await api.sendSticker("/caminho/para/imagem.png");
```
**Parâmetros:**
- `bufferOuPath` (`Buffer` | `string`): Dados da imagem ou caminho
**Retorno:** `Promise<void>`
---
### Métodos de Plugin
#### `api.getPlugin(name)`
Acessa a API pública de outro plugin.
```javascript
const utils = api.getPlugin("utilidades");
const data = utils.formatarData(new Date());
```
**Parâmetros:**
- `name` (string): Nome do plugin
**Retorno:** `object | undefined`
---
### Métodos de Log
#### `api.log.info(...args)`
Log informativo.
```javascript
api.log.info("Mensagem recebida:", msg.body);
```
#### `api.log.warn(...args)`
Log de aviso.
```javascript
api.log.warn("Configuração ausente, usando padrão");
```
#### `api.log.error(...args)`
Log de erro.
```javascript
api.log.error("Falha ao processar:", erro);
```
---
## Objeto de Configuração
Importe configurações do `manybot.conf`:
```javascript
import { CMD_PREFIX, CLIENT_ID, CHATS, PLUGINS } from "../../config.js";
// Configurações personalizadas também funcionam
import { MEU_PREFIXO } from "../../config.js";
```
---
## Exemplo Completo
```javascript
import { CMD_PREFIX } from "../../config.js";
import fs from "fs";
export default async function ({ msg, api }) {
// Ignora mensagens do próprio bot
if (msg.fromMe) return;
// Comando: !eco
if (!msg.is(CMD_PREFIX + "eco")) return;
api.log.info("Comando eco recebido de:", msg.senderName);
// Se tem mídia, baixa e reenvia
if (msg.hasMedia) {
const media = await msg.downloadMedia();
await api.sendSticker(media.data);
return;
}
// Se é resposta, ecoa a mensagem citada
if (msg.hasReply) {
const citada = msg.getReply();
await msg.reply(`Você citou: "${citada.body}"`);
return;
}
// Resposta padrão
await msg.reply("Envie uma mídia ou responda uma mensagem!");
}
```

146
docs/CONFIGURACAO.md Normal file
View File

@@ -0,0 +1,146 @@
# ⚙️ Configuração
Guia completo do arquivo `manybot.conf`.
---
## Estrutura Básica
```bash
# Comentários começam com '#'
CLIENT_ID=bot_permanente
CMD_PREFIX=!
LANGUAGE=pt
CHATS=[]
PLUGINS=[]
```
---
## Opções
### CLIENT_ID
Identificador único da sessão do bot.
```bash
CLIENT_ID=bot_permanente
```
- **Padrão:** `bot_permanente`
- **Uso:** Cria uma pasta `session/` com esse nome para armazenar dados de autenticação
### CMD_PREFIX
Caractere que indica o início de um comando.
```bash
CMD_PREFIX=!
```
- **Padrão:** `!`
- **Exemplo:** Com prefixo `!`, o comando é `!figurinha`. Com `.`, seria `.figurinha`.
### LANGUAGE
Idioma das mensagens do bot.
```bash
LANGUAGE=pt
```
- **Padrão:** `en` (inglês)
- **Opções:** `en` (inglês), `pt` (português), `es` (espanhol)
- **Nota:** Se o idioma selecionado não existir, o bot usará inglês como fallback
### CHATS
Lista de IDs de chats onde o bot responderá.
```bash
CHATS=[
123456789@c.us, # Chat privado
123456789@g.us # Grupo
]
```
- **Padrão:** `[]` (vazio = responde em todos)
- **Formato:**
- Privado: `NUMERO@c.us`
- Grupo: `NUMERO@g.us`
#### Como descobrir o ID
```bash
node src/utils/get_id.js
```
Escaneie o QR Code e mande uma mensagem no chat. O ID aparecerá no terminal.
> Nota: O utilitário usa um `CLIENT_ID` separado para não conflitar com a sessão principal.
### PLUGINS
Lista de plugins a serem carregados.
```bash
PLUGINS=[
video,
audio,
figurinha,
adivinhacao,
forca,
many,
obrigado
]
```
- **Padrão:** `[]` (nenhum)
- Cada nome corresponde a uma pasta em `src/plugins/`
- Remova ou comente para desativar sem apagar
---
## Configurações Personalizadas
Você pode adicionar suas próprias variáveis para plugins:
```bash
# manybot.conf
MEU_PREFIXO=>
API_KEY=minha_chave
```
E acessar no código do plugin:
```javascript
import { MEU_PREFIXO, API_KEY } from "../../config.js";
```
---
## Exemplo Completo
```bash
# ManyBot Configuration
CLIENT_ID=meu_bot_prod
CMD_PREFIX=/
LANGUAGE=pt
CHATS=[
5511999999999@c.us,
5511888888888-123456789@g.us
]
PLUGINS=[
figurinha,
video,
audio,
many
]
# Configurações extras
ADMIN_NUMBER=5511999999999@c.us
```

146
docs/CONFIGURATION.md Normal file
View File

@@ -0,0 +1,146 @@
# Configuration
Complete guide for the `manybot.conf` file.
---
## Basic Structure
```bash
# Comments start with '#'
CLIENT_ID=bot_permanente
CMD_PREFIX=!
LANGUAGE=en
CHATS=[]
PLUGINS=[]
```
---
## Options
### CLIENT_ID
Unique identifier for the bot session.
```bash
CLIENT_ID=my_bot
```
- **Default:** `bot_permanente`
- **Usage:** Creates a `session/` folder with this name to store authentication data
### CMD_PREFIX
Character that indicates the start of a command.
```bash
CMD_PREFIX=!
```
- **Default:** `!`
- **Example:** With prefix `!`, the command is `!sticker`. With `.`, it would be `.sticker`.
### LANGUAGE
Bot message language.
```bash
LANGUAGE=en
```
- **Default:** `en` (English)
- **Options:** `en` (English), `pt` (Portuguese), `es` (Spanish)
- **Note:** If the selected language doesn't exist, the bot will fall back to English
### CHATS
List of chat IDs where the bot will respond.
```bash
CHATS=[
123456789@c.us, # Private chat
123456789@g.us # Group
]
```
- **Default:** `[]` (empty = responds to all)
- **Format:**
- Private: `NUMBER@c.us`
- Group: `NUMBER@g.us`
#### How to discover the ID
```bash
node src/utils/get_id.js
```
Scan the QR Code and send a message in the chat. The ID will appear in the terminal.
> Note: The utility uses a separate `CLIENT_ID` to avoid conflicting with the main session.
### PLUGINS
List of plugins to be loaded.
```bash
PLUGINS=[
video,
audio,
sticker,
guess,
hangman,
many,
thanks
]
```
- **Default:** `[]` (none)
- Each name corresponds to a folder in `src/plugins/`
- Remove or comment to disable without deleting
---
## Custom Settings
You can add your own variables for plugins:
```bash
# manybot.conf
MY_PREFIX=>
API_KEY=my_key
```
And access in the plugin code:
```javascript
import { MY_PREFIX, API_KEY } from "../../config.js";
```
---
## Complete Example
```bash
# ManyBot Configuration
CLIENT_ID=my_bot_prod
CMD_PREFIX=/
LANGUAGE=en
CHATS=[
5511999999999@c.us,
5511888888888-123456789@g.us
]
PLUGINS=[
sticker,
video,
audio,
many
]
# Extra settings
ADMIN_NUMBER=5511999999999@c.us
```

144
docs/INSTALACAO.md Normal file
View File

@@ -0,0 +1,144 @@
# 📥 Instalação
Guia completo de instalação do ManyBot em diferentes plataformas.
---
## 📑 Índice
- [Linux](#linux)
- [Windows](#windows)
- [Termux (Android)](#termux-android)
---
## Linux
### 1. Clone o repositório
```bash
git clone https://github.com/synt-xerror/manybot
cd manybot
```
### 2. Configure o bot
Crie o arquivo de configuração:
```bash
touch manybot.conf
nano manybot.conf
```
Exemplo de configuração:
```bash
# Comentários com '#'
CLIENT_ID=bot_permanente
CMD_PREFIX=!
LANGUAGE=pt
CHATS=[
123456789@c.us,
123456789@g.us
]
PLUGINS=[
video,
audio,
figurinha,
adivinhacao
]
```
**Detalhes:**
- `CLIENT_ID`: ID da sessão (padrão: `bot_permanente`)
- `CMD_PREFIX`: Prefixo dos comandos (padrão: `!`)
- `LANGUAGE`: Idioma do bot - `pt`, `en` ou `es` (padrão: `en`)
- `CHATS`: IDs dos chats permitidos (deixe vazio para todos)
- `PLUGINS`: Lista de plugins ativos
### 3. Execute a instalação
```bash
bash ./setup
```
### 4. Primeira execução
```bash
node ./src/main.js
```
Escaneie o QR Code no WhatsApp:
**Menu → Dispositivos conectados → Conectar um dispositivo**
---
## Windows
O ManyBot foi pensado para Linux, mas funciona no Windows via **Git Bash**.
### Pré-requisitos
1. **Git Bash**: https://git-scm.com/download/win
2. **Node.js**: https://nodejs.org (escolha "Instalador Windows (.msi)")
### Instalação
Após instalar ambos, abra o **Git Bash** e siga os mesmos passos da [instalação Linux](#linux).
---
## Termux (Android)
> ⚠️ **Aviso:** Suporte experimental. Não há garantia de funcionamento.
```bash
# Instale o Termux pela F-Droid (não use Play Store)
# https://f-droid.org/packages/com.termux/
# Atualize pacotes
pkg update && pkg upgrade
# Instale dependências
pkg install nodejs git
# Clone e instale
git clone https://github.com/synt-xerror/manybot
cd manybot
```
Siga os passos de configuração Linux a partir do passo 2.
---
## 🔧 Resolução de Problemas
### Erro ao escanear QR Code
- Limpe os dados do Chrome/Chromium do Termux
- Delete a pasta `session/` e tente novamente
### Bot não responde comandos
- Verifique o `CMD_PREFIX` no `manybot.conf`
- Confira se o plugin está na lista `PLUGINS`
### Erros de instalação
```bash
# Limpe a cache do npm
npm cache clean --force
# Reinstale dependências
rm -rf node_modules package-lock.json
npm install
```
---
## 📚 Próximos Passos
- [Configuração avançada](./CONFIGURACAO.md)
- [Criando plugins](./PLUGINS.md)

144
docs/INSTALLATION.md Normal file
View File

@@ -0,0 +1,144 @@
# Installation
Complete installation guide for ManyBot on different platforms.
---
## Index
- [Linux](#linux)
- [Windows](#windows)
- [Termux (Android)](#termux-android)
---
## Linux
### 1. Clone the repository
```bash
git clone https://github.com/synt-xerror/manybot
cd manybot
```
### 2. Configure the bot
Create the configuration file:
```bash
touch manybot.conf
nano manybot.conf
```
Example configuration:
```bash
# Comments with '#'
CLIENT_ID=bot_permanente
CMD_PREFIX=!
LANGUAGE=en
CHATS=[
123456789@c.us,
123456789@g.us
]
PLUGINS=[
video,
audio,
sticker,
guess
]
```
**Details:**
- `CLIENT_ID`: Session ID (default: `bot_permanente`)
- `CMD_PREFIX`: Command prefix (default: `!`)
- `LANGUAGE`: Bot language - `pt`, `en`, or `es` (default: `en`)
- `CHATS`: Allowed chat IDs (leave empty for all)
- `PLUGINS`: List of active plugins
### 3. Run installation
```bash
bash ./setup
```
### 4. First run
```bash
node ./src/main.js
```
Scan the QR Code in WhatsApp:
**Menu → Linked Devices → Link a Device**
---
## Windows
ManyBot was designed for Linux, but works on Windows via **Git Bash**.
### Prerequisites
1. **Git Bash**: https://git-scm.com/download/win
2. **Node.js**: https://nodejs.org (choose "Windows Installer (.msi)")
### Installation
After installing both, open **Git Bash** and follow the same steps as the [Linux installation](#linux).
---
## Termux (Android)
> ⚠️ **Warning:** Experimental support. No guarantee of functionality.
```bash
# Install Termux from F-Droid (don't use Play Store)
# https://f-droid.org/packages/com.termux/
# Update packages
pkg update && pkg upgrade
# Install dependencies
pkg install nodejs git
# Clone and install
git clone https://github.com/synt-xerror/manybot
cd manybot
```
Follow the Linux configuration steps from step 2.
---
## Troubleshooting
### QR Code scanning error
- Clear Chrome/Chromium data from Termux
- Delete the `session/` folder and try again
### Bot not responding to commands
- Check `CMD_PREFIX` in `manybot.conf`
- Make sure the plugin is in the `PLUGINS` list
### Installation errors
```bash
# Clean npm cache
npm cache clean --force
# Reinstall dependencies
rm -rf node_modules package-lock.json
npm install
```
---
## Next Steps
- [Advanced configuration](./CONFIGURATION.md)
- [Creating plugins](./PLUGINS_EN.md)

317
docs/PLUGINS (en).md Normal file
View File

@@ -0,0 +1,317 @@
# 🔌 Creating Plugins
Complete guide to creating plugins in ManyBot.
---
## 📑 Index
- [Basic Structure](#basic-structure)
- [Plugin Manifest](#plugin-manifest-manyplug-json)
- [Creating Your First Plugin](#creating-your-first-plugin)
- [Object API](#object-api)
- [Exposing API](#exposing-api-to-other-plugins)
- [Translating Your Plugin](#translating-your-plugin)
- [Error Handling](#error-handling)
---
## Basic Structure
```
src/plugins/
└── my-plugin/
├── index.js
├── manyplug.json
└── locale/ (optional)
├── en.json
├── pt.json
└── es.json
```
`index.js` must export a `default` function that receives `{ msg, api }`:
```javascript
export default async function ({ msg, api }) {
// Your logic here
}
```
---
## Plugin Manifest (manyplug.json)
Every plugin should have a `manyplug.json` at its root. It describes the plugin and declares any extra npm dependencies it needs.
```json
{
"name": "my-plugin",
"version": "1.0.0",
"category": "utility",
"service": false,
"dependencies": {}
}
```
### Fields
| Field | Type | Description |
|-------|------|-------------|
| `name` | `string` | Plugin identifier, must match the folder name |
| `version` | `string` | Semantic version (e.g., `"1.0.0"`) |
| `category` | `string` | Plugin category: `utility`, `media`, `game`, `humor`, `info` |
| `service` | `boolean` | `true` if the plugin runs in the background (scheduler, listener). `false` if triggered by a command or event |
| `dependencies` | `object` | Extra npm packages required by the plugin, same format as `package.json` |
### Example with dependencies
```json
{
"name": "weather",
"version": "1.0.0",
"category": "utility",
"service": false,
"dependencies": {
"axios": "^1.6.0"
}
}
```
After adding dependencies, run `npm install` at the project root to install them.
---
## Creating Your First Plugin
### Example 1: Simple command
```javascript
// plugins/greeting/index.js
import { CMD_PREFIX } from "../../config.js";
export default async function ({ msg, api }) {
// Only responds if the message starts with "!hi"
if (!msg.is(CMD_PREFIX + "hi")) return;
await msg.reply("Hello! 👋");
}
```
### Example 2: Command with arguments
```javascript
// plugins/calculate/index.js
import { CMD_PREFIX } from "../../config.js";
export default async function ({ msg, api }) {
if (!msg.is(CMD_PREFIX + "calculate")) return;
// msg.args = ["!calculate", "5", "+", "3"]
const [, a, operator, b] = msg.args;
let result;
switch (operator) {
case "+": result = Number(a) + Number(b); break;
case "-": result = Number(a) - Number(b); break;
case "*": result = Number(a) * Number(b); break;
case "/": result = Number(a) / Number(b); break;
default: return msg.reply("Invalid operator!");
}
await msg.reply(`Result: ${result}`);
}
```
### Example 3: Processing media
```javascript
// plugins/echo-media/index.js
import { CMD_PREFIX } from "../../config.js";
export default async function ({ msg, api }) {
if (!msg.is(CMD_PREFIX + "echo")) return;
// Checks if the message has media
if (!msg.hasMedia) {
return msg.reply("Send a media file with the command!");
}
// Downloads the media
const media = await msg.downloadMedia();
// Resends in the chat
await api.sendSticker(media.data);
}
```
---
## Object API
### `msg` Object
| Property | Type | Description |
|----------|------|-------------|
| `msg.body` | `string` | Message text |
| `msg.args` | `string[]` | Message tokens |
| `msg.type` | `string` | Type: `chat`, `image`, `video`, `audio`, `sticker` |
| `msg.sender` | `string` | Sender ID |
| `msg.senderName` | `string` | Sender name |
| `msg.fromMe` | `boolean` | Whether the bot sent it |
| `msg.hasMedia` | `boolean` | Whether it has media |
| `msg.hasReply` | `boolean` | Whether it is a reply |
| `msg.isGif` | `boolean` | Whether it is a GIF |
| `msg.is(cmd)` | `function` | Checks if starts with command |
| `msg.reply(text)` | `function` | Replies with quote |
| `msg.downloadMedia()` | `function` | Returns `{ mimetype, data }` |
| `msg.getReply()` | `function` | Returns quoted message |
### `api` Object
| Method | Description |
|--------|-------------|
| `api.send(text)` | Sends text |
| `api.sendVideo(path)` | Sends video |
| `api.sendAudio(path)` | Sends audio (voice) |
| `api.sendImage(path, caption?)` | Sends image |
| `api.sendSticker(bufferOrPath)` | Sends sticker |
| `api.getPlugin(name)` | Accesses another plugin |
| `api.chat.id` | Chat ID |
| `api.chat.name` | Chat name |
| `api.chat.isGroup` | Whether it is a group |
| `api.log.info(...)` | Info log |
| `api.log.warn(...)` | Warning log |
| `api.log.error(...)` | Error log |
---
## Exposing API to Other Plugins
A plugin can export functions for others to use:
```javascript
// plugins/utilities/index.js
// Public API
export const api = {
formatDate: (date) => date.toLocaleDateString("en-US"),
formatCurrency: (value) => `$${value.toFixed(2)}`,
wait: (ms) => new Promise(resolve => setTimeout(resolve, ms))
};
// Normal plugin logic
export default async function ({ msg }) {
if (msg.is("!ping")) {
await msg.reply("pong!");
}
}
```
Another plugin using it:
```javascript
// plugins/other/index.js
export default async function ({ msg, api }) {
const utils = api.getPlugin("utilities");
const date = utils.formatDate(new Date());
await msg.reply(`Today is ${date}`);
}
```
---
## Translating Your Plugin
Each plugin can have its own translations, completely independent from the bot core. The bot locale (set in `manybot.conf`) is used automatically.
### Structure
```
src/plugins/
└── my-plugin/
├── index.js
└── locale/
├── en.json
├── pt.json
└── es.json
```
### locale/en.json
```json
{
"hello": "Hello, {{name}}! 👋",
"error": {
"notFound": "Item not found."
}
}
```
### index.js
```javascript
import { CMD_PREFIX } from "../../config.js";
import { createPluginI18n } from "../../utils/pluginI18n.js";
const { t } = createPluginI18n(import.meta.url);
export default async function ({ msg }) {
if (!msg.is(CMD_PREFIX + "hi")) return;
// Simple key
await msg.reply(t("hello", { name: msg.senderName }));
// Nested key
await msg.reply(t("error.notFound"));
}
```
### Notes
- If the configured locale has no translation file, falls back to `en.json`.
- If the key doesn't exist in any file, the key itself is returned as-is.
- Use `{{variable}}` syntax for interpolation.
- Each plugin manages its own translations — never import `t` from the bot core.
---
## Error Handling
If a plugin throws an error, the kernel automatically disables it:
```javascript
export default async function ({ msg, api }) {
try {
// Code that might fail
const result = await somethingRisky();
await msg.reply(result);
} catch (error) {
// Logs the error and notifies
api.log.error("Plugin error:", error);
await msg.reply("Oops! Something went wrong.");
}
}
```
---
## Enabling the Plugin
After creating it, add to `manybot.conf`:
```bash
PLUGINS=[
# ... other plugins
my-plugin
]
```
Restart the bot to load it.
---
## See Also
- [API Reference](./API.md)
- [Plugin examples](../src/plugins/)

317
docs/PLUGINS.md Normal file
View File

@@ -0,0 +1,317 @@
# 🔌 Criando Plugins
Guia completo para criar plugins no ManyBot.
---
## 📑 Índice
- [Estrutura Básica](#estrutura-básica)
- [Manifesto do Plugin](#manifesto-do-plugin-manyplugjson)
- [Criando Seu Primeiro Plugin](#criando-seu-primeiro-plugin)
- [API de Objetos](#api-de-objetos)
- [Expondo API](#expondo-api-para-outros-plugins)
- [Traduzindo Seu Plugin](#traduzindo-seu-plugin)
- [Tratamento de Erros](#tratamento-de-erros)
---
## Estrutura Básica
```
src/plugins/
└── meu-plugin/
├── index.js
├── manyplug.json
└── locale/ (opcional)
├── en.json
├── pt.json
└── es.json
```
O `index.js` deve exportar uma função `default` que recebe `{ msg, api }`:
```javascript
export default async function ({ msg, api }) {
// Sua lógica aqui
}
```
---
## Manifesto do Plugin (manyplug.json)
Todo plugin deve ter um `manyplug.json` na raiz. Ele descreve o plugin e declara dependências npm extras que ele precisar.
```json
{
"name": "meu-plugin",
"version": "1.0.0",
"category": "utility",
"service": false,
"dependencies": {}
}
```
### Campos
| Campo | Tipo | Descrição |
|-------|------|-----------|
| `name` | `string` | Identificador do plugin, deve ser igual ao nome da pasta |
| `version` | `string` | Versão semântica (ex: `"1.0.0"`) |
| `category` | `string` | Categoria do plugin: `utility`, `media`, `game`, `humor`, `info` |
| `service` | `boolean` | `true` se o plugin roda em segundo plano (agendador, listener). `false` se acionado por comando ou evento |
| `dependencies` | `object` | Pacotes npm extras necessários, mesmo formato do `package.json` |
### Exemplo com dependências
```json
{
"name": "clima",
"version": "1.0.0",
"category": "utility",
"service": false,
"dependencies": {
"axios": "^1.6.0"
}
}
```
Após adicionar dependências, rode `npm install` na raiz do projeto para instalá-las.
---
## Criando Seu Primeiro Plugin
### Exemplo 1: Comando simples
```javascript
// plugins/saudacao/index.js
import { CMD_PREFIX } from "../../config.js";
export default async function ({ msg, api }) {
// Só responde se a mensagem começar com "!oi"
if (!msg.is(CMD_PREFIX + "oi")) return;
await msg.reply("Olá! 👋");
}
```
### Exemplo 2: Comando com argumentos
```javascript
// plugins/calcular/index.js
import { CMD_PREFIX } from "../../config.js";
export default async function ({ msg, api }) {
if (!msg.is(CMD_PREFIX + "calcular")) return;
// msg.args = ["!calcular", "5", "+", "3"]
const [, a, operador, b] = msg.args;
let resultado;
switch (operador) {
case "+": resultado = Number(a) + Number(b); break;
case "-": resultado = Number(a) - Number(b); break;
case "*": resultado = Number(a) * Number(b); break;
case "/": resultado = Number(a) / Number(b); break;
default: return msg.reply("Operador inválido!");
}
await msg.reply(`Resultado: ${resultado}`);
}
```
### Exemplo 3: Processando mídia
```javascript
// plugins/echo-media/index.js
import { CMD_PREFIX } from "../../config.js";
export default async function ({ msg, api }) {
if (!msg.is(CMD_PREFIX + "echo")) return;
// Verifica se a mensagem tem mídia
if (!msg.hasMedia) {
return msg.reply("Envie uma mídia com o comando!");
}
// Baixa a mídia
const media = await msg.downloadMedia();
// Reenvia no chat
await api.sendSticker(media.data);
}
```
---
## API de Objetos
### Objeto `msg`
| Propriedade | Tipo | Descrição |
|-------------|------|-----------|
| `msg.body` | `string` | Texto da mensagem |
| `msg.args` | `string[]` | Tokens da mensagem |
| `msg.type` | `string` | Tipo: `chat`, `image`, `video`, `audio`, `sticker` |
| `msg.sender` | `string` | ID do remetente |
| `msg.senderName` | `string` | Nome do remetente |
| `msg.fromMe` | `boolean` | Se o bot enviou |
| `msg.hasMedia` | `boolean` | Se tem mídia |
| `msg.hasReply` | `boolean` | Se é resposta |
| `msg.isGif` | `boolean` | Se é GIF |
| `msg.is(cmd)` | `function` | Verifica se começa com comando |
| `msg.reply(text)` | `function` | Responde com quote |
| `msg.downloadMedia()` | `function` | Retorna `{ mimetype, data }` |
| `msg.getReply()` | `function` | Retorna mensagem citada |
### Objeto `api`
| Método | Descrição |
|--------|-----------|
| `api.send(text)` | Envia texto |
| `api.sendVideo(path)` | Envia vídeo |
| `api.sendAudio(path)` | Envia áudio (voz) |
| `api.sendImage(path, caption?)` | Envia imagem |
| `api.sendSticker(bufferOrPath)` | Envia figurinha |
| `api.getPlugin(name)` | Acessa outro plugin |
| `api.chat.id` | ID do chat |
| `api.chat.name` | Nome do chat |
| `api.chat.isGroup` | Se é grupo |
| `api.log.info(...)` | Log informativo |
| `api.log.warn(...)` | Log de aviso |
| `api.log.error(...)` | Log de erro |
---
## Expondo API para Outros Plugins
Um plugin pode exportar funções para outros usarem:
```javascript
// plugins/utilidades/index.js
// API pública
export const api = {
formatarData: (date) => date.toLocaleDateString("pt-BR"),
formatarMoeda: (valor) => `R$ ${valor.toFixed(2).replace(".", ",")}`,
esperar: (ms) => new Promise(resolve => setTimeout(resolve, ms))
};
// Lógica normal do plugin
export default async function ({ msg }) {
if (msg.is("!ping")) {
await msg.reply("pong!");
}
}
```
Outro plugin usando:
```javascript
// plugins/outro/index.js
export default async function ({ msg, api }) {
const utils = api.getPlugin("utilidades");
const data = utils.formatarData(new Date());
await msg.reply(`Hoje é ${data}`);
}
```
---
## Traduzindo Seu Plugin
Cada plugin pode ter suas próprias traduções, completamente independentes do core do bot. O locale do bot (definido no `manybot.conf`) é usado automaticamente.
### Estrutura
```
src/plugins/
└── meu-plugin/
├── index.js
└── locale/
├── en.json
├── pt.json
└── es.json
```
### locale/pt.json
```json
{
"ola": "Olá, {{nome}}! 👋",
"erro": {
"naoEncontrado": "Item não encontrado."
}
}
```
### index.js
```javascript
import { CMD_PREFIX } from "../../config.js";
import { createPluginI18n } from "../../utils/pluginI18n.js";
const { t } = createPluginI18n(import.meta.url);
export default async function ({ msg }) {
if (!msg.is(CMD_PREFIX + "oi")) return;
// Chave simples
await msg.reply(t("ola", { nome: msg.senderName }));
// Chave aninhada
await msg.reply(t("erro.naoEncontrado"));
}
```
### Observações
- Se o locale configurado não tiver arquivo de tradução, cai automaticamente para `en.json`.
- Se a chave não existir em nenhum arquivo, a própria chave é retornada.
- Use a sintaxe `{{variavel}}` para interpolação.
- Cada plugin gerencia suas próprias traduções — nunca importe `t` do core do bot.
---
## Tratamento de Erros
Se um plugin lançar erro, o kernel o desativa automaticamente:
```javascript
export default async function ({ msg, api }) {
try {
// Código que pode falhar
const resultado = await algoPerigoso();
await msg.reply(resultado);
} catch (erro) {
// Loga o erro e notifica
api.log.error("Erro no plugin:", erro);
await msg.reply("Ops! Algo deu errado.");
}
}
```
---
## Ativando o Plugin
Depois de criar, adicione ao `manybot.conf`:
```bash
PLUGINS=[
# ... outros plugins
meu-plugin
]
```
Reinicie o bot para carregar.
---
## Veja Também
- [Referência da API](./API.md)
- [Exemplos de plugins](../src/plugins/)