+

-ManyBot é um bot para WhatsApp que roda 100% localmente, sem depender da API oficial do WhatsApp. Ele utiliza a biblioteca `whatsapp-web.js`, que automatiza o WhatsApp Web sem depender de gráficos (headless).
+
+ Bot para WhatsApp 100% local, sem API oficial
+
-Algumas funcionalidades desse bot incluem:
-- Suporte a múltiplos chats em uma única sessão
-- Sistema de plugins — adicione, remova ou crie funcionalidades sem mexer no núcleo do bot
+
+
+
+
+> **Versão Oficial Online**
+> Quer usar o ManyBot sem instalar? Adicione o bot oficial:
+>
+> **+55 (16) 99459-1903**
+>
+> Online 24h (quando possível) - Disponibilidade não garantida
+>
+> Ao adicionar, você concorda com os [Termos de Uso](TERMOS_pt-br.md)

-
+
---
-# Requisitos
-- Node.js
-- NPM
-- Sistema Linux ou Windows
+## Recursos
-obs: Sistemas Android e iOS ainda não são 100% compatíveis. O suporte para Termux está em fases de testes e sem garantia de funcionamento correto.
+- **100% Local** - Sem depender da API oficial do WhatsApp
+- **Multi-chat** - Suporte a múltiplos chats em uma única sessão
+- **Sistema de Plugins** - Adicione, remova ou crie funcionalidades sem mexer no núcleo
+- **Headless** - Funciona em segundo plano sem interface gráfica
+- **Fácil Configuração** - Arquivo de config simples e intuitivo
-# Instalação (Linux)
+---
+
+## Instalação Rápida
+
+### Opção 1: Usar o Bot Oficial (Sem instalar)
+
+Adicione o número **+55 (16) 99459-1903** aos seus contatos e envie `!many` para ver os comandos disponíveis.
+
+**Status:** 🟢 Online (24h quando possível, mas sem garantia)
+
+> ⚠️ **Importante:** Ao usar o bot oficial, você concorda com os [Termos de Uso](TERMOS_pt-br.md). Leia antes de adicionar!
+
+---
+
+### Opção 2: Instalar sua Própria Versão
-1. Clone o repositório e entre:
```bash
+# 1. Clone o repositório
git clone https://github.com/synt-xerror/manybot
cd manybot
-```
-2. Crie e abra o arquivo de configuração (use o editor de sua preferência):
-```bash
-touch manybot.conf
+# 2. Crie o arquivo de configuração
+cp manybot.conf.example manybot.conf
+
+# 3. Configure conforme sua necessidade (veja a documentação)
nano manybot.conf
-```
-3. Nele você pode configurar algumas coisas do ManyBot. Esse é o arquivo base para que possa modificar:
-```bash
-# Comentários com '#'
-
-CLIENT_ID=bot_permanente
-CMD_PREFIX=!
-CHATS=[
- 123456789@c.us,
- 123456789@g.us
-]
-PLUGINS=[
- video,
- audio,
- figurinha,
- adivinhacao
-]
-```
-- **CLIENT_ID:** ID do cliente, serve para identificar sua sessão.
- - Valor padrão: `bot_permanente`
-- **CMD_PREFIX:** Prefixo do comando, o caractere que você usa para executar um comando (!many, !figurinha).
- - Valor padrão: `!`
-- **CHATS:** ID dos chats no qual você quer que o bot assista. Use o utilitário: `src/utils/get_id.js` para descobrir os IDs. Deixe vazio caso queira que funcione com qualquer chat.
- - Valor padrão: (nenhum)
-- **PLUGINS:** Lista de plugins ativos. Cada nome corresponde a uma pasta dentro de `src/plugins/`. Remova ou comente uma linha para desativar o plugin sem apagá-lo.
- - Valor padrão: (nenhum)
-
-obs: o utilitário `src/utils/get_id.js` usa um CLIENT_ID separado para que não entre em conflito com a sessão principal do ManyBot. Você terá que escanear o QR Code novamente para executá-lo.
-
-4. Execute o script de instalação:
-```bash
+# 4. Execute o script de instalação
bash ./setup
-```
-5. Rode o bot pela primeira vez (você deve rodar da raiz, não dentro de `src`):
-```bash
-node ./src/main.js
-```
-Ele vai pedir para que escaneie o QR Code com seu celular.
-
-No WhatsApp:
-Menu (três pontos) > Dispositivos conectados > Conectar um dispositivo
-
-# Instalação (Windows)
-
-O uso desse bot foi pensado para rodar em um terminal Linux. No entanto, você pode usar o Git Bash, que simula um terminal Linux com Bash real:
-
-1. Para baixar o Git Bash: https://git-scm.com/install/windows
-Selecione a versão que deseja (portátil ou instalador)
-
-2. Para baixar o Node.js: https://nodejs.org/pt-br/download
-Role a tela e selecione "Instalador Windows (.msi)"
-Ou se preferir, use um gerenciador de pacotes como mostra no conteúdo inicial
-
-Depois de instalar ambos, abra o Git Bash e execute exatamente os mesmos comandos mostrados na seção Linux.
-
-# Uso
-
-Feito a instalação, você pode executar o bot apenas rodando:
-```bash
+# 5. Rode o bot
node ./src/main.js
```
-## Atualizações
+📱 **Escaneie o QR Code** no WhatsApp: Menu → Dispositivos conectados → Conectar um dispositivo
+
+> **⚡ Pronto!** Veja a [documentação completa](docs/INSTALACAO.md) para mais detalhes.
+
+---
+
+## 💻 Uso
-É recomendável sempre ter a versão mais recente do ManyBot. Para isso, temos um utilitário logo na raíz. Para executar:
```bash
+# Iniciar o bot
+node ./src/main.js
+
+# Atualizar para a versão mais recente
bash ./update
+
+# Descobrir IDs de chats
+node src/utils/get_id.js
```
-## Criando um serviço (opcional)
+---
-Se estiver rodando numa VPS ou apenas quer mais controle, é recomendável criar um serviço systemd. Siga os passos abaixo para saber como criar, habilitar e gerenciar um.
+## 🔌 Plugins
-1. Configurando o diretório
+O ManyBot é construído em torno de um sistema de plugins. O kernel apenas conecta ao WhatsApp e distribui as mensagens — os plugins decidem o que fazer.
-Primeiro passo é garantir que o diretório do ManyBot esteja no local adequado, é recomendável guardar em `/root/manybot` (os passos a seguir supõem que esteja essa localização)
+### Plugins Incluídos
-2. Criando o serviço
+| Plugin | Comando | Descrição |
+|--------|---------|-----------|
+| **figurinha** | `!figurinha` | Converte imagens, GIFs e vídeos em figurinhas |
+| **video** | `!video ` | Baixa vídeos da internet |
+| **audio** | `!audio ` | Baixa áudio de vídeos como mensagem de voz |
+| **adivinhacao** | `!adivinhacao comecar` | Jogo de adivinhação (1-100) |
+| **forca** | `!forca comecar` | Jogo da forca clássico |
+| **many** | `!many` | Lista todos os comandos disponíveis |
+| **obrigado** | `!obrigado` | Responde agradecimentos |
-Abra o arquivo:
-```bash
-/etc/systemd/system/manybot.service
-```
+### Criar um Plugin
-E cole o seguinte conteúdo:
-```conf
-[Unit]
-Description=ManyBot
-After=network.target
-
-[Service]
-ExecStart=/usr/bin/env node /root/manybot/src/main.js
-WorkingDirectory=/root/manybot
-Restart=always
-Environment=NODE_ENV=production
-
-[Install]
-WantedBy=multi-user.target
-```
-
-3. Iniciando e habilitando o serviço:
-
-Primeiro reinicie o daemon do systemd:
-```bash
-systemctl daemon-reload
-```
-
-Inicie o serviço:
-```bash
-systemctl start manybot
-```
-
-Habilite para que ele seja iniciado junto com o seu sistema (opcional):
-```bash
-systemctl enable manybot
-```
-
-4. Gerenciando o serviço:
-
-Ver logs:
-```bash
-journalctl -u manybot
-```
-
-Em tempo real:
-```bash
-journalctl -u manybot -f
-```
-
-Parar o serviço:
-```bash
-systemctl stop manybot
-```
-
-Reiniciar o serviço:
-```bash
-systemctl restart manybot
-```
-
-Saiba mais sobre como gerenciar serviços em: https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units-pt
-Sobre o journalctl: https://www.digitalocean.com/community/tutorials/how-to-use-journalctl-to-view-and-manipulate-systemd-logs-pt
-
-# Plugins
-
-O ManyBot é construído em torno de um sistema de plugins. O núcleo do bot (kernel) apenas conecta ao WhatsApp e distribui as mensagens — quem decide o que fazer com elas são os plugins.
-
-Isso significa que você pode adicionar, remover ou criar funcionalidades sem tocar no código principal do bot.
-
-## Plugins incluídos
-
-O ManyBot vem com alguns plugins prontos para uso, como:
-
-- **video** — baixa um vídeo da internet e envia no chat (`!video `)
-- **audio** — baixa o áudio de um vídeo e envia como mensagem de voz (`!audio `)
-- **figurinha** — converte imagens, GIFs e vídeos em figurinhas (`!figurinha`)
-- **adivinhacao** — jogo de adivinhação de um número entre 1 e 100 (`!adivinhação começar`)
-- **forca** — clássico jogo da forca (`!forca começar`)
-- **many** — exibe a lista de comandos disponíveis (`!many`)
-- **obrigado** — responde agradecimentos (`!obrigado`, `!valeu`, `!brigado`)
-
-Para ativar ou desativar qualquer um deles, basta editar a lista `PLUGINS` no `manybot.conf`.
-
-## Criando um plugin
-
-Cada plugin é uma pasta dentro de `plugins/` com um arquivo `index.js`. O bot carrega automaticamente todos os plugins listados no `manybot.conf`.
-
-A estrutura mínima de um plugin:
-
-```
-plugins/
-└── meu-plugin/
- └── index.js
-```
-
-O `index.js` deve exportar uma função `default` que o kernel chama a cada mensagem recebida. A função recebe `{ msg, api }` e decide por conta própria se age ou ignora:
-
-```js
+```javascript
// plugins/meu-plugin/index.js
-
-import { CMD_PREFIX } from "../../config.js"
+import { CMD_PREFIX } from "../../config.js";
export default async function ({ msg, api }) {
if (!msg.is(CMD_PREFIX + "oi")) return;
-
await msg.reply("Olá! 👋");
}
```
-### O objeto `msg`
+Veja mais na [documentação de plugins](docs/PLUGINS.md).
-Contém as informações da mensagem recebida:
+---
-| Propriedade | Descrição |
-|---|---|
-| `msg.body` | Texto da mensagem |
-| `msg.args` | Tokens da mensagem — `["!video", "https://..."]` |
-| `msg.type` | Tipo — `"chat"`, `"image"`, `"video"`, `"audio"`, `"sticker"` |
-| `msg.sender` | ID de quem enviou |
-| `msg.senderName` | Nome de quem enviou |
-| `msg.fromMe` | `true` se foi o próprio bot que enviou |
-| `msg.hasMedia` | `true` se a mensagem tem mídia |
-| `msg.hasReply` | `true` se é uma resposta a outra mensagem |
-| `msg.isGif` | `true` se a mídia é um GIF |
-| `msg.is(cmd)` | Retorna `true` se a mensagem começa com `cmd` |
-| `msg.reply(text)` | Responde à mensagem com quote |
-| `msg.downloadMedia()` | Baixa a mídia — retorna `{ mimetype, data }` |
-| `msg.getReply()` | Retorna a mensagem citada, ou `null` |
+## 📚 Documentação
-### O objeto `api`
+- [📥 Instalação Completa](docs/INSTALACAO.md) — Linux, Windows, Termux
+- [⚙️ Configuração](docs/CONFIGURACAO.md) — Todas as opções do `manybot.conf`
+- [🔌 Criando Plugins](docs/PLUGINS.md) — Guia completo de desenvolvimento
+- [🖥️ Serviço Systemd](docs/SYSTEMD.md) — Rodar como serviço Linux
+- [🛠️ API de Plugins](docs/API.md) — Referência de objetos `msg` e `api`
-Contém tudo que o plugin pode fazer — enviar mensagens, acessar outros plugins, registrar logs:
+## 🌍 Internacionalização
-| Método | Descrição |
-|---|---|
-| `api.send(text)` | Envia texto no chat |
-| `api.sendVideo(filePath)` | Envia um vídeo a partir de um arquivo local |
-| `api.sendAudio(filePath)` | Envia um áudio a partir de um arquivo local |
-| `api.sendImage(filePath, caption?)` | Envia uma imagem a partir de um arquivo local |
-| `api.sendSticker(bufferOuPath)` | Envia uma figurinha — aceita `Buffer` ou caminho |
-| `api.getPlugin(name)` | Retorna a API pública de outro plugin |
-| `api.chat.id` | ID do chat atual |
-| `api.chat.name` | Nome do chat atual |
-| `api.chat.isGroup` | `true` se é um grupo |
-| `api.log.info(...)` | Loga uma mensagem informativa |
-| `api.log.warn(...)` | Loga um aviso |
-| `api.log.error(...)` | Loga um erro |
+O ManyBot suporta múltiplos idiomas. Configure no `manybot.conf`:
-### Lendo o manybot.conf no plugin
-
-Se o seu plugin precisar de configurações próprias, você pode adicioná-las diretamente no `manybot.conf` e importá-las no código:
-
-```js
-import { MEU_PREFIXO } from "../../src/config.js";
-
-const prefixo = MEU_PREFIXO ?? "padrão";
+```bash
+LANGUAGE=pt # Português
+LANGUAGE=en # English
+LANGUAGE=es # Español
```
-### Expondo uma API para outros plugins
+- **Padrão:** Inglês (`en`)
+- **Fallback:** Se o idioma selecionado não existir, o bot usa inglês
-Um plugin pode expor funções para que outros plugins as utilizem. Para isso, basta exportar um objeto `api`:
+---
-```js
-// plugins/utilidades/index.js
+## 📋 Requisitos
-export const api = {
- formatarData: (date) => date.toLocaleDateString("pt-BR"),
-};
+- **Node.js** 18+
+- **NPM** 9+
+- **Linux** ou **Windows** (via Git Bash)
-export default async function ({ msg }) {
- // lógica normal do plugin
-}
-```
+> ⚠️ Android/iOS e Termux têm suporte experimental sem garantias.
-Outro plugin pode chamar:
+---
-```js
-const utils = api.getPlugin("utilidades");
-utils.formatarData(new Date());
-```
+## 📝 Licença
-### Erros no plugin
+Distribuído sob a licença **GPLv3**. Veja [LICENSE](LICENSE) para mais detalhes.
-Se um plugin lançar um erro, o kernel o desativa automaticamente e loga o problema — o restante dos plugins continua funcionando normalmente. Isso garante que um plugin com bug não derruba o bot inteiro.
+---
-# Considerações
+
-ManyBot é distribuído sob a licença GPLv3. Você pode usar, modificar e redistribuir o software conforme os termos da licença.
+**[⬆ Voltar ao topo](#)**
-Saiba mais sobre as permissões lendo o arquivo [LICENSE](LICENSE) ou em: https://www.gnu.org/licenses/quick-guide-gplv3.pt-br.html
\ No newline at end of file
+
diff --git a/README_EN.md b/README_EN.md
new file mode 100644
index 0000000..e3b0677
--- /dev/null
+++ b/README_EN.md
@@ -0,0 +1,188 @@
+
+
+
+
+> 🟢 **Official Instance Online**
+> Want to use ManyBot without installing? Add the official bot:
+>
+> **+55 (16) 99459-1903**
+>
+> Online 24h (when possible) · Availability not guaranteed
+>
+> By adding, you agree to the [Terms of Use](TERMS_en-us.md)
+
+
+
+
+
+---
+
+## ✨ Features
+
+- **100% Local** — No dependency on the official WhatsApp API
+- **Multi-chat** — Support for multiple chats in a single session
+- **Plugin System** — Add, remove, or create features without touching the core
+- **Headless** — Runs in the background without a GUI
+- **Easy Configuration** — Simple and intuitive config file
+
+---
+
+## 🚀 Quick Install
+
+### Option 1: Use the Official Bot (No install)
+
+Add the number **+55 (16) 99459-1903** to your contacts and send `!many` to see available commands.
+
+**Status:** 🟢 Online (24h when possible, but no guarantee)
+
+> ⚠️ **Important:** By using the official bot, you agree to the [Terms of Use](TERMS_en-us.md). Read before adding!
+
+---
+
+### Option 2: Install Your Own Version
+
+```bash
+# 1. Clone the repository
+git clone https://github.com/synt-xerror/manybot
+cd manybot
+
+# 2. Create the config file
+cp manybot.conf.example manybot.conf
+
+# 3. Configure as needed (see documentation)
+nano manybot.conf
+
+# 4. Run the install script
+bash ./setup
+
+# 5. Run the bot
+node ./src/main.js
+```
+
+📱 **Scan the QR Code** on WhatsApp: Menu → Linked Devices → Link a Device
+
+> **⚡ Done!** See the [full documentation](docs/INSTALLATION.md) for more details.
+
+---
+
+## 💻 Usage
+
+```bash
+# Start the bot
+node ./src/main.js
+
+# Update to the latest version
+bash ./update
+
+# Discover chat IDs
+node src/utils/get_id.js
+```
+
+---
+
+## 🔌 Plugins
+
+ManyBot is built around a plugin system. The kernel only connects to WhatsApp and distributes messages — plugins decide what to do.
+
+### Included Plugins
+
+| Plugin | Command | Description |
+|--------|---------|-------------|
+| **sticker** | `!sticker` | Converts images, GIFs, and videos into stickers |
+| **video** | `!video ` | Downloads videos from the internet |
+| **audio** | `!audio ` | Downloads audio from videos as voice messages |
+| **guess** | `!guess start` | Guessing game (1-100) |
+| **hangman** | `!hangman start` | Classic hangman game |
+| **many** | `!many` | Lists all available commands |
+| **thanks** | `!thanks` | Responds to thanks |
+
+### Create a Plugin
+
+```javascript
+// plugins/my-plugin/index.js
+import { CMD_PREFIX } from "../../config.js";
+
+export default async function ({ msg, api }) {
+ if (!msg.is(CMD_PREFIX + "hello")) return;
+ await msg.reply("Hello! 👋");
+}
+```
+
+See more in the [plugin documentation](docs/PLUGINS_EN.md).
+
+---
+
+## 📚 Documentation
+
+- [📥 Full Installation](docs/INSTALLATION.md) — Linux, Windows, Termux
+- [⚙️ Configuration](docs/CONFIGURATION.md) — All `manybot.conf` options
+- [🔌 Creating Plugins](docs/PLUGINS.md) — Complete development guide
+- [🖥️ Systemd Service](docs/SYSTEMD.md) — Run as a Linux service
+- [🛠️ Plugin API](docs/API.md) — Reference for `msg` and `api` objects
+
+## 🌍 Internationalization
+
+ManyBot supports multiple languages. Configure in `manybot.conf`:
+
+```bash
+LANGUAGE=pt # Português
+LANGUAGE=en # English
+LANGUAGE=es # Español
+```
+
+- **Default:** English (`en`)
+- **Fallback:** If selected language doesn't exist, bot falls back to English
+
+---
+
+## 📋 Requirements
+
+- **Node.js** 18+
+- **NPM** 9+
+- **Linux** or **Windows** (via Git Bash)
+
+> ⚠️ Android/iOS and Termux have experimental support with no guarantees.
+
+---
+
+## 📝 License
+
+Distributed under the **GPLv3** license. See [LICENSE](LICENSE) for details.
+
+---
+
+
+
+**[⬆ Back to top](#)**
+
+
diff --git a/TERMOS_pt-br.md b/TERMOS_pt-br.md
index 473bc86..abb5d0b 100644
--- a/TERMOS_pt-br.md
+++ b/TERMOS_pt-br.md
@@ -1,6 +1,6 @@
## Termos de Uso
-> Este arquivo poderá ser excluído no futuro, assim que o site oficial for lançado.
+> Este arquivo poderá ser movido no futuro, assim que o site oficial for lançado.
### 1. Natureza do Software
diff --git a/TERMS_en-us.md b/TERMS_en-us.md
index d6c385b..3cd6e9e 100644
--- a/TERMS_en-us.md
+++ b/TERMS_en-us.md
@@ -1,6 +1,6 @@
## Terms of Use
-. This is file may be deleted in the future as the official webpage is launched.
+> This is file may be moved in the future as the official webpage is launched.
### 1. Nature of the Software
diff --git a/docs/API (en).md b/docs/API (en).md
new file mode 100644
index 0000000..f2bc673
--- /dev/null
+++ b/docs/API (en).md
@@ -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`
+
+---
+
+#### `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`
+
+---
+
+#### `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`
+
+---
+
+#### `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`
+
+---
+
+#### `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`
+
+---
+
+#### `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`
+
+---
+
+### 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!");
+}
+```
\ No newline at end of file
diff --git a/docs/API.md b/docs/API.md
new file mode 100644
index 0000000..6a28b9f
--- /dev/null
+++ b/docs/API.md
@@ -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`
+
+---
+
+#### `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`
+
+---
+
+#### `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`
+
+---
+
+#### `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`
+
+---
+
+#### `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`
+
+---
+
+#### `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`
+
+---
+
+### 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!");
+}
+```
diff --git a/docs/CONFIGURACAO.md b/docs/CONFIGURACAO.md
new file mode 100644
index 0000000..7876473
--- /dev/null
+++ b/docs/CONFIGURACAO.md
@@ -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
+```
diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md
new file mode 100644
index 0000000..a3ed47b
--- /dev/null
+++ b/docs/CONFIGURATION.md
@@ -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
+```
diff --git a/docs/INSTALACAO.md b/docs/INSTALACAO.md
new file mode 100644
index 0000000..efce707
--- /dev/null
+++ b/docs/INSTALACAO.md
@@ -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)
diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md
new file mode 100644
index 0000000..9a20404
--- /dev/null
+++ b/docs/INSTALLATION.md
@@ -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)
diff --git a/docs/PLUGINS (en).md b/docs/PLUGINS (en).md
new file mode 100644
index 0000000..476a952
--- /dev/null
+++ b/docs/PLUGINS (en).md
@@ -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/)
\ No newline at end of file
diff --git a/docs/PLUGINS.md b/docs/PLUGINS.md
new file mode 100644
index 0000000..9275ebd
--- /dev/null
+++ b/docs/PLUGINS.md
@@ -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/)
\ No newline at end of file
diff --git a/man/man1/manybot-plugin.1 b/man/man1/manybot-plugin.1
new file mode 100644
index 0000000..525e27f
--- /dev/null
+++ b/man/man1/manybot-plugin.1
@@ -0,0 +1,267 @@
+.TH MANYBOT-PLUGIN 1 "April 2026" "ManyBot 2.4.3" "User Commands"
+.SH NAME
+manybot-plugin \- ManyBot plugin development guide
+.SH SYNOPSIS
+.B manyplug.json
+.I manifest file
+.br
+.I src/plugins/
+.B plugin directory
+.SH DESCRIPTION
+ManyBot plugins extend the bot's functionality without modifying the core
+kernel. The kernel connects to WhatsApp and distributes messages to plugins,
+which decide how to respond.
+.PP
+Each plugin lives in its own folder under
+.I src/plugins/
+with a
+.B manyplug.json
+manifest file and an
+.B index.js
+entry point.
+.SH PLUGIN STRUCTURE
+.nf
+src/plugins/
+\(do__ my-plugin/
+ \(bu__ manyplug.json # Plugin manifest
+ \(bu__ index.js # Main entry point
+ \(bu__ locale/ # Translations (optional)
+ \(bu__ en.json
+ \(bu__ pt.json
+ \(bu__ es.json
+.fi
+.SH MANIFEST (manyplug.json)
+Every plugin must include a manifest describing its metadata:
+.PP
+.nf
+{
+ "name": "my-plugin",
+ "version": "1.0.0",
+ "category": "utility",
+ "service": false,
+ "dependencies": {
+ "axios": "^1.6.0"
+ }
+}
+.fi
+.TP
+.B name
+Plugin identifier. Must match the folder name.
+.TP
+.B version
+Semantic version (e.g., "1.0.0").
+.TP
+.B category
+Plugin type: \fButility\fR, \fBmedia\fR, \fBgame\fR, \fBhumor\fR, or \fBinfo\fR.
+.TP
+.B service
+\fBtrue\fR for background plugins (schedulers, listeners).
+\fBfalse\fR for command/event-triggered plugins.
+.TP
+.B dependencies
+Extra npm packages required. Install with \fBnpm install\fR from project root.
+.SH PLUGIN ENTRY POINT
+The
+.I index.js
+file must export a default async function:
+.PP
+.nf
+.B "export default async function ({ msg, api }) {"
+ // Plugin logic here
+.B "}"
+.fi
+.SS Parameters
+.TP
+.B msg
+Message object containing:
+.RS
+.IP \(bu 2
+\fBbody\fR - Full message text
+.IP \(bu 2
+\fBargs\fR - Array of message tokens
+.IP \(bu 2
+\fBtype\fR - Message type: chat, image, video, audio, sticker, ptt, document, location
+.IP \(bu 2
+\fBsender\fR - Sender ID (NUMBER@c.us or NUMBER@g.us)
+.IP \(bu 2
+\fBsenderName\fR - Display name
+.IP \(bu 2
+\fBfromMe\fR - True if bot sent the message
+.IP \(bu 2
+\fBhasMedia\fR - True if contains media
+.IP \(bu 2
+\fBhasReply\fR - True if it's a reply
+.IP \(bu 2
+\fBisGif\fR - True if media is GIF
+.IP \(bu 2
+\fBtimestamp\fR - Unix timestamp
+.IP \(bu 2
+\fBis(cmd)\fR - Check if message starts with command
+.IP \(bu 2
+\fBreply(text)\fR - Reply with quote
+.IP \(bu 2
+\fBdownloadMedia()\fR - Download media (returns {mimetype, data})
+.IP \(bu 2
+\fBgetReply()\fR - Get quoted message object
+.RE
+.TP
+.B api
+API object containing:
+.RS
+.IP \(bu 2
+\fBsend(text)\fR - Send text message
+.IP \(bu 2
+\fBsendVideo(path)\fR - Send video file
+.IP \(bu 2
+\fBsendAudio(path)\fR - Send audio as voice message
+.IP \(bu 2
+\fBsendImage(path, caption?)\fR - Send image with optional caption
+.IP \(bu 2
+\fBsendSticker(bufferOrPath)\fR - Send sticker from buffer or file
+.IP \(bu 2
+\fBgetPlugin(name)\fR - Access another plugin's public API
+.IP \(bu 2
+\fBchat\fR - Chat info: \fBid\fR, \fBname\fR, \fBisGroup\fR
+.IP \(bu 2
+\fBlog.info(...), log.warn(...), log.error(...)\fR - Logging methods
+.RE
+.SH EXAMPLES
+.SS Simple Command
+.nf
+import { CMD_PREFIX } from "../../config.js";
+
+export default async function ({ msg, api }) {
+ if (!msg.is(CMD_PREFIX + "hi")) return;
+ await msg.reply("Hello! 👋");
+}
+.fi
+.SS Command with Arguments
+.nf
+import { CMD_PREFIX } from "../../config.js";
+
+export default async function ({ msg, api }) {
+ if (!msg.is(CMD_PREFIX + "calc")) return;
+
+ const [, a, op, b] = msg.args;
+ let result;
+
+ switch (op) {
+ 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}`);
+}
+.fi
+.SS Processing Media
+.nf
+import { CMD_PREFIX } from "../../config.js";
+
+export default async function ({ msg, api }) {
+ if (!msg.is(CMD_PREFIX + "echo")) return;
+
+ if (!msg.hasMedia) {
+ return msg.reply("Send media with the command!");
+ }
+
+ const media = await msg.downloadMedia();
+ await api.sendSticker(media.data);
+}
+.fi
+.SS Exposing API to Other Plugins
+.nf
+// Public API for other plugins
+export const api = {
+ formatDate: (d) => d.toLocaleDateString("en-US"),
+ wait: (ms) => new Promise(r => setTimeout(r, ms))
+};
+
+// Normal plugin logic
+export default async function ({ msg }) {
+ if (msg.is("!ping")) await msg.reply("pong!");
+}
+.fi
+.PP
+Used by another plugin:
+.nf
+export default async function ({ msg, api }) {
+ const utils = api.getPlugin("utilities");
+ const date = utils.formatDate(new Date());
+ await msg.reply(`Today is ${date}`);
+}
+.fi
+.SH TRANSLATIONS
+Plugins can include their own translations:
+.PP
+.nf
+import { createPluginI18n } from "../../utils/pluginI18n.js";
+
+const { t } = createPluginI18n(import.meta.url);
+
+export default async function ({ msg }) {
+ if (!msg.is(CMD_PREFIX + "hello")) return;
+ await msg.reply(t("greeting", { name: msg.senderName }));
+}
+.fi
+.PP
+Locale file (\fIlocale/en.json\fR):
+.nf
+{
+ "greeting": "Hello, {{name}}! 👋"
+}
+.fi
+.PP
+If the configured locale has no translation file, falls back to \fBen.json\fR.
+Use \fB{{variable}}\fR syntax for interpolation.
+.SH ENABLING A PLUGIN
+Add the plugin folder name to
+.I manybot.confR:
+.PP
+.nf
+PLUGINS=[
+ many,
+ figurinha,
+ my-plugin
+]
+.fi
+.PP
+Restart ManyBot to load the plugin.
+.SH ERROR HANDLING
+If a plugin throws an error, the kernel automatically disables it.
+Use try/catch for graceful error handling:
+.PP
+.nf
+export default async function ({ msg, api }) {
+ try {
+ const result = await riskyOperation();
+ await msg.reply(result);
+ } catch (error) {
+ api.log.error("Plugin error:", error);
+ await msg.reply("Oops! Something went wrong.");
+ }
+}
+.fi
+.SH CONFIGURATION ACCESS
+Import settings from the main config:
+.PP
+.nf
+import { CMD_PREFIX, CLIENT_ID, CHATS, PLUGINS } from "../../config.js";
+
+// Custom config values also work
+import { MY_API_KEY } from "../../config.js";
+.fi
+.PP
+Add custom values to
+.I manybot.confR:
+.nf
+MY_API_KEY=secret_key_here
+.fi
+.SH SEE ALSO
+.BR manybot (1),
+.BR manyplug (1),
+.BR manybot.conf (5)
+.SH AUTHOR
+Written by synt-xerror.
+.SH REPORTING BUGS
+Report bugs at: https://github.com/synt-xerror/manybot/issues
diff --git a/man/man1/manybot.1 b/man/man1/manybot.1
new file mode 100644
index 0000000..dfbb7f2
--- /dev/null
+++ b/man/man1/manybot.1
@@ -0,0 +1,171 @@
+.TH MANYBOT 1 "April 2026" "ManyBot 2.4.3" "User Commands"
+.SH NAME
+manybot \- local WhatsApp bot with plugin system
+.SH SYNOPSIS
+.B node
+.I ./src/main.js
+.br
+.B node
+.I src/utils/get_id.js
+.br
+.B bash
+.I ./setup
+.br
+.B bash
+.I ./update
+.SH DESCRIPTION
+ManyBot is a 100%% local WhatsApp bot that operates without relying on the
+official WhatsApp API. It uses whatsapp-web.js to connect as a regular
+WhatsApp client and provides a modular plugin system for extending functionality.
+.PP
+The bot supports multiple chats in a single session, runs headless (without
+a GUI), and can be configured through a simple configuration file.
+.SH COMMANDS
+.TP
+.B !many
+List all available commands from loaded plugins.
+.TP
+.B !figurinha
+Convert images, GIFs, and videos to stickers.
+.TP
+.B !video \fIURL\fR
+Download videos from supported platforms.
+.TP
+.B !audio \fIURL\fR
+Download audio from videos and send as voice message.
+.TP
+.B !adivinhacao comecar
+Start a guessing game (1-100).
+.TP
+.B !forca comecar
+Start a hangman game.
+.TP
+.B !obrigado
+Bot responds with a thank-you message.
+.PP
+Command prefix can be configured via
+.B CMD_PREFIX
+in
+.IR manybot.conf .
+Default is
+.BR ! .
+.SH CONFIGURATION
+ManyBot uses a configuration file
+.I manybot.conf
+in the project root. Key options:
+.TP
+.B CLIENT_ID=\fIname\fR
+Unique identifier for the bot session. Creates a session/\fIname\fR folder
+for authentication data. Default: \fIbot_permanente\fR.
+.TP
+.B CMD_PREFIX=\fIchar\fR
+Character prefixing all commands. Default: \fI!\fR.
+.TP
+.B LANGUAGE=\fIcode\fR
+Bot interface language: \fBen\fR (English), \fBpt\fR (Portuguese), or \fBes\fR (Spanish).
+Default: \fBen\fR.
+.TP
+.B CHATS=[\fIid1\fR, \fIid2\fR, ...]
+List of allowed chat IDs. Empty array allows all chats.
+Format: \fBnumber@c.us\fR for private chats, \fBnumber@g.us\fR for groups.
+.TP
+.B PLUGINS=[\fIname1\fR, \fIname2\fR, ...]
+List of plugins to load at startup. Each name corresponds to a folder in
+.IR src/plugins/ .
+.PP
+See
+.BR manybot.conf (5)
+for complete configuration reference.
+.SH PLUGINS
+Plugins extend ManyBot functionality without modifying the kernel. Each plugin
+is a folder under
+.I src/plugins/
+containing:
+.TP
+.I index.js
+Main plugin file exporting a default async function receiving \fB{ msg, api }\fR.
+.TP
+.I manyplug.json
+Plugin manifest describing name, version, category, service status, and dependencies.
+.TP
+.I locale/
+Optional translation files (\fBen.json\fR, \fBpt.json\fR, \fBes.json\fR).
+.PP
+Plugins receive two objects:
+.TP
+.B msg
+Message information including \fBbody\fR, \fBargs\fR, \fBtype\fR, \fBsender\fR,
+\fBhasMedia\fR, methods \fBis()\fR, \fBreply()\fR, \fBdownloadMedia()\fR.
+.TP
+.B api
+Interaction methods including \fBsend()\fR, \fBsendVideo()\fR, \fBsendAudio()\fR,
+\fBsendImage()\fR, \fBsendSticker()\fR, \fBgetPlugin()\fR, and \fBlog\fR methods.
+.SH FILES
+.TP
+.I manybot.conf
+Main configuration file. See \fBmanybot.conf(5)\fR.
+.TP
+.I session/
+Authentication data and WhatsApp session storage.
+.TP
+.I src/plugins/
+Plugin directory containing all installed plugins.
+.TP
+.I src/main.js
+Bot entry point.
+.TP
+.I logs/
+Log files directory.
+.TP
+.I update.log
+Update script log output.
+.SH ENVIRONMENT
+.TP
+.B NODE_ENV
+Set to \fBproduction\fR to disable development features.
+.SH EXIT STATUS
+.TP
+.B 0
+Success
+.TP
+.B 1
+General error
+.TP
+.B 130
+Interrupted by user (Ctrl+C)
+.SH EXAMPLES
+.SS First run
+.nf
+$ node ./src/main.js
+# Scan QR code with WhatsApp:
+# Menu \-> Linked Devices \-> Link a Device
+.fi
+.SS Get chat IDs
+.nf
+$ node src/utils/get_id.js
+# Send a message in the target chat to see the ID
+.fi
+.SS Update to latest version
+.nf
+$ bash ./update
+.fi
+.SH SECURITY
+\(bu Bot runs with same privileges as the user running it
+.br
+\(bu Session data stored in \fIsession/\fR should be protected (chmod 700)
+.br
+\(bu CHATS whitelist recommended to limit bot exposure
+.br
+\(bu No official WhatsApp API keys required or used
+.SH SEE ALSO
+.BR manybot.conf (5),
+.BR manybot-plugin (1),
+.BR manyplug (1)
+.SH AUTHOR
+Written by synt-xerror.
+.SH COPYRIGHT
+Licensed under GPLv3. See LICENSE file for details.
+.br
+https://github.com/synt-xerror/manybot
+.SH BUGS
+Report bugs at: https://github.com/synt-xerror/manybot/issues
diff --git a/man/man5/manybot.conf.5 b/man/man5/manybot.conf.5
new file mode 100644
index 0000000..2d5d890
--- /dev/null
+++ b/man/man5/manybot.conf.5
@@ -0,0 +1,225 @@
+.TH MANYBOT.CONF 5 "April 2026" "ManyBot 2.4.3" "File Formats"
+.SH NAME
+manybot.conf \- ManyBot configuration file
+.SH SYNOPSIS
+.I manybot.conf
+.SH DESCRIPTION
+The
+.I manybot.conf
+file configures the ManyBot WhatsApp bot. It uses a simple key-value format
+with support for multiline lists. Comments start with \fB#\fR.
+.PP
+The file must be located in the project root directory, alongside
+.IR package.json .
+.SH FORMAT
+.nf
+# Comments start with '#'
+
+KEY=value
+KEY=[item1, item2, item3]
+.fi
+.SS Key-Value Pairs
+Simple configuration values:
+.PP
+.nf
+CLIENT_ID=my_bot
+CMD_PREFIX=!
+LANGUAGE=en
+.fi
+.SS Multiline Lists
+Arrays spanning multiple lines:
+.PP
+.nf
+CHATS=[
+ 123456789@c.us,
+ 123456789@g.us
+]
+
+PLUGINS=[
+ many,
+ figurinha,
+ audio,
+ video
+]
+.fi
+.SH OPTIONS
+.SS Core Settings
+.TP
+.B CLIENT_ID=\fIstring\fR
+Unique identifier for the bot session.
+.RS
+.IP \(bu 2
+Default: \fBbot_permanente\fR
+.IP \(bu 2
+Creates a \fIsession/CLIENT_ID/\fR folder for authentication data
+.IP \(bu 2
+Changing this starts a new session (requires QR code rescan)
+.RE
+.TP
+.B CMD_PREFIX=\fIcharacter\fR
+Character that prefixes all bot commands.
+.RS
+.IP \(bu 2
+Default: \fB!\fR
+.IP \(bu 2
+Example: \fB!\fR makes commands like \fB!video\fR, \fB!audio\fR
+.IP \(bu 2
+Changing to \fB.\fR would make commands \fB.video\fR, \fB.audio\fR
+.RE
+.TP
+.B LANGUAGE=\fIcode\fR
+Bot interface language.
+.RS
+.IP \(bu 2
+Default: \fBen\fR (English)
+.IP \(bu 2
+Options: \fBen\fR, \fBpt\fR (Portuguese), \fBes\fR (Spanish)
+.IP \(bu 2
+Fallback to English if selected language not found
+.RE
+.SS Chat Settings
+.TP
+.B CHATS=[\fIid1\fR, \fIid2\fR, ...]
+Whitelist of chat IDs where the bot responds.
+.RS
+.IP \(bu 2
+Default: \fB[]\fR (empty = respond to all chats)
+.IP \(bu 2
+Private chat format: \fBnumber@c.us\fR
+.IP \(bu 2
+Group format: \fBnumber@g.us\fR or \fBnumber-number@g.us\fR
+.IP \(bu 2
+Use \fBnode src/utils/get_id.js\fR to discover chat IDs
+.RE
+.SS Plugin Settings
+.TP
+.B PLUGINS=[\fIname1\fR, \fIname2\fR, ...]
+List of plugins to load at startup.
+.RS
+.IP \(bu 2
+Default: \fB[]\fR (no plugins loaded)
+.IP \(bu 2
+Each name must match a folder in \fIsrc/plugins/\fR
+.IP \(bu 2
+Order matters: plugins load in listed order
+.IP \(bu 2
+Comment out or remove to disable without deleting files
+.RE
+.SS Built-in Plugins
+.TP
+.B many
+Lists all available commands. Required for \fB!many\fR to work.
+.TP
+.B figurinha
+Converts images/GIFs/videos to WhatsApp stickers.
+.TP
+.B video
+Downloads videos from URLs.
+.TP
+.B audio
+Downloads audio from videos as voice messages.
+.TP
+.B adivinha\(,c\(oao
+Guessing game (1-100).
+.TP
+.B forca
+Hangman game.
+.TP
+.B obrigado
+Responds to thank-you messages.
+.SH CUSTOM SETTINGS
+You can add any custom key-value pairs for use by plugins:
+.PP
+.nf
+# In manybot.conf
+ADMIN_NUMBER=5511999999999@c.us
+API_KEY=your_secret_key
+MAX_DOWNLOAD_SIZE=50MB
+.fi
+.PP
+Access in plugins:
+.nf
+import { ADMIN_NUMBER, API_KEY, MAX_DOWNLOAD_SIZE } from "../../config.js";
+.fi
+.SH EXAMPLES
+.SS Minimal Configuration
+.nf
+# Basic bot setup
+CLIENT_ID=my_bot
+CMD_PREFIX=!
+LANGUAGE=en
+
+PLUGINS=[
+ many
+]
+.fi
+.SS Production Configuration
+.nf
+# Production bot with whitelist
+CLIENT_ID=bot_prod
+CMD_PREFIX=/
+LANGUAGE=pt
+
+CHATS=[
+ 5511999999999@c.us,
+ 5511888888888-123456789@g.us
+]
+
+PLUGINS=[
+ many,
+ figurinha,
+ video,
+ audio,
+ obrigado
+]
+
+# Custom settings
+ADMIN_NUMBER=5511999999999@c.us
+LOG_LEVEL=info
+.fi
+.SS Development Configuration
+.nf
+# Debug/development setup
+CLIENT_ID=bot_dev
+CMD_PREFIX=!
+LANGUAGE=en
+
+# Respond to all chats
+CHATS=[]
+
+# All plugins for testing
+PLUGINS=[
+ many,
+ figurinha,
+ video,
+ audio,
+ adivinha\(,c\(oao,
+ forca,
+ obrigado
+]
+.fi
+.SH FILES
+.TP
+.I manybot.conf
+Main configuration file (must be created by user)
+.TP
+.I manybot.conf.example
+Example configuration with documentation comments
+.SH NOTES
+\(bu Keys are case-sensitive
+.br
+\(bu Values are read as strings unless they're list syntax
+.br
+\(bu Inline comments supported: \fBKEY=value # comment\fR
+.br
+\(bu Multiline lists must end with \fB]\fR on its own line or last item line
+.br
+\(bu Whitespace in values is trimmed
+.br
+\(u Missing optional values use built-in defaults
+.SH SEE ALSO
+.BR manybot (1),
+.BR manybot-plugin (1),
+.BR manyplug (1)
+.SH AUTHOR
+Written by synt-xerror.
diff --git a/manybot.conf.example b/manybot.conf.example
new file mode 100644
index 0000000..0a8d4d1
--- /dev/null
+++ b/manybot.conf.example
@@ -0,0 +1,30 @@
+# ManyBot Configuration File
+# Copy this file to manybot.conf and customize as needed
+
+# Bot identification
+CLIENT_ID=meu_bot
+
+# Command prefix (default: !)
+CMD_PREFIX=!
+
+# Language setting (en, pt, es)
+# Default: en (English)
+LANGUAGE=en
+
+# Allowed chats (leave empty for all chats)
+# Format: chatId1@g.us, chatId2@g.us for groups
+# Format: number@c.us for private chats
+CHATS=[
+]
+
+# Active plugins
+PLUGINS=[
+many,
+figurinha,
+audio,
+video,
+adivinhação,
+forca,
+obrigado,
+a
+]
diff --git a/package-lock.json b/package-lock.json
index 9b91d61..358ba90 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,6 +14,9 @@
"qrcode-terminal": "^0.12.0",
"wa-sticker-formatter": "^4.4.4",
"whatsapp-web.js": "^1.24.0"
+ },
+ "devDependencies": {
+ "conventional-changelog-cli": "^5.0.0"
}
},
"node_modules/@babel/code-frame": {
@@ -39,6 +42,33 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@conventional-changelog/git-client": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@conventional-changelog/git-client/-/git-client-2.6.0.tgz",
+ "integrity": "sha512-T+uPDciKf0/ioNNDpMGc8FDsehJClZP0yR3Q5MN6wE/Y/1QZ7F+80OgznnTCOlMEG4AV0LvH2UJi3C/nBnaBUg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@simple-libs/child-process-utils": "^1.0.0",
+ "@simple-libs/stream-utils": "^1.2.0",
+ "semver": "^7.5.2"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "conventional-commits-filter": "^5.0.0",
+ "conventional-commits-parser": "^6.3.0"
+ },
+ "peerDependenciesMeta": {
+ "conventional-commits-filter": {
+ "optional": true
+ },
+ "conventional-commits-parser": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@gar/promise-retry": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@gar/promise-retry/-/promise-retry-1.0.2.tgz",
@@ -51,6 +81,16 @@
"node": "^20.17.0 || >=22.9.0"
}
},
+ "node_modules/@hutson/parse-repository-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-5.0.0.tgz",
+ "integrity": "sha512-e5+YUKENATs1JgYHMzTr2MW/NDcXGfYFAuOQU8gJgF/kEh4EqKgfGrfLI67bMD4tbhZVlkigz/9YYwWcbOFthg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
"node_modules/@isaacs/fs-minipass": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
@@ -127,6 +167,35 @@
"node": ">=18"
}
},
+ "node_modules/@simple-libs/child-process-utils": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@simple-libs/child-process-utils/-/child-process-utils-1.0.2.tgz",
+ "integrity": "sha512-/4R8QKnd/8agJynkNdJmNw2MBxuFTRcNFnE5Sg/G+jkSsV8/UBgULMzhizWWW42p8L5H7flImV2ATi79Ove2Tw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@simple-libs/stream-utils": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://ko-fi.com/dangreen"
+ }
+ },
+ "node_modules/@simple-libs/stream-utils": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@simple-libs/stream-utils/-/stream-utils-1.2.0.tgz",
+ "integrity": "sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://ko-fi.com/dangreen"
+ }
+ },
"node_modules/@tokenizer/token": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
@@ -149,6 +218,13 @@
"undici-types": "~7.18.0"
}
},
+ "node_modules/@types/normalize-package-data": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz",
+ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/yauzl": {
"version": "2.10.3",
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
@@ -180,6 +256,13 @@
"node": ">=6.5"
}
},
+ "node_modules/add-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz",
+ "integrity": "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/agent-base": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
@@ -293,6 +376,13 @@
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"license": "Python-2.0"
},
+ "node_modules/array-ify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz",
+ "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/ast-types": {
"version": "0.13.4",
"resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
@@ -746,6 +836,17 @@
"simple-swizzle": "^0.2.2"
}
},
+ "node_modules/compare-func": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz",
+ "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-ify": "^1.0.0",
+ "dot-prop": "^5.1.0"
+ }
+ },
"node_modules/compress-commons": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz",
@@ -769,6 +870,227 @@
"license": "MIT",
"optional": true
},
+ "node_modules/conventional-changelog": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-6.0.0.tgz",
+ "integrity": "sha512-tuUH8H/19VjtD9Ig7l6TQRh+Z0Yt0NZ6w/cCkkyzUbGQTnUEmKfGtkC9gGfVgCfOL1Rzno5NgNF4KY8vR+Jo3w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "conventional-changelog-angular": "^8.0.0",
+ "conventional-changelog-atom": "^5.0.0",
+ "conventional-changelog-codemirror": "^5.0.0",
+ "conventional-changelog-conventionalcommits": "^8.0.0",
+ "conventional-changelog-core": "^8.0.0",
+ "conventional-changelog-ember": "^5.0.0",
+ "conventional-changelog-eslint": "^6.0.0",
+ "conventional-changelog-express": "^5.0.0",
+ "conventional-changelog-jquery": "^6.0.0",
+ "conventional-changelog-jshint": "^5.0.0",
+ "conventional-changelog-preset-loader": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/conventional-changelog-angular": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.3.0.tgz",
+ "integrity": "sha512-DOuBwYSqWzfwuRByY9O4oOIvDlkUCTDzfbOgcSbkY+imXXj+4tmrEFao3K+FxemClYfYnZzsvudbwrhje9VHDA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "compare-func": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/conventional-changelog-atom": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-5.1.0.tgz",
+ "integrity": "sha512-fw7GpI9jHNCWGBnTsPRI452ypQbNupGwsjrXfozvRNE0c92pJRpoj9rXfzDKUYJcsmk0H4XKaQjhjelwI9z27w==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/conventional-changelog-cli": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-cli/-/conventional-changelog-cli-5.0.0.tgz",
+ "integrity": "sha512-9Y8fucJe18/6ef6ZlyIlT2YQUbczvoQZZuYmDLaGvcSBP+M6h+LAvf7ON7waRxKJemcCII8Yqu5/8HEfskTxJQ==",
+ "deprecated": "This package is no longer maintained. Please use the conventional-changelog package instead.",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "add-stream": "^1.0.0",
+ "conventional-changelog": "^6.0.0",
+ "meow": "^13.0.0",
+ "tempfile": "^5.0.0"
+ },
+ "bin": {
+ "conventional-changelog": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/conventional-changelog-codemirror": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-5.1.0.tgz",
+ "integrity": "sha512-iXhy63YczB+yWA9DrsYbquSYLvWKsK9M3WC+xQPEm8cOn4oXzKpmTp2uH3qi7+i10oTcGJTvq9lsBpZmMADaNg==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/conventional-changelog-conventionalcommits": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-8.0.0.tgz",
+ "integrity": "sha512-eOvlTO6OcySPyyyk8pKz2dP4jjElYunj9hn9/s0OB+gapTO8zwS9UQWrZ1pmF2hFs3vw1xhonOLGcGjy/zgsuA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "compare-func": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/conventional-changelog-core": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-8.0.0.tgz",
+ "integrity": "sha512-EATUx5y9xewpEe10UEGNpbSHRC6cVZgO+hXQjofMqpy+gFIrcGvH3Fl6yk2VFKh7m+ffenup2N7SZJYpyD9evw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@hutson/parse-repository-url": "^5.0.0",
+ "add-stream": "^1.0.0",
+ "conventional-changelog-writer": "^8.0.0",
+ "conventional-commits-parser": "^6.0.0",
+ "git-raw-commits": "^5.0.0",
+ "git-semver-tags": "^8.0.0",
+ "hosted-git-info": "^7.0.0",
+ "normalize-package-data": "^6.0.0",
+ "read-package-up": "^11.0.0",
+ "read-pkg": "^9.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/conventional-changelog-ember": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-5.1.0.tgz",
+ "integrity": "sha512-XNcgGcdJt7wh341BBML0CI8DKpqE5lKD1WahzFHGZFvKTzJr1rZW976cw7beqKLOBbzdrH9ZIkE/s2TfbOuM3g==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/conventional-changelog-eslint": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-6.1.0.tgz",
+ "integrity": "sha512-beWr3qzuEMN9gznMWa8PhTVfGkGXoq+XnUzViNXg5KygrgV728ZRqZngz3uPhz5+ayUhPrpNFYqIE0qHWz9NAw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/conventional-changelog-express": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-5.1.0.tgz",
+ "integrity": "sha512-g/s9eLohrefYTSNQaB6+k0ONbiVx41YOKBbIOIM3ST/NtedAgppCJnrpKXVN9sOmpPkN4vjFwURlfvpEDUjoeg==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/conventional-changelog-jquery": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-6.1.0.tgz",
+ "integrity": "sha512-/sFhULybhFrMg+qc8MHHHSj7kTVMfx5C7rSM6Z9EjduVoAQJdGRq/wpv/SWPMQ+KPNSYHqDLwm/x2Z5hOcYvqQ==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/conventional-changelog-jshint": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-5.2.0.tgz",
+ "integrity": "sha512-OaatyvHXP1fjI7Mx0b1IkmhbhTsVHsytnsQSkOj4rhGbFMoTcfvbwm/vAtCzRMXOxojK1EDMBBmBj1pM9KNy/Q==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "compare-func": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/conventional-changelog-preset-loader": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-5.0.0.tgz",
+ "integrity": "sha512-SetDSntXLk8Jh1NOAl1Gu5uLiCNSYenB5tm0YVeZKePRIgDW9lQImromTwLa3c/Gae298tsgOM+/CYT9XAl0NA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/conventional-changelog-writer": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-8.4.0.tgz",
+ "integrity": "sha512-HHBFkk1EECxxmCi4CTu091iuDpQv5/OavuCUAuZmrkWpmYfyD816nom1CvtfXJ/uYfAAjavgHvXHX291tSLK8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@simple-libs/stream-utils": "^1.2.0",
+ "conventional-commits-filter": "^5.0.0",
+ "handlebars": "^4.7.7",
+ "meow": "^13.0.0",
+ "semver": "^7.5.2"
+ },
+ "bin": {
+ "conventional-changelog-writer": "dist/cli/index.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/conventional-commits-filter": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-5.0.0.tgz",
+ "integrity": "sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/conventional-commits-parser": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-6.3.0.tgz",
+ "integrity": "sha512-RfOq/Cqy9xV9bOA8N+ZH6DlrDR+5S3Mi0B5kACEjESpE+AviIpAptx9a9cFpWCCvgRtWT+0BbUw+e1BZfts9jg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@simple-libs/stream-utils": "^1.2.0",
+ "meow": "^13.0.0"
+ },
+ "bin": {
+ "conventional-commits-parser": "dist/cli/index.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
@@ -908,6 +1230,19 @@
"integrity": "sha512-nv7iKtNZQshSW2hKzYNr46nM/Cfh5SEvE2oV0/SEGgc9XupIY5ggf84Cz8eJIkBce7S3bmTAauFD6aysMpnqsQ==",
"license": "BSD-3-Clause"
},
+ "node_modules/dot-prop": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
+ "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-obj": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/duplexer2": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
@@ -1156,6 +1491,19 @@
"url": "https://github.com/sindresorhus/file-type?sponsor=1"
}
},
+ "node_modules/find-up-simple": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz",
+ "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/fluent-ffmpeg": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.3.tgz",
@@ -1289,6 +1637,40 @@
"node": ">= 14"
}
},
+ "node_modules/git-raw-commits": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-5.0.1.tgz",
+ "integrity": "sha512-Y+csSm2GD/PCSh6Isd/WiMjNAydu0VBiG9J7EdQsNA5P9uXvLayqjmTsNlK5Gs9IhblFZqOU0yid5Il5JPoLiQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@conventional-changelog/git-client": "^2.6.0",
+ "meow": "^13.0.0"
+ },
+ "bin": {
+ "git-raw-commits": "src/cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/git-semver-tags": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-8.0.1.tgz",
+ "integrity": "sha512-zMbamckSNdlT4U48IMFa2Cn6FTzM+2yF6/gEmStPJI8PiLxd/bT6dw10+mc6u5Qe4fhrc/y9nU290FWjQhAV7g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@conventional-changelog/git-client": "^2.6.0",
+ "meow": "^13.0.0"
+ },
+ "bin": {
+ "git-semver-tags": "src/cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/github-from-package": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
@@ -1323,6 +1705,48 @@
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"license": "ISC"
},
+ "node_modules/handlebars": {
+ "version": "4.7.9",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz",
+ "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.2",
+ "source-map": "^0.6.1",
+ "wordwrap": "^1.0.0"
+ },
+ "bin": {
+ "handlebars": "bin/handlebars"
+ },
+ "engines": {
+ "node": ">=0.4.7"
+ },
+ "optionalDependencies": {
+ "uglify-js": "^3.1.4"
+ }
+ },
+ "node_modules/hosted-git-info": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz",
+ "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "lru-cache": "^10.0.1"
+ },
+ "engines": {
+ "node": "^16.14.0 || >=18.0.0"
+ }
+ },
+ "node_modules/hosted-git-info/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/http-cache-semantics": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
@@ -1432,6 +1856,19 @@
"node": ">=0.8.19"
}
},
+ "node_modules/index-to-position": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz",
+ "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -1480,6 +1917,16 @@
"node": ">=8"
}
},
+ "node_modules/is-obj": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -1654,6 +2101,19 @@
"node": "^20.17.0 || >=22.9.0"
}
},
+ "node_modules/meow": {
+ "version": "13.2.0",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz",
+ "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/mime": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
@@ -1868,6 +2328,13 @@
"node": ">= 0.6"
}
},
+ "node_modules/neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/netmask": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
@@ -1984,6 +2451,21 @@
"node": "^20.17.0 || >=22.9.0"
}
},
+ "node_modules/normalize-package-data": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz",
+ "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "hosted-git-info": "^7.0.0",
+ "semver": "^7.3.5",
+ "validate-npm-package-license": "^3.0.4"
+ },
+ "engines": {
+ "node": "^16.14.0 || >=18.0.0"
+ }
+ },
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -2334,6 +2816,62 @@
"rc": "cli.js"
}
},
+ "node_modules/read-package-up": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz",
+ "integrity": "sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "find-up-simple": "^1.0.0",
+ "read-pkg": "^9.0.0",
+ "type-fest": "^4.6.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz",
+ "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/normalize-package-data": "^2.4.3",
+ "normalize-package-data": "^6.0.0",
+ "parse-json": "^8.0.0",
+ "type-fest": "^4.6.0",
+ "unicorn-magic": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg/node_modules/parse-json": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz",
+ "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.26.2",
+ "index-to-position": "^1.1.0",
+ "type-fest": "^4.39.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
@@ -2673,12 +3211,48 @@
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "devOptional": true,
"license": "BSD-3-Clause",
- "optional": true,
"engines": {
"node": ">=0.10.0"
}
},
+ "node_modules/spdx-correct": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
+ "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-exceptions": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
+ "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
+ "dev": true,
+ "license": "CC-BY-3.0"
+ },
+ "node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-license-ids": {
+ "version": "3.0.23",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz",
+ "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
"node_modules/ssri": {
"version": "13.0.1",
"resolved": "https://registry.npmjs.org/ssri/-/ssri-13.0.1.tgz",
@@ -2830,6 +3404,32 @@
"streamx": "^2.12.5"
}
},
+ "node_modules/temp-dir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz",
+ "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.16"
+ }
+ },
+ "node_modules/tempfile": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-5.0.0.tgz",
+ "integrity": "sha512-bX655WZI/F7EoTDw9JvQURqAXiPHi8o8+yFxPF2lWYyz1aHnmMRuXWqL6YB6GmeO0o4DIYWHLgGNi/X64T+X4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "temp-dir": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/text-decoder": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz",
@@ -2906,12 +3506,39 @@
"node": "*"
}
},
+ "node_modules/type-fest": {
+ "version": "4.41.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
+ "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/typed-query-selector": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.1.tgz",
"integrity": "sha512-uzR+FzI8qrUEIu96oaeBJmd9E7CFEiQ3goA5qCVgc4s5llSubcfGHq9yUstZx/k4s9dXHVKsE35YWoFyvEqEHA==",
"license": "MIT"
},
+ "node_modules/uglify-js": {
+ "version": "3.19.3",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
+ "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "optional": true,
+ "bin": {
+ "uglifyjs": "bin/uglifyjs"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
"node_modules/undici-types": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
@@ -2919,6 +3546,19 @@
"license": "MIT",
"optional": true
},
+ "node_modules/unicorn-magic": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz",
+ "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/unique-filename": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-5.0.0.tgz",
@@ -3010,6 +3650,17 @@
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"license": "MIT"
},
+ "node_modules/validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
"node_modules/wa-sticker-formatter": {
"version": "4.4.4",
"resolved": "https://registry.npmjs.org/wa-sticker-formatter/-/wa-sticker-formatter-4.4.4.tgz",
@@ -3087,6 +3738,13 @@
"which": "bin/which"
}
},
+ "node_modules/wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
diff --git a/package.json b/package.json
index 806ddfd..a2e3de4 100755
--- a/package.json
+++ b/package.json
@@ -9,5 +9,11 @@
"qrcode-terminal": "^0.12.0",
"wa-sticker-formatter": "^4.4.4",
"whatsapp-web.js": "^1.24.0"
+ },
+ "devDependencies": {
+ "conventional-changelog-cli": "^5.0.0"
+ },
+ "scripts": {
+ "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0"
}
}