update documentation and remove systemd support

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

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

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