[repo] reorganization

This commit is contained in:
synt-xerror
2026-03-16 18:32:57 -03:00
parent 04765868db
commit e60c5819e2
34 changed files with 1023 additions and 829 deletions

48
src/client/banner.js Normal file
View File

@@ -0,0 +1,48 @@
import { c } from "../logger/formatter.js";
export function printBanner() {
const banner = [
` _____ _____ _ `,
` | |___ ___ _ _| __ |___| |_ `,
` | | | | . | | | | __ -| . | _|`,
` |_|_|_|__,|_|_|_ |_____|___|_| `,
` |___| `
];
const pony = [
` ⠴⢮⠭⠍⠉⠉⠒⠤⣀`,
` ⢀⢊ ⢱⠊⠑⡀`,
` ⠋⡎ ⣀⡠⠤⠠⠖⠋⢉⠉ ⡄⢸`,
` ⣘⡠⠊⣩⡅ ⣴⡟⣯⠙⣊ ⢁⠜`,
` ⣿⡇⢸⣿⣷⡿⢀⠇⢀⢎`,
` ⠰⡉ ⠈⠛⠛⠋⠁⢀⠜ ⢂`,
` ⠈⠒⠒⡲⠂⣠⣔⠁ ⡇ ⢀⡴⣾⣛⡛⠻⣦`,
` ⢠⠃ ⢠⠞ ⡸⠉⠲⣿⠿⢿⣿⣿⣷⡌⢷`,
` ⢀⠔⠂⢼ ⡎⡔⡄⠰⠃ ⢣ ⢻⣿⣿⣿⠘⣷`,
` ⡐⠁ ⠸⡀ ⠏ ⠈⠃ ⢸ ⣿⣿⣿⡇⣿⡇`,
` ⡇ ⡎⠉⠉⢳ ⡤⠤⡤⠲⡀ ⢇ ⣿⣿⣿⣇⣿⣷`,
` ⡇ ⡠⠃ ⡸ ⡇ ⡇ ⢱⡀ ⢣ ⣿⣿⣿⣿⣿⡄`,
` ⠑⠊ ⢰ ⠇ ⢸ ⡇⡇ ⡇ ⢳⣿⣿⣿⣿⡇`,
` ⢠⠃ ⡸ ⡎ ⡜⡇ ⡇ ⠻⡏⠻⣿⣿⣄`,
` ⣔⣁⣀⣀⡠⠁ ⠈⠉⠉⠁⣎⣀⣀⣀⡸`
];
console.log(`${c.blue}${c.bold}`);
const max = Math.max(banner.length, pony.length);
for (let i = 0; i < max; i++) {
const left = banner[i] || " ".repeat(banner[0].length);
const right = pony[i] || "";
console.log(left + " " + right);
}
console.log();
console.log(` website : ${c.reset}${c.cyan}www.mlplovers.com.br/manybot${c.reset}`);
console.log(` repo : ${c.reset}${c.cyan}github.com/synt-xerror/manybot${c.reset}`);
console.log();
}

25
src/client/environment.js Normal file
View File

@@ -0,0 +1,25 @@
import os from "os";
/**
* Detecta se o processo está rodando dentro do Termux.
*/
export const isTermux =
(os.platform() === "linux" || os.platform() === "android") &&
process.env.PREFIX?.startsWith("/data/data/com.termux");
/**
* Retorna a config de Puppeteer adequada ao ambiente.
* @returns {import("puppeteer").LaunchOptions}
*/
export function resolvePuppeteerConfig() {
if (!isTermux) return {};
return {
executablePath: "/data/data/com.termux/files/usr/bin/chromium-browser",
args: [
"--headless=new", "--no-sandbox", "--disable-setuid-sandbox",
"--disable-dev-shm-usage", "--disable-gpu", "--single-process",
"--no-zygote", "--disable-software-rasterizer",
],
};
}

25
src/client/qrHandler.js Normal file
View File

@@ -0,0 +1,25 @@
import qrcode from "qrcode-terminal";
import path from "path";
import { logger } from "../logger/logger.js";
import { isTermux } from "./environment.js";
const QR_PATH = path.resolve("qr.png");
/**
* Exibe ou salva o QR Code conforme o ambiente.
* @param {string} qr — string bruta do evento "qr"
*/
export async function handleQR(qr) {
if (isTermux) {
try {
await QRCode.toFile(QR_PATH, qr, { width: 400 });
logger.info(`QR Code salvo em: ${QR_PATH}`);
logger.info(`Abra com: termux-open qr.png`);
} catch (err) {
logger.error("Falha ao salvar QR Code:", err.message);
}
} else {
logger.info("Escaneie o QR Code abaixo:");
qrcode.generate(qr, { small: true });
}
}

View File

