[repo] reorganization using plugins instead of built-in commands, [plugin] new game: forca, [dev] changes on log format, [config] removed botMsg, [plugin] on stickers, you can create just one sending an image or replying to one, [setup] exec permissions and comand to install Chrome
This commit is contained in:
88
src/kernel/pluginLoader.js
Normal file
88
src/kernel/pluginLoader.js
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* pluginLoader.js
|
||||
*
|
||||
* Responsável por:
|
||||
* 1. Ler quais plugins estão ativos no manybot.conf (PLUGINS=[...])
|
||||
* 2. Carregar cada plugin da pasta /plugins
|
||||
* 3. Registrar no pluginRegistry com status e exports públicos
|
||||
* 4. Expor o pluginRegistry para o kernel e para a pluginApi
|
||||
*/
|
||||
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { logger } from "../logger/logger.js";
|
||||
|
||||
const PLUGINS_DIR = path.resolve("src/plugins");
|
||||
|
||||
/**
|
||||
* Cada entrada no registry:
|
||||
* {
|
||||
* name: string,
|
||||
* status: "active" | "disabled" | "error",
|
||||
* run: async function({ msg, chat, api }) — a função default do plugin
|
||||
* exports: any — o que o plugin expôs via `export const api = { ... }`
|
||||
* error: Error | null
|
||||
* }
|
||||
*
|
||||
* @type {Map<string, object>}
|
||||
*/
|
||||
export const pluginRegistry = new Map();
|
||||
|
||||
/**
|
||||
* Carrega todos os plugins ativos listados em `activePlugins`.
|
||||
* Chamado uma vez na inicialização do bot.
|
||||
*
|
||||
* @param {string[]} activePlugins — nomes dos plugins ativos (do .conf)
|
||||
*/
|
||||
export async function loadPlugins(activePlugins) {
|
||||
if (!fs.existsSync(PLUGINS_DIR)) {
|
||||
logger.warn("Pasta /plugins não encontrada. Nenhum plugin carregado.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (const name of activePlugins) {
|
||||
await loadPlugin(name);
|
||||
}
|
||||
|
||||
const total = pluginRegistry.size;
|
||||
const ativos = [...pluginRegistry.values()].filter(p => p.status === "active").length;
|
||||
const erros = total - ativos;
|
||||
|
||||
logger.success(`Plugins carregados: ${ativos} ativos${erros ? `, ${erros} com erro` : ""}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Carrega um único plugin pelo nome.
|
||||
* @param {string} name
|
||||
*/
|
||||
async function loadPlugin(name) {
|
||||
const pluginPath = path.join(PLUGINS_DIR, name, "index.js");
|
||||
|
||||
if (!fs.existsSync(pluginPath)) {
|
||||
logger.warn(`Plugin "${name}" não encontrado em ${pluginPath}`);
|
||||
pluginRegistry.set(name, { name, status: "disabled", run: null, exports: null, error: null });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const mod = await import(pluginPath);
|
||||
|
||||
// O plugin deve exportar uma função default — essa é a função chamada a cada mensagem
|
||||
if (typeof mod.default !== "function") {
|
||||
throw new Error(`Plugin "${name}" não exporta uma função default`);
|
||||
}
|
||||
|
||||
pluginRegistry.set(name, {
|
||||
name,
|
||||
status: "active",
|
||||
run: mod.default,
|
||||
exports: mod.api ?? null, // exports públicos opcionais (api de outros plugins)
|
||||
error: null,
|
||||
});
|
||||
|
||||
logger.info(`Plugin carregado: ${name}`);
|
||||
} catch (err) {
|
||||
logger.error(`Falha ao carregar plugin "${name}": ${err.message}`);
|
||||
pluginRegistry.set(name, { name, status: "error", run: null, exports: null, error: err });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user