Files
manybot/docs/PLUGINS (en).md
2026-04-21 11:18:19 -03:00

7.2 KiB

🔌 Creating Plugins

Complete guide to creating plugins in ManyBot.


📑 Index


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 }:

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.

{
  "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

{
  "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

// 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

// 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

// 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:

// 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:

// 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

{
  "hello": "Hello, {{name}}! 👋",
  "error": {
    "notFound": "Item not found."
  }
}

index.js

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:

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:

PLUGINS=[
    # ... other plugins
    my-plugin
]

Restart the bot to load it.


See Also