@@ -1,100 +1,39 @@
import pkg from "whatsapp-web.js";
import qrcode from "qrcode-terminal";
import { exec } from "child_process";
import { CLIENT_ID } from "../config.js";
import os from "os";
import pkg from "whatsapp-web.js";
import { CLIENT_ID } from "../config.js";
import { logger } from "../logger/logger.js";
import { isTermux, resolvePuppeteerConfig } from "./environment.js";
import { handleQR } from "./qrHandler.js";
import { printBanner } from "./banner.js";
export const { Client, LocalAuth, MessageMedia } = pkg;
// ── Logger ──────────────────────────────────────────────────
const c = {
reset: "\x1b[0m", bold: "\x1b[1m", dim: "\x1b[2m",
green: "\x1b[32m", yellow: "\x1b[33m", cyan: "\x1b[36m",
red: "\x1b[31m", gray: "\x1b[90m", white: "\x1b[37m",
blue: "\x1b[34m", magenta: "\x1b[35m",
};
const now = () =>
new Date().toLocaleString("pt-BR", { dateStyle: "short", timeStyle: "short" });
export const logger = {
info: (...a) => console.log(`${c.gray}${now()}${c.reset} `, ...a),
success: (...a) => console.log(`${c.gray}${now()}${c.reset} ${c.green}${c.reset}`, ...a),
warn: (...a) => console.log(`${c.gray}${now()}${c.reset} ${c.yellow}⚠️ ${c.reset}`, ...a),
error: (...a) => console.log(`${c.gray}${now()}${c.reset} ${c.red}${c.reset}`, ...a),
bot: (...a) => console.log(`${c.gray}${now()}${c.reset} ${c.magenta}🤖${c.reset}`, ...a),
};
// ── Banner ───────────────────────────────────────────────────
function printBanner() {
console.log(`${c.blue}${c.bold}`);
console.log(` _____ _____ _ `);
console.log(`| |___ ___ _ _| __ |___| |_ `);
console.log(`| | | | .'| | | | __ -| . | _|`);
console.log(`|_|_|_|__,|_|_|_ |_____|___|_| `);
console.log(` |___| `);
console.log();
console.log(` website : ${c.reset}${c.cyan}www.mlplovers.com.br/manybot${c.reset}`);
console.log(` repo : ${c.reset}${c.cyan}github.com/synt-xerror/manybot${c.reset}`);
console.log();
console.log(` ${c.bold}✨ A Amizade é Mágica!${c.reset}`);
console.log();
}
// ── Ambiente ─────────────────────────────────────────────────
const isTermux =
(os.platform() === "linux" || os.platform() === "android") &&
process.env.PREFIX?.startsWith("/data/data/com.termux");
logger.info(isTermux
? `Ambiente: ${c.yellow}${c.bold}Termux${c.reset} — usando Chromium do sistema`
: `Ambiente: ${c.blue}${c.bold}${os.platform()}${c.reset} — usando Puppeteer padrão`
? "Ambiente: Termux — usando Chromium do sistema"
: `Ambiente: ${process.platform} — usando Puppeteer padrão`
);
const puppeteerConfig = isTermux
? {
executablePath: "/data/data/com.termux/files/usr/bin/chromium-browser",
args: [
"--headless=new", "--no-sandbox", "--disable-setuid-sandbox",
"--disable-dev-shm-usage", "--disable-gpu", "--single-process",
"--no-zygote", "--disable-software-rasterizer",
],
}
: {};
// ── Cliente ──────────────────────────────────────────────────
// ── Instância ─────────────────────────────────────────────────
export const client = new Client({
authStrategy: new LocalAuth({ clientId: CLIENT_ID }),
puppeteer: { headless: true, ...puppeteerConfig },
puppeteer: { headless: true, ...resolvePuppeteerConfig() },
});
client.on("qr", async qr => {
if (isTermux) {
try {
await QRCode.toFile(QR_PATH, qr, { width: 400 });
logger.bot(`QR Code salvo em: ${c.cyan}${c.bold}${QR_PATH}${c.reset}`);
logger.bot(`Abra com: ${c.yellow}termux-open qr.png${c.reset}`);
} catch (err) {
logger.error("Falha ao salvar QR Code:", err.message);
}
} else {
logger.bot(`Escaneie o ${c.yellow}${c.bold}QR Code${c.reset} abaixo:`);
qrcode.generate(qr, { small: true });
}
});
// ── Eventos ───────────────────────────────────────────────────
client.on("qr", handleQR);
client.on("ready", () => {
exec("clear");
console.log("READY DISPAROU"); // temporário
printBanner();
logger.success(`${c.green}${c.bold}WhatsApp conectado e pronto!${c.reset}`);
logger.info(`Client ID: ${c.cyan}${CLIENT_ID}${c.reset}`);
logger.success("WhatsApp conectado e pronto!");
logger.info(`Client ID: ${CLIENT_ID}`);
});
client.on("disconnected", reason => {
logger.warn(`Desconectado — motivo: ${c.yellow}${reason}${c.reset}`);
logger.info(`Reconectando em ${c.cyan}5s${c.reset}...`);
client.on("disconnected", (reason) => {
logger.warn(`Desconectado — motivo: ${reason}`);
logger.info("Reconectando em 5s...");
setTimeout(() => {
logger.bot("Reinicializando cliente...");
logger.info("Reinicializando cliente...");
client.initialize();
}, 5000);
});