Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb50d4b8f8 | ||
|
|
f2e6c12af4 | ||
|
|
308db818da | ||
|
|
541f11af6d |
14
deploy.sh
14
deploy.sh
@@ -24,13 +24,6 @@ EOF
|
|||||||
# mudar para a branch
|
# mudar para a branch
|
||||||
git checkout $BRANCH || { echo "Error ao change to $BRANCH"; exit 1; }
|
git checkout $BRANCH || { echo "Error ao change to $BRANCH"; exit 1; }
|
||||||
|
|
||||||
# adicionar alterações e commit
|
|
||||||
git add .
|
|
||||||
git commit -m "$COMMIT_MSG"
|
|
||||||
|
|
||||||
# push
|
|
||||||
git push origin $BRANCH
|
|
||||||
|
|
||||||
# se for master, atualizar versão
|
# se for master, atualizar versão
|
||||||
if [ "$BRANCH" == "master" ] && [ -n "$VERSION" ]; then
|
if [ "$BRANCH" == "master" ] && [ -n "$VERSION" ]; then
|
||||||
echo "Updating version to $VERSION"
|
echo "Updating version to $VERSION"
|
||||||
@@ -41,4 +34,11 @@ if [ "$BRANCH" == "master" ] && [ -n "$VERSION" ]; then
|
|||||||
git push origin $VERSION
|
git push origin $VERSION
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# adicionar alterações e commit
|
||||||
|
git add .
|
||||||
|
git commit -m "$COMMIT_MSG"
|
||||||
|
|
||||||
|
# push
|
||||||
|
git push origin $BRANCH
|
||||||
|
|
||||||
echo "Deploy completed."
|
echo "Deploy completed."
|
||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "whatsapp-bot",
|
"name": "whatsapp-bot",
|
||||||
"version": "2.2.0",
|
"version": "2.3.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "whatsapp-bot",
|
"name": "whatsapp-bot",
|
||||||
"version": "2.2.0",
|
"version": "2.3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-addon-api": "^7",
|
"node-addon-api": "^7",
|
||||||
"node-gyp": "^12.2.0",
|
"node-gyp": "^12.2.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "whatsapp-bot",
|
"name": "whatsapp-bot",
|
||||||
"version": "2.2.0",
|
"version": "2.3.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-addon-api": "^7",
|
"node-addon-api": "^7",
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ async function convertVideoToGif(inputPath, outputPath, fps = 12) {
|
|||||||
|
|
||||||
await execFileAsync(FFMPEG, [
|
await execFileAsync(FFMPEG, [
|
||||||
"-i", inputPath,
|
"-i", inputPath,
|
||||||
"-filter_complex", filter, // <-- era -vf, tem que ser -filter_complex pro split funcionar
|
"-filter_complex", filter,
|
||||||
"-loop", "0",
|
"-loop", "0",
|
||||||
"-y",
|
"-y",
|
||||||
outputPath
|
outputPath
|
||||||
@@ -63,7 +63,7 @@ async function resizeToSticker(inputPath, outputPath) {
|
|||||||
|
|
||||||
await execFileAsync(FFMPEG, [
|
await execFileAsync(FFMPEG, [
|
||||||
"-i", inputPath,
|
"-i", inputPath,
|
||||||
"-vf", "scale=512:512:flags=lanczos", // lanczos = melhor qualidade no resize
|
"-vf", "scale=512:512:flags=lanczos",
|
||||||
"-y",
|
"-y",
|
||||||
outputPath
|
outputPath
|
||||||
]);
|
]);
|
||||||
@@ -98,33 +98,40 @@ async function createStickerWithFallback(stickerInputPath, isAnimated) {
|
|||||||
|
|
||||||
// ───────────────── Sessão ─────────────────
|
// ───────────────── Sessão ─────────────────
|
||||||
|
|
||||||
export function iniciarSessao(chatId, author) {
|
export const help =
|
||||||
|
"📌 *Como criar figurinhas:*\n\n" +
|
||||||
|
"1️⃣ Digite `!figurinha` para iniciar\n" +
|
||||||
|
"2️⃣ Envie as imagens, GIFs ou vídeos que quer transformar\n" +
|
||||||
|
"3️⃣ Digite `!figurinha criar` para gerar as figurinhas\n\n" +
|
||||||
|
"⏳ A sessão expira em 2 minutos se nenhuma mídia for enviada.";
|
||||||
|
|
||||||
|
export function iniciarSessao(chatId, author, msg) {
|
||||||
if (stickerSessions.has(chatId)) return false;
|
if (stickerSessions.has(chatId)) return false;
|
||||||
|
|
||||||
const timeout = setTimeout(() => {
|
const timeout = setTimeout(async () => {
|
||||||
|
|
||||||
stickerSessions.delete(chatId);
|
stickerSessions.delete(chatId);
|
||||||
client.sendMessage(chatId, botMsg("Sessão de figurinha expirou."));
|
try {
|
||||||
|
await msg.reply(botMsg(
|
||||||
|
"⏰ *Sessão expirada!*\n\n" +
|
||||||
|
"Você demorou mais de 2 minutos para enviar as mídias.\n" +
|
||||||
|
"Digite `!figurinha` para começar de novo."
|
||||||
|
));
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Erro ao notificar expiração:", err.message);
|
||||||
|
}
|
||||||
}, SESSION_TIMEOUT);
|
}, SESSION_TIMEOUT);
|
||||||
|
|
||||||
stickerSessions.set(chatId, {
|
stickerSessions.set(chatId, { author, medias: [], timeout });
|
||||||
author,
|
|
||||||
medias: [],
|
|
||||||
timeout
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ───────────────── Coleta de mídia ─────────────────
|
// ───────────────── Coleta de mídia ─────────────────
|
||||||
|
|
||||||
export async function coletarMidia(msg) {
|
export async function coletarMidia(msg) {
|
||||||
|
;
|
||||||
|
// figurinha.js — coletarMidia
|
||||||
const chat = await msg.getChat();
|
const chat = await msg.getChat();
|
||||||
const chatId = chat.id._serialized;
|
const chatId = chat.id._serialized; // ← volta pra isso
|
||||||
|
|
||||||
const session = stickerSessions.get(chatId);
|
const session = stickerSessions.get(chatId);
|
||||||
if (!session) return;
|
if (!session) return;
|
||||||
@@ -158,29 +165,36 @@ export async function coletarMidia(msg) {
|
|||||||
// ───────────────── Criar stickers ─────────────────
|
// ───────────────── Criar stickers ─────────────────
|
||||||
|
|
||||||
export async function gerarSticker(msg, chatId) {
|
export async function gerarSticker(msg, chatId) {
|
||||||
|
console.log("[gerarSticker] chatId:", chatId);
|
||||||
|
|
||||||
const sender = msg.author || msg.from;
|
const sender = msg.author || msg.from;
|
||||||
const session = stickerSessions.get(chatId);
|
const session = stickerSessions.get(chatId);
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
return msg.reply(botMsg("Nenhuma sessão de figurinha ativa."));
|
return msg.reply(botMsg(
|
||||||
|
"❌ *Nenhuma sessão ativa.*\n\n" + help
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session.author !== sender) {
|
if (session.author !== sender) {
|
||||||
return msg.reply(botMsg("Apenas quem iniciou a sessão pode criar as figurinhas."));
|
return msg.reply(botMsg(
|
||||||
|
"🚫 Só quem digitou `!figurinha` pode usar `!figurinha criar`."
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
const medias = session.medias;
|
const medias = session.medias;
|
||||||
|
|
||||||
if (!medias.length) {
|
if (!medias.length) {
|
||||||
return msg.reply(botMsg("Nenhuma imagem recebida."));
|
return msg.reply(botMsg(
|
||||||
|
"📭 *Você ainda não enviou nenhuma mídia!*\n\n" + help
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
clearTimeout(session.timeout);
|
clearTimeout(session.timeout);
|
||||||
|
|
||||||
console.log("midias:", medias.length);
|
console.log("midias:", medias.length);
|
||||||
|
|
||||||
await msg.reply(botMsg("Aguarde! Estou criando as suas figurinhas..."));
|
await msg.reply(botMsg("⏳ Gerando suas figurinhas, aguarde um momento..."));
|
||||||
|
|
||||||
ensureDownloadsDir();
|
ensureDownloadsDir();
|
||||||
|
|
||||||
@@ -198,7 +212,6 @@ export async function gerarSticker(msg, chatId) {
|
|||||||
|
|
||||||
fs.writeFileSync(inputPath, Buffer.from(media.data, "base64"));
|
fs.writeFileSync(inputPath, Buffer.from(media.data, "base64"));
|
||||||
|
|
||||||
// LOG 1 — arquivo de entrada
|
|
||||||
const inputSize = fs.statSync(inputPath).size;
|
const inputSize = fs.statSync(inputPath).size;
|
||||||
console.log(`[1] mimetype: ${media.mimetype} | isAnimated: ${isAnimated} | inputPath: ${inputPath} | size: ${inputSize} bytes`);
|
console.log(`[1] mimetype: ${media.mimetype} | isAnimated: ${isAnimated} | inputPath: ${inputPath} | size: ${inputSize} bytes`);
|
||||||
|
|
||||||
@@ -208,7 +221,6 @@ export async function gerarSticker(msg, chatId) {
|
|||||||
console.log("[2] Convertendo para GIF...");
|
console.log("[2] Convertendo para GIF...");
|
||||||
await convertVideoToGif(inputPath, gifPath, isVideo ? 12 : 24);
|
await convertVideoToGif(inputPath, gifPath, isVideo ? 12 : 24);
|
||||||
|
|
||||||
// LOG 2 — gif gerado
|
|
||||||
if (fs.existsSync(gifPath)) {
|
if (fs.existsSync(gifPath)) {
|
||||||
console.log(`[2] GIF gerado: ${fs.statSync(gifPath).size} bytes`);
|
console.log(`[2] GIF gerado: ${fs.statSync(gifPath).size} bytes`);
|
||||||
} else {
|
} else {
|
||||||
@@ -229,12 +241,10 @@ export async function gerarSticker(msg, chatId) {
|
|||||||
stickerInputPath = resizedPath;
|
stickerInputPath = resizedPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// LOG 3 — antes de criar o sticker
|
|
||||||
console.log(`[3] stickerInputPath: ${stickerInputPath} | exists: ${fs.existsSync(stickerInputPath)} | size: ${fs.existsSync(stickerInputPath) ? fs.statSync(stickerInputPath).size : "N/A"} bytes`);
|
console.log(`[3] stickerInputPath: ${stickerInputPath} | exists: ${fs.existsSync(stickerInputPath)} | size: ${fs.existsSync(stickerInputPath) ? fs.statSync(stickerInputPath).size : "N/A"} bytes`);
|
||||||
|
|
||||||
const stickerBuffer = await createStickerWithFallback(stickerInputPath, isAnimated);
|
const stickerBuffer = await createStickerWithFallback(stickerInputPath, isAnimated);
|
||||||
|
|
||||||
// LOG 4 — sticker gerado
|
|
||||||
console.log(`[4] Sticker buffer: ${stickerBuffer.length} bytes`);
|
console.log(`[4] Sticker buffer: ${stickerBuffer.length} bytes`);
|
||||||
|
|
||||||
const stickerMedia = new MessageMedia("image/webp", stickerBuffer.toString("base64"));
|
const stickerMedia = new MessageMedia("image/webp", stickerBuffer.toString("base64"));
|
||||||
@@ -244,11 +254,17 @@ export async function gerarSticker(msg, chatId) {
|
|||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Erro ao gerar sticker:", err);
|
console.error("Erro ao gerar sticker:", err);
|
||||||
await msg.reply(botMsg("Erro ao gerar uma das figurinhas."));
|
await msg.reply(botMsg(
|
||||||
|
"⚠️ Não consegui criar uma das figurinhas.\n" +
|
||||||
|
"Tente reenviar essa mídia ou use outro formato (JPG, PNG, GIF, MP4)."
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await msg.reply(botMsg("Figurinhas geradas com sucesso!"));
|
await msg.reply(botMsg(
|
||||||
|
"✅ *Figurinhas criadas com sucesso!*\n" +
|
||||||
|
"Salve as que quiser no seu WhatsApp. 😄"
|
||||||
|
));
|
||||||
|
|
||||||
stickerSessions.delete(chatId);
|
stickerSessions.delete(chatId);
|
||||||
emptyFolder("downloads");
|
emptyFolder("downloads");
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { enqueueDownload } from "../download/queue.js";
|
import { enqueueDownload } from "../download/queue.js";
|
||||||
import { iniciarSessao, gerarSticker } from "./figurinha.js";
|
import { iniciarSessao, gerarSticker, help } from "./figurinha.js";
|
||||||
import { botMsg } from "../utils/botMsg.js";
|
import { botMsg } from "../utils/botMsg.js";
|
||||||
import { iniciarJogo, pararJogo } from "../games/adivinhacao.js";
|
import { iniciarJogo, pararJogo } from "../games/adivinhacao.js";
|
||||||
import { processarInfo } from "./info.js";
|
import { processarInfo } from "./info.js";
|
||||||
|
import client from "../client/whatsappClient.js";
|
||||||
|
|
||||||
export const stickerSessions = new Map();
|
export const stickerSessions = new Map();
|
||||||
|
|
||||||
@@ -34,88 +35,93 @@ export async function processarComando(msg, chat, chatId) {
|
|||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case "!many":
|
case "!many":
|
||||||
await chat.sendMessage(botMsg(
|
await chat.sendMessage(botMsg(
|
||||||
"Comandos:\n\n" +
|
"*Comandos disponíveis:*\n\n" +
|
||||||
"- `!ping`\n" +
|
"🎬 `!video <link>` — baixa um vídeo\n" +
|
||||||
"- `!video <link>`\n" +
|
"🎵 `!audio <link>` — baixa um áudio\n" +
|
||||||
"- `!audio <link>`\n" +
|
"🖼️ `!figurinha` — cria figurinhas\n" +
|
||||||
"- `!figurinha`\n" +
|
"🎮 `!adivinhação começar|parar` — jogo de adivinhar número\n"
|
||||||
"- `!adivinhação começar|parar`\n" +
|
|
||||||
"- `!info <comando>`"
|
|
||||||
));
|
));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "!ping":
|
|
||||||
await msg.reply(botMsg("pong 🏓"));
|
|
||||||
log.ok("pong enviado");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "!video":
|
case "!video":
|
||||||
if (!tokens[1]) { log.warn("!video sem link"); return; }
|
if (!tokens[1]) {
|
||||||
await msg.reply(botMsg("⏳ Baixando vídeo..."));
|
await msg.reply(botMsg("❌ Você precisa informar um link.\n\nExemplo: `!video https://youtube.com/...`"));
|
||||||
|
log.warn("!video sem link");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await msg.reply(botMsg("⏳ Baixando o vídeo, aguarde..."));
|
||||||
enqueueDownload("video", tokens[1], msg, chatId);
|
enqueueDownload("video", tokens[1], msg, chatId);
|
||||||
log.ok("vídeo enfileirado →", tokens[1]);
|
log.ok("vídeo enfileirado →", tokens[1]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "!audio":
|
case "!audio":
|
||||||
if (!tokens[1]) { log.warn("!audio sem link"); return; }
|
if (!tokens[1]) {
|
||||||
await msg.reply(botMsg("⏳ Baixando áudio..."));
|
await msg.reply(botMsg("❌ Você precisa informar um link.\n\nExemplo: `!audio https://youtube.com/...`"));
|
||||||
|
log.warn("!audio sem link");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await msg.reply(botMsg("⏳ Baixando o áudio, aguarde..."));
|
||||||
enqueueDownload("audio", tokens[1], msg, chatId);
|
enqueueDownload("audio", tokens[1], msg, chatId);
|
||||||
log.ok("áudio enfileirado →", tokens[1]);
|
log.ok("áudio enfileirado →", tokens[1]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "!figurinha":
|
case "!figurinha":
|
||||||
const author = msg.author || msg.from;
|
const author = msg.author || msg.from;
|
||||||
|
const name = msg._data?.notifyName || author.replace(/(:\d+)?@.*$/, "");
|
||||||
|
const groupId = chat.id._serialized; // < fonte única de verdade
|
||||||
|
|
||||||
if (tokens[1] === "criar") {
|
if (tokens[1] === "criar") {
|
||||||
await gerarSticker(msg, chatId);
|
await gerarSticker(msg, groupId);
|
||||||
} else {
|
} else {
|
||||||
if (stickerSessions.has(chatId)) {
|
if (stickerSessions.has(groupId)) {
|
||||||
return msg.reply(botMsg("Já existe uma sessão ativa."));
|
return msg.reply(botMsg(
|
||||||
}
|
"⚠️ Já existe uma sessão aberta.\n\n" +
|
||||||
|
"Envie as mídias e depois use `!figurinha criar`.\n" +
|
||||||
iniciarSessao(chatId, author);
|
"Ou aguarde 2 minutos para a sessão expirar."
|
||||||
|
));
|
||||||
await msg.reply(botMsg(
|
}
|
||||||
`Sessão de figurinha iniciada por @${author.split("@")[0]}. Envie no máximo 10 imagens, quando estiver pronto mande \`!figurinha criar\``,
|
iniciarSessao(groupId, author, msg);
|
||||||
null,
|
await msg.reply(botMsg(
|
||||||
{ mentions: [author] }
|
`✅ Sessão iniciada por *${name}*!\n\n` + help
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case "!adivinhação":
|
case "!adivinhação":
|
||||||
if (!tokens[1]) {
|
if (!tokens[1]) {
|
||||||
await chat.sendMessage(botMsg("`!adivinhação começar`\n`!adivinhação parar`"));
|
await chat.sendMessage(botMsg(
|
||||||
|
"🎮 *Jogo de adivinhação:*\n\n" +
|
||||||
|
"`!adivinhação começar` — inicia o jogo\n" +
|
||||||
|
"`!adivinhação parar` — encerra o jogo"
|
||||||
|
));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tokens[1] === "começar") {
|
if (tokens[1] === "começar") {
|
||||||
iniciarJogo();
|
iniciarJogo();
|
||||||
await chat.sendMessage(botMsg("Jogo iniciado! Tente adivinhar o número de 1 a 100."));
|
await chat.sendMessage(botMsg(
|
||||||
|
"🎮 *Jogo iniciado!*\n\n" +
|
||||||
|
"Estou pensando em um número de 1 a 100.\n" +
|
||||||
|
"Tente adivinhar! 🤔"
|
||||||
|
));
|
||||||
log.ok("jogo iniciado");
|
log.ok("jogo iniciado");
|
||||||
} else if (tokens[1] === "parar") {
|
} else if (tokens[1] === "parar") {
|
||||||
pararJogo();
|
pararJogo();
|
||||||
await chat.sendMessage(botMsg("Jogo parado."));
|
await chat.sendMessage(botMsg("🛑 Jogo encerrado."));
|
||||||
log.ok("jogo parado");
|
log.ok("jogo parado");
|
||||||
} else {
|
} else {
|
||||||
|
await chat.sendMessage(botMsg(
|
||||||
|
`❌ Subcomando *${tokens[1]}* não existe.\n\n` +
|
||||||
|
"Use `!adivinhação começar` ou `!adivinhação parar`."
|
||||||
|
));
|
||||||
log.warn("!adivinhação — subcomando desconhecido:", tokens[1]);
|
log.warn("!adivinhação — subcomando desconhecido:", tokens[1]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "!info":
|
|
||||||
if (!tokens[1]) {
|
|
||||||
await chat.sendMessage(botMsg("Use:\n`!info <comando>`"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
processarInfo(tokens[1], chat);
|
|
||||||
log.ok("info →", tokens[1]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "!obrigado":
|
case "!obrigado":
|
||||||
case "!valeu":
|
case "!valeu":
|
||||||
case "!brigado":
|
case "!brigado":
|
||||||
await msg.reply(botMsg("Por nada!"));
|
await msg.reply(botMsg("😊 Por nada!"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "a":
|
case "a":
|
||||||
@@ -124,6 +130,9 @@ export async function processarComando(msg, chat, chatId) {
|
|||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log.error("Falha em", cmd, "—", err.message);
|
log.error("Falha em", cmd, "—", err.message);
|
||||||
await chat.sendMessage(botMsg("Erro:\n`" + err.message + "`"));
|
await chat.sendMessage(botMsg(
|
||||||
|
"❌ Algo deu errado ao executar esse comando.\n" +
|
||||||
|
"Tente novamente em instantes."
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,8 +7,9 @@ const so = os.platform();
|
|||||||
export async function get_audio(url, id) {
|
export async function get_audio(url, id) {
|
||||||
const video = await get_video(url, id);
|
const video = await get_video(url, id);
|
||||||
const output = `downloads/${id}.mp3`;
|
const output = `downloads/${id}.mp3`;
|
||||||
|
|
||||||
const cmd = so === "win32" ? ".\\bin\\ffmpeg.exe" : "./bin/ffmpeg";
|
const cmd = so === "win32" ? ".\\bin\\ffmpeg.exe" : "./bin/ffmpeg";
|
||||||
const args = ['-i', video, '-vn', '-acodec', 'libmp3lame', '-q:a', '2', output];
|
const args = ["-i", video, "-vn", "-acodec", "libmp3lame", "-q:a", "2", output];
|
||||||
|
|
||||||
await runCmd(cmd, args);
|
await runCmd(cmd, args);
|
||||||
return output;
|
return output;
|
||||||
@@ -17,8 +18,17 @@ export async function get_audio(url, id) {
|
|||||||
async function runCmd(cmd, args) {
|
async function runCmd(cmd, args) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const proc = spawn(cmd, args);
|
const proc = spawn(cmd, args);
|
||||||
|
|
||||||
proc.stdout.on("data", data => console.log("[cmd]", data.toString()));
|
proc.stdout.on("data", data => console.log("[cmd]", data.toString()));
|
||||||
proc.stderr.on("data", data => console.error("[cmd ERR]", data.toString()));
|
proc.stderr.on("data", data => console.error("[cmd ERR]", data.toString()));
|
||||||
proc.on("close", code => code === 0 ? resolve() : reject(new Error("Processo saiu com código "+code)));
|
|
||||||
|
proc.on("close", code => {
|
||||||
|
if (code !== 0) {
|
||||||
|
return reject(new Error(
|
||||||
|
"Não foi possível converter o áudio. Tente novamente com outro link."
|
||||||
|
));
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
import { get_video } from "./video.js";
|
import { get_video } from "./video.js";
|
||||||
import { get_audio } from "./audio.js";
|
import { get_audio } from "./audio.js";
|
||||||
import pkg from "whatsapp-web.js";
|
import pkg from "whatsapp-web.js";
|
||||||
const { MessageMedia } = pkg;
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import { botMsg } from "../utils/botMsg.js";
|
import { botMsg } from "../utils/botMsg.js";
|
||||||
import { emptyFolder } from "../utils/file.js";
|
import { emptyFolder } from "../utils/file.js";
|
||||||
import client from "../client/whatsappClient.js";
|
import client from "../client/whatsappClient.js";
|
||||||
|
|
||||||
|
const { MessageMedia } = pkg;
|
||||||
|
|
||||||
let downloadQueue = [];
|
let downloadQueue = [];
|
||||||
let processingQueue = false;
|
let processingQueue = false;
|
||||||
|
|
||||||
@@ -17,26 +18,36 @@ export function enqueueDownload(type, url, msg, chatId) {
|
|||||||
|
|
||||||
async function processQueue() {
|
async function processQueue() {
|
||||||
processingQueue = true;
|
processingQueue = true;
|
||||||
|
|
||||||
while (downloadQueue.length) {
|
while (downloadQueue.length) {
|
||||||
const job = downloadQueue.shift();
|
const job = downloadQueue.shift();
|
||||||
try {
|
const label = job.type === "video" ? "vídeo" : "áudio";
|
||||||
let path;
|
|
||||||
if (job.type === "video") path = await get_video(job.url, job.msg.id._serialized);
|
|
||||||
else path = await get_audio(job.url, job.msg.id._serialized);
|
|
||||||
|
|
||||||
const file = fs.readFileSync(path);
|
try {
|
||||||
|
const filePath = job.type === "video"
|
||||||
|
? await get_video(job.url, job.msg.id._serialized)
|
||||||
|
: await get_audio(job.url, job.msg.id._serialized);
|
||||||
|
|
||||||
|
const file = fs.readFileSync(filePath);
|
||||||
const media = new MessageMedia(
|
const media = new MessageMedia(
|
||||||
job.type === "video" ? "video/mp4" : "audio/mpeg",
|
job.type === "video" ? "video/mp4" : "audio/mpeg",
|
||||||
file.toString("base64"),
|
file.toString("base64"),
|
||||||
path.split("/").pop()
|
filePath.split("/").pop()
|
||||||
);
|
);
|
||||||
|
|
||||||
await client.sendMessage(job.chatId, media);
|
await client.sendMessage(job.chatId, media);
|
||||||
fs.unlinkSync(path);
|
fs.unlinkSync(filePath);
|
||||||
emptyFolder("downloads");
|
emptyFolder("downloads");
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await client.sendMessage(job.chatId, botMsg(`❌ Erro ao baixar ${job.type}\n\`${err.message}\``));
|
console.error(`[queue] Erro ao baixar ${label}:`, err.message);
|
||||||
|
await job.msg.reply(botMsg(
|
||||||
|
`❌ Não consegui baixar o ${label}.\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."
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
processingQueue = false;
|
processingQueue = false;
|
||||||
}
|
}
|
||||||
@@ -6,25 +6,24 @@ import os from "os";
|
|||||||
const platform = os.platform();
|
const platform = os.platform();
|
||||||
|
|
||||||
export async function get_video(url, id) {
|
export async function get_video(url, id) {
|
||||||
// garante que a pasta exista
|
|
||||||
const downloadsDir = path.resolve("downloads");
|
const downloadsDir = path.resolve("downloads");
|
||||||
fs.mkdirSync(downloadsDir, { recursive: true });
|
fs.mkdirSync(downloadsDir, { recursive: true });
|
||||||
|
|
||||||
const cmd = platform === "win32" ? ".\\bin\\yt-dlp.exe" : "./bin/yt-dlp";
|
const cmd = platform === "win32" ? ".\\bin\\yt-dlp.exe" : "./bin/yt-dlp";
|
||||||
const args = [
|
const args = [
|
||||||
'--extractor-args', 'youtube:player_client=android',
|
"--extractor-args", "youtube:player_client=android",
|
||||||
'-f', 'bv+ba/best',
|
"-f", "bv+ba/best",
|
||||||
'--print', 'after_move:filepath',
|
"--print", "after_move:filepath",
|
||||||
'--output', path.join(downloadsDir, `${id}.%(ext)s`),
|
"--output", path.join(downloadsDir, `${id}.%(ext)s`),
|
||||||
'--cookies', 'cookies.txt',
|
"--cookies", "cookies.txt",
|
||||||
'--add-header', 'User-Agent:Mozilla/5.0',
|
"--add-header", "User-Agent:Mozilla/5.0",
|
||||||
'--add-header', 'Referer:https://www.youtube.com/',
|
"--add-header", "Referer:https://www.youtube.com/",
|
||||||
'--retries', '4',
|
"--retries", "4",
|
||||||
'--fragment-retries', '5',
|
"--fragment-retries", "5",
|
||||||
'--socket-timeout', '15',
|
"--socket-timeout", "15",
|
||||||
'--sleep-interval', '1', '--max-sleep-interval', '4',
|
"--sleep-interval", "1", "--max-sleep-interval", "4",
|
||||||
'--no-playlist',
|
"--no-playlist",
|
||||||
url
|
url,
|
||||||
];
|
];
|
||||||
|
|
||||||
return await runCmd(cmd, args);
|
return await runCmd(cmd, args);
|
||||||
@@ -39,14 +38,19 @@ async function runCmd(cmd, args) {
|
|||||||
proc.stderr.on("data", data => console.error("[yt-dlp ERR]", data.toString()));
|
proc.stderr.on("data", data => console.error("[yt-dlp ERR]", data.toString()));
|
||||||
|
|
||||||
proc.on("close", code => {
|
proc.on("close", code => {
|
||||||
if (code !== 0) return reject(new Error("yt-dlp saiu com código " + 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."
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// Pega a última linha, que é o caminho final do arquivo
|
|
||||||
const lines = stdout.trim().split("\n").filter(l => l.trim());
|
const lines = stdout.trim().split("\n").filter(l => l.trim());
|
||||||
const filepath = lines[lines.length - 1];
|
const filepath = lines[lines.length - 1];
|
||||||
|
|
||||||
if (!fs.existsSync(filepath)) {
|
if (!fs.existsSync(filepath)) {
|
||||||
return reject(new Error("Arquivo não encontrado: " + filepath));
|
return reject(new Error(
|
||||||
|
"O download foi concluído, mas o arquivo não foi encontrado. Tente novamente."
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(filepath);
|
resolve(filepath);
|
||||||
|
|||||||
@@ -18,12 +18,18 @@ export async function processarJogo(msg, chat) {
|
|||||||
if (!/^\d+$/.test(tentativa)) return;
|
if (!/^\d+$/.test(tentativa)) return;
|
||||||
|
|
||||||
const num = parseInt(tentativa);
|
const num = parseInt(tentativa);
|
||||||
|
|
||||||
if (num === jogoAtivo) {
|
if (num === jogoAtivo) {
|
||||||
await msg.reply(botMsg(`Acertou! Número: ${jogoAtivo}`));
|
await msg.reply(botMsg(
|
||||||
|
`🎉 *Acertou!* O número era ${jogoAtivo}!\n\n` +
|
||||||
|
"Use `!adivinhação começar` para jogar de novo."
|
||||||
|
));
|
||||||
pararJogo();
|
pararJogo();
|
||||||
|
} else if (num < 1 || num > 100) {
|
||||||
|
await msg.reply(botMsg("⚠️ Digite um número entre 1 e 100."));
|
||||||
} else if (num > jogoAtivo) {
|
} else if (num > jogoAtivo) {
|
||||||
await chat.sendMessage(botMsg("Menor."));
|
await chat.sendMessage(botMsg("📉 Tente um número *menor*!"));
|
||||||
} else {
|
} else {
|
||||||
await chat.sendMessage(botMsg("Maior."));
|
await chat.sendMessage(botMsg("📈 Tente um número *maior*!"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@ const logger = {
|
|||||||
: `${c.bold}${chatName}${c.reset} ${c.dim}(privado)${c.reset}`;
|
: `${c.bold}${chatName}${c.reset} ${c.dim}(privado)${c.reset}`;
|
||||||
|
|
||||||
const bodyPreview = body?.trim()
|
const bodyPreview = body?.trim()
|
||||||
? `${isCommand ? c.yellow : c.green}"${body.length > 80 ? body.slice(0, 80) + "…" : body}"${c.reset}`
|
? `${isCommand ? c.yellow : c.green}"${body.length > 200 ? body.slice(0, 200) + "..." : body}"${c.reset}`
|
||||||
: `${c.dim}<${typeLabel}>${c.reset}`;
|
: `${c.dim}<${typeLabel}>${c.reset}`;
|
||||||
|
|
||||||
// Resolve reply
|
// Resolve reply
|
||||||
@@ -70,7 +70,7 @@ const logger = {
|
|||||||
quotedName = quotedContact?.pushname || quotedContact?.formattedName || quotedNumber;
|
quotedName = quotedContact?.pushname || quotedContact?.formattedName || quotedNumber;
|
||||||
} catch {}
|
} catch {}
|
||||||
const quotedPreview = quoted.body?.trim()
|
const quotedPreview = quoted.body?.trim()
|
||||||
? `"${quoted.body.length > 60 ? quoted.body.slice(0, 60) + "…" : quoted.body}"`
|
? `"${quoted.body.length > 80 ? quoted.body.slice(0, 80) + "…" : quoted.body}"`
|
||||||
: `<${quoted.type}>`;
|
: `<${quoted.type}>`;
|
||||||
replyLine =
|
replyLine =
|
||||||
`\n${c.gray} ↩ Para: ${c.reset}${c.white}${quotedName}${c.reset} ${c.dim}+${quotedNumber}${c.reset}` +
|
`\n${c.gray} ↩ Para: ${c.reset}${c.white}${quotedName}${c.reset} ${c.dim}+${quotedNumber}${c.reset}` +
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
// get_id.js
|
// get_id.js
|
||||||
|
import { CLIENT_ID } from "../config.js";
|
||||||
|
|
||||||
|
|
||||||
const arg = process.argv[2]; // argumento passado no node
|
const arg = process.argv[2]; // argumento passado no node
|
||||||
if (!arg) {
|
if (!arg) {
|
||||||
@@ -12,8 +14,6 @@ import pkg from 'whatsapp-web.js';
|
|||||||
const { Client, LocalAuth } = pkg;
|
const { Client, LocalAuth } = pkg;
|
||||||
import qrcode from 'qrcode-terminal';
|
import qrcode from 'qrcode-terminal';
|
||||||
|
|
||||||
const CLIENT_ID = "bot_permanente"; // sempre o mesmo
|
|
||||||
|
|
||||||
const client = new Client({
|
const client = new Client({
|
||||||
authStrategy: new LocalAuth({ clientId: CLIENT_ID }),
|
authStrategy: new LocalAuth({ clientId: CLIENT_ID }),
|
||||||
puppeteer: { headless: true }
|
puppeteer: { headless: true }
|
||||||
@@ -24,10 +24,10 @@ client.on('qr', qr => {
|
|||||||
qrcode.generate(qr, { small: true });
|
qrcode.generate(qr, { small: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on('ready', async () => {
|
client.on('change_state', async state => {
|
||||||
console.log("[WPP] Conectado");
|
console.log("[WPP] Conectado");
|
||||||
|
|
||||||
const chats = await client.getChats(); // <- precisa do await
|
const chats = await client.getChats();
|
||||||
|
|
||||||
let filtered = [];
|
let filtered = [];
|
||||||
|
|
||||||
@@ -40,18 +40,14 @@ client.on('ready', async () => {
|
|||||||
filtered = chats.filter(c => (c.name || c.id.user).toLowerCase().includes(search));
|
filtered = chats.filter(c => (c.name || c.id.user).toLowerCase().includes(search));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filtered.length === 0) {
|
|
||||||
console.log("Nenhum chat encontrado com esse filtro.");
|
|
||||||
} else {
|
|
||||||
console.log(`Encontrados ${filtered.length} chats:`);
|
|
||||||
filtered.forEach(c => {
|
filtered.forEach(c => {
|
||||||
console.log("================================");
|
console.log("================================");
|
||||||
console.log("NAME:", c.name || c.id.user);
|
console.log("NAME:", c.name || c.id.user);
|
||||||
console.log("ID:", c.id._serialized);
|
console.log("ID:", c.id._serialized);
|
||||||
console.log("GROUP:", c.isGroup);
|
console.log("GROUP:", c.isGroup);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
|
await client.destroy();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user