From 18821dd9516b819518e4a82f37fa0e782f886e09 Mon Sep 17 00:00:00 2001
From: synt-xerror <169557594+synt-xerror@users.noreply.github.com>
Date: Tue, 21 Apr 2026 11:18:19 -0300
Subject: [PATCH] remove embedded plugins - now managed via manyplug
---
src/plugins/a/index.js | 9 --
src/plugins/adivinhação/index.js | 79 ----------
src/plugins/audio/index.js | 123 ---------------
src/plugins/figurinha/index.js | 247 -------------------------------
src/plugins/forca/index.js | 159 --------------------
src/plugins/many/index.js | 14 --
src/plugins/obrigado/index.js | 8 -
src/plugins/video/index.js | 98 ------------
src/plugins/xp/index.js | 21 ---
9 files changed, 758 deletions(-)
delete mode 100644 src/plugins/a/index.js
delete mode 100644 src/plugins/adivinhação/index.js
delete mode 100644 src/plugins/audio/index.js
delete mode 100644 src/plugins/figurinha/index.js
delete mode 100644 src/plugins/forca/index.js
delete mode 100644 src/plugins/many/index.js
delete mode 100644 src/plugins/obrigado/index.js
delete mode 100644 src/plugins/video/index.js
delete mode 100644 src/plugins/xp/index.js
diff --git a/src/plugins/a/index.js b/src/plugins/a/index.js
deleted file mode 100644
index 7850963..0000000
--- a/src/plugins/a/index.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import { forcaAtiva } from "../forca/index.js";
-
-export default async function ({ msg }) {
- if (msg.body.trim().toLowerCase() !== "a") return;
- if (msg.args.length > 1) return;
- if (forcaAtiva) return;
-
- await msg.reply("B!");
-}
\ No newline at end of file
diff --git a/src/plugins/adivinhação/index.js b/src/plugins/adivinhação/index.js
deleted file mode 100644
index e50f639..0000000
--- a/src/plugins/adivinhação/index.js
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * plugins/adivinhacao/index.js
- *
- * Estado dos jogos fica aqui dentro — isolado no plugin.
- * Múltiplos grupos jogam simultaneamente sem conflito.
- */
-
-const RANGE = { min: 1, max: 100 };
-const jogosAtivos = new Map();
-import { CMD_PREFIX } from "../../config.js"
-
-const sorteio = () =>
- Math.floor(Math.random() * (RANGE.max - RANGE.min + 1)) + RANGE.min;
-
-export default async function ({ msg, api }) {
- const chatId = api.chat.id;
-
- // ── Comando adivinhação ──────────────────────────────────
- if (msg.is(CMD_PREFIX + "adivinhação")) {
- const sub = msg.args[1];
-
- if (!sub) {
- await api.send(
- "🎮 *Jogo de adivinhação:*\n\n" +
- `\`${CMD_PREFIX}adivinhação começar\` — inicia o jogo\n` +
- `\`${CMD_PREFIX}adivinhação parar\` — encerra o jogo`
- );
- return;
- }
-
- if (sub === "começar") {
- jogosAtivos.set(chatId, sorteio());
- await api.send(
- "🎮 *Jogo iniciado!*\n\n" +
- "Estou pensando em um número de 1 a 100.\n" +
- "Tente adivinhar! 🤔"
- );
- api.log.info(CMD_PREFIX + "adivinhação — jogo iniciado");
- return;
- }
-
- if (sub === "parar") {
- jogosAtivos.delete(chatId);
- await api.send("🛑 Jogo encerrado.");
- api.log.info(CMD_PREFIX + "adivinhação — jogo parado");
- return;
- }
-
- await api.send(
- `❌ Subcomando *${sub}* não existe.\n\n` +
- `Use ${CMD_PREFIX} + \`adivinhação começar\` ou ${CMD_PREFIX} + \`adivinhação parar\`.`
- );
- return;
- }
-
- // ── Tentativas durante o jogo ─────────────────────────────
- const numero = jogosAtivos.get(chatId);
- if (numero === undefined) return;
-
- const tentativa = msg.body.trim();
- if (!/^\d+$/.test(tentativa)) return;
-
- const num = parseInt(tentativa, 10);
-
- if (num < RANGE.min || num > RANGE.max) {
- await msg.reply(`⚠️ Digite um número entre ${RANGE.min} e ${RANGE.max}.`);
- return;
- }
-
- if (num === numero) {
- await msg.reply(
- `🎉 *Acertou!* O número era ${numero}!\n\n` +
- `Use ${CMD_PREFIX} + \`adivinhação começar\` para jogar de novo.`
- );
- jogosAtivos.delete(chatId);
- } else {
- await api.send(num > numero ? "📉 Tente um número *menor*!" : "📈 Tente um número *maior*!");
- }
-}
\ No newline at end of file
diff --git a/src/plugins/audio/index.js b/src/plugins/audio/index.js
deleted file mode 100644
index 9a8dcdb..0000000
--- a/src/plugins/audio/index.js
+++ /dev/null
@@ -1,123 +0,0 @@
-/**
- * plugins/audio/index.js
- *
- * Baixa vídeo via yt-dlp, converte para mp3 via ffmpeg e envia no chat.
- * Todo o processo (download + conversão + envio + limpeza) fica aqui.
- */
-
-import { spawn } from "child_process";
-import { execFile } from "child_process";
-import { promisify } from "util";
-import fs from "fs";
-import path from "path";
-import os from "os";
-import { enqueue } from "../../download/queue.js";
-import { emptyFolder } from "../../utils/file.js";
-import { CMD_PREFIX } from "../../config.js";
-
-const logStream = fs.createWriteStream("logs/audio-error.log", { flags: "a" });
-
-const execFileAsync = promisify(execFile);
-
-const DOWNLOADS_DIR = path.resolve("downloads");
-const YT_DLP = os.platform() === "win32" ? ".\\bin\\yt-dlp.exe" : "./bin/yt-dlp";
-const FFMPEG = os.platform() === "win32" ? ".\\bin\\ffmpeg.exe" : "./bin/ffmpeg";
-
-const ARGS_BASE = [
- "--extractor-args", "youtube:player_client=android",
- "--print", "after_move:filepath",
- "--cookies", "cookies.txt",
- "--add-header", "User-Agent:Mozilla/5.0",
- "--add-header", "Referer:https://www.youtube.com/",
- "--retries", "4",
- "--fragment-retries", "5",
- "--socket-timeout", "15",
- "--sleep-interval", "1",
- "--max-sleep-interval", "4",
- "--no-playlist",
- "-f", "bv+ba/best",
-];
-
-function downloadRaw(url, id) {
- return new Promise((resolve, reject) => {
- fs.mkdirSync(DOWNLOADS_DIR, { recursive: true });
-
- const output = path.join(DOWNLOADS_DIR, `${id}.%(ext)s`);
- const proc = spawn(YT_DLP, [...ARGS_BASE, "--output", output, url]);
- let stdout = "";
-
- proc.on("error", err => reject(new Error(
- err.code === "EACCES"
- ? "Sem permissão para executar o yt-dlp. Rode: chmod +x ./bin/yt-dlp"
- : err.code === "ENOENT"
- ? "yt-dlp não encontrado em ./bin/yt-dlp"
- : `Erro ao iniciar o yt-dlp: ${err.message}`
- )));
-
- proc.stdout.on("data", d => { stdout += d.toString(); });
- proc.stderr.on("data", d => logStream.write(d));
-
- proc.on("close", code => {
- if (code !== 0) return reject(new Error(
- "Não foi possível baixar o áudio. Verifique se o link é válido e tente novamente."
- ));
-
- const filePath = stdout.trim().split("\n").filter(Boolean).at(-1);
- if (!filePath || !fs.existsSync(filePath)) return reject(new Error(
- "Download concluído mas arquivo não encontrado. Tente novamente."
- ));
-
- resolve(filePath);
- });
- });
-}
-
-async function convertToMp3(videoPath, id) {
- const mp3Path = path.join(DOWNLOADS_DIR, `${id}.mp3`);
-
- await execFileAsync(FFMPEG, [
- "-i", videoPath,
- "-vn", // sem vídeo
- "-ar", "44100", // sample rate
- "-ac", "2", // stereo
- "-b:a", "192k", // bitrate
- "-y", // sobrescreve se existir
- mp3Path,
- ]);
-
- fs.unlinkSync(videoPath); // remove o vídeo intermediário
- return mp3Path;
-}
-
-export default async function ({ msg, api }) {
- if (!msg.is(CMD_PREFIX + "audio")) return;
-
- const url = msg.args[1];
-
- if (!url) {
- await msg.reply(`❌ Você precisa informar um link.\n\nExemplo: \`${CMD_PREFIX}audio https://youtube.com/...\``);
- return;
- }
-
- await msg.reply("⏳ Baixando o áudio, aguarde...");
-
- const id = `audio-${Date.now()}`;
-
- enqueue(
- async () => {
- const videoPath = await downloadRaw(url, id);
- const mp3Path = await convertToMp3(videoPath, id);
- await api.sendAudio(mp3Path);
- fs.unlinkSync(mp3Path);
- emptyFolder(DOWNLOADS_DIR);
- api.log.info(`${CMD_PREFIX}audio concluído → ${url}`);
- },
- async () => {
- await msg.reply(
- "❌ Não consegui baixar o áudio.\n\n" +
- "Verifique se o link é válido e tente novamente.\n" +
- "Se o problema persistir, o conteúdo pode estar indisponível ou protegido."
- );
- }
- );
-}
\ No newline at end of file
diff --git a/src/plugins/figurinha/index.js b/src/plugins/figurinha/index.js
deleted file mode 100644
index 7553b6d..0000000
--- a/src/plugins/figurinha/index.js
+++ /dev/null
@@ -1,247 +0,0 @@
-/**
- * plugins/figurinha/index.js
- *
- * Modos de uso:
- * comando + mídia anexa → cria 1 sticker direto
- * comando + respondendo mídia → cria 1 sticker direto
- * comando + mídia anexa + respondendo mídia → cria 2 stickers direto
- * comando (sem mídia nenhuma) → abre sessão
- * comando criar (com sessão aberta) → processa as mídias da sessão
- */
-
-import fs from "fs";
-import path from "path";
-import os from "os";
-import { execFile } from "child_process";
-import { promisify } from "util";
-
-import { createSticker } from "wa-sticker-formatter";
-import { emptyFolder } from "../../utils/file.js";
-import { CMD_PREFIX } from "../../config.js";
-
-const execFileAsync = promisify(execFile);
-
-// ── Constantes ────────────────────────────────────────────────
-const DOWNLOADS_DIR = path.resolve("downloads");
-const FFMPEG = os.platform() === "win32" ? ".\\bin\\ffmpeg.exe" : "./bin/ffmpeg";
-const MAX_STICKER_SIZE = 900 * 1024;
-const SESSION_TIMEOUT = 2 * 60 * 1000;
-const MAX_MEDIA = 30;
-
-const HELP =
- "📌 *Como criar figurinhas:*\n\n" +
- `1️⃣ Envie \`${CMD_PREFIX}figurinha\` junto com uma mídia, ou respondendo uma mídia\n` +
- " — o sticker é criado na hora\n\n" +
- "2️⃣ Ou use o modo sessão para várias mídias de uma vez:\n" +
- ` — \`${CMD_PREFIX}figurinha\` sem mídia para iniciar\n` +
- " — envie as imagens, GIFs ou vídeos\n" +
- ` — \`${CMD_PREFIX}figurinha criar\` para gerar todas\n\n` +
- "⏳ A sessão expira em 2 minutos se nenhuma mídia for enviada.";
-
-// ── Estado interno ────────────────────────────────────────────
-// { chatId → { author, medias[], timeout } }
-const sessions = new Map();
-
-// ── Conversão ─────────────────────────────────────────────────
-function ensureDir() {
- fs.mkdirSync(DOWNLOADS_DIR, { recursive: true });
-}
-
-function cleanup(...files) {
- for (const f of files) {
- try { if (f && fs.existsSync(f)) fs.unlinkSync(f); } catch { }
- }
-}
-
-async function convertToGif(input, output, fps = 12) {
- const filter = [
- `fps=${Math.min(fps, 12)},scale=512:512:flags=lanczos,split[s0][s1]`,
- `[s0]palettegen=max_colors=256:reserve_transparent=1[p]`,
- `[s1][p]paletteuse=dither=bayer`,
- ].join(";");
- await execFileAsync(FFMPEG, ["-i", input, "-filter_complex", filter, "-loop", "0", "-y", output]);
-}
-
-async function resizeImage(input, output) {
- await execFileAsync(FFMPEG, ["-i", input, "-vf", "scale=512:512:flags=lanczos", "-y", output]);
-}
-
-async function buildSticker(inputPath, isAnimated) {
- for (const quality of [80, 60, 40, 20]) {
- const buf = await createSticker(fs.readFileSync(inputPath), {
- pack: "Criada por ManyBot\n",
- author: "\ngithub.com/synt-xerror/manybot",
- type: isAnimated ? "FULL" : "STATIC",
- categories: ["🤖"],
- quality,
- });
- if (buf.length <= MAX_STICKER_SIZE) return buf;
- }
- throw new Error("Não foi possível reduzir o sticker para menos de 900 KB.");
-}
-
-/**
- * Converte um objeto { mimetype, data } em sticker e envia.
- * Retorna true se ok, false se falhou.
- */
-async function processarUmaMedia(media, isGif, api, msg) {
- ensureDir();
-
- const ext = media.mimetype.split("/")[1];
- const isVideo = media.mimetype.startsWith("video/");
- const isAnimated = isVideo || isGif;
-
- const id = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
- const inputPath = path.join(DOWNLOADS_DIR, `${id}.${ext}`);
- const gifPath = path.join(DOWNLOADS_DIR, `${id}.gif`);
- const resizedPath = path.join(DOWNLOADS_DIR, `${id}-scaled.${ext}`);
-
- try {
- fs.writeFileSync(inputPath, Buffer.from(media.data, "base64"));
-
- let stickerInput;
- if (isAnimated) {
- await convertToGif(inputPath, gifPath, isVideo ? 12 : 24);
- stickerInput = gifPath;
- } else {
- await resizeImage(inputPath, resizedPath);
- stickerInput = resizedPath;
- }
-
- const buf = await buildSticker(stickerInput, isAnimated);
- await api.sendSticker(buf);
- return true;
- } catch (err) {
- api.log.error(`Erro ao gerar sticker: ${err.message}`);
- await msg.reply(
- "⚠️ Não consegui criar uma das figurinhas.\n" +
- "Tente reenviar essa mídia ou use outro formato (JPG, PNG, GIF, MP4)."
- );
- return false;
- } finally {
- cleanup(inputPath, gifPath, resizedPath);
- }
-}
-
-/**
- * Verifica se uma mídia é suportada para sticker.
- */
-function isSupported(media, isGif) {
- return (
- media.mimetype?.startsWith("image/") ||
- media.mimetype?.startsWith("video/") ||
- isGif
- );
-}
-
-// ── Plugin ────────────────────────────────────────────────────
-export default async function ({ msg, api }) {
- const chatId = api.chat.id;
-
- if (!msg.is(CMD_PREFIX + "figurinha")) {
- // ── Coleta de mídia durante sessão ──────────────────────
- const session = sessions.get(chatId);
- if (!session) return;
- if (!msg.hasMedia) return;
- if (msg.sender !== session.author) return;
-
- const media = await msg.downloadMedia();
- if (!media) return;
-
- const gif = media.mimetype === "image/gif" ||
- (media.mimetype === "video/mp4" && msg.isGif);
-
- if (isSupported(media, gif) && session.medias.length < MAX_MEDIA) {
- session.medias.push({ media, isGif: gif });
- }
- return;
- }
-
- // ── figurinha criar ──────────────────────────────────────
- const sub = msg.args[1];
-
- if (sub === "criar") {
- const session = sessions.get(chatId);
-
- if (!session) {
- await msg.reply(`❌ *Nenhuma sessão ativa.*\n\n${HELP}`);
- return;
- }
- if (!session.medias.length) {
- await msg.reply(`📭 *Você ainda não enviou nenhuma mídia!*\n\n${HELP}`);
- return;
- }
-
- clearTimeout(session.timeout);
- await msg.reply("⏳ Gerando suas figurinhas, aguarde um momento...");
-
- for (const { media, isGif } of session.medias) {
- await processarUmaMedia(media, isGif, api, msg);
- }
-
- await msg.reply("✅ *Figurinhas criadas com sucesso!*\nSalve as que quiser no seu WhatsApp. 😄");
- sessions.delete(chatId);
- emptyFolder(DOWNLOADS_DIR);
- return;
- }
-
- // ── figurinha com mídia direta ───────────────────────────
- const mediasParaCriar = [];
-
- // Mídia anexa à própria mensagem
- if (msg.hasMedia) {
- const media = await msg.downloadMedia();
- if (media) {
- const gif = media.mimetype === "image/gif" ||
- (media.mimetype === "video/mp4" && msg.isGif);
- if (isSupported(media, gif)) mediasParaCriar.push({ media, isGif: gif });
- }
- }
-
- // Mídia da mensagem citada
- if (msg.hasReply) {
- const quoted = await msg.getReply();
- if (quoted?.hasMedia) {
- const media = await quoted.downloadMedia();
- if (media) {
- const gif = media.mimetype === "image/gif" ||
- (media.mimetype === "video/mp4" && quoted.isGif);
- if (isSupported(media, gif)) mediasParaCriar.push({ media, isGif: gif });
- }
- }
- }
-
- // Tem mídia para criar direto
- if (mediasParaCriar.length > 0) {
- await msg.reply("⏳ Gerando figurinha, aguarde...");
- for (const { media, isGif } of mediasParaCriar) {
- await processarUmaMedia(media, isGif, api, msg);
- }
- emptyFolder(DOWNLOADS_DIR);
- return;
- }
-
- // ── figurinha sem mídia → abre sessão ───────────────────
- if (sessions.has(chatId)) {
- await msg.reply(
- "⚠️ Já existe uma sessão aberta.\n\n" +
- `Envie as mídias e depois use \`${CMD_PREFIX}figurinha criar\`.\n` +
- "Ou aguarde 2 minutos para a sessão expirar."
- );
- return;
- }
-
- const timeout = setTimeout(async () => {
- sessions.delete(chatId);
- try {
- await msg.reply(
- "⏰ *Sessão expirada!*\n\n" +
- "Você demorou mais de 2 minutos para enviar as mídias.\n" +
- `Digite \`${CMD_PREFIX}figurinha\` para começar de novo.`
- );
- } catch { }
- }, SESSION_TIMEOUT);
-
- sessions.set(chatId, { author: msg.sender, medias: [], timeout });
- await msg.reply(`✅ Sessão iniciada por *${msg.senderName}*!\n\n${HELP}`);
-}
\ No newline at end of file
diff --git a/src/plugins/forca/index.js b/src/plugins/forca/index.js
deleted file mode 100644
index aad8518..0000000
--- a/src/plugins/forca/index.js
+++ /dev/null
@@ -1,159 +0,0 @@
-/**
- * plugins/forca/index.js
- *
- * Estado dos jogos de forca fica aqui dentro — isolado no plugin.
- * Múltiplos grupos jogam simultaneamente sem conflito.
- */
-
-import { CMD_PREFIX } from "../../config.js";
-
-// Estados dos jogos
-const jogosAtivos = new Map(); // chatId -> { palavra, tema, vidas, progresso }
-const participantesAtivos = new Map(); // chatId -> Set de usuários que reagiram
-export let forcaAtiva = false;
-
-
-// Palavras de exemplo
-const PALAVRAS = [
- { palavra: "python", tema: "Linguagem de programação" },
- { palavra: "javascript", tema: "Linguagem de programação" },
- { palavra: "java", tema: "Linguagem de programação" },
- { palavra: "cachorro", tema: "Animal" },
- { palavra: "gato", tema: "Animal" },
- { palavra: "elefante", tema: "Animal" },
- { palavra: "girafa", tema: "Animal" },
- { palavra: "guitarra", tema: "Instrumento musical" },
- { palavra: "piano", tema: "Instrumento musical" },
- { palavra: "bateria", tema: "Instrumento musical" },
- { palavra: "violino", tema: "Instrumento musical" },
- { palavra: "futebol", tema: "Esporte" },
- { palavra: "basquete", tema: "Esporte" },
- { palavra: "natação", tema: "Esporte" },
- { palavra: "tênis", tema: "Esporte" },
- { palavra: "brasil", tema: "País" },
- { palavra: "japão", tema: "País" },
- { palavra: "canadá", tema: "País" },
- { palavra: "frança", tema: "País" },
- { palavra: "marte", tema: "Planeta" },
- { palavra: "vênus", tema: "Planeta" },
- { palavra: "júpiter", tema: "Planeta" },
- { palavra: "saturno", tema: "Planeta" },
- { palavra: "minecraft", tema: "Jogo" },
- { palavra: "fortnite", tema: "Jogo" },
- { palavra: "roblox", tema: "Jogo" },
- { palavra: "amongus", tema: "Jogo" },
- { palavra: "rosa", tema: "Flor" },
- { palavra: "girassol", tema: "Flor" },
- { palavra: "tulipa", tema: "Flor" },
- { palavra: "orquídea", tema: "Flor" },
- { palavra: "tesoura", tema: "Objeto" },
- { palavra: "caderno", tema: "Objeto" },
- { palavra: "computador", tema: "Objeto" },
- { palavra: "telefone", tema: "Objeto" },
- { palavra: "lua", tema: "Corpo celeste" },
- { palavra: "sol", tema: "Corpo celeste" },
- { palavra: "estrela", tema: "Corpo celeste" },
- { palavra: "cometa", tema: "Corpo celeste" },
- { palavra: "oceano", tema: "Natureza" },
- { palavra: "montanha", tema: "Natureza" },
-];
-
-// Função para gerar a palavra com underscores
-const gerarProgresso = palavra =>
- palavra.replace(/[a-zA-Z]/g, "_");
-
-export default async function ({ msg, api }) {
- const chatId = api.chat.id;
- const sub = msg.args[1];
-
- // ── Comando principal do jogo
- if (msg.is(CMD_PREFIX + "forca")) {
- if (!sub) {
- await api.send(
- `🎮 *Jogo da Forca*\n\n` +
- `\`${CMD_PREFIX}forca começar\` — inicia o jogo\n` +
- `\`${CMD_PREFIX}forca parar\` — encerra o jogo`
- );
- return;
- }
-
- if (sub === "começar") {
- forcaAtiva = true;
- // Pega uma palavra aleatória
- const sorteio = PALAVRAS[Math.floor(Math.random() * PALAVRAS.length)];
-
- // Inicializa o jogo
- jogosAtivos.set(chatId, {
- palavra: sorteio.palavra.toLowerCase(),
- tema: sorteio.tema,
- vidas: 6,
- progresso: gerarProgresso(sorteio.palavra)
- });
-
- participantesAtivos.set(chatId, new Set()); // reset participantes
-
- await api.send(
- `🎮 *Jogo da Forca iniciado!*\n\n` +
- `Tema: *${sorteio.tema}*\n` +
- `Palavra: \`${gerarProgresso(sorteio.palavra)}\`\n` +
- `Vidas: 6\n\n` +
- `Digite uma letra para adivinhar!`
- );
- return;
- }
-
- if (sub === "parar") {
- jogosAtivos.delete(chatId);
- participantesAtivos.delete(chatId);
- await api.send("🛑 Jogo da Forca encerrado.");
- return;
- }
-
- await api.send(
- `❌ Subcomando *${sub}* não existe.\n` +
- `Use ${CMD_PREFIX} + \`forca começar\` ou ${CMD_PREFIX} + \`forca parar\`.`
- );
- return;
- }
-
- // ── Tentativas durante o jogo
- const jogo = jogosAtivos.get(chatId);
- if (!jogo) return; // Nenhum jogo ativo
-
- const tentativa = msg.body.trim().toLowerCase();
- if (!/^[a-z]$/.test(tentativa)) return; // apenas letras simples
-
- // Se a letra está na palavra
- let acerto = false;
- let novoProgresso = jogo.progresso.split("");
- for (let i = 0; i < jogo.palavra.length; i++) {
- if (jogo.palavra[i] === tentativa) {
- novoProgresso[i] = tentativa;
- acerto = true;
- }
- }
- jogo.progresso = novoProgresso.join("");
-
- if (!acerto) jogo.vidas--;
-
- // Feedback para o grupo
- if (jogo.progresso === jogo.palavra) {
- await msg.reply(`🎉 Parabéns! Palavra completa: \`${jogo.palavra}\``);
- jogosAtivos.delete(chatId);
- participantesAtivos.delete(chatId);
- return;
- }
-
- if (jogo.vidas <= 0) {
- await msg.reply(`💀 Fim de jogo! Palavra era: \`${jogo.palavra}\``);
- jogosAtivos.delete(chatId);
- participantesAtivos.delete(chatId);
- return;
- }
-
- await msg.reply(
- `Palavra: \`${jogo.progresso}\`\n` +
- `Vidas: ${jogo.vidas}\n` +
- (acerto ? "✅ Acertou a letra!" : "❌ Errou a letra!")
- );
-}
\ No newline at end of file
diff --git a/src/plugins/many/index.js b/src/plugins/many/index.js
deleted file mode 100644
index d70f9e7..0000000
--- a/src/plugins/many/index.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import { CMD_PREFIX } from "../../config.js"
-
-export default async function ({ msg, api }) {
- if (!msg.is(CMD_PREFIX + "many")) return;
-
- await api.send(
- `🤖 *ManyBot — Comandos disponíveis:*\n\n` +
- `🎬 \`${CMD_PREFIX}video \` — baixa um vídeo\n` +
- `🎵 \`${CMD_PREFIX}audio \` — baixa um áudio\n` +
- `🖼️ \`${CMD_PREFIX}figurinha\` — cria figurinhas\n` +
- `🎮 \`${CMD_PREFIX}adivinhação começar|parar\` — jogo de adivinhar número\n` +
- `🎮 \`${CMD_PREFIX}forca começar|parar\` — jogo da forca\n`
- );
-}
\ No newline at end of file
diff --git a/src/plugins/obrigado/index.js b/src/plugins/obrigado/index.js
deleted file mode 100644
index eb4dfaf..0000000
--- a/src/plugins/obrigado/index.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import { CMD_PREFIX } from "../../config.js";
-const gatilhos = ["obrigado", "valeu", "brigado"];
-
-export default async function ({ msg }) {
- if (!gatilhos.some(g => msg.is(CMD_PREFIX + g))) return;
-
- await msg.reply("😊 Por nada!");
-}
\ No newline at end of file
diff --git a/src/plugins/video/index.js b/src/plugins/video/index.js
deleted file mode 100644
index 1a302eb..0000000
--- a/src/plugins/video/index.js
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
- * plugins/video/index.js
- *
- * Baixa vídeo via yt-dlp e envia no chat.
- * Todo o processo (download + envio + limpeza) fica aqui.
- */
-
-import { spawn } from "child_process";
-import fs from "fs";
-import path from "path";
-import os from "os";
-import { enqueue } from "../../download/queue.js";
-import { emptyFolder } from "../../utils/file.js";
-import { CMD_PREFIX } from "../../config.js";
-
-const logStream = fs.createWriteStream("logs/video-error.log", { flags: "a" });
-
-const DOWNLOADS_DIR = path.resolve("downloads");
-const YT_DLP = os.platform() === "win32" ? ".\\bin\\yt-dlp.exe" : "./bin/yt-dlp";
-
-const ARGS_BASE = [
- "--extractor-args", "youtube:player_client=android",
- "--print", "after_move:filepath",
- "--cookies", "cookies.txt",
- "--add-header", "User-Agent:Mozilla/5.0",
- "--add-header", "Referer:https://www.youtube.com/",
- "--retries", "4",
- "--fragment-retries", "5",
- "--socket-timeout", "15",
- "--sleep-interval", "1",
- "--max-sleep-interval", "4",
- "--no-playlist",
- "-f", "bv+ba/best",
-];
-
-function downloadVideo(url, id) {
- return new Promise((resolve, reject) => {
- fs.mkdirSync(DOWNLOADS_DIR, { recursive: true });
-
- const output = path.join(DOWNLOADS_DIR, `${id}.%(ext)s`);
- const proc = spawn(YT_DLP, [...ARGS_BASE, "--output", output, url]);
- let stdout = "";
-
- proc.on("error", err => reject(new Error(
- err.code === "EACCES"
- ? "Sem permissão para executar o yt-dlp. Rode: chmod +x ./bin/yt-dlp"
- : err.code === "ENOENT"
- ? "yt-dlp não encontrado em ./bin/yt-dlp"
- : `Erro ao iniciar o yt-dlp: ${err.message}`
- )));
-
- proc.stdout.on("data", d => { stdout += d.toString(); });
- proc.stderr.on("data", d => logStream.write(d));
-
- proc.on("close", code => {
- if (code !== 0) return reject(new Error(
- "Não foi possível baixar o vídeo. Verifique se o link é válido e tente novamente."
- ));
-
- const filePath = stdout.trim().split("\n").filter(Boolean).at(-1);
- if (!filePath || !fs.existsSync(filePath)) return reject(new Error(
- "Download concluído mas arquivo não encontrado. Tente novamente."
- ));
-
- resolve(filePath);
- });
- });
-}
-
-export default async function ({ msg, api }) {
- if (!msg.is(CMD_PREFIX + "video")) return;
-
- const url = msg.args[1];
-
- if (!url) {
- await msg.reply(`❌ Você precisa informar um link.\n\nExemplo: \`${CMD_PREFIX}video https://youtube.com/...\``);
- return;
- }
-
- await msg.reply("⏳ Baixando o vídeo, aguarde...");
-
- enqueue(
- async () => {
- const filePath = await downloadVideo(url, `video-${Date.now()}`);
- await api.sendVideo(filePath);
- fs.unlinkSync(filePath);
- emptyFolder(DOWNLOADS_DIR);
- api.log.info(`${CMD_PREFIX}video concluído → ${url}`);
- },
- async () => {
- await msg.reply(
- "❌ Não consegui baixar o vídeo.\n\n" +
- "Verifique se o link é válido e tente novamente.\n" +
- "Se o problema persistir, o conteúdo pode estar indisponível ou protegido."
- );
- }
- );
-}
\ No newline at end of file
diff --git a/src/plugins/xp/index.js b/src/plugins/xp/index.js
deleted file mode 100644
index 4d398cd..0000000
--- a/src/plugins/xp/index.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Ideia:
- *
- * Quando esse plugin for chamado, vai salvar o id de quem mandou no banco de dados.
- * Quando esse id mandar mensagem de novo, o plugin vai "se lembrar" dessa pessoa e contar xp com:
- *
- * - Número de mensagens a cada 30s > conta 1 ponto cada mensagem sendo de texto ou de audio. Durante o intervalo de 30s ele não conta nada.
- * - Tipo da mensagem:
- * - Texto/Audio: multiplicar por 1
- * - Vídeo/Foto: multiplcar por 2
- *
- * - Aculma karma dependendo da mensagem. Se suas mensagens conterem palavrões frequentes ou muito spam (ex. 5 mensagens/s), seu karma diminui:
- * - Karma negativo (abaixo de 0): divide pontos de xp por 2
- * - Karma baixo (10-20): multplica pontos por 1
- * - Karma médio (30-40): multiplica pontos por 2
- * - Karma alto (50-80): multiplca pontos por 3
- *
- * No final de cada mês, esse plugin organiza uma lista com o ranking dos top 10 com maiores XP do mês e manda em ID (chat).
- *
- * Esse plugin é a base para fazer um sistema de economia daqui um tempo.
-*/
\ No newline at end of file