From 4b28a2b61843a034cc6bdacdfe49691313123895 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 17:22:10 -0300 Subject: [PATCH 01/49] =?UTF-8?q?Corrigir=20diagn=C3=B3stico=20do=20Termux?= =?UTF-8?q?=20no=20preflight?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/preflight-platform.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/preflight-platform.mjs b/scripts/preflight-platform.mjs index b405dfe..ab00220 100755 --- a/scripts/preflight-platform.mjs +++ b/scripts/preflight-platform.mjs @@ -47,7 +47,7 @@ const platformName = isTermux ? 'Termux/Android' : `${process.platform}/${proces console.log(`✅ Plataforma detectada — ${platformName}`); if (isTermux && !probe('termux-wake-lock', 'termux-wake-lock', [], false)) { - warnings.push('Use pkg install termux-api e o aplicativo Termux:API para manter o aparelho acordado.'); + warnings.push('Atualize o pacote termux-tools (pkg install termux-tools). O comando termux-wake-lock não exige o aplicativo Termux:API.'); } const configPath = path.join(ROOT, 'dados', 'src', 'config.json'); From b994c4da1064385d0e1288ce806c7cfdc22d63e3 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 17:22:40 -0300 Subject: [PATCH 02/49] Reescrever guia Termux conforme o instalador real --- docs/instalacao/termux.md | 423 ++++++++++---------------------------- 1 file changed, 105 insertions(+), 318 deletions(-) diff --git a/docs/instalacao/termux.md b/docs/instalacao/termux.md index de5f90d..c821a21 100644 --- a/docs/instalacao/termux.md +++ b/docs/instalacao/termux.md @@ -1,422 +1,209 @@ -# Instalar o 𝖘𝖍𝖔𝖌𝖚𝖓 no Android +# Instalar o 𝖘𝖍𝖔𝖌𝖚𝖓 no Android com Termux -Este guia começa do zero. Você não precisa conhecer programação nem ter usado -um terminal antes. Faça uma etapa por vez e só passe para a próxima quando vir -o resultado indicado. +Este guia parte de um Android limpo e acompanha exatamente o fluxo atual do repositório público. O instalador cria a configuração local, instala as dependências e deixa o bot pronto para `npm start`. -> **Tempo da primeira instalação:** normalmente 15 a 35 minutos. Use Wi-Fi, -> deixe o aparelho carregando e reserve pelo menos 2 GB livres. +> **Tempo normal:** 15 a 35 minutos na primeira instalação. Use Wi-Fi, mantenha o aparelho carregando e reserve pelo menos 2 GB livres. -### Como ler este guia - -Cada etapa tem um bloco assim, mostrando o que deve aparecer na sua tela: - -> ✅ **Deu certo se você vir:** uma descrição do que a tela mostra quando o -> passo funcionou. -> -> ⚠️ **Se aparecer outra coisa:** o erro mais comum daquele passo e o que fazer. - -**Copie e cole um comando por vez.** Espere ele terminar antes do próximo — a -linha só volta a aceitar digitação quando o anterior acabou. Se a tela ficar -parada com texto correndo, está trabalhando: aguarde. - -## O que você precisa antes de começar - -Você vai precisar de: - -- um aparelho com Android 7 ou mais recente; -- WhatsApp funcionando no número que será conectado; -- internet estável durante a instalação; -- o navegador do celular; -- de preferência, um aparelho reserva para deixar o bot ligado direto. - -O 𝖘𝖍𝖔𝖌𝖚𝖓 funciona como um aparelho conectado à sua conta. Quando possível, -comece com um número e um grupo de testes antes de colocá-lo numa comunidade. - -## Etapa 1 — baixar o Termux verdadeiro - -O Termux é o aplicativo que abre a linha de comando onde o bot vai rodar. -Não use cópias encontradas em sites de APK e não use a edição antiga da Play -Store. - -### Baixe o APK - -Toque no link e o download começa. Os dois servem; o do F-Droid costuma estar -numa versão mais nova. - -| Fonte | Link direto | Observação | -| --- | --- | --- | -| **F-Droid** (recomendado) | [Baixar Termux](https://f-droid.org/repo/com.termux_1022.apk) | Versão mais recente. Não precisa instalar a loja F-Droid | -| **GitHub oficial** | [Baixar Termux](https://github.com/termux/termux-app/releases/download/v0.118.3/termux-app_v0.118.3%2Bgithub-debug_universal.apk) | Arquivo `universal`, funciona em qualquer aparelho | - -Se algum link estiver fora do ar ou você quiser conferir se saiu versão nova, -as páginas oficiais são -[F-Droid](https://f-droid.org/packages/com.termux/) e -[GitHub Releases](https://github.com/termux/termux-app/releases). - -> ⚠️ **Não baixe o Termux da Play Store.** A versão de lá está congelada há -> anos e não funciona para isso. Também não use sites de APK genéricos. - -### Instalar o arquivo baixado - -1. Abra o arquivo baixado. O Android costuma mostrar a notificação de download - concluído — toque nela. -2. Vai aparecer um aviso de que o navegador não tem permissão para instalar - aplicativos. Toque em **Configurações**, ligue **Permitir desta fonte** e - volte com o botão de voltar. -3. Toque em **Instalar** e aguarde. -4. Se quiser deixar o aparelho mais fechado, volte às configurações e desligue - essa permissão depois da instalação. - -> Escolha uma fonte e permaneça nela. Termux, Termux:API e Termux:Boot precisam -> vir todos do F-Droid ou todos do GitHub. Misturar fontes causa erro de -> assinatura e o Android recusa a instalação dos complementos. +

+ Verificação do ambiente no Termux +

-> ✅ **Deu certo se você vir:** o Termux abrindo numa tela preta com um cursor -> piscando, e não uma tela de erro do Android. -> -> ⚠️ **Se o app não instalar:** quase sempre é a permissão de "instalar apps -> desconhecidos" desligada para o navegador. Volte ao passo da permissão. +## 1. Instale o Termux -## Etapa 2 — conhecer a tela preta +A fonte recomendada para a maioria das pessoas é o **F-Droid**. A versão publicada no Google Play existe novamente, mas é uma variante experimental com diferenças de compatibilidade em relação à linha tradicional do Termux. -1. Abra o **Termux** pelo ícone recém-instalado. -2. Na primeira abertura, aguarde a linha de texto com um sinal `$` aparecer. - Esse sinal quer dizer: “pronto para receber um comando”. -3. Para colar um comando, mantenha o dedo pressionado na tela e toque em - **Paste/Colar**. Depois toque na tecla **Enter** do teclado. +- [Termux no F-Droid](https://f-droid.org/packages/com.termux/) +- [Releases oficiais no GitHub](https://github.com/termux/termux-app/releases) -Você sempre vai copiar **somente o conteúdo dentro da caixa**, uma caixa por -vez. Não copie o sinal `$`, números de etapa ou explicações. +Não misture aplicativo e plugins vindos de fontes diferentes. Eles usam assinaturas diferentes e o Android não trata isso com a delicadeza que a humanidade gostaria. -> ✅ **Deu certo se você vir:** uma linha terminada em `$` esperando você -> digitar. Esse `$` é o convite: quando ele aparece, o Termux está livre. -> -> ⚠️ **Se a tela ficar em branco:** toque nela uma vez. O teclado sobe e o -> cursor volta. +Abra o Termux após a instalação. Você verá um terminal com uma linha terminando em `$`. -## Etapa 3 — atualizar o Termux +## 2. Atualize os pacotes básicos -Cole este primeiro comando e pressione Enter: +Cole este comando e aguarde até o prompt voltar: ```bash -pkg update -y +pkg update -y && pkg upgrade -y ``` -Várias linhas vão passar pela tela. Isso é normal. Aguarde até o `$` aparecer -novamente. Se o Termux perguntar qual configuração manter, aceite a opção -padrão pressionando Enter. +Se o Termux perguntar sobre manter ou substituir algum arquivo de configuração que você nunca alterou, pode aceitar a opção padrão pressionando **Enter**. -Agora instale a ferramenta que vai buscar o 𝖘𝖍𝖔𝖌𝖚𝖓: +## 3. Baixe o SHOGUN ```bash -pkg install -y git +cd ~ +git clone https://github.com/dgreych/shogun.git +cd shogun ``` -Espere o `$` voltar. +> ✅ **Deu certo se:** o comando `pwd` terminar em `/shogun`. -> ✅ **Deu certo se você vir:** várias linhas correndo e, no fim, o `$` de -> volta sem nenhuma linha começando com `E:` ou `Error`. -> -> ⚠️ **Se pedir confirmação:** digite `y` e toque em Enter. É normal. -> -> ⚠️ **Se travar em "Waiting for headers":** sua rede está instável. Aguarde -> ou troque de Wi-Fi e rode o comando de novo — repetir não estraga nada. +Se aparecer `destination path 'shogun' already exists`, você já possui uma cópia. Entre nela com `cd ~/shogun` em vez de clonar outra. -## Etapa 4 — baixar o 𝖘𝖍𝖔𝖌𝖚𝖓 - -Cole: +## 4. Rode o instalador do próprio projeto ```bash -git clone https://github.com/dgreych/shogun.git +bash scripts/install-termux.sh ``` -Quando aparecer `done` e o `$` voltar, entre na pasta que acabou de chegar: +O script atual faz, nesta ordem: -```bash -cd shogun -``` +1. atualiza o índice de pacotes do Termux; +2. instala Git, Node.js LTS, FFmpeg e as ferramentas básicas do Termux; +3. executa a verificação de plataforma; +4. instala exatamente as dependências travadas em `package-lock.json` com `npm ci`; +5. abre a configuração inicial do SHOGUN. -O terminal não mostra uma animação ao entrar. Você pode confirmar o lugar com: +Durante a configuração, informe: -```bash -pwd -``` - -O fim da linha deve ser `/shogun`. +- seu nome; +- número do dono com país + DDD + número, somente dígitos; +- nome do bot; +- prefixo dos comandos. -> ✅ **Deu certo se você vir:** uma pasta nova chamada `shogun`. Confirme -> digitando `ls` e Enter: o nome precisa aparecer na lista. -> -> ⚠️ **Se disser "already exists":** a pasta já foi baixada antes. Entre nela -> com `cd shogun` e siga. +A configuração é salva somente no aparelho, em `dados/src/config.json`. -## Etapa 5 — preparar o bot +## 5. Mantenha o Android acordado -Cole: +Antes de iniciar o bot: ```bash -bash scripts/install-termux.sh +termux-wake-lock ``` -O instalador prepara Node.js, FFmpeg e os componentes do 𝖘𝖍𝖔𝖌𝖚𝖓. Pode parecer -parado durante alguns minutos; não feche o Termux. A instalação chegou ao ponto -certo quando aparecer o título **Quartel de configuração do 𝖘𝖍𝖔𝖌𝖚𝖓**. - -### Responder à configuração - -O assistente faz quatro perguntas. Digite a resposta e pressione Enter em cada -uma: +Esse comando faz parte das ferramentas do próprio Termux. **Não é necessário instalar o aplicativo Termux:API somente para usar o wake lock.** -1. **Como o 𝖘𝖍𝖔𝖌𝖚𝖓 deve chamar você?** — por exemplo, `Mauricio`. -2. **Seu número com país e DDD** — somente dígitos. Exemplo fictício: - `5511999999999` (`55` do Brasil, DDD e número; sem `+`, espaço ou traço). -3. **Nome do bot** — pressione Enter para manter `𝖘𝖍𝖔𝖌𝖚𝖓`. -4. **Prefixo de comando** — pressione Enter para manter `!`. - -Ao final, você deve ver **Configuração local salva** e **𝖘𝖍𝖔𝖌𝖚𝖓 pronto**. O -arquivo com esses dados fica apenas no aparelho e não entra no repositório. - -Se digitou algo errado, não reinstale tudo. Rode: +Se o comando não existir: ```bash -npm run setup +pkg install -y termux-tools +termux-wake-lock ``` -> ✅ **Deu certo se você vir:** as perguntas de configuração aparecendo uma a -> uma, e no fim uma mensagem de conclusão. -> -> ⚠️ **Se parar com erro de permissão:** feche o Termux por completo, abra de -> novo e repita a partir do `cd shogun`. +Também vale retirar o Termux da otimização agressiva de bateria do fabricante. Androids adoram encerrar processos úteis em nome de economizar 0,4% de bateria e depois fingir surpresa. -## Etapa 6 — conferir se está tudo certo - -Cole: +## 6. Inicie o bot ```bash -npm run preflight +npm start ``` -Node.js, npm, Git e FFmpeg devem aparecer aprovados. Um aviso sobre -`termux-wake-lock` não impede o primeiro teste; cuidaremos disso depois. +Na primeira execução, o SHOGUN abre o painel de conexão real da aplicação. Ele oferece: -> ✅ **Deu certo se você vir:** uma lista de verificações com marcas de -> aprovado, sem nenhuma linha vermelha. +1. **QR Code**; +2. **código de pareamento**; +3. sair.

- Saída do comando de verificação, com Node.js, npm, Git e FFmpeg aprovados + Painel de conexão do SHOGUN

-Imagem gerada da execução real do comando. O aviso amarelo sobre -configuração é esperado antes da etapa seguinte. -> -> ⚠️ **Se o FFmpeg aparecer como ausente:** rode `pkg install ffmpeg -y` e -> repita a verificação. - -## Etapa 7 — conectar o WhatsApp no mesmo celular - -Inicie o 𝖘𝖍𝖔𝖌𝖚𝖓: - -```bash -npm start -``` +### Opção A: QR Code -Na primeira vez, o terminal oferece três opções. Como WhatsApp e Termux estão -no mesmo celular, digite `2` para **código de pareamento** e pressione Enter. -Quando ele pedir o telefone, informe novamente país + DDD + número, somente -dígitos. +Escolha a opção de QR e, no WhatsApp do número do bot, abra **Aparelhos conectados → Conectar um aparelho**. Leia o QR exibido pelo SHOGUN. -Um código curto aparecerá no terminal. Anote-o ou copie-o antes de sair da tela. -Agora: +### Opção B: código de pareamento -1. abra o WhatsApp sem encerrar o Termux; -2. toque no menu de três pontos; -3. abra **Aparelhos conectados** ou **Dispositivos conectados**; -4. toque em **Conectar um aparelho**; -5. escolha **Conectar com número de telefone**; -6. digite o código mostrado pelo 𝖘𝖍𝖔𝖌𝖚𝖓. +Escolha a opção de código. O programa usa o número configurado no setup e solicita ao WhatsApp um código de pareamento. Digite esse código no fluxo de aparelhos conectados do WhatsApp. -Volte ao Termux. Aguarde a confirmação de conexão. Na próxima abertura, essa -sessão será reconhecida automaticamente e não será necessário parear de novo. +Quando a sessão for salva, as próximas inicializações usam a sessão existente e não pedem novo QR enquanto ela continuar válida. -### Se o WhatsApp estiver em outro aparelho +## 7. Confirme que está realmente conectado -Digite `1` para usar QR Code. No aparelho que tem o WhatsApp, abra **Aparelhos -conectados → Conectar um aparelho** e leia o QR mostrado no Termux. - -> ✅ **Deu certo se você vir:** a palavra **CONECTADO** na tela e, logo -> depois, uma mensagem chegando no WhatsApp do dono. - -

- Terminal mostrando o bot iniciando e detectando a sessão -

+Depois da conexão, o terminal muda para o feed de execução.

- Terminal mostrando a conexão estabelecida + SHOGUN conectado

-> -> ⚠️ **Se o QR sumir antes de você ler:** ele expira em segundos e é gerado de -> novo sozinho. Deixe a câmera pronta antes de olhar a tela. -> -> ⚠️ **Se pedir o QR toda vez que reinicia:** a sessão não está sendo salva. -> Confirme que você não apagou a pasta `dados/database`. - -## Etapa 8 — o primeiro comando -Com o 𝖘𝖍𝖔𝖌𝖚𝖓 conectado, abra uma conversa de teste no WhatsApp e envie: +Envie no grupo: ```text !menu ``` -Se o menu chegou, a instalação está concluída. Antes de dar cargo de -administrador, teste comandos simples e leia o guia de -[primeiros passos](../primeiros-passos.md). - -> ✅ **Deu certo se você vir:** o bot respondendo o `!menu` no grupo, com a -> lista de comandos. -> -> ⚠️ **Se ele não responder:** confirme que está no grupo, que o prefixo é o -> mesmo que você configurou, e que a tela do Termux ainda mostra o bot ligado. - -## Etapa 9 — impedir que o Android desligue o bot - -O Android economiza bateria fechando aplicativos em segundo plano. Para o -𝖘𝖍𝖔𝖌𝖚𝖓 permanecer conectado, faça as duas proteções abaixo. - -### Retirar a otimização de bateria - -Nas configurações do Android, procure **Aplicativos → Termux → Bateria** e -escolha algo como **Sem restrições**, **Não otimizar** ou **Permitir atividade -em segundo plano**. O nome muda conforme a marca do celular. +Se você escolheu outro prefixo no setup, use esse prefixo no lugar de `!`. -### Ativar o bloqueio de suspensão +## Iniciar novamente depois -Instale o aplicativo **Termux:API** pela mesma fonte usada para o Termux. Depois -abra o Termux e rode: - -```bash -pkg install -y termux-api -``` - -Ative a proteção: +Sempre que fechar o Termux ou reiniciar o celular: ```bash +cd ~/shogun termux-wake-lock +npm start ``` -Se o Android pedir confirmação, permita. Para liberar a proteção quando o bot -estiver parado, use: - -```bash -termux-wake-unlock -``` - -## Sua rotina depois da instalação - -### Abrir o 𝖘𝖍𝖔𝖌𝖚𝖓 outro dia - -Abra o Termux e use, um por vez: - -```bash -cd shogun -``` +## Atualizar a instalação -```bash -termux-wake-lock -``` +Pare o bot com `Ctrl + C` e execute: ```bash +cd ~/shogun +git pull --ff-only +npm ci --no-audit --no-fund npm start ``` -### Parar com segurança - -Volte ao Termux e pressione `Ctrl+C`. Na fileira extra do Termux, toque em -`CTRL` e depois na letra `C`. Quando o `$` reaparecer, o processo parou. - -### Atualizar o 𝖘𝖍𝖔𝖌𝖚𝖓 +O `npm ci` usa o lockfile público e evita que uma atualização transforme seu celular num congresso de versões aleatórias. -Pare o bot com `Ctrl+C`, confirme que está na pasta `shogun` e rode: +## Diagnóstico rápido -```bash -git pull --ff-only -``` +Se o bot não iniciar: ```bash -npm ci --no-audit --no-fund -``` - -```bash -npm start +cd ~/shogun +npm run preflight ``` -Não apague `dados/database/qr-code/`: essa pasta contém a sessão conectada. +O preflight verifica a versão do Node.js, npm, Git, FFmpeg, detecta Termux e informa se configuração e dependências locais existem. -## Opcional — iniciar após reiniciar o celular +### Node.js antigo -Só faça isto depois de ter iniciado manualmente, conectado o WhatsApp e -confirmado `!menu`. - -1. Instale **Termux:Boot** pela mesma fonte usada para o Termux. -2. Toque uma vez no ícone **Termux:Boot**. Essa primeira abertura autoriza o - complemento a agir no próximo reinício. -3. Volte ao Termux e instale o editor usado nesta etapa: +O SHOGUN exige **Node.js 20.19.0 ou superior**. Atualize: ```bash -pkg install -y nano +pkg update -y +pkg upgrade -y +pkg install -y nodejs-lts +node --version ``` -4. Crie a pasta: +### FFmpeg ausente ```bash -mkdir -p ~/.termux/boot +pkg install -y ffmpeg +ffmpeg -version ``` -5. Abra o arquivo: +### `npm ci` falhou depois de uma instalação antiga ```bash -nano ~/.termux/boot/start-shogun +cd ~/shogun +rm -rf node_modules +npm ci --no-audit --no-fund ``` -6. Cole exatamente: +### Sessão do WhatsApp precisa ser refeita -```bash -#!/data/data/com.termux/files/usr/bin/bash -termux-wake-lock -cd "$HOME/shogun" -npm start >> "$HOME/shogun/termux-boot.log" 2>&1 -``` +A sessão fica em `dados/database/qr-code/`. Ela dá acesso à conta vinculada, então **não envie essa pasta para ninguém** e não a publique em GitHub, Drive ou grupos. -7. Salve tocando em `CTRL`, depois `O`, Enter, `CTRL` e `X`. -8. Torne o arquivo executável: +Só apague a sessão quando realmente quiser desvincular e parear de novo. -```bash -chmod 700 ~/.termux/boot/start-shogun -``` +## O que é obrigatório e o que é opcional -O 𝖘𝖍𝖔𝖌𝖚𝖓 não altera `.bashrc` e não ativa isso sozinho. Para conferir depois -de reiniciar, abra o Termux e veja: +Para o núcleo do bot iniciar no Termux, o caminho público exige: -```bash -tail -n 40 ~/shogun/termux-boot.log -``` +- Android com Termux funcional; +- Node.js 20.19+; +- npm; +- Git; +- FFmpeg; +- conexão com o WhatsApp. + +Chaves externas e integrações de IA são opcionais. Recursos que dependem de uma API externa específica só funcionam quando essa integração é configurada, mas isso não impede o SHOGUN de iniciar, conectar e executar o núcleo local. + +--- -## Socorro rápido - -- **`pkg` ou downloads falham:** troque de Wi-Fi/dados móveis, reabra o Termux - e repita apenas o comando que falhou. -- **`cd: shogun: No such file or directory`:** o download não terminou ou você - está em outro lugar. Rode `cd`, depois repita a etapa 4. -- **O instalador parece parado:** mantenha o aplicativo aberto; a primeira - instalação pode levar vários minutos. -- **O código expirou:** pare com `Ctrl+C`, rode `npm start` e gere outro. -- **O bot cai com a tela apagada:** revise a bateria, rode - `termux-wake-lock` e mantenha a notificação do Termux ativa. -- **Termux:API ou Termux:Boot não instala:** provavelmente as fontes foram - misturadas. Todos os aplicativos Termux precisam vir da mesma fonte. -- **Apareceu um erro que você não entende:** rode `npm run preflight` e procure - a seção correspondente em [solução de problemas](../solucao-de-problemas.md). - -Nunca envie a pasta de sessão, seu código de pareamento ou uma captura contendo -credenciais. Para pedir ajuda, copie apenas a mensagem de erro. +[← Voltar ao README](../../README.md) From f2f69302e396b6d3952e4b4f325bd4bf0bc00d1b Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 17:23:00 -0300 Subject: [PATCH 03/49] Evitar side effect ao verificar wake lock --- scripts/preflight-platform.mjs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/preflight-platform.mjs b/scripts/preflight-platform.mjs index ab00220..2ff91e4 100755 --- a/scripts/preflight-platform.mjs +++ b/scripts/preflight-platform.mjs @@ -46,8 +46,11 @@ const isTermux = Boolean(process.env.TERMUX_VERSION) || fs.existsSync('/data/dat const platformName = isTermux ? 'Termux/Android' : `${process.platform}/${process.arch}`; console.log(`✅ Plataforma detectada — ${platformName}`); -if (isTermux && !probe('termux-wake-lock', 'termux-wake-lock', [], false)) { - warnings.push('Atualize o pacote termux-tools (pkg install termux-tools). O comando termux-wake-lock não exige o aplicativo Termux:API.'); +if (isTermux) { + const prefix = process.env.PREFIX || '/data/data/com.termux/files/usr'; + const wakeLockPath = path.join(prefix, 'bin', 'termux-wake-lock'); + if (fs.existsSync(wakeLockPath)) console.log('✅ termux-wake-lock — disponível'); + else warnings.push('termux-wake-lock não foi encontrado. Atualize termux-tools com: pkg install termux-tools. Não é necessário instalar Termux:API para esse comando.'); } const configPath = path.join(ROOT, 'dados', 'src', 'config.json'); From 2538be741eca59ae6dfc9afe03f030908fe83e7f Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 17:23:10 -0300 Subject: [PATCH 04/49] =?UTF-8?q?Fortalecer=20instala=C3=A7=C3=A3o=20limpa?= =?UTF-8?q?=20no=20Termux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/install-termux.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/install-termux.sh b/scripts/install-termux.sh index 28fbcb4..bf2c786 100755 --- a/scripts/install-termux.sh +++ b/scripts/install-termux.sh @@ -4,7 +4,7 @@ set -euo pipefail cd "$(dirname "$0")/.." pkg update -y -pkg install -y git nodejs-lts ffmpeg +pkg install -y git nodejs-lts ffmpeg termux-tools node scripts/preflight-platform.mjs @@ -15,4 +15,7 @@ npm ci --no-audit --no-fund npm run setup -echo "SHOGUN pronto. Use termux-wake-lock e depois npm start." +node --check dados/src/.scripts/start-v9-fixed.js +node --check dados/src/connect.js + +echo "SHOGUN pronto. Execute termux-wake-lock e depois npm start." From 65a5236c24d29e6d366425f64fe4f8be2ae6f1b1 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 17:23:18 -0300 Subject: [PATCH 05/49] Adicionar instalador para macOS --- scripts/install-macos.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 scripts/install-macos.sh diff --git a/scripts/install-macos.sh b/scripts/install-macos.sh new file mode 100644 index 0000000..e342894 --- /dev/null +++ b/scripts/install-macos.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd "$(dirname "$0")/.." + +missing=0 +for cmd in git node npm ffmpeg; do + if ! command -v "$cmd" >/dev/null 2>&1; then + echo "Falta o comando: $cmd" + missing=1 + fi +done + +if [ "$missing" -ne 0 ]; then + echo "Instale os requisitos e rode novamente. Com Homebrew: brew install node git ffmpeg" + exit 1 +fi + +node scripts/preflight-platform.mjs + +GIT_CONFIG_COUNT=1 \ +GIT_CONFIG_KEY_0=url.https://github.com/.insteadOf \ +GIT_CONFIG_VALUE_0=ssh://git@github.com/ \ +npm ci --no-audit --no-fund + +npm run setup + +node --check dados/src/.scripts/start-v9-fixed.js +node --check dados/src/connect.js + +echo "SHOGUN pronto. Execute npm start." From decfb2d62fd47893a8c58a5e313f47259328acd3 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 17:23:25 -0300 Subject: [PATCH 06/49] =?UTF-8?q?Documentar=20instala=C3=A7=C3=A3o=20no=20?= =?UTF-8?q?macOS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/instalacao/macos.md | 65 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 docs/instalacao/macos.md diff --git a/docs/instalacao/macos.md b/docs/instalacao/macos.md new file mode 100644 index 0000000..9bcde11 --- /dev/null +++ b/docs/instalacao/macos.md @@ -0,0 +1,65 @@ +# Instalar o 𝖘𝖍𝖔𝖌𝖚𝖓 no macOS + +O fluxo público do SHOGUN também é validado para macOS. O requisito é Node.js 20.19 ou superior, Git e FFmpeg. + +## 1. Instale os requisitos + +Se você usa Homebrew: + +```bash +brew update +brew install node git ffmpeg +``` + +Confirme: + +```bash +node --version +git --version +ffmpeg -version +``` + +## 2. Clone o repositório público + +```bash +cd ~ +git clone https://github.com/dgreych/shogun.git +cd shogun +``` + +## 3. Execute o instalador + +```bash +bash scripts/install-macos.sh +``` + +Ele executa o preflight, instala as dependências exatamente pelo `package-lock.json`, abre o setup e verifica as entradas principais do runtime. + +## 4. Inicie + +```bash +npm start +``` + +O painel oferece QR Code ou código de pareamento. Depois que a sessão for criada, as próximas inicializações reutilizam a sessão enquanto ela permanecer válida. + +## Atualizar + +```bash +cd ~/shogun +git pull --ff-only +npm ci --no-audit --no-fund +npm start +``` + +## Diagnóstico + +```bash +npm run preflight +``` + +A sessão do WhatsApp fica em `dados/database/qr-code/`. Não publique nem compartilhe essa pasta. + +--- + +[← Voltar ao README](../../README.md) From 24acc89d84e8ba70abdec30c8430d44e81cc23a6 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 17:23:52 -0300 Subject: [PATCH 07/49] Alinhar README com plataformas realmente suportadas --- README.md | 120 ++++++++++++++++++++---------------------------------- 1 file changed, 44 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index 8fa63ba..b5a6db1 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@

Um bot para os seus grupos de WhatsApp.
- Ele modera, baixa vídeo e música, faz figurinha, joga e tem um RPG inteiro.
- Roda no seu computador ou num celular Android parado na gaveta — e é de graça. + Ele modera, trabalha com mídia, faz figurinhas, joga e mantém um RPG inteiro.
+ Roda no seu computador ou num celular Android pelo Termux.

@@ -17,33 +17,36 @@

- Assim que ele fica quando está ligado: a tela de conexão e o - acompanhamento ao vivo de tudo que chega. + O painel de conexão e o acompanhamento ao vivo do bot em execução.

--- ## 👉 Nunca instalou nada assim? Comece por aqui -Escolha onde o bot vai rodar. Cada guia começa do zero, mostra **o que aparece -na sua tela** a cada passo e o que fazer quando não aparece. +Escolha onde o bot vai rodar. Os guias seguem os scripts e o fluxo que existem de fato neste repositório público. - - - + @@ -55,38 +58,30 @@ na sua tela** a cada passo e o que fazer quando não aparece. Feed do terminal mostrando comandos e mensagens chegando

-

- À esquerda, a tela de conexão. À direita, o feed ao vivo — cada comando - e mensagem que chega aparece assim no seu terminal. -

- --- ## Vai rodar no Android? -Antes de tudo, instale o **Termux** — é o aplicativo onde o bot roda. Toque e o -download começa: +Para a linha tradicional do Termux, prefira uma das fontes oficiais abaixo: -**[⬇️ Baixar Termux (F-Droid)](https://f-droid.org/repo/com.termux_1022.apk)** - · [alternativa no GitHub](https://github.com/termux/termux-app/releases/download/v0.118.3/termux-app_v0.118.3%2Bgithub-debug_universal.apk) +**[F-Droid](https://f-droid.org/packages/com.termux/)** · **[GitHub Releases](https://github.com/termux/termux-app/releases)** -> Não use a versão da Play Store: está parada há anos e não funciona para isso. +A edição do Google Play voltou a existir, mas segue uma linha experimental com diferenças de compatibilidade. O guia do SHOGUN usa a linha tradicional de F-Droid/GitHub para reduzir variações de ambiente. -Depois siga o [guia do Android](docs/instalacao/termux.md), que explica o resto -tela por tela. +Depois siga o [guia do Android](docs/instalacao/termux.md), que corresponde ao instalador `scripts/install-termux.sh` e ao painel real do bot. ## Já usa terminal? Comece em três minutos ```bash git clone https://github.com/dgreych/shogun.git cd shogun -bash scripts/install-linux.sh # Windows: install-windows.ps1 · Android: install-termux.sh +bash scripts/install-linux.sh # macOS: install-macos.sh · Android: install-termux.sh npm start ``` -Leia o QR no WhatsApp, mande `!menu` no grupo e pronto. Se a palavra "terminal" -já assusta, comece pelo [guia da sua plataforma](#-nunca-instalou-nada-assim-comece-por-aqui) — ele explica cada -tela, sem pressupor nada. +No Windows, use `powershell -ExecutionPolicy Bypass -File .\scripts\install-windows.ps1`. + +O primeiro boot abre o painel de conexão e oferece QR Code ou código de pareamento. Se a palavra "terminal" já assusta, comece pelo [guia da sua plataforma](#-nunca-instalou-nada-assim-comece-por-aqui). ## Como funciona @@ -94,38 +89,21 @@ tela, sem pressupor nada. flowchart LR A[Seu WhatsApp] <--> B[𝖘𝖍𝖔𝖌𝖚𝖓
no seu aparelho] B --> C[Grupos
moderação e jogos] - B --> D[Downloads
YouTube, TikTok e mais] - B -.opcional.-> E[API de IA
imagem e transcrição] + B --> D[Mídia
downloads e figurinhas] + B -.opcional.-> E[APIs externas
IA e mídia avançada] ``` -A sessão e os dados dos grupos ficam **no seu aparelho**. Nada de servidor de -terceiro, salvo as APIs que você mesmo configurar. +A sessão e os dados dos grupos ficam **no aparelho onde você executa o bot**. Integrações externas só entram quando o recurso correspondente é configurado. ## O que ele faz -**Cuida do grupo.** Boas-vindas, anti-link, anti-flood e advertências com -banimento automático na terceira. Moderadores com permissões próprias, separadas -das do administrador do WhatsApp. Silenciar quem está atrapalhando, abrir e -fechar o grupo por horário. - -**Resolve mídia.** Baixa de YouTube, TikTok, Instagram, Twitter, Facebook, -Pinterest e Kwai. Vídeo vira áudio, áudio vira texto, imagem vira figurinha e -figurinha vira imagem. Faz figurinha animada de vídeo curto e mistura dois -emojis num só. - -**Gera imagem por IA.** Texto vira imagem, remove fundo, aumenta resolução. O -roteador escolhe o modelo pelo tipo de pedido: pedido rápido vai para o modelo -rápido, pedido caprichado vai para o modelo de qualidade. +**Cuida do grupo.** Boas-vindas, anti-link, anti-flood, advertências, moderação e automações de administração. -**Conversa.** A assistente responde quando mencionada. Cada grupo escolhe a -personalidade, e ela muda o tom das respostas e o visual dos menus junto. +**Trabalha com mídia.** O runtime inclui fluxos de download, conversão, áudio, imagem e figurinhas. Recursos que dependem da BunnyFy ou de outro serviço externo precisam da integração correspondente configurada. -**Tem um RPG inteiro.** Trabalho, mineração, pesca, caça, forja, plantio, -cozinha, propriedades que rendem por dia, mercado entre jogadores, habilidades -que evoluem e ranking. Cada grupo tem a própria economia. +**Conversa e gera mídia por IA quando configurado.** O núcleo local não exige chave de IA para iniciar. Recursos externos permanecem opcionais. -**E jogos.** Velha, forca, quiz, roleta, caça-palavras e uma taverna de duelos -por turnos. +**Tem economia, RPG e jogos.** O bot mantém sistemas persistentes por grupo e comandos interativos no próprio WhatsApp. ## Configuração @@ -134,16 +112,15 @@ por turnos.

- npm run preflight confere tudo que o bot precisa antes de você começar. + npm run preflight confere Node.js, npm, Git, FFmpeg e detecta a plataforma antes do boot.

-O instalador pergunta seu nome, seu número com país e DDD, o nome do bot e o -prefixo dos comandos. Nada disso sai do seu aparelho. +O instalador pergunta seu nome, seu número com país e DDD, o nome do bot e o prefixo dos comandos. A configuração local é escrita em `dados/src/config.json`. ## Manutenção ```bash -npm run preflight # confere Node.js, npm, Git, FFmpeg e a plataforma +npm run preflight # confere o ambiente npm run setup # refaz a configuração inicial npm start # inicia o bot ``` @@ -156,41 +133,32 @@ git pull --ff-only && npm ci --no-audit --no-fund && npm start ## Dúvidas frequentes -**Preciso de um número separado?** Sim. Use um chip só do bot — ele conecta -como aparelho vinculado e responde por essa conta. +**Preciso de um número separado?** É fortemente recomendado. O bot conecta como aparelho vinculado e responde por essa conta. -**Preciso deixar o computador ligado?** Sim, enquanto quiser o bot no ar. Por -isso muita gente usa um Android antigo na tomada. +**Preciso deixar o aparelho ligado?** Sim, enquanto quiser o bot no ar. No Android, use `termux-wake-lock` e retire o Termux da otimização agressiva de bateria. -**Funciona sem chave de IA?** Funciona. Moderação, downloads, figurinhas, jogos -e RPG não dependem de IA. Só geração de imagem e transcrição precisam. +**Funciona sem chave de IA?** Sim. O núcleo do bot inicia e conecta sem chave de IA. Recursos que chamam provedores externos dependem da configuração daquele provedor. -**Vão banir meu número?** O bot usa a conexão oficial de aparelhos vinculados. -O que causa bloqueio é comportamento: disparo em massa e spam. Use com bom -senso. - -**Meus dados vão para algum servidor?** Não. Sessão, bancos e configuração -ficam no aparelho onde o bot roda. +**O Termux precisa do aplicativo Termux:API para `termux-wake-lock`?** Não. O wake lock vem das ferramentas do próprio Termux; se o comando estiver ausente, atualize `termux-tools`. ## Segurança -A pasta `dados/database/qr-code/` guarda a sessão do WhatsApp. **Quem tem essa -pasta entra na sua conta**: não compacte, não envie, não publique. Ela já está -protegida pelo `.gitignore`. +A pasta `dados/database/qr-code/` guarda a sessão do WhatsApp. **Quem obtiver essa pasta pode comprometer a sessão vinculada.** Não compacte, não envie e não publique. Ela já está protegida pelo `.gitignore`. ## Requisitos

Node.js 20.19+ WhatsApp Baileys - Windows, Linux e Termux + Windows, Linux, macOS e Termux Licença ISC

-Node.js 20.19 ou superior · FFmpeg · Git · um número de WhatsApp dedicado +Node.js 20.19 ou superior · FFmpeg · Git · um número de WhatsApp para a sessão do bot + +## Portabilidade verificada -Os instaladores cuidam disso para você. A lista está aqui para quem já tem o -ambiente montado e quer conferir. +O workflow público valida o lockfile e a construção do projeto em Windows, Linux e macOS. O contrato do Termux é validado separadamente no CI, e o instalador Android usa apenas pacotes disponíveis no ecossistema Termux. ## Licença From 8b21a23b305755d0b811336a715ea5c9c57c9ee2 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 17:24:08 -0300 Subject: [PATCH 08/49] Ampliar CI de portabilidade para macOS e Termux --- .github/workflows/shogun-validate.yml | 43 ++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/.github/workflows/shogun-validate.yml b/.github/workflows/shogun-validate.yml index e2e5f1c..57c6229 100644 --- a/.github/workflows/shogun-validate.yml +++ b/.github/workflows/shogun-validate.yml @@ -59,7 +59,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest] + os: [ubuntu-latest, windows-latest, macos-latest] node: ['20.19.0', '22', '24'] steps: - name: Baixar o repositório @@ -80,7 +80,48 @@ jobs: node --check dados/src/.scripts/start-v9-fixed.js node --check dados/src/connect.js node --check dados/src/index.js + bash -n scripts/install-linux.sh + bash -n scripts/install-macos.sh + bash -n scripts/install-termux.sh - name: Conferir configuração neutra run: node -e "const c=require('./dados/src/config.example.json'); if(c.nomebot!=='SHOGUN'||c.numerodono!=='55DDDNUMERO') process.exit(1)" - name: Construir arquitetura modular run: npm run build:vnext + + contrato-termux: + name: Contrato Termux/Android + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - name: Baixar o repositório + uses: actions/checkout@v4 + - name: Preparar Node.js mínimo suportado + uses: actions/setup-node@v4 + with: + node-version: '20.19.0' + cache: npm + - name: Preparar FFmpeg + run: | + sudo apt-get update + sudo apt-get install -y ffmpeg + - name: Instalar dependências como clone limpo + run: npm ci --no-audit --no-fund + - name: Validar script Android + run: | + bash -n scripts/install-termux.sh + grep -q 'nodejs-lts' scripts/install-termux.sh + grep -q 'ffmpeg' scripts/install-termux.sh + grep -q 'termux-tools' scripts/install-termux.sh + - name: Exercitar ramificação Termux do preflight + env: + TERMUX_VERSION: ci + PREFIX: /tmp/shogun-termux-prefix + run: | + mkdir -p "$PREFIX/bin" + touch "$PREFIX/bin/termux-wake-lock" + node scripts/preflight-platform.mjs + - name: Validar entradas do runtime + run: | + node --check dados/src/.scripts/start-v9-fixed.js + node --check dados/src/connect.js + node --check dados/src/index.js From fdb6ccb80377c8191ac4c676ba9024abdf5b918e Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 17:30:01 -0300 Subject: [PATCH 09/49] =?UTF-8?q?Restaurar=20store=20exigida=20pelo=20runt?= =?UTF-8?q?ime=20p=C3=BAblico?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dados/src/utils/shogunStore.js | 149 +++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 dados/src/utils/shogunStore.js diff --git a/dados/src/utils/shogunStore.js b/dados/src/utils/shogunStore.js new file mode 100644 index 0000000..d8e7543 --- /dev/null +++ b/dados/src/utils/shogunStore.js @@ -0,0 +1,149 @@ +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +import { DEFAULT_NVIDIA_MODEL, isKnownNvidiaModel } from './nvidiaApi.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +export const SRC_DIR = path.resolve(__dirname, '..'); +export const DATABASE_DIR = path.resolve(SRC_DIR, '..', 'database'); +export const OWNER_DB_DIR = path.join(DATABASE_DIR, 'dono'); +export const AUTOMATIONS_FILE = path.join(OWNER_DB_DIR, 'automacoes-v9.json'); +export const MEDIA_DIR = path.join(OWNER_DB_DIR, 'command-media'); +export const DELETED_FILE = path.join(OWNER_DB_DIR, 'deleted-messages-v9.json'); +export const CONFIG_FILE = path.join(SRC_DIR, 'config.json'); + +export const DEFAULT_DATA = { + autoTranscriptionGroups: {}, + commandMedia: {}, + additionalOwners: [], + assistantPrompts: {}, + activePersona: 'gyomei' +}; + +export function ensureDirectories() { + fs.mkdirSync(OWNER_DB_DIR, { recursive: true }); + fs.mkdirSync(MEDIA_DIR, { recursive: true }); +} + +function reviveJsonValue(_key, value) { + if ( + value + && value.type === 'Buffer' + && Array.isArray(value.data) + && value.data.every(item => Number.isInteger(item) && item >= 0 && item <= 255) + ) { + return Buffer.from(value.data); + } + return value; +} + +export function readJson(file, fallback) { + try { + return JSON.parse(fs.readFileSync(file, 'utf8'), reviveJsonValue); + } catch { + return fallback; + } +} + +export function writeJson(file, value) { + ensureDirectories(); + const temporary = `${file}.tmp`; + fs.writeFileSync( + temporary, + JSON.stringify(value, (_, item) => typeof item === 'bigint' ? item.toString() : item, 2) + ); + fs.renameSync(temporary, file); +} + +export function getAutomationData() { + const stored = readJson(AUTOMATIONS_FILE, {}); + return { + ...DEFAULT_DATA, + ...stored, + autoTranscriptionGroups: stored.autoTranscriptionGroups || {}, + commandMedia: stored.commandMedia || {}, + additionalOwners: Array.isArray(stored.additionalOwners) ? stored.additionalOwners : [], + assistantPrompts: stored.assistantPrompts || {} + }; +} + +export function saveAutomationData(data) { + writeJson(AUTOMATIONS_FILE, data); +} + +export function getConfig() { + const stored = readJson(CONFIG_FILE, {}); + return { + ...stored, + nvidia_model: isKnownNvidiaModel(stored.nvidia_model) ? stored.nvidia_model : DEFAULT_NVIDIA_MODEL, + apikey_vex: process.env.VEX_API_KEY || stored.apikey_vex || '', + site_vex: process.env.VEX_SITE || stored.site_vex || '', + upload_github_token: process.env.UPLOAD_GITHUB_TOKEN || stored.upload_github_token || '', + upload_github_repo: process.env.UPLOAD_GITHUB_REPO || stored.upload_github_repo || 'uploadsnew/uploads' + }; +} + +export function normalizeCommand(command) { + return String(command || '') + .trim() + .replace(/^[!./#]+/, '') + .toLowerCase(); +} + +export function normalizeIdentity(value) { + const raw = String(value || '').trim().replace(/^@/, ''); + if (!raw) return ''; + if (raw.includes('@')) return raw.split(':')[0].toLowerCase(); + const digits = raw.replace(/\D/g, ''); + return digits || raw.toLowerCase(); +} + +export function identityAliases(value) { + const normalized = normalizeIdentity(value); + if (!normalized) return new Set(); + const aliases = new Set([normalized]); + const base = normalized.split('@')[0].split(':')[0].replace(/\D/g, ''); + if (base) aliases.add(base); + if (/^\d+$/.test(normalized)) { + aliases.add(`${normalized}@s.whatsapp.net`); + aliases.add(`${normalized}@lid`); + } + return aliases; +} + +export function identitiesMatch(left, right) { + const leftAliases = identityAliases(left); + const rightAliases = identityAliases(right); + return [...leftAliases].some(alias => rightAliases.has(alias)); +} + +export function unwrapMessageContent(message) { + let current = message?.message || message || null; + const wrappers = [ + 'ephemeralMessage', + 'viewOnceMessage', + 'viewOnceMessageV2', + 'viewOnceMessageV2Extension', + 'documentWithCaptionMessage', + 'editedMessage' + ]; + + for (let depth = 0; depth < 8 && current; depth++) { + const wrapper = wrappers.find(key => current?.[key]?.message); + if (!wrapper) break; + current = current[wrapper].message; + } + return current; +} + +export function contextInfoFromContent(content) { + return content?.extendedTextMessage?.contextInfo + || content?.imageMessage?.contextInfo + || content?.videoMessage?.contextInfo + || content?.audioMessage?.contextInfo + || content?.documentMessage?.contextInfo + || content?.stickerMessage?.contextInfo + || null; +} From b93d9f4cf2c84c39f85868e99f927fbe3be21f18 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 17:30:08 -0300 Subject: [PATCH 10/49] =?UTF-8?q?Restaurar=20agregador=20do=20runtime=20p?= =?UTF-8?q?=C3=BAblico?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dados/src/utils/shogunRuntime.js | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 dados/src/utils/shogunRuntime.js diff --git a/dados/src/utils/shogunRuntime.js b/dados/src/utils/shogunRuntime.js new file mode 100644 index 0000000..d79971c --- /dev/null +++ b/dados/src/utils/shogunRuntime.js @@ -0,0 +1,4 @@ +export { getConfig } from './shogunStore.js'; +export * from './shogunCore.js'; +export * from './shogunOperations.js'; +export * from './shogunMedia.js'; From bf1ed10378393045ef26b8df4a41efb3c633a59b Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 17:30:16 -0300 Subject: [PATCH 11/49] =?UTF-8?q?Restaurar=20m=C3=ADdia=20citada=20no=20sn?= =?UTF-8?q?apshot=20p=C3=BAblico?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dados/src/utils/shogunMedia.js | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 dados/src/utils/shogunMedia.js diff --git a/dados/src/utils/shogunMedia.js b/dados/src/utils/shogunMedia.js new file mode 100644 index 0000000..61d42a1 --- /dev/null +++ b/dados/src/utils/shogunMedia.js @@ -0,0 +1,44 @@ +import { downloadContentFromMessage } from 'baileys'; +import { getQuotedMediaSource } from './shogunCore.js'; + +async function streamToBuffer(stream) { + const chunks = []; + for await (const chunk of stream) { + chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)); + } + return Buffer.concat(chunks); +} + +export async function downloadQuotedCommandMedia(message) { + const source = getQuotedMediaSource(message); + if (!source?.message) { + return { + ok: false, + msg: 'Responda a uma foto, GIF ou vídeo válido.' + }; + } + + try { + const stream = await downloadContentFromMessage(source.message, source.type); + const buffer = await streamToBuffer(stream); + + if (!Buffer.isBuffer(buffer) || buffer.length === 0) { + return { + ok: false, + msg: 'A mídia citada foi reconhecida, mas veio vazia.' + }; + } + + return { + ok: true, + buffer, + type: source.type, + gifPlayback: source.gifPlayback === true + }; + } catch (error) { + return { + ok: false, + msg: `Não foi possível baixar a mídia citada: ${error.message}` + }; + } +} From 4112a5352b5ee87d16c7c1a067f036d5505c6ffb Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 17:30:45 -0300 Subject: [PATCH 12/49] =?UTF-8?q?Restaurar=20opera=C3=A7=C3=B5es=20exigida?= =?UTF-8?q?s=20pelo=20runtime=20p=C3=BAblico?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dados/src/utils/shogunOperations.js | 373 ++++++++++++++++++++++++++++ 1 file changed, 373 insertions(+) create mode 100644 dados/src/utils/shogunOperations.js diff --git a/dados/src/utils/shogunOperations.js b/dados/src/utils/shogunOperations.js new file mode 100644 index 0000000..0a2f14d --- /dev/null +++ b/dados/src/utils/shogunOperations.js @@ -0,0 +1,373 @@ +import axios from 'axios'; +import fs from 'fs'; +import { downloadContentFromMessage } from 'baileys'; +import { + DELETED_FILE, + MEDIA_DIR, + getAutomationData, + getConfig, + normalizeCommand, + readJson, + saveAutomationData, + unwrapMessageContent, + writeJson +} from './shogunStore.js'; +import { getActivePersona } from './shogunCore.js'; +import { transcriptionWithBunnyFy } from '../services/bunnyfy/capabilityGateway.js'; + +const MAX_RECENT_MESSAGES = 5000; +const commandContext = new Map(); +const deletedMessages = new Map(); +const recentMessages = new Map(); +const mediaInterceptorSockets = new WeakSet(); +const deletedTrackerSockets = new WeakSet(); + +export function isAutoTranscriptionEnabled(chatId) { + return getAutomationData().autoTranscriptionGroups?.[chatId] === true; +} + +export function toggleAutoTranscription(chatId) { + const data = getAutomationData(); + data.autoTranscriptionGroups[chatId] = !data.autoTranscriptionGroups[chatId]; + saveAutomationData(data); + return data.autoTranscriptionGroups[chatId]; +} + +export async function transcribeAudioUrl(audioUrl) { + const config = getConfig(); + const site = String(config.site_vex || '').replace(/\/$/, ''); + const apiKey = String(config.apikey_vex || '').trim(); + + if (!site || !apiKey || apiKey.startsWith('COLOQUE_')) { + return { ok: false, msg: 'Configure site_vex e apikey_vex em dados/src/config.json.' }; + } + if (!audioUrl) return { ok: false, msg: 'Não foi possível gerar o link temporário do áudio.' }; + + try { + const url = `${site}/api/ias/transcrever?apikey=${encodeURIComponent(apiKey)}&query=${encodeURIComponent(audioUrl)}`; + const response = await axios.get(url, { + headers: { Accept: '*/*', 'User-Agent': 'Node.js' }, + timeout: 120000 + }); + const data = response.data; + const text = data?.resultado?.data?.texto + || data?.resultado?.texto + || data?.data?.texto + || data?.data?.text + || data?.texto + || data?.text + || data?.resposta + || data?.result; + + if (!text) { + return { ok: false, msg: data?.message || data?.msg || 'A API não retornou uma transcrição.' }; + } + return { ok: true, texto: String(text).trim(), source: 'vex' }; + } catch (error) { + return { + ok: false, + msg: error?.response?.data?.message + || error?.response?.data?.msg + || error?.response?.data?.detail + || error.message + }; + } +} + +export async function transcribeAudio(buffer, { mime = 'audio/ogg', language, uploadForFallback } = {}) { + try { + return await transcriptionWithBunnyFy(buffer, { + mime, + language, + legacyFallback: async () => { + if (typeof uploadForFallback !== 'function') { + return { ok: false, msg: 'Não foi possível gerar o link temporário do áudio.' }; + } + const audioUrl = await uploadForFallback(); + return transcribeAudioUrl(audioUrl); + } + }); + } catch (error) { + return { ok: false, msg: error?.message || 'Não foi possível transcrever o áudio agora.' }; + } +} + +export async function saveCommandMedia(command, buffer, type, gifPlayback = false) { + const normalized = normalizeCommand(command); + if (!normalized) throw new Error('Informe o comando que receberá a mídia.'); + if (!Buffer.isBuffer(buffer) || buffer.length === 0) throw new Error('Mídia inválida.'); + + fs.mkdirSync(MEDIA_DIR, { recursive: true }); + const normalizedType = type === 'image' ? 'image' : type === 'gif' ? 'gif' : 'video'; + const extension = normalizedType === 'image' ? 'jpg' : normalizedType === 'gif' ? 'gif' : 'mp4'; + const safeName = normalized.replace(/[^a-z0-9_-]/gi, '_'); + const filePath = `${MEDIA_DIR}/${safeName}.${extension}`; + fs.writeFileSync(filePath, buffer); + + const data = getAutomationData(); + data.commandMedia[normalized] = { + type: normalizedType, + path: filePath, + gifPlayback: Boolean(gifPlayback), + updatedAt: new Date().toISOString() + }; + saveAutomationData(data); + return data.commandMedia[normalized]; +} + +export function listCommandMedia() { + return Object.entries(getAutomationData().commandMedia || {}) + .filter(([, item]) => item?.path) + .map(([command, item]) => ({ command, ...item })); +} + +export function getCommandMedia(command) { + const normalized = normalizeCommand(command); + const item = getAutomationData().commandMedia?.[normalized]; + return item?.path ? item : null; +} + +export function resolveCommandMedia(command) { + const persona = getActivePersona(); + return getCommandMedia(`${persona}_${command}`) || getCommandMedia(command); +} + +export function removeCommandMedia(command) { + const normalized = normalizeCommand(command); + const data = getAutomationData(); + const current = data.commandMedia?.[normalized]; + if (!current) return false; + + try { + if (current.path && fs.existsSync(current.path)) fs.unlinkSync(current.path); + } catch {} + + delete data.commandMedia[normalized]; + saveAutomationData(data); + return true; +} + +function installCommandMediaInterceptor(sock) { + if (!sock?.sendMessage || mediaInterceptorSockets.has(sock)) return; + mediaInterceptorSockets.add(sock); + + const originalSendMessage = sock.sendMessage.bind(sock); + sock.sendMessage = async (jid, content, options) => { + try { + const context = commandContext.get(jid); + const fresh = context && Date.now() - context.timestamp < 20000; + const replaceable = content && ( + content.image + || content.video + || typeof content.text === 'string' + || typeof content.caption === 'string' + ); + + if (fresh && replaceable) { + const custom = resolveCommandMedia(context.command); + if (custom?.path && fs.existsSync(custom.path)) { + const nextContent = { ...content }; + const caption = String(content.caption ?? content.text ?? ''); + delete nextContent.text; + delete nextContent.caption; + delete nextContent.image; + delete nextContent.video; + + const mediaBuffer = fs.readFileSync(custom.path); + if (custom.type === 'image') { + nextContent.image = mediaBuffer; + nextContent.caption = caption; + nextContent.mimetype = 'image/jpeg'; + } else { + nextContent.video = mediaBuffer; + nextContent.caption = caption; + nextContent.gifPlayback = Boolean(custom.gifPlayback); + nextContent.mimetype = custom.type === 'gif' ? 'image/gif' : 'video/mp4'; + } + + commandContext.delete(jid); + return originalSendMessage(jid, nextContent, options); + } + } + } catch (error) { + console.error('[GYOMEI/MÍDIA] Falha ao aplicar mídia personalizada:', error.message); + } + return originalSendMessage(jid, content, options); + }; +} + +export function prepareCommandMediaContext(sock, chatId, command) { + const normalized = normalizeCommand(command); + const ignored = new Set([ + 'setmidia', 'delmidia', 'remmidia', 'menumidia', 'listmidias', + 'setmidia-profilep', 'setperfilpersona', 'changeperso', 'mudarpersona', + 'setprompt', 'verprompt', 'resetprompt', 'prompts', 'menuprompt', + 'adddono', 'deldono', 'listdonos' + ]); + if (!chatId || !normalized || ignored.has(normalized)) return; + installCommandMediaInterceptor(sock); + commandContext.set(chatId, { command: normalized, timestamp: Date.now() }); +} + +function recentKey(remoteJid, id) { + return remoteJid && id ? `${remoteJid}_${id}` : ''; +} + +function extractDeleteKey(message) { + return unwrapMessageContent(message)?.protocolMessage?.key || null; +} + +function cacheIncomingMessage(message) { + const remoteJids = [message?.key?.remoteJid, message?.key?.remoteJidAlt].filter(Boolean); + const id = message?.key?.id; + if (!id || !remoteJids.length || extractDeleteKey(message)) return; + + for (const remoteJid of remoteJids) recentMessages.set(recentKey(remoteJid, id), message); + while (recentMessages.size > MAX_RECENT_MESSAGES) { + const oldest = recentMessages.keys().next().value; + if (!oldest) break; + recentMessages.delete(oldest); + } +} + +function rememberDeleted(chatId, message) { + if (!chatId || !message?.key?.id) return; + const list = deletedMessages.get(chatId) || []; + if (list.some(item => item?.key?.id === message.key.id)) return; + list.unshift(message); + deletedMessages.set(chatId, list.slice(0, 5)); + + const serializable = {}; + for (const [jid, items] of deletedMessages.entries()) serializable[jid] = items.slice(0, 5); + writeJson(DELETED_FILE, serializable); +} + +function findCachedMessage(cacheGetter, key) { + if (!key?.id) return null; + const possibleChats = [key.remoteJid, key.remoteJidAlt].filter(Boolean); + for (const chatId of possibleChats) { + const internal = recentMessages.get(recentKey(chatId, key.id)); + if (internal) return internal; + } + + const cache = typeof cacheGetter === 'function' ? cacheGetter() : cacheGetter; + if (!cache) return null; + for (const chatId of possibleChats) { + const external = cache.get?.(recentKey(chatId, key.id)); + if (external) return external; + } + return null; +} + +export function installDeletedMessageTracker(sock, cacheGetter) { + if (!sock?.ev || deletedTrackerSockets.has(sock)) return; + deletedTrackerSockets.add(sock); + + const persisted = readJson(DELETED_FILE, {}); + for (const [jid, items] of Object.entries(persisted)) { + if (Array.isArray(items)) deletedMessages.set(jid, items.slice(0, 5)); + } + + const captureKey = key => { + const original = findCachedMessage(cacheGetter, key); + if (original) { + const chatId = key.remoteJid || original.key?.remoteJid; + if (chatId) rememberDeleted(chatId, original); + } + }; + + sock.ev.on('messages.delete', event => { + const keys = Array.isArray(event?.keys) ? event.keys : Array.isArray(event) ? event : []; + keys.forEach(captureKey); + }); + + sock.ev.on('messages.update', updates => { + if (!Array.isArray(updates)) return; + for (const item of updates) { + const key = extractDeleteKey(item?.update?.message || item?.message); + if (key) captureKey(key); + } + }); + + sock.ev.on('messages.upsert', event => { + for (const message of event?.messages || []) { + const deleteKey = extractDeleteKey(message); + if (deleteKey) captureKey(deleteKey); + else cacheIncomingMessage(message); + } + }); +} + +async function streamToBuffer(stream) { + const chunks = []; + for await (const chunk of stream) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)); + return Buffer.concat(chunks); +} + +export async function returnDeletedMessage(sock, chatId, position, quotedMessage) { + const index = Number(position) - 1; + if (!Number.isInteger(index) || index < 0 || index > 4) { + return { ok: false, msg: 'Use return1 a return5 ou return 1 a return 5.' }; + } + + const original = (deletedMessages.get(chatId) || [])[index]; + if (!original?.message) { + return { ok: false, msg: `Não há mensagem apagada na posição ${position}.` }; + } + + const content = unwrapMessageContent(original.message); + const sender = original.key?.participant || original.key?.remoteJid; + const prefix = sender + ? `🗑️ *Mensagem apagada #${position}*\n👤 @${String(sender).split('@')[0]}\n\n` + : `🗑️ *Mensagem apagada #${position}*\n\n`; + const mentions = sender ? [sender] : []; + const options = quotedMessage ? { quoted: quotedMessage } : undefined; + + try { + const text = content?.conversation || content?.extendedTextMessage?.text; + if (text) { + await sock.sendMessage(chatId, { text: `${prefix}${text}`, mentions }, options); + return { ok: true }; + } + + const candidates = [ + ['imageMessage', 'image'], + ['videoMessage', 'video'], + ['audioMessage', 'audio'], + ['stickerMessage', 'sticker'], + ['documentMessage', 'document'] + ]; + + for (const [field, type] of candidates) { + const media = content?.[field]; + if (!media) continue; + const stream = await downloadContentFromMessage(media, type); + const buffer = await streamToBuffer(stream); + const caption = media.caption ? `${prefix}${media.caption}` : prefix.trim(); + const payload = { mentions }; + + if (type === 'image') Object.assign(payload, { image: buffer, caption }); + if (type === 'video') Object.assign(payload, { video: buffer, caption, gifPlayback: media.gifPlayback === true }); + if (type === 'audio') Object.assign(payload, { + audio: buffer, + mimetype: media.mimetype || 'audio/ogg; codecs=opus', + ptt: media.ptt === true + }); + if (type === 'sticker') Object.assign(payload, { sticker: buffer }); + if (type === 'document') Object.assign(payload, { + document: buffer, + fileName: media.fileName || 'arquivo', + mimetype: media.mimetype || 'application/octet-stream', + caption + }); + + await sock.sendMessage(chatId, payload, options); + return { ok: true }; + } + + await sock.sendMessage(chatId, { text: `${prefix}[Tipo de mensagem ainda não suportado]`, mentions }, options); + return { ok: true }; + } catch (error) { + return { ok: false, msg: `Não foi possível recuperar a mídia: ${error.message}` }; + } +} From 5e46bc2780c4572de4ffe7995e1361bb4ed5d922 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 17:36:37 -0300 Subject: [PATCH 13/49] =?UTF-8?q?Alinhar=20valida=C3=A7=C3=A3o=20ao=20cart?= =?UTF-8?q?=C3=A3o=20real=20do=20criador?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dados/src/.scripts/validate-release-output.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dados/src/.scripts/validate-release-output.js b/dados/src/.scripts/validate-release-output.js index e5e897f..568116c 100644 --- a/dados/src/.scripts/validate-release-output.js +++ b/dados/src/.scripts/validate-release-output.js @@ -37,7 +37,7 @@ if (fs.existsSync(runtimeIndexPath)) { const runtimeIndex = fs.readFileSync(runtimeIndexPath, 'utf8'); assert(runtimeIndex.includes("case 'criador'"), 'comando criador presente'); assert(runtimeIndex.includes('github.com/dgreych/shogun'), 'repositório do produto presente'); - assert(runtimeIndex.includes('*Maurício Almeida*'), 'autoria do produto presente'); + assert(runtimeIndex.includes('*Alaska dev* (Maurício)'), 'autoria do produto presente no cartão real do criador'); assert(!runtimeIndex.includes('Hiudy'), 'crédito de terceiro não aparece em saída do bot'); assert(!/sentinela/i.test(runtimeIndex), 'sem rótulo genérico na identidade'); assert(runtimeIndex.includes('Comando não reconhecido'), 'cartão de comando inválido presente'); @@ -68,6 +68,7 @@ if (fs.existsSync(packagePath)) { assert(packageData.name === 'shogun-whatsapp', 'pacote identificado como SHOGUN'); assert(packageData.version === '2.0.0', 'versão principal definida como 2.0.0'); assert(String(packageData.description || '').startsWith('SHOGUN é seu sentinela'), 'descrição independente presente'); + assert(packageData.author === 'Maurício Almeida', 'autoria canônica declarada no pacote'); assert(packageData.engines?.node === '>=20.19.0', 'piso real do Node.js declarado'); assert(Boolean(packageData.scripts?.preflight), 'inspeção multiplataforma disponível'); } From 90de8f7453cffa4b23bc65e439ec2f85799db80d Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 18:00:13 -0300 Subject: [PATCH 14/49] =?UTF-8?q?Corrigir=20store=20usado=20pela=20integra?= =?UTF-8?q?=C3=A7=C3=A3o=20BunnyFy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dados/src/services/bunnyfy/runtimeConfig.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dados/src/services/bunnyfy/runtimeConfig.js b/dados/src/services/bunnyfy/runtimeConfig.js index bb33597..7140c00 100644 --- a/dados/src/services/bunnyfy/runtimeConfig.js +++ b/dados/src/services/bunnyfy/runtimeConfig.js @@ -1,4 +1,4 @@ -import { getConfig } from '../../utils/gyomeiStore.js'; +import { getConfig } from '../../utils/shogunStore.js'; const BUNNYFY_CONFIG_KEYS = Object.freeze([ 'BUNNYFY_ENABLED', @@ -59,4 +59,4 @@ function resolveBunnyFyRuntimeEnv(env = process.env, config = getConfig()) { export { BUNNYFY_CONFIG_KEYS, resolveBunnyFyRuntimeEnv -}; +}; \ No newline at end of file From 395cb1863aec0c9616689218cb2c56e0f13f4c71 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 18:02:16 -0300 Subject: [PATCH 15/49] =?UTF-8?q?Refor=C3=A7ar=20apresenta=C3=A7=C3=A3o=20?= =?UTF-8?q?visual=20do=20projeto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 272 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 186 insertions(+), 86 deletions(-) diff --git a/README.md b/README.md index b5a6db1..ec185e5 100644 --- a/README.md +++ b/README.md @@ -5,161 +5,261 @@

𝖘𝖍𝖔𝖌𝖚𝖓

- Um bot para os seus grupos de WhatsApp.
- Ele modera, trabalha com mídia, faz figurinhas, joga e mantém um RPG inteiro.
- Roda no seu computador ou num celular Android pelo Termux. + Seu grupo não precisa de mais um bot. Precisa de um sistema.
+ Moderação, mídia, jogos, economia e automações em uma única experiência para WhatsApp.

- Tela do bot conectando, com arte em pixel -    - Feed mostrando comandos chegando em tempo real + Node.js 20.19+ + WhatsApp via Baileys + Windows Linux macOS Termux + Licença ISC

- O painel de conexão e o acompanhamento ao vivo do bot em execução. + Instalar +  •  + Recursos +  •  + Arquitetura +  •  + Primeiros passos +  •  + Problemas

--- -## 👉 Nunca instalou nada assim? Comece por aqui - -Escolha onde o bot vai rodar. Os guias seguem os scripts e o fluxo que existem de fato neste repositório público. -
+ 📱 Android
-Celular reserva na tomada
+Termux
15 a 35 min
-baixar o Termux +obter Termux
+ 🪟 Windows
-10 ou 11, no seu PC
+Windows 10 ou 11
10 a 20 min
+ 🐧 Linux
-Desktop, mini PC ou servidor
+Desktop ou servidor
+10 a 20 min +
+🍎 macOS
+Intel ou Apple Silicon
10 a 20 min
- - - -
-📱 Android
-Termux
-15 a 35 min
-obter Termux -
-🪟 Windows
-Windows 10 ou 11
-10 a 20 min -
-🐧 Linux
-Desktop ou servidor
-10 a 20 min +
+ +### Um bot que realmente vive no grupo + +O SHOGUN foi pensado para grupos que querem mais do que meia dúzia de respostas automáticas. Ele combina administração, mídia, interação entre membros, economia persistente, RPG e recursos opcionais de IA sem transformar a instalação numa peregrinação por quinze serviços obrigatórios. + +- **funciona sem IA** e ganha recursos extras quando integrações são configuradas; +- **mantém sessão e dados localmente** no aparelho onde está rodando; +- **trata Termux como plataforma de verdade**, não como nota de rodapé; +- **separa o núcleo do bot de serviços externos**, evitando que uma API indisponível derrube tudo. + -🍎 macOS
-Intel ou Apple Silicon
-10 a 20 min +
+ Painel de conexão do SHOGUN
+ Painel de conexão e primeira execução.

- Painel de conexão do bot no terminal, com arte em pixel -    - Feed do terminal mostrando comandos e mensagens chegando + Feed do SHOGUN mostrando comandos em tempo real

+

Mensagens e comandos chegando em tempo real. Sem painel web obrigatório, sem teatro.

--- -## Vai rodar no Android? +## ✦ O que vem no SHOGUN -Para a linha tradicional do Termux, prefira uma das fontes oficiais abaixo: + + + + + + + + + + + +
+

🛡️ Moderação

+Boas-vindas, anti-link, anti-flood, advertências, controles administrativos e automações para manter o grupo utilizável quando os humanos resolvem testar os limites da civilização. +
+

🎞️ Mídia

+Figurinhas, conversões, áudio, imagem e fluxos de download. Capacidades avançadas podem usar a BunnyFy quando configuradas. +
+

🎮 Jogos

+Brincadeiras, comandos sociais e experiências interativas pensadas para acontecer dentro da conversa, sem mandar todo mundo para outro aplicativo. +
+

🪙 Economia & RPG

+Progressão, inventário, recursos persistentes e sistemas de grupo que continuam existindo depois que a mensagem some do histórico. +
+

🧠 IA opcional

+O núcleo inicia sem chave de IA. Quando provedores externos são configurados, o SHOGUN libera conversação e geração de mídia sem acoplar o boot a eles. +
+

💾 Estado local

+Sessão, configuração e bancos pertencem à instalação. Atualizar o código não deveria significar sacrificar o estado vivo do bot aos deuses do `rm -rf`. +
-**[F-Droid](https://f-droid.org/packages/com.termux/)** · **[GitHub Releases](https://github.com/termux/termux-app/releases)** +--- -A edição do Google Play voltou a existir, mas segue uma linha experimental com diferenças de compatibilidade. O guia do SHOGUN usa a linha tradicional de F-Droid/GitHub para reduzir variações de ambiente. +## ⬇ Instale onde quiser -Depois siga o [guia do Android](docs/instalacao/termux.md), que corresponde ao instalador `scripts/install-termux.sh` e ao painel real do bot. + + + + + + + +
+

📱 Android

+Termux

+Guia completo →
+F-Droid ou GitHub Releases +
+

🪟 Windows

+Windows 10/11

+Guia completo →
+PowerShell +
+

🐧 Linux

+Desktop / servidor

+Guia completo →
+Bash +
+

🍎 macOS

+Intel / Apple Silicon

+Guia completo →
+Bash + Homebrew +
+ +> [!IMPORTANT] +> No Android, use preferencialmente a linha tradicional do **Termux pelo F-Droid ou GitHub Releases**. A edição do Google Play segue uma linha diferente e pode apresentar incompatibilidades que o guia do SHOGUN não assume. -## Já usa terminal? Comece em três minutos +### Terminal já não mete medo? ```bash git clone https://github.com/dgreych/shogun.git cd shogun -bash scripts/install-linux.sh # macOS: install-macos.sh · Android: install-termux.sh +bash scripts/install-linux.sh # Android: install-termux.sh | macOS: install-macos.sh npm start ``` -No Windows, use `powershell -ExecutionPolicy Bypass -File .\scripts\install-windows.ps1`. +No Windows: -O primeiro boot abre o painel de conexão e oferece QR Code ou código de pareamento. Se a palavra "terminal" já assusta, comece pelo [guia da sua plataforma](#-nunca-instalou-nada-assim-comece-por-aqui). +```powershell +powershell -ExecutionPolicy Bypass -File .\scripts\install-windows.ps1 +npm start +``` -## Como funciona +A primeira execução abre o fluxo de conexão e oferece **QR Code** ou **código de pareamento**. Depois disso, a sessão é reaproveitada nas próximas inicializações. + +--- + +## ◈ Como ele se organiza ```mermaid flowchart LR - A[Seu WhatsApp] <--> B[𝖘𝖍𝖔𝖌𝖚𝖓
no seu aparelho] - B --> C[Grupos
moderação e jogos] - B --> D[Mídia
downloads e figurinhas] - B -.opcional.-> E[APIs externas
IA e mídia avançada] + W[WhatsApp] <--> S[𝖘𝖍𝖔𝖌𝖚𝖓] + S --> G[Grupos] + S --> M[Mídia] + S --> R[Jogos · RPG · Economia] + S --> L[(Sessão e dados locais)] + S -. quando configurado .-> E[Serviços externos] + E -. mídia avançada .-> B[BunnyFy] + E -. recursos opcionais .-> A[IA / APIs] ``` -A sessão e os dados dos grupos ficam **no aparelho onde você executa o bot**. Integrações externas só entram quando o recurso correspondente é configurado. +O bot continua responsável pelo fluxo do WhatsApp e pelo estado do grupo. Integrações externas entram como capacidades adicionais, não como condição para o processo existir. -## O que ele faz +--- -**Cuida do grupo.** Boas-vindas, anti-link, anti-flood, advertências, moderação e automações de administração. +## ✓ Primeira inicialização -**Trabalha com mídia.** O runtime inclui fluxos de download, conversão, áudio, imagem e figurinhas. Recursos que dependem da BunnyFy ou de outro serviço externo precisam da integração correspondente configurada. + + + + + + +
1. Verifique
npm run preflight
confere Node, npm, Git e FFmpeg.
2. Configure
npm run setup
define dono, nome e prefixo.
3. Conecte
npm start
abre QR ou pareamento.
-**Conversa e gera mídia por IA quando configurado.** O núcleo local não exige chave de IA para iniciar. Recursos externos permanecem opcionais. +

+ Preflight do SHOGUN +

-**Tem economia, RPG e jogos.** O bot mantém sistemas persistentes por grupo e comandos interativos no próprio WhatsApp. +A configuração local fica em `dados/src/config.json`. A sessão do WhatsApp fica em `dados/database/qr-code/`. -## Configuração +> [!CAUTION] +> A pasta `dados/database/qr-code/` contém credenciais da sessão vinculada. **Não envie, compacte nem publique esse diretório.** Quem obtiver esses arquivos pode comprometer a conta conectada. -

- Saída do comando de verificação do ambiente -

+--- -

- npm run preflight confere Node.js, npm, Git, FFmpeg e detecta a plataforma antes do boot. -

+## ⚙ Operação do dia a dia -O instalador pergunta seu nome, seu número com país e DDD, o nome do bot e o prefixo dos comandos. A configuração local é escrita em `dados/src/config.json`. +```bash +npm run preflight # diagnóstico do ambiente +npm run setup # configuração inicial +npm start # iniciar +``` -## Manutenção +Para atualizar uma instalação existente: ```bash -npm run preflight # confere o ambiente -npm run setup # refaz a configuração inicial -npm start # inicia o bot +git pull --ff-only +npm ci --no-audit --no-fund +npm run preflight +npm start ``` -Atualizar: +No Termux, mantenha o processo acordado com: ```bash -git pull --ff-only && npm ci --no-audit --no-fund && npm start +termux-wake-lock ``` -## Dúvidas frequentes +O comando faz parte das ferramentas do Termux. **Não é necessário instalar o aplicativo Termux:API apenas para usar o wake lock.** -**Preciso de um número separado?** É fortemente recomendado. O bot conecta como aparelho vinculado e responde por essa conta. +--- -**Preciso deixar o aparelho ligado?** Sim, enquanto quiser o bot no ar. No Android, use `termux-wake-lock` e retire o Termux da otimização agressiva de bateria. +## ◉ Portabilidade verificada -**Funciona sem chave de IA?** Sim. O núcleo do bot inicia e conecta sem chave de IA. Recursos que chamam provedores externos dependem da configuração daquele provedor. +A validação pública não se resume a “rodou na máquina de quem fez”. O workflow testa o projeto em combinações de Node.js sobre **Linux, Windows e macOS**, além de manter um contrato específico para os caminhos usados no **Termux**. -**O Termux precisa do aplicativo Termux:API para `termux-wake-lock`?** Não. O wake lock vem das ferramentas do próprio Termux; se o comando estiver ausente, atualize `termux-tools`. +| Superfície | Verificação | +| --- | --- | +| Linux | instalação, build e validações do projeto | +| Windows | lockfile, runtime e portabilidade | +| macOS | Intel/Apple Silicon no caminho suportado pelo Node | +| Termux | instalador, dependências e contrato Android | -## Segurança +Requisito mínimo: **Node.js 20.19+**, npm, Git e FFmpeg. -A pasta `dados/database/qr-code/` guarda a sessão do WhatsApp. **Quem obtiver essa pasta pode comprometer a sessão vinculada.** Não compacte, não envie e não publique. Ela já está protegida pelo `.gitignore`. +--- -## Requisitos +## ? Dúvidas rápidas -

- Node.js 20.19+ - WhatsApp Baileys - Windows, Linux, macOS e Termux - Licença ISC -

+
+Preciso de um número separado? +
+É fortemente recomendado. O SHOGUN funciona como aparelho vinculado à conta conectada. +
-Node.js 20.19 ou superior · FFmpeg · Git · um número de WhatsApp para a sessão do bot +
+Preciso deixar o aparelho ligado? +
+Sim. O processo precisa continuar rodando. No Android, use termux-wake-lock e retire o Termux da otimização agressiva de bateria. +
+ +
+Funciona sem IA? +
+Sim. IA e serviços externos são capacidades opcionais; o núcleo do bot não depende deles para iniciar. +
+ +
+Onde começo se nunca usei terminal? +
+Use o guia da sua plataforma. Ele acompanha os scripts existentes no repositório, em vez de mandar você executar uma coleção arqueológica de comandos copiados da internet. +
+ +--- -## Portabilidade verificada +## Documentação -O workflow público valida o lockfile e a construção do projeto em Windows, Linux e macOS. O contrato do Termux é validado separadamente no CI, e o instalador Android usa apenas pacotes disponíveis no ecossistema Termux. +**[Primeiros passos](docs/primeiros-passos.md)** · **[Segurança](docs/seguranca.md)** · **[Solução de problemas](docs/solucao-de-problemas.md)** · **[Termux](docs/instalacao/termux.md)** · **[Windows](docs/instalacao/windows.md)** · **[Linux](docs/instalacao/linux.md)** · **[macOS](docs/instalacao/macos.md)** -## Licença +## Licença e créditos -Publicado sob a licença ISC. Veja [LICENSE](LICENSE) e [NOTICE](NOTICE). +Publicado sob a licença ISC. Consulte [LICENSE](LICENSE) e [NOTICE](NOTICE). \ No newline at end of file From 1bef70dcac94d6b4f8d0154b7e4567122c946358 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 18:04:28 -0300 Subject: [PATCH 16/49] Refazer guia visual do Termux --- docs/instalacao/termux.md | 211 ++++++++++++++++++++++++-------------- 1 file changed, 135 insertions(+), 76 deletions(-) diff --git a/docs/instalacao/termux.md b/docs/instalacao/termux.md index c821a21..add5b3c 100644 --- a/docs/instalacao/termux.md +++ b/docs/instalacao/termux.md @@ -1,35 +1,60 @@ -# Instalar o 𝖘𝖍𝖔𝖌𝖚𝖓 no Android com Termux +

📱 SHOGUN no Android

+

Instalação pelo Termux, do zero ao primeiro !menu.

-Este guia parte de um Android limpo e acompanha exatamente o fluxo atual do repositório público. O instalador cria a configuração local, instala as dependências e deixa o bot pronto para `npm start`. +

+ Android + Node 20.19+ + Tempo +

-> **Tempo normal:** 15 a 35 minutos na primeira instalação. Use Wi-Fi, mantenha o aparelho carregando e reserve pelo menos 2 GB livres. +> [!TIP] +> Faça a primeira instalação no Wi‑Fi, com o aparelho carregando e pelo menos **2 GB livres**. O bot não exige Termux:API para manter o wake lock.

- Verificação do ambiente no Termux + Preflight do SHOGUN no Termux

-## 1. Instale o Termux +## Rota completa -A fonte recomendada para a maioria das pessoas é o **F-Droid**. A versão publicada no Google Play existe novamente, mas é uma variante experimental com diferenças de compatibilidade em relação à linha tradicional do Termux. +| Etapa | O que acontece | Você sabe que deu certo quando… | +| --- | --- | --- | +| **1** | instalar o Termux | aparece o terminal com `$` | +| **2** | atualizar pacotes | o prompt volta sem erro | +| **3** | clonar o SHOGUN | `pwd` termina em `/shogun` | +| **4** | rodar o instalador | aparece a configuração do bot | +| **5** | manter o processo acordado | `termux-wake-lock` não retorna erro | +| **6** | conectar o WhatsApp | o feed do SHOGUN começa a rodar | +| **7** | testar | `!menu` recebe resposta | -- [Termux no F-Droid](https://f-droid.org/packages/com.termux/) -- [Releases oficiais no GitHub](https://github.com/termux/termux-app/releases) +--- -Não misture aplicativo e plugins vindos de fontes diferentes. Eles usam assinaturas diferentes e o Android não trata isso com a delicadeza que a humanidade gostaria. +## 1 · Instale o Termux -Abra o Termux após a instalação. Você verá um terminal com uma linha terminando em `$`. +Use preferencialmente uma das fontes oficiais da linha tradicional: -## 2. Atualize os pacotes básicos +- **[F-Droid](https://f-droid.org/packages/com.termux/)** +- **[GitHub Releases](https://github.com/termux/termux-app/releases)** -Cole este comando e aguarde até o prompt voltar: +> [!IMPORTANT] +> A edição do Google Play segue uma linha diferente e ainda pode variar em compatibilidade. Também não misture o aplicativo principal e plugins baixados de fontes diferentes, porque as assinaturas não combinam. + +Abra o Termux. Se você vê uma linha terminando em `$`, está no lugar certo. É só um terminal. Ele parece hostil porque terminais foram desenhados antes de alguém descobrir bordas arredondadas. + +--- + +## 2 · Atualize o ambiente ```bash pkg update -y && pkg upgrade -y ``` -Se o Termux perguntar sobre manter ou substituir algum arquivo de configuração que você nunca alterou, pode aceitar a opção padrão pressionando **Enter**. +**O que isso faz:** atualiza a lista de pacotes e instala as versões mais recentes disponíveis para o seu Termux. + +Se surgir uma pergunta sobre arquivo de configuração que você nunca alterou, a opção padrão costuma ser suficiente: pressione **Enter**. + +--- -## 3. Baixe o SHOGUN +## 3 · Baixe o SHOGUN ```bash cd ~ @@ -37,97 +62,113 @@ git clone https://github.com/dgreych/shogun.git cd shogun ``` -> ✅ **Deu certo se:** o comando `pwd` terminar em `/shogun`. +Confira onde está: -Se aparecer `destination path 'shogun' already exists`, você já possui uma cópia. Entre nela com `cd ~/shogun` em vez de clonar outra. +```bash +pwd +``` -## 4. Rode o instalador do próprio projeto +> [!NOTE] +> Se aparecer `destination path 'shogun' already exists`, não clone de novo. Use `cd ~/shogun`. + +--- + +## 4 · Deixe o projeto preparar o aparelho ```bash bash scripts/install-termux.sh ``` -O script atual faz, nesta ordem: +O instalador do repositório faz a parte tediosa em ordem previsível: -1. atualiza o índice de pacotes do Termux; -2. instala Git, Node.js LTS, FFmpeg e as ferramentas básicas do Termux; -3. executa a verificação de plataforma; -4. instala exatamente as dependências travadas em `package-lock.json` com `npm ci`; -5. abre a configuração inicial do SHOGUN. +1. atualiza o índice do Termux; +2. instala **Git, Node.js LTS, FFmpeg e termux-tools**; +3. executa o preflight da plataforma; +4. instala as dependências travadas em `package-lock.json` com `npm ci`; +5. abre a configuração inicial. -Durante a configuração, informe: +### O setup pergunta -- seu nome; -- número do dono com país + DDD + número, somente dígitos; -- nome do bot; -- prefixo dos comandos. + + + + + +
Seu nomecomo o bot identifica o dono
Seu númeropaís + DDD + número, somente dígitos
Nome do boto nome exibido pela instalação
Prefixopor exemplo !
-A configuração é salva somente no aparelho, em `dados/src/config.json`. +A configuração é gravada localmente em `dados/src/config.json`. -## 5. Mantenha o Android acordado +--- -Antes de iniciar o bot: +## 5 · Impeça o Android de dormir em cima do bot ```bash termux-wake-lock ``` -Esse comando faz parte das ferramentas do próprio Termux. **Não é necessário instalar o aplicativo Termux:API somente para usar o wake lock.** +O wake lock vem de `termux-tools`. **Não é necessário instalar o aplicativo Termux:API só para isso.** -Se o comando não existir: +Se o comando estiver ausente: ```bash pkg install -y termux-tools termux-wake-lock ``` -Também vale retirar o Termux da otimização agressiva de bateria do fabricante. Androids adoram encerrar processos úteis em nome de economizar 0,4% de bateria e depois fingir surpresa. +Também retire o Termux da otimização agressiva de bateria do fabricante. Android adora matar exatamente o processo que você queria manter vivo e chamar isso de otimização. + +--- -## 6. Inicie o bot +## 6 · Inicie e conecte ```bash npm start ``` -Na primeira execução, o SHOGUN abre o painel de conexão real da aplicação. Ele oferece: +O painel real da aplicação oferece: -1. **QR Code**; -2. **código de pareamento**; -3. sair. +- **QR Code**; +- **código de pareamento**; +- sair.

- Painel de conexão do SHOGUN + Painel de conexão do SHOGUN

-### Opção A: QR Code +### QR Code -Escolha a opção de QR e, no WhatsApp do número do bot, abra **Aparelhos conectados → Conectar um aparelho**. Leia o QR exibido pelo SHOGUN. +No WhatsApp do número que será usado pelo bot, abra **Aparelhos conectados → Conectar um aparelho** e leia o QR mostrado no Termux. -### Opção B: código de pareamento +### Código de pareamento -Escolha a opção de código. O programa usa o número configurado no setup e solicita ao WhatsApp um código de pareamento. Digite esse código no fluxo de aparelhos conectados do WhatsApp. +Escolha a opção correspondente. O SHOGUN usa o número salvo no setup e pede ao WhatsApp um código para ser informado no fluxo de aparelhos conectados. -Quando a sessão for salva, as próximas inicializações usam a sessão existente e não pedem novo QR enquanto ela continuar válida. +> [!TIP] +> Depois que a sessão é criada, inicializações futuras reutilizam essa sessão enquanto ela permanecer válida. Novo QR em todo boot não é comportamento normal. -## 7. Confirme que está realmente conectado +--- + +## 7 · Faça o teste que importa -Depois da conexão, o terminal muda para o feed de execução. +Quando o feed aparecer:

- SHOGUN conectado + SHOGUN conectado no Termux

-Envie no grupo: +Envie em um grupo de teste: ```text !menu ``` -Se você escolheu outro prefixo no setup, use esse prefixo no lugar de `!`. +Se escolheu outro prefixo, troque `!` por ele. -## Iniciar novamente depois +**Recebeu resposta?** Instalação, conexão e roteamento básico estão funcionando. -Sempre que fechar o Termux ou reiniciar o celular: +--- + +## Da próxima vez ```bash cd ~/shogun @@ -135,33 +176,34 @@ termux-wake-lock npm start ``` -## Atualizar a instalação +## Atualizar sem destruir a sessão -Pare o bot com `Ctrl + C` e execute: +Pare o processo com `Ctrl + C` e execute: ```bash cd ~/shogun git pull --ff-only npm ci --no-audit --no-fund +npm run preflight npm start ``` -O `npm ci` usa o lockfile público e evita que uma atualização transforme seu celular num congresso de versões aleatórias. +`npm ci` respeita o lockfile do projeto. O diretório de sessão não deve ser apagado durante uma atualização normal. -## Diagnóstico rápido +--- -Se o bot não iniciar: +## Diagnóstico rápido ```bash cd ~/shogun npm run preflight ``` -O preflight verifica a versão do Node.js, npm, Git, FFmpeg, detecta Termux e informa se configuração e dependências locais existem. - -### Node.js antigo +O preflight verifica **Node.js, npm, Git, FFmpeg, Termux, configuração e dependências locais**. -O SHOGUN exige **Node.js 20.19.0 ou superior**. Atualize: +
+Node.js está abaixo de 20.19 +
```bash pkg update -y @@ -169,41 +211,58 @@ pkg upgrade -y pkg install -y nodejs-lts node --version ``` +
-### FFmpeg ausente +
+FFmpeg não existe +
```bash pkg install -y ffmpeg ffmpeg -version ``` +
-### `npm ci` falhou depois de uma instalação antiga +
+npm ci falhou depois de uma instalação antiga +
```bash cd ~/shogun rm -rf node_modules npm ci --no-audit --no-fund ``` +
-### Sessão do WhatsApp precisa ser refeita +
+Quero refazer a configuração +
-A sessão fica em `dados/database/qr-code/`. Ela dá acesso à conta vinculada, então **não envie essa pasta para ninguém** e não a publique em GitHub, Drive ou grupos. +```bash +cd ~/shogun +npm run setup +``` +
+ +--- -Só apague a sessão quando realmente quiser desvincular e parear de novo. +## 🔐 A parte que você não deve mandar para ninguém + +A sessão fica em: + +```text +dados/database/qr-code/ +``` -## O que é obrigatório e o que é opcional +> [!CAUTION] +> Esses arquivos representam acesso à sessão vinculada do WhatsApp. **Não envie a pasta, não coloque em Drive, não publique em GitHub e não cole seu conteúdo em suporte.** Só apague a sessão se realmente quiser desvincular e parear novamente. -Para o núcleo do bot iniciar no Termux, o caminho público exige: +## O mínimo obrigatório -- Android com Termux funcional; -- Node.js 20.19+; -- npm; -- Git; -- FFmpeg; -- conexão com o WhatsApp. +**Necessário para o núcleo:** Android + Termux, Node.js 20.19+, npm, Git, FFmpeg e conexão com WhatsApp. -Chaves externas e integrações de IA são opcionais. Recursos que dependem de uma API externa específica só funcionam quando essa integração é configurada, mas isso não impede o SHOGUN de iniciar, conectar e executar o núcleo local. +**Opcional:** integrações externas, IA e capacidades que dependam de APIs específicas. A ausência delas não impede o núcleo do SHOGUN de iniciar e conectar. --- -[← Voltar ao README](../../README.md) +

← Voltar à página principal

\ No newline at end of file From d12c8e70ff7447d116ad9c8560f95b9ae9454dc6 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 18:04:49 -0300 Subject: [PATCH 17/49] Refazer guia visual do Windows --- docs/instalacao/windows.md | 226 +++++++++++++++++++++---------------- 1 file changed, 126 insertions(+), 100 deletions(-) diff --git a/docs/instalacao/windows.md b/docs/instalacao/windows.md index a6e92ba..1ed55a2 100644 --- a/docs/instalacao/windows.md +++ b/docs/instalacao/windows.md @@ -1,198 +1,224 @@ -# SHOGUN no Windows: instalação para iniciantes +

🪟 SHOGUN no Windows

+

Do PowerShell ao primeiro !menu, sem pular as partes que normalmente viram problema depois.

-Este caminho serve para Windows 10 e 11. Reserve cerca de 20 minutos, use uma -conta que possa instalar programas e mantenha o computador conectado à internet. +

+ Windows + Node 20.19+ + Tempo +

+ +## Rota completa + +| Etapa | Ação | Sinal de sucesso | +| --- | --- | --- | +| **1** | abrir PowerShell | prompt disponível | +| **2** | instalar Git, Node e FFmpeg | comandos mostram versões | +| **3** | clonar o projeto | pasta `shogun` criada | +| **4** | rodar o instalador | setup concluído | +| **5** | executar preflight | requisitos obrigatórios aprovados | +| **6** | conectar WhatsApp | feed do bot ativo | +| **7** | testar | `!menu` responde | -## Etapa 1 — abrir o PowerShell +--- -1. Abra o menu **Iniciar**. -2. Digite `PowerShell`. -3. Abra **Windows PowerShell**. Não é necessário abrir como administrador para - rodar o SHOGUN. +## 1 · Abra o PowerShell -Você vai copiar uma caixa por vez, colar com o botão direito ou `Ctrl+V` e -pressionar Enter. Espere o cursor voltar antes de seguir. +No menu **Iniciar**, procure por **PowerShell**. Para executar o SHOGUN normalmente não é necessário abrir como administrador. -## Etapa 2 — instalar as ferramentas +Você pode colar os comandos com `Ctrl+V`. Execute um bloco de cada vez e espere o prompt voltar. -O Windows 10/11 atualizado inclui o `winget`, instalador oficial do sistema. -Confira: +--- + +## 2 · Instale as ferramentas + +Primeiro confira se o `winget` está disponível: ```powershell winget --version ``` -Se o comando não existir, instale ou atualize **Instalador de Aplicativo** pela -Microsoft Store, feche o PowerShell e abra-o de novo. +Se não estiver, atualize o **Instalador de Aplicativo** pela Microsoft Store e abra uma nova janela do PowerShell. -Instale o Git: +### Git ```powershell winget install --id Git.Git -e --source winget ``` -Instale o Node.js LTS: +### Node.js LTS ```powershell winget install --id OpenJS.NodeJS.LTS -e --source winget ``` -Instale o FFmpeg: +### FFmpeg ```powershell winget install --id Gyan.FFmpeg -e --source winget ``` -Aceite os termos quando o Windows pedir. Feche completamente o PowerShell e -abra uma janela nova para que os novos comandos sejam reconhecidos. - -Se preferir instalar clicando, use somente as páginas oficiais de -[Node.js](https://nodejs.org/en/download), -[Git](https://git-scm.com/install/windows) e -[FFmpeg](https://ffmpeg.org/download.html). Escolha Node.js 22 ou 24 LTS e -lembre-se de adicionar FFmpeg ao `PATH`. - -## Etapa 3 — conferir o terreno +Feche o PowerShell e abra outro depois das instalações. O Windows precisa reconstruir o `PATH`, porque descobrir imediatamente que um programa acabou de ser instalado seria aparentemente pedir demais. -Na janela nova, rode um por vez: +### Confira ```powershell node --version -``` - -```powershell npm --version -``` - -```powershell git --version -``` - -```powershell ffmpeg -version ``` -Cada comando deve mostrar uma versão. Se algum disser “não é reconhecido”, -reinicie o computador uma vez antes de reinstalar. +> [!IMPORTANT] +> O SHOGUN exige **Node.js 20.19.0 ou superior**. Node 22/24 LTS é uma boa escolha para instalação nova. -## Etapa 4 — baixar o SHOGUN +--- -Escolha uma pasta simples. Este comando vai para sua pasta de usuário: +## 3 · Baixe o projeto ```powershell Set-Location $HOME -``` - -Baixe o projeto: - -```powershell git clone https://github.com/dgreych/shogun.git +Set-Location shogun ``` -Entre no quartel: +Se a pasta já existir, não clone por cima: ```powershell -Set-Location shogun +Set-Location "$HOME\shogun" ``` -## Etapa 5 — preparar e configurar +--- + +## 4 · Execute o instalador do SHOGUN ```powershell powershell -ExecutionPolicy Bypass -File .\scripts\install-windows.ps1 ``` -O preparo baixa os componentes do bot e depois faz quatro perguntas: +O instalador verifica o ambiente, instala as dependências travadas pelo projeto e abre o setup. -1. como o SHOGUN deve chamar você; -2. seu número com país e DDD, somente dígitos — exemplo fictício - `5511999999999`; -3. nome do bot — pressione Enter para manter `SHOGUN`; -4. prefixo — pressione Enter para manter `!`. + + + + + +
Seu nomeidentificação local do dono
Númeropaís + DDD + número, somente dígitos
Nome do botnome desta instalação
Prefixopor exemplo !
-Espere aparecer **SHOGUN pronto**. Para corrigir uma resposta depois, use: +Para refazer apenas essa configuração depois: ```powershell npm run setup ``` -## Etapa 6 — inspeção e conexão +--- + +## 5 · Faça a inspeção antes do boot ```powershell npm run preflight ```

- Saída da verificação do ambiente + Preflight do SHOGUN no Windows

-Imagem gerada da execução real do comando. O aviso amarelo sobre -configuração é esperado antes da etapa seguinte. +O preflight verifica Node.js, npm, Git, FFmpeg e os arquivos locais necessários para iniciar. -Se todos os itens obrigatórios estiverem aprovados, inicie: +--- + +## 6 · Inicie e conecte o WhatsApp ```powershell npm start ``` -Escolha `1` para QR Code. No telefone, abra WhatsApp → menu de três pontos → -**Aparelhos conectados/Dispositivos conectados → Conectar um aparelho** e leia -o QR da tela do computador. +O painel oferece **QR Code** e **código de pareamento**. -Se a câmera não puder ler a tela, pare com `Ctrl+C`, inicie novamente, escolha -`2` e siga o código de pareamento. +

+ Painel de conexão do SHOGUN +

-## Etapa 7 — confirmar a primeira missão +Para QR Code, no telefone abra **WhatsApp → Aparelhos conectados → Conectar um aparelho**. -Numa conversa de teste, envie: +Se preferir não usar a câmera, reinicie o fluxo e escolha o código de pareamento. Depois que a sessão for criada, ela é reaproveitada nos próximos boots enquanto continuar válida. + +--- + +## 7 · Prove que terminou + +Envie em um grupo de teste: ```text !menu ``` -Recebeu o menu? O posto está pronto. O PowerShell precisa permanecer aberto -enquanto o SHOGUN estiver em serviço. +Se escolheu outro prefixo, use-o no lugar de `!`. -## Sua rotina +> [!TIP] +> O PowerShell precisa permanecer aberto enquanto o processo estiver rodando. Fechar a janela encerra essa execução do bot. -Para parar com segurança, clique no PowerShell e pressione `Ctrl+C`. +--- -Para voltar outro dia: +## Uso diário -```powershell -Set-Location "$HOME\shogun" -``` +### Parar + +Pressione `Ctrl+C`. + +### Iniciar novamente ```powershell +Set-Location "$HOME\shogun" npm start ``` -Para atualizar, pare o bot e rode: +### Atualizar ```powershell +Set-Location "$HOME\shogun" git pull --ff-only -``` - -```powershell npm ci --no-audit --no-fund -``` - -```powershell +npm run preflight npm start ``` -Não copie apenas `node_modules` para outro PC. Em uma máquina nova, clone o -projeto e execute o instalador novamente. Preserve com cuidado a pasta local de -sessão; ela vale como uma chave do WhatsApp. - -## Socorro rápido - -- **Execução de scripts foi desabilitada:** use exatamente o comando com - `-ExecutionPolicy Bypass` mostrado na etapa 5; ele vale apenas para esse - instalador. -- **`ffmpeg` não é reconhecido:** feche todas as janelas do PowerShell e abra - outra. Se persistir, reinstale o FFmpeg e reinicie o Windows. -- **O QR ficou pequeno:** maximize a janela ou use código de pareamento. -- **A pasta `shogun` já existe:** entre nela com `Set-Location shogun`; não - clone por cima. -- **Ainda não funcionou:** rode `npm run preflight` e consulte - [solução de problemas](../solucao-de-problemas.md). +--- + +## Diagnóstico + +
+PowerShell diz que execução de scripts foi desabilitada +
+Use o comando do instalador exatamente com -ExecutionPolicy Bypass. Ele aplica a exceção ao processo usado para essa instalação. +
+ +
+ffmpeg, node ou git não é reconhecido +
+Feche todas as janelas do PowerShell, abra outra e teste novamente. Se persistir, reinicie o Windows uma vez e rode npm run preflight antes de reinstalar qualquer coisa. +
+ +
+O QR ficou pequeno ou ilegível +
+Maximize a janela ou use o código de pareamento. +
+ +
+A pasta shogun já existe +
+Entre nela com Set-Location "$HOME\shogun". Não clone outra cópia por cima. +
+ +--- + +## 🔐 Proteja a sessão + +A sessão vinculada fica em `dados/database/qr-code/`. + +> [!CAUTION] +> Não envie essa pasta para suporte, GitHub, Drive ou outras pessoas. Ela contém material de autenticação da conta conectada. + +Para diagnóstico adicional, execute `npm run preflight` e consulte **[Solução de problemas](../solucao-de-problemas.md)**. + +

← Voltar à página principal

\ No newline at end of file From 37cff817511a028323ac8bbb0104f23ef97d8615 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 18:05:10 -0300 Subject: [PATCH 18/49] Refazer guia visual do Linux --- docs/instalacao/linux.md | 219 +++++++++++++++++++++++---------------- 1 file changed, 129 insertions(+), 90 deletions(-) diff --git a/docs/instalacao/linux.md b/docs/instalacao/linux.md index 44557af..9ac1a5a 100644 --- a/docs/instalacao/linux.md +++ b/docs/instalacao/linux.md @@ -1,19 +1,31 @@ -# SHOGUN no Linux: do terminal ao primeiro menu +

🐧 SHOGUN no Linux

+

Instalação em desktop ou servidor, com cada etapa verificável.

-Este guia atende computadores e servidores Linux. Se é sua primeira vez, -Ubuntu ou Debian oferecem o caminho mais simples. Reserve cerca de 20 minutos. +

+ Linux + Node 20.19+ + Tempo +

-## Etapa 1 — abrir o Terminal +## Rota completa -No Ubuntu, pressione `Ctrl+Alt+T`. Em outras distribuições, procure o aplicativo -**Terminal** no menu. Copie uma caixa por vez, cole com `Ctrl+Shift+V` e -pressione Enter. +| Etapa | Ação | Sinal de sucesso | +| --- | --- | --- | +| **1** | instalar Git e FFmpeg | versões aparecem no terminal | +| **2** | instalar Node.js | `node --version` ≥ 20.19 | +| **3** | clonar o SHOGUN | pasta `~/shogun` criada | +| **4** | executar instalador | setup concluído | +| **5** | rodar preflight | requisitos obrigatórios aprovados | +| **6** | conectar WhatsApp | feed do bot ativo | +| **7** | testar | `!menu` responde | -## Etapa 2 — instalar Git e FFmpeg +--- -Use somente o bloco da sua distribuição. +## 1 · Prepare o sistema -### Ubuntu, Debian, Linux Mint e derivados +Use **somente** o bloco correspondente à sua distribuição. + +### Ubuntu · Debian · Linux Mint ```bash sudo apt update @@ -32,161 +44,188 @@ sudo dnf install -y git ffmpeg curl sudo pacman -Syu --needed git ffmpeg curl ``` -Quando `sudo` pedir a senha, digite mesmo que nenhum caractere apareça e -pressione Enter. Isso é uma proteção normal do Linux. +> [!NOTE] +> Quando `sudo` pede a senha, nenhum caractere aparece enquanto você digita. Isso é normal. O terminal não travou, ele só decidiu que feedback visual era luxo. -## Etapa 3 — instalar Node.js LTS +--- -O SHOGUN exige Node.js 20.19 ou mais recente e recomenda a linha LTS 22 ou 24. -Se sua distribuição já oferece uma dessas versões, instale `nodejs` e `npm` -pelo gerenciador de pacotes dela. Caso contrário, siga o método mostrado na -página oficial [Baixar Node.js](https://nodejs.org/en/download). +## 2 · Instale Node.js -Não use Node.js 18. Depois de instalar, feche e abra o Terminal. +O SHOGUN exige **Node.js 20.19.0 ou superior**. Para uma instalação nova, prefira uma linha LTS atual suportada pelo projeto. -## Etapa 4 — conferir o terreno +Se sua distribuição já oferece uma versão adequada, instale `nodejs` e `npm` pelo gerenciador de pacotes. Caso contrário, use o método indicado na página oficial do Node.js. -Rode um por vez: +Depois confira: ```bash node --version -``` - -```bash npm --version -``` - -```bash git --version -``` - -```bash ffmpeg -version ``` -Cada comando deve mostrar uma versão. Para Node.js, espere algo como `v22...` -ou `v24...`. +Se Node mostrar `v18`, ainda não terminou esta etapa. -## Etapa 5 — baixar o SHOGUN +--- -Volte à sua pasta pessoal: +## 3 · Baixe o projeto ```bash -cd +cd ~ +git clone https://github.com/dgreych/shogun.git +cd shogun ``` -Baixe o projeto: +Confira: ```bash -git clone https://github.com/dgreych/shogun.git +pwd ``` -Entre na pasta: +O caminho deve terminar em `/shogun`. -```bash -cd shogun -``` +--- -## Etapa 6 — preparar e configurar +## 4 · Execute o instalador ```bash bash scripts/install-linux.sh ``` -O instalador baixa os componentes e faz quatro perguntas: +O instalador executa o preflight, instala as dependências travadas em `package-lock.json` e abre a configuração inicial. -1. como o SHOGUN deve chamar você; -2. seu número com país e DDD, somente dígitos — exemplo fictício - `5511999999999`; -3. nome do bot — pressione Enter para manter `SHOGUN`; -4. prefixo — pressione Enter para manter `!`. + + + + + +
Seu nomeidentificação local do dono
Númeropaís + DDD + número, somente dígitos
Nome do botnome desta instalação
Prefixopor exemplo !
-Quando aparecer **SHOGUN pronto**, a configuração local está protegida e a -instalação terminou. Para refazer apenas as perguntas: +Para refazer apenas o setup depois: ```bash npm run setup ``` -## Etapa 7 — inspeção e conexão +--- + +## 5 · Verifique antes de iniciar ```bash npm run preflight ```

- Saída da verificação do ambiente + Preflight do SHOGUN no Linux

-Imagem gerada da execução real do comando. O aviso amarelo sobre -configuração é esperado antes da etapa seguinte. +O comando verifica Node.js, npm, Git, FFmpeg, configuração e dependências locais. + +--- -Com os itens obrigatórios aprovados, inicie: +## 6 · Inicie e conecte ```bash npm start ``` -Escolha `1` para QR Code. No telefone, abra WhatsApp → menu de três pontos → -**Aparelhos conectados/Dispositivos conectados → Conectar um aparelho** e leia -o QR do terminal. +Escolha **QR Code** ou **código de pareamento** no painel. -Se o WhatsApp estiver no mesmo equipamento ou o QR não couber, reinicie com -`Ctrl+C`, escolha `2` e use o código de pareamento. +

+ Painel de conexão do SHOGUN +

+ +No telefone, para QR, abra **WhatsApp → Aparelhos conectados → Conectar um aparelho**. Se QR não for conveniente, reinicie o fluxo e escolha pareamento por código. -## Etapa 8 — confirmar a primeira missão +A sessão criada é reutilizada nas próximas inicializações enquanto continuar válida. -Numa conversa de teste, envie: +--- + +## 7 · Teste de aceite + +Envie em um grupo de teste: ```text !menu ``` -Se o menu chegou, o posto está pronto. O Terminal precisa permanecer aberto -enquanto o SHOGUN estiver em serviço. +Se escolheu outro prefixo, substitua `!`. -## Sua rotina +**Recebeu resposta?** O núcleo instalou, conectou e está despachando comandos. -Para parar, pressione `Ctrl+C`. +--- -Para voltar outro dia: +## Uso diário -```bash -cd ~/shogun -``` +### Parar + +`Ctrl+C` + +### Iniciar de novo ```bash +cd ~/shogun npm start ``` -Para atualizar, pare o processo e rode: +### Atualizar ```bash +cd ~/shogun git pull --ff-only -``` - -```bash npm ci --no-audit --no-fund -``` - -```bash +npm run preflight npm start ``` -## Servidor ligado continuamente +> [!TIP] +> Em servidor que ficará ligado continuamente, faça primeiro a instalação manual e confirme `!menu`. Só depois configure supervisão de processo. Isso separa problema de instalação de problema de serviço, uma pequena gentileza para o seu futuro eu. + +Veja **[Implantação em servidor](../../DEPLOY.md)** para uma instalação pública supervisionada. + +--- + +## Diagnóstico + +
+sudo: command not found +
+Sua distribuição usa outro método de administração ou você está num ambiente restrito. Instale Git, Node.js e FFmpeg pelo mecanismo adequado ao sistema antes de continuar. +
+ +
+Node ainda mostra v18 +
+Instale uma versão compatível e abra um novo terminal. Depois confirme com node --version e npm run preflight. +
+ +
+Permissão negada no instalador +
+Use bash scripts/install-linux.sh. Não é necessário marcar o arquivo executável para esse fluxo. +
+ +
+A pasta shogun já existe +
+Entre nela com cd ~/shogun; não clone outra cópia por cima. +
+ +--- + +## 🔐 Proteja o estado local + +A sessão e a configuração devem sobreviver às atualizações: + +```text +dados/database/ +dados/src/config.json +.env.local +``` -Primeiro conclua a instalação manual e confirme `!menu`. Depois consulte -[Implantação em servidor](../../DEPLOY.md) para manter o processo supervisionado. -Não publique a pasta de sessão nem o arquivo de configuração ao mover o bot. +> [!CAUTION] +> Nunca publique a pasta de sessão. Ela contém material de autenticação do WhatsApp vinculado. -## Socorro rápido +Para diagnóstico adicional, rode `npm run preflight` e consulte **[Solução de problemas](../solucao-de-problemas.md)**. -- **`sudo: command not found`:** sua distribuição usa outro método de - administração; consulte a documentação dela ou peça ao administrador para - instalar Git, Node.js e FFmpeg. -- **Node mostra `v18`:** atualize para Node.js 22 ou 24 e reabra o Terminal. -- **Permissão negada no instalador:** rode com `bash scripts/install-linux.sh`, - exatamente como na etapa 6. -- **A pasta `shogun` já existe:** use `cd ~/shogun`; não clone por cima. -- **Ainda não funcionou:** rode `npm run preflight` e consulte - [solução de problemas](../solucao-de-problemas.md). +

← Voltar à página principal

\ No newline at end of file From c7110cf85e3579bd3338fdaafa91cee05f6adce9 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 18:05:23 -0300 Subject: [PATCH 19/49] Refazer guia visual do macOS --- docs/instalacao/macos.md | 119 ++++++++++++++++++++++++++++++++++----- 1 file changed, 105 insertions(+), 14 deletions(-) diff --git a/docs/instalacao/macos.md b/docs/instalacao/macos.md index 9bcde11..0c65235 100644 --- a/docs/instalacao/macos.md +++ b/docs/instalacao/macos.md @@ -1,10 +1,28 @@ -# Instalar o 𝖘𝖍𝖔𝖌𝖚𝖓 no macOS +

🍎 SHOGUN no macOS

+

Intel ou Apple Silicon, do Terminal ao WhatsApp conectado.

+ +

+ macOS + Node 20.19+ + Tempo +

+ +## Rota completa + +| Etapa | Ação | Sinal de sucesso | +| --- | --- | --- | +| **1** | instalar requisitos | versões aparecem no Terminal | +| **2** | clonar o SHOGUN | pasta `~/shogun` criada | +| **3** | executar instalador | setup concluído | +| **4** | rodar preflight | requisitos obrigatórios aprovados | +| **5** | conectar WhatsApp | feed ativo | +| **6** | testar | `!menu` responde | -O fluxo público do SHOGUN também é validado para macOS. O requisito é Node.js 20.19 ou superior, Git e FFmpeg. +--- -## 1. Instale os requisitos +## 1 · Prepare o Mac -Se você usa Homebrew: +Se usa Homebrew: ```bash brew update @@ -15,11 +33,19 @@ Confirme: ```bash node --version +npm --version git --version ffmpeg -version ``` -## 2. Clone o repositório público +> [!IMPORTANT] +> O SHOGUN exige **Node.js 20.19.0 ou superior**. + +Se `brew` não existir, instale os requisitos pelos distribuidores oficiais antes de continuar. + +--- + +## 2 · Baixe o projeto ```bash cd ~ @@ -27,39 +53,104 @@ git clone https://github.com/dgreych/shogun.git cd shogun ``` -## 3. Execute o instalador +Se a pasta já existir, use `cd ~/shogun` em vez de clonar novamente. + +--- + +## 3 · Execute o instalador ```bash bash scripts/install-macos.sh ``` -Ele executa o preflight, instala as dependências exatamente pelo `package-lock.json`, abre o setup e verifica as entradas principais do runtime. +O script executa o preflight, instala as dependências travadas pelo `package-lock.json`, abre o setup e verifica as entradas principais do runtime. + + + + + + +
Seu nomeidentificação local do dono
Númeropaís + DDD + número, somente dígitos
Nome do botnome desta instalação
Prefixopor exemplo !
-## 4. Inicie +--- + +## 4 · Faça o preflight + +```bash +npm run preflight +``` + +Esse comando confere os requisitos antes de você descobrir um deles faltando no meio do boot, que é o método clássico e menos divertido. + +--- + +## 5 · Inicie e conecte ```bash npm start ``` -O painel oferece QR Code ou código de pareamento. Depois que a sessão for criada, as próximas inicializações reutilizam a sessão enquanto ela permanecer válida. +O painel oferece **QR Code** ou **código de pareamento**. + +

+ Painel de conexão do SHOGUN +

+ +Para QR Code, no telefone abra **WhatsApp → Aparelhos conectados → Conectar um aparelho**. Depois que a sessão for criada, os próximos boots reutilizam a sessão enquanto ela permanecer válida. + +--- + +## 6 · Teste + +Em um grupo de teste: + +```text +!menu +``` + +Se escolheu outro prefixo, use-o no lugar de `!`. + +--- + +## Uso diário -## Atualizar +### Iniciar novamente + +```bash +cd ~/shogun +npm start +``` + +### Atualizar ```bash cd ~/shogun git pull --ff-only npm ci --no-audit --no-fund +npm run preflight npm start ``` -## Diagnóstico +### Diagnosticar ```bash +cd ~/shogun npm run preflight ``` -A sessão do WhatsApp fica em `dados/database/qr-code/`. Não publique nem compartilhe essa pasta. - --- -[← Voltar ao README](../../README.md) +## 🔐 Sessão do WhatsApp + +A sessão vinculada fica em: + +```text +dados/database/qr-code/ +``` + +> [!CAUTION] +> Não publique, envie ou compartilhe essa pasta. Ela contém material de autenticação da conta conectada. + +Para problemas adicionais, consulte **[Solução de problemas](../solucao-de-problemas.md)**. + +

← Voltar à página principal

\ No newline at end of file From 13156b02fd835defc35956c6c8a7383d59c03659 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 18:09:03 -0300 Subject: [PATCH 20/49] Corrigir store legado no downloader do YouTube --- dados/src/funcs/downloads/youtube.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dados/src/funcs/downloads/youtube.js b/dados/src/funcs/downloads/youtube.js index 4615cf3..2eee42f 100644 --- a/dados/src/funcs/downloads/youtube.js +++ b/dados/src/funcs/downloads/youtube.js @@ -7,7 +7,7 @@ import axios from 'axios'; import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; -import { getConfig } from '../../utils/gyomeiStore.js'; +import { getConfig } from '../../utils/shogunStore.js'; import { downloadYoutubeAudioForPlay, downloadYoutubeVideoForPlay } from '../../services/bunnyfy/youtubeGateway.js'; const DOWNLOAD_TIMEOUT = 180000; From 5a71a7ac32ae8ad8697f1d1d31e3e93b74eb7be9 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 18:13:21 -0300 Subject: [PATCH 21/49] =?UTF-8?q?Aplicar=20sanitiza=C3=A7=C3=A3o=20final?= =?UTF-8?q?=20da=20identidade=20p=C3=BAblica?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/identity-sanitize-once.yml | 78 ++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 .github/workflows/identity-sanitize-once.yml diff --git a/.github/workflows/identity-sanitize-once.yml b/.github/workflows/identity-sanitize-once.yml new file mode 100644 index 0000000..4e0bc52 --- /dev/null +++ b/.github/workflows/identity-sanitize-once.yml @@ -0,0 +1,78 @@ +name: Sanitização pontual da identidade pública + +on: + push: + branches: + - fix/portabilidade-publica-20260824 + +permissions: + contents: write + +jobs: + sanitize: + if: github.actor != 'github-actions[bot]' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: fix/portabilidade-publica-20260824 + fetch-depth: 0 + + - name: Atualizar mensagens legadas e remover o workflow temporário + shell: python + run: | + from pathlib import Path + import re + + path = Path('dados/src/utils/database.js') + text = path.read_text(encoding='utf-8') + + pattern = re.compile( + r"(ensureJsonFileExists\(MSGBOTON_FILE, \{ enabled: defaultMsgBotOnEnabled,\s*message: `)(.*?)(`\s*\}\);)", + re.S, + ) + replacement = """⚔️ ────────────────── ⚔️ + + *𝖘𝖍𝖔𝖌𝖚𝖓 no comando* + + Grupo sob controle. Moderação, + mídia, jogos e economia prontos + para uso. + + Digite *{prefix}menu* para ver + tudo o que dá para fazer aqui. + +_Para encerrar este aviso nas próximas +inicializações, use *msgboton*._""" + text, count = pattern.subn(lambda m: m.group(1) + replacement + m.group(3), text, count=1) + if count != 1: + raise SystemExit('bloco inicial de msgboton não encontrado de forma única') + + text, online_count = re.subn( + r"✅ \*GYOMEI est[aá] online\*", + "✅ *𝖘𝖍𝖔𝖌𝖚𝖓 online*", + text, + ) + if online_count != 1: + raise SystemExit(f'mensagem online esperada uma vez; encontrada {online_count}') + + forbidden = [ + r'GYOMEI est[aá] (desperto|online)', + r'base d[ao]\s+Nazuna', + r'continuidade da Nazuna', + r'vers[aã]o GYOMEI', + ] + for item in forbidden: + if re.search(item, text, flags=re.I): + raise SystemExit(f'vestígio público ainda presente em database.js: {item}') + + path.write_text(text, encoding='utf-8') + Path('.github/workflows/identity-sanitize-once.yml').unlink() + + - name: Commitar a correção na própria branch + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add dados/src/utils/database.js .github/workflows/identity-sanitize-once.yml + git commit -m "Remover mensagens da identidade anterior" + git push origin HEAD:fix/portabilidade-publica-20260824 From b752f4e068403f7a6bb1c7a5b953dcb494525253 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 18:14:13 -0300 Subject: [PATCH 22/49] =?UTF-8?q?Executar=20sanitiza=C3=A7=C3=A3o=20na=20v?= =?UTF-8?q?alida=C3=A7=C3=A3o=20do=20PR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/identity-sanitize-once.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/identity-sanitize-once.yml b/.github/workflows/identity-sanitize-once.yml index 4e0bc52..7660871 100644 --- a/.github/workflows/identity-sanitize-once.yml +++ b/.github/workflows/identity-sanitize-once.yml @@ -1,16 +1,16 @@ name: Sanitização pontual da identidade pública on: - push: + pull_request: branches: - - fix/portabilidade-publica-20260824 + - main permissions: contents: write jobs: sanitize: - if: github.actor != 'github-actions[bot]' + if: github.event.pull_request.head.ref == 'fix/portabilidade-publica-20260824' && github.actor != 'github-actions[bot]' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 From f0d383deb6d1a733245983c64b6979f69e90cfdf Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 18:15:01 -0300 Subject: [PATCH 23/49] =?UTF-8?q?Aplicar=20corre=C3=A7=C3=A3o=20final=20de?= =?UTF-8?q?=20identidade=20no=20snapshot=20p=C3=BAblico?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/shogun-validate.yml | 72 +++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/.github/workflows/shogun-validate.yml b/.github/workflows/shogun-validate.yml index 57c6229..a370576 100644 --- a/.github/workflows/shogun-validate.yml +++ b/.github/workflows/shogun-validate.yml @@ -13,6 +13,78 @@ permissions: contents: read jobs: + sanitizar-identidade: + name: Sanitizar identidade pública + if: github.event_name == 'pull_request' && github.event.pull_request.head.ref == 'fix/portabilidade-publica-20260824' + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Baixar a branch do PR + uses: actions/checkout@v4 + with: + ref: fix/portabilidade-publica-20260824 + fetch-depth: 0 + - name: Corrigir mensagens legadas + shell: python + run: | + from pathlib import Path + import re + + path = Path('dados/src/utils/database.js') + text = path.read_text(encoding='utf-8') + + pattern = re.compile( + r"(ensureJsonFileExists\(MSGBOTON_FILE, \{ enabled: defaultMsgBotOnEnabled,\s*message: `)(.*?)(`\s*\}\);)", + re.S, + ) + replacement = """⚔️ ────────────────── ⚔️ + + *𝖘𝖍𝖔𝖌𝖚𝖓 no comando* + + Grupo sob controle. Moderação, + mídia, jogos e economia prontos + para uso. + + Digite *{prefix}menu* para ver + tudo o que dá para fazer aqui. + +_Para encerrar este aviso nas próximas +inicializações, use *msgboton*._""" + text, count = pattern.subn(lambda m: m.group(1) + replacement + m.group(3), text, count=1) + if count != 1: + raise SystemExit('bloco inicial de msgboton não encontrado de forma única') + + text, online_count = re.subn( + r"✅ \*GYOMEI est[aá] online\*", + "✅ *𝖘𝖍𝖔𝖌𝖚𝖓 online*", + text, + ) + if online_count != 1: + raise SystemExit(f'mensagem online esperada uma vez; encontrada {online_count}') + + for item in [ + r'GYOMEI est[aá] (desperto|online)', + r'base d[ao]\s+Nazuna', + r'continuidade da Nazuna', + r'vers[aã]o GYOMEI', + ]: + if re.search(item, text, flags=re.I): + raise SystemExit(f'vestígio público ainda presente em database.js: {item}') + + path.write_text(text, encoding='utf-8') + - name: Publicar a correção na branch + run: | + if git diff --quiet -- dados/src/utils/database.js; then + echo "database.js já está sanitizado" + exit 0 + fi + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add dados/src/utils/database.js + git commit -m "Remover mensagens da identidade anterior" + git push origin HEAD:fix/portabilidade-publica-20260824 + qualidade: name: Qualidade completa runs-on: ubuntu-latest From 32dc985b86472e895c23545f4f8339493dec1766 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 18:16:53 -0300 Subject: [PATCH 24/49] =?UTF-8?q?Documentar=20matriz=20p=C3=BAblica=20de?= =?UTF-8?q?=20portabilidade?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/portabilidade.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 docs/portabilidade.md diff --git a/docs/portabilidade.md b/docs/portabilidade.md new file mode 100644 index 0000000..5e62be5 --- /dev/null +++ b/docs/portabilidade.md @@ -0,0 +1,25 @@ +# Portabilidade do SHOGUN + +O repositório público é tratado como uma distribuição instalável, não como uma fotografia ornamental do código. + +| Plataforma | Entrada recomendada | Validação automatizada | +| --- | --- | --- | +| Android / Termux | `bash scripts/install-termux.sh` | contrato Termux + Node 20.19 | +| Windows 10/11 | `scripts/install-windows.ps1` | Windows + Node 20.19/22/24 | +| Linux | `bash scripts/install-linux.sh` | Ubuntu + Node 20.19/22/24 | +| macOS | `bash scripts/install-macos.sh` | macOS + Node 20.19/22/24 | + +## O que “suportado” significa + +A matriz verifica instalação de dependências, entradas principais do runtime, build modular e requisitos de plataforma. O job de qualidade executa também os testes de domínio, roteamento, estado, compatibilidade, regressões e validação de release. + +No Android, o GitHub Actions não finge ser um aparelho físico. O contrato automatizado valida o caminho específico do Termux, enquanto o guia documenta as etapas que dependem do dispositivo e do pareamento real com o WhatsApp. + +## Guias + +- [Termux](instalacao/termux.md) +- [Windows](instalacao/windows.md) +- [Linux](instalacao/linux.md) +- [macOS](instalacao/macos.md) + +Para a primeira conexão e os cuidados com a sessão, veja também [Primeiros passos](primeiros-passos.md) e [Segurança](seguranca.md). From 9e2997bef4bb30580d3b74a2884304c05128b811 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 18:18:19 -0300 Subject: [PATCH 25/49] =?UTF-8?q?Remover=20automa=C3=A7=C3=A3o=20tempor?= =?UTF-8?q?=C3=A1ria=20de=20sanitiza=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/identity-sanitize-once.yml | 78 -------------------- 1 file changed, 78 deletions(-) delete mode 100644 .github/workflows/identity-sanitize-once.yml diff --git a/.github/workflows/identity-sanitize-once.yml b/.github/workflows/identity-sanitize-once.yml deleted file mode 100644 index 7660871..0000000 --- a/.github/workflows/identity-sanitize-once.yml +++ /dev/null @@ -1,78 +0,0 @@ -name: Sanitização pontual da identidade pública - -on: - pull_request: - branches: - - main - -permissions: - contents: write - -jobs: - sanitize: - if: github.event.pull_request.head.ref == 'fix/portabilidade-publica-20260824' && github.actor != 'github-actions[bot]' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: fix/portabilidade-publica-20260824 - fetch-depth: 0 - - - name: Atualizar mensagens legadas e remover o workflow temporário - shell: python - run: | - from pathlib import Path - import re - - path = Path('dados/src/utils/database.js') - text = path.read_text(encoding='utf-8') - - pattern = re.compile( - r"(ensureJsonFileExists\(MSGBOTON_FILE, \{ enabled: defaultMsgBotOnEnabled,\s*message: `)(.*?)(`\s*\}\);)", - re.S, - ) - replacement = """⚔️ ────────────────── ⚔️ - - *𝖘𝖍𝖔𝖌𝖚𝖓 no comando* - - Grupo sob controle. Moderação, - mídia, jogos e economia prontos - para uso. - - Digite *{prefix}menu* para ver - tudo o que dá para fazer aqui. - -_Para encerrar este aviso nas próximas -inicializações, use *msgboton*._""" - text, count = pattern.subn(lambda m: m.group(1) + replacement + m.group(3), text, count=1) - if count != 1: - raise SystemExit('bloco inicial de msgboton não encontrado de forma única') - - text, online_count = re.subn( - r"✅ \*GYOMEI est[aá] online\*", - "✅ *𝖘𝖍𝖔𝖌𝖚𝖓 online*", - text, - ) - if online_count != 1: - raise SystemExit(f'mensagem online esperada uma vez; encontrada {online_count}') - - forbidden = [ - r'GYOMEI est[aá] (desperto|online)', - r'base d[ao]\s+Nazuna', - r'continuidade da Nazuna', - r'vers[aã]o GYOMEI', - ] - for item in forbidden: - if re.search(item, text, flags=re.I): - raise SystemExit(f'vestígio público ainda presente em database.js: {item}') - - path.write_text(text, encoding='utf-8') - Path('.github/workflows/identity-sanitize-once.yml').unlink() - - - name: Commitar a correção na própria branch - run: | - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add dados/src/utils/database.js .github/workflows/identity-sanitize-once.yml - git commit -m "Remover mensagens da identidade anterior" - git push origin HEAD:fix/portabilidade-publica-20260824 From 1d58f35dc70bc6c3c660f587ae144473538d31ed Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Mon, 24 Aug 2026 18:18:35 -0300 Subject: [PATCH 26/49] =?UTF-8?q?Restaurar=20valida=C3=A7=C3=A3o=20p=C3=BA?= =?UTF-8?q?blica=20definitiva?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/shogun-validate.yml | 72 --------------------------- 1 file changed, 72 deletions(-) diff --git a/.github/workflows/shogun-validate.yml b/.github/workflows/shogun-validate.yml index a370576..57c6229 100644 --- a/.github/workflows/shogun-validate.yml +++ b/.github/workflows/shogun-validate.yml @@ -13,78 +13,6 @@ permissions: contents: read jobs: - sanitizar-identidade: - name: Sanitizar identidade pública - if: github.event_name == 'pull_request' && github.event.pull_request.head.ref == 'fix/portabilidade-publica-20260824' - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - name: Baixar a branch do PR - uses: actions/checkout@v4 - with: - ref: fix/portabilidade-publica-20260824 - fetch-depth: 0 - - name: Corrigir mensagens legadas - shell: python - run: | - from pathlib import Path - import re - - path = Path('dados/src/utils/database.js') - text = path.read_text(encoding='utf-8') - - pattern = re.compile( - r"(ensureJsonFileExists\(MSGBOTON_FILE, \{ enabled: defaultMsgBotOnEnabled,\s*message: `)(.*?)(`\s*\}\);)", - re.S, - ) - replacement = """⚔️ ────────────────── ⚔️ - - *𝖘𝖍𝖔𝖌𝖚𝖓 no comando* - - Grupo sob controle. Moderação, - mídia, jogos e economia prontos - para uso. - - Digite *{prefix}menu* para ver - tudo o que dá para fazer aqui. - -_Para encerrar este aviso nas próximas -inicializações, use *msgboton*._""" - text, count = pattern.subn(lambda m: m.group(1) + replacement + m.group(3), text, count=1) - if count != 1: - raise SystemExit('bloco inicial de msgboton não encontrado de forma única') - - text, online_count = re.subn( - r"✅ \*GYOMEI est[aá] online\*", - "✅ *𝖘𝖍𝖔𝖌𝖚𝖓 online*", - text, - ) - if online_count != 1: - raise SystemExit(f'mensagem online esperada uma vez; encontrada {online_count}') - - for item in [ - r'GYOMEI est[aá] (desperto|online)', - r'base d[ao]\s+Nazuna', - r'continuidade da Nazuna', - r'vers[aã]o GYOMEI', - ]: - if re.search(item, text, flags=re.I): - raise SystemExit(f'vestígio público ainda presente em database.js: {item}') - - path.write_text(text, encoding='utf-8') - - name: Publicar a correção na branch - run: | - if git diff --quiet -- dados/src/utils/database.js; then - echo "database.js já está sanitizado" - exit 0 - fi - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add dados/src/utils/database.js - git commit -m "Remover mensagens da identidade anterior" - git push origin HEAD:fix/portabilidade-publica-20260824 - qualidade: name: Qualidade completa runs-on: ubuntu-latest From fbd8bb643ccb0158395a754e2f337f3213c00cdf Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:12:09 -0300 Subject: [PATCH 27/49] =?UTF-8?q?Documentar=20configura=C3=A7=C3=A3o=20e?= =?UTF-8?q?=20dono=20da=20inst=C3=A2ncia?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/configuracao-da-instancia.md | 280 ++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+) create mode 100644 docs/configuracao-da-instancia.md diff --git a/docs/configuracao-da-instancia.md b/docs/configuracao-da-instancia.md new file mode 100644 index 0000000..8a654a2 --- /dev/null +++ b/docs/configuracao-da-instancia.md @@ -0,0 +1,280 @@ +# Configuração da sua instância do SHOGUN + +Este guia responde três perguntas antes que você precise abrir código: + +1. **quem é o dono desta instalação?** +2. **o que é obrigatório para o bot iniciar?** +3. **quais chaves de API só são necessárias para recursos opcionais?** + +O objetivo é que uma instalação nova seja previsível. Nada de descobrir uma +credencial escondida depois de quinze minutos encarando um stack trace como se +ele fosse um oráculo. + +--- + +## 1. Quem é o “dono” do bot? + +Quando você clona o SHOGUN e executa `npm run setup`, o número informado em +`numerodono` define o **dono principal daquela instância**. + +```text +Projeto SHOGUN +│ +├── autoria e créditos do projeto +│ └── continuam os mesmos em qualquer clone +│ +└── sua instalação + │ + ├── dono principal da instância + │ └── seu número configurado em numerodono + │ + ├── sessão WhatsApp desta instalação + │ + └── grupos onde o bot participa + └── administradores do grupo ≠ dono principal da instância +``` + +### Em termos simples + +- **Dono principal da instância:** pessoa que controla esta cópia do bot e pode + usar comandos reservados ao dono. +- **Administrador de grupo:** cargo concedido pelo próprio WhatsApp dentro de um + grupo. Não transforma alguém em dono da instância. +- **Autor/criador do projeto:** crédito de quem criou ou desenvolveu o software. + Clonar o projeto não altera autoria. + +O número do dono deve incluir país + DDD + número e conter somente dígitos. +Exemplo de formato brasileiro: `55DDDNUMERO`. + +A configuração fica em `dados/src/config.json`. Esse arquivo é local e não deve +ser enviado ao GitHub. + +--- + +## 2. O que é obrigatório para o SHOGUN funcionar? + +### Núcleo do bot + +Para iniciar o núcleo e conectar ao WhatsApp, você precisa de: + +- Node.js compatível; +- npm; +- Git; +- FFmpeg; +- `dados/src/config.json`, criado pelo setup; +- uma sessão WhatsApp criada por QR Code ou código de pareamento. + +**Nenhuma chave de API é obrigatória apenas para o bot iniciar.** Recursos que +dependem de serviços externos ficam disponíveis conforme você os configura. + +Execute: + +```bash +npm run preflight +``` + +O diagnóstico informa o que está pronto sem imprimir seus segredos. + +--- + +## 3. `.env.local`: onde ficam as opções privadas + +O SHOGUN carrega configurações privadas de: + +```text +.env.local +``` + +O repositório fornece um modelo seguro: + +```text +.env.example +``` + +Os instaladores oficiais criam `.env.local` a partir do exemplo quando ele +não existe. Se estiver fazendo o processo manualmente: + +### Linux, macOS ou Termux + +```bash +cp -n .env.example .env.local +chmod 600 .env.local +``` + +### Windows PowerShell + +```powershell +if (-not (Test-Path .env.local)) { Copy-Item .env.example .env.local } +``` + +Nunca publique `.env.local`. + +--- + +## 4. Matriz de integrações e credenciais + +| Recurso | Precisa de chave? | Configuração | Quando usar | +| --- | --- | --- | --- | +| Núcleo + WhatsApp | **não** | setup + sessão | sempre | +| BunnyFy | sim, se ativada | `BUNNYFY_ENABLED`, `BUNNYFY_BASE_URL`, `BUNNYFY_API_TOKEN` | capacidades servidas pela BunnyFy | +| Assistente via BunnyFy | chave BunnyFy | `BUNNYFY_AI_MODE=exclusive` | IA totalmente pela BunnyFy | +| Assistente BunnyFy + fallback NVIDIA | BunnyFy + NVIDIA | `BUNNYFY_AI_MODE=primary`, `NVIDIA_API_KEY` | BunnyFy primeiro, NVIDIA direta se houver falha transitória | +| Assistente NVIDIA direta | NVIDIA | `BUNNYFY_AI_MODE=off`, `NVIDIA_API_KEY` | IA sem BunnyFy | +| Transcrição via BunnyFy | chave BunnyFy | BunnyFy ativa + modo correspondente | caminho recomendado quando disponível | +| Transcrição VEX legado | VEX | `VEX_API_KEY`, `VEX_SITE` | somente quando o fallback legado for usado | +| Upload GitHub legado | GitHub | `UPLOAD_GITHUB_TOKEN`, `UPLOAD_GITHUB_REPO` | somente nos fluxos legados que ainda dependam dele | + +### Regra importante sobre BunnyFy + +A BunnyFy é uma plataforma separada. Se uma instância do SHOGUN usa a BunnyFy, +o bot recebe **somente uma credencial de consumidor da BunnyFy**. + +Chaves internas de provedores usados pela BunnyFy, como NVIDIA ou outros +serviços da infraestrutura da API, pertencem ao operador da BunnyFy e **não +devem ser copiadas para o bot**. + +--- + +## 5. Modos BunnyFy + +A chave mestra é: + +```env +BUNNYFY_ENABLED=false +``` + +Com `false`, as capacidades BunnyFy ficam desligadas e os caminhos legados ou +locais continuam sendo usados quando existirem. + +Ao ativar: + +```env +BUNNYFY_ENABLED=true +BUNNYFY_BASE_URL=https://SUA-BUNNYFY.example +BUNNYFY_API_TOKEN=SUA_CREDENCIAL_DE_CONSUMIDOR +``` + +Cada família usa um modo: + +```text +off -> não usa BunnyFy nessa capacidade +primary -> tenta BunnyFy; em falha transitória usa fallback quando houver +exclusive -> usa BunnyFy; não cai para o provider legado +``` + +As famílias atuais incluem IA, YouTube, imagens, stickers, canvas, logos, +geração visual, Tavern e NEXO. O `.env.example` é a referência dos nomes +exatos disponíveis nesta versão. + +> Não ative `exclusive` em uma capacidade antes de confirmar que a BunnyFy +> configurada oferece aquele contrato. + +--- + +## 6. Configurações da IA + +### Opção A — IA totalmente pela BunnyFy + +```env +BUNNYFY_ENABLED=true +BUNNYFY_AI_MODE=exclusive +BUNNYFY_BASE_URL=https://SUA-BUNNYFY.example +BUNNYFY_API_TOKEN=SUA_CREDENCIAL +NVIDIA_API_KEY= +``` + +O bot não precisa conhecer a chave do provedor de IA da BunnyFy. + +### Opção B — NVIDIA direta + +```env +BUNNYFY_ENABLED=false +NVIDIA_API_KEY=SUA_CHAVE_NVIDIA +``` + +O modelo pode ser escolhido pelos mecanismos do próprio bot. + +### Opção C — BunnyFy com fallback NVIDIA + +```env +BUNNYFY_ENABLED=true +BUNNYFY_AI_MODE=primary +BUNNYFY_BASE_URL=https://SUA-BUNNYFY.example +BUNNYFY_API_TOKEN=SUA_CREDENCIAL +NVIDIA_API_KEY=SUA_CHAVE_NVIDIA +``` + +Aqui a chave NVIDIA é necessária para o fallback direto realmente funcionar. + +--- + +## 7. VEX e integrações legadas + +O SHOGUN ainda preserva alguns fallbacks para não remover recursos antes de uma +substituição comprovada. + +Para o fallback VEX de transcrição: + +```env +VEX_API_KEY= +VEX_SITE= +``` + +Deixe vazio se você não usa esse caminho. + +Da mesma forma, `UPLOAD_GITHUB_TOKEN` não é requisito geral do bot. Só configure +credenciais legadas quando você souber qual recurso as consome. + +--- + +## 8. Como verificar sem vazar segredo + +Use: + +```bash +npm run preflight +``` + +E, quando estiver configurando NVIDIA direta: + +```bash +npm run test:nvidia:live +``` + +O preflight deve mostrar **presença/ausência e modo**, nunca o valor de tokens. + +Nunca cole em issue, print, vídeo ou pedido de suporte: + +- `.env.local`; +- `dados/src/config.json`; +- `dados/database/qr-code/`; +- tokens e chaves; +- cookies; +- URLs assinadas. + +--- + +## 9. Sequência recomendada para uma instalação nova + +```text +1. instalar Git + Node + FFmpeg + ↓ +2. clonar o repositório + ↓ +3. executar o instalador da sua plataforma + ↓ +4. informar o dono principal da instância + ↓ +5. rodar npm run preflight + ↓ +6. iniciar com npm start + ↓ +7. conectar o WhatsApp + ↓ +8. testar !menu + ↓ +9. só então ativar APIs opcionais que você realmente quiser +``` + +Isso mantém o primeiro boot simples e deixa integrações externas como extensão, +não como pedágio para chegar ao menu. From ce8f10b7ccf6fdb0eb64306e26310a6cd9d9c40e Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:12:30 -0300 Subject: [PATCH 28/49] =?UTF-8?q?Explicitar=20ambiente=20e=20integra=C3=A7?= =?UTF-8?q?=C3=B5es=20opcionais?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 0f938b1..379103a 100644 --- a/.env.example +++ b/.env.example @@ -1,12 +1,68 @@ -# Identidade padrão do SHOGUN +# SHOGUN — configuração privada da instância +# +# Os instaladores copiam este arquivo para .env.local quando ele não existe. +# O núcleo do bot não exige chave de API para iniciar. Preencha somente as +# integrações que você realmente utilizar. Nunca versione .env.local. + +# Identidade visual padrão do produto. O dono principal é configurado por +# `npm run setup` e fica em dados/src/config.json, não neste arquivo. BOT_NAME=𝖘𝖍𝖔𝖌𝖚𝖓 DEFAULT_PERSONA=shogun # Recomendado para Termux e aparelhos com pouca memória. SHOGUN_LOW_MEMORY=false -# Controles seguros do módulo de downloads. +# --------------------------------------------------------------------------- +# BunnyFy — opcional +# --------------------------------------------------------------------------- +# false = o bot usa caminhos locais/legados quando disponíveis. +# true = habilita as capacidades BunnyFy configuradas abaixo. +BUNNYFY_ENABLED=false +BUNNYFY_BASE_URL= +BUNNYFY_API_TOKEN= +BUNNYFY_ALLOW_INSECURE_HTTP=false +BUNNYFY_ACCOUNT_URL= +BUNNYFY_CAPABILITY_TIMEOUT_MS=120000 + +# Modos: off | primary | exclusive +# off = não usa BunnyFy nessa capacidade +# primary = tenta BunnyFy e usa fallback quando o contrato permitir +# exclusive = usa BunnyFy sem fallback legado +BUNNYFY_AI_MODE=off +BUNNYFY_AI_TIMEOUT_MS=120000 BUNNYFY_YOUTUBE_MODE=off BUNNYFY_YOUTUBE_TIMEOUT_MS=190000 BUNNYFY_YOUTUBE_MAX_BYTES=52428800 BUNNYFY_YOUTUBE_MAX_CONCURRENCY=4 +BUNNYFY_IMAGES_MODE=off +BUNNYFY_STICKERS_MODE=off +BUNNYFY_CANVAS_MODE=off +BUNNYFY_LOGOS_MODE=off +BUNNYFY_GAMES_MODE=off +BUNNYFY_IMAGE_GEN_MODE=off +BUNNYFY_TAVERN_RENDER_MODE=off +BUNNYFY_NEXO_RENDER_MODE=off + +# --------------------------------------------------------------------------- +# IA direta NVIDIA — opcional +# --------------------------------------------------------------------------- +# Necessária somente quando a assistente usar NVIDIA diretamente: +# - BUNNYFY_AI_MODE=off; ou +# - BUNNYFY_AI_MODE=primary e você quiser fallback direto. +# Em BUNNYFY_AI_MODE=exclusive, a credencial do provider pertence à BunnyFy. +NVIDIA_API_KEY= + +# --------------------------------------------------------------------------- +# Transcrição VEX legada — opcional +# --------------------------------------------------------------------------- +# Preencha apenas se sua instalação usar o fallback legado de transcrição. +VEX_API_KEY= +VEX_SITE= + +# --------------------------------------------------------------------------- +# Upload GitHub legado — opcional +# --------------------------------------------------------------------------- +# Não é requisito geral do SHOGUN. Use apenas nos fluxos que ainda dependam +# desse mecanismo e crie um token dedicado com o menor escopo possível. +UPLOAD_GITHUB_TOKEN= +UPLOAD_GITHUB_REPO=uploadsnew/uploads From 05693041de986ab1a829ec20206d619454fc97ee Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:12:49 -0300 Subject: [PATCH 29/49] Criar ambiente local no instalador Linux --- scripts/install-linux.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/install-linux.sh b/scripts/install-linux.sh index 5b385ab..6e5eb51 100755 --- a/scripts/install-linux.sh +++ b/scripts/install-linux.sh @@ -10,6 +10,15 @@ for command in git node npm ffmpeg; do fi done +if [ ! -f .env.local ]; then + cp .env.example .env.local + chmod 600 .env.local + echo "🔐 .env.local criado a partir de .env.example. APIs opcionais continuam desativadas." +else + chmod 600 .env.local 2>/dev/null || true + echo "🔐 .env.local existente preservado." +fi + node scripts/preflight-platform.mjs GIT_CONFIG_COUNT=1 \ GIT_CONFIG_KEY_0=url.https://github.com/.insteadOf \ @@ -17,4 +26,4 @@ GIT_CONFIG_VALUE_0=ssh://git@github.com/ \ npm ci --no-audit --no-fund npm run setup -echo "SHOGUN pronto. Inicie com: npm start" +echo "SHOGUN pronto. Rode 'npm run preflight' e depois 'npm start'." From 21a5edbf5bbb8e6947f54a7f6019d8e1a53f3469 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:12:57 -0300 Subject: [PATCH 30/49] Criar ambiente local no instalador Termux --- scripts/install-termux.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/install-termux.sh b/scripts/install-termux.sh index bf2c786..805bb2e 100755 --- a/scripts/install-termux.sh +++ b/scripts/install-termux.sh @@ -6,6 +6,15 @@ cd "$(dirname "$0")/.." pkg update -y pkg install -y git nodejs-lts ffmpeg termux-tools +if [ ! -f .env.local ]; then + cp .env.example .env.local + chmod 600 .env.local + echo "🔐 .env.local criado a partir de .env.example. APIs opcionais continuam desativadas." +else + chmod 600 .env.local 2>/dev/null || true + echo "🔐 .env.local existente preservado." +fi + node scripts/preflight-platform.mjs GIT_CONFIG_COUNT=1 \ @@ -18,4 +27,4 @@ npm run setup node --check dados/src/.scripts/start-v9-fixed.js node --check dados/src/connect.js -echo "SHOGUN pronto. Execute termux-wake-lock e depois npm start." +echo "SHOGUN pronto. Execute termux-wake-lock, rode 'npm run preflight' e depois 'npm start'." From 3b959d298c123c1fab4c817a7727678156d4afff Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:13:05 -0300 Subject: [PATCH 31/49] Criar ambiente local no instalador macOS --- scripts/install-macos.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/install-macos.sh b/scripts/install-macos.sh index e342894..08e9dbf 100644 --- a/scripts/install-macos.sh +++ b/scripts/install-macos.sh @@ -16,6 +16,15 @@ if [ "$missing" -ne 0 ]; then exit 1 fi +if [ ! -f .env.local ]; then + cp .env.example .env.local + chmod 600 .env.local + echo "🔐 .env.local criado a partir de .env.example. APIs opcionais continuam desativadas." +else + chmod 600 .env.local 2>/dev/null || true + echo "🔐 .env.local existente preservado." +fi + node scripts/preflight-platform.mjs GIT_CONFIG_COUNT=1 \ @@ -28,4 +37,4 @@ npm run setup node --check dados/src/.scripts/start-v9-fixed.js node --check dados/src/connect.js -echo "SHOGUN pronto. Execute npm start." +echo "SHOGUN pronto. Rode 'npm run preflight' e depois 'npm start'." From 01308df8f488b5304d70cec2c98024e59f4ea32e Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:13:15 -0300 Subject: [PATCH 32/49] Criar ambiente local no instalador Windows --- scripts/install-windows.ps1 | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/install-windows.ps1 b/scripts/install-windows.ps1 index 9c213b7..4b9a4c1 100644 --- a/scripts/install-windows.ps1 +++ b/scripts/install-windows.ps1 @@ -7,6 +7,14 @@ foreach ($command in @("git", "node", "npm", "ffmpeg")) { } } +if (-not (Test-Path ".env.local")) { + Copy-Item ".env.example" ".env.local" + Write-Host "🔐 .env.local criado a partir de .env.example. APIs opcionais continuam desativadas." -ForegroundColor Cyan +} +else { + Write-Host "🔐 .env.local existente preservado." -ForegroundColor Cyan +} + node scripts/preflight-platform.mjs $previousGitConfigCount = $env:GIT_CONFIG_COUNT @@ -25,4 +33,4 @@ finally { $env:GIT_CONFIG_VALUE_0 = $previousGitConfigValue } -Write-Host "SHOGUN pronto. Inicie com: npm start" -ForegroundColor Green +Write-Host "SHOGUN pronto. Rode 'npm run preflight' e depois 'npm start'." -ForegroundColor Green From 2fe8b95121b938a8de7025454aae76f15e60280a Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:13:51 -0300 Subject: [PATCH 33/49] =?UTF-8?q?Auditar=20configura=C3=A7=C3=A3o=20e=20in?= =?UTF-8?q?tegra=C3=A7=C3=B5es=20no=20preflight?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/preflight-platform.mjs | 140 ++++++++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 4 deletions(-) diff --git a/scripts/preflight-platform.mjs b/scripts/preflight-platform.mjs index 2ff91e4..7734740 100755 --- a/scripts/preflight-platform.mjs +++ b/scripts/preflight-platform.mjs @@ -4,6 +4,8 @@ import fs from 'fs'; import path from 'path'; import { spawnSync } from 'child_process'; +import { loadLocalEnv } from '../dados/src/.scripts/envLoader.js'; + const ROOT = path.resolve(import.meta.dirname, '..'); const MIN_NODE = [20, 19, 0]; const failures = []; @@ -32,6 +34,116 @@ function probe(label, command, args, required = true) { return false; } +function isTrue(value) { + return ['true', '1', 'yes', 'on'].includes(String(value || '').trim().toLowerCase()); +} + +function isPresent(value) { + return Boolean(String(value || '').trim()); +} + +function maskedState(value) { + return isPresent(value) ? 'configurado' : 'não configurado'; +} + +function readLocalConfig(configPath) { + if (!fs.existsSync(configPath)) return null; + try { + return JSON.parse(fs.readFileSync(configPath, 'utf8')); + } catch (error) { + failures.push(`dados/src/config.json não pôde ser lido: ${error.message}`); + return null; + } +} + +function inspectInstanceConfig(config) { + if (!config) return; + + const ownerName = String(config.nomedono || '').trim(); + const ownerNumber = String(config.numerodono || '').replace(/\D/g, ''); + const botName = String(config.nomebot || '').trim(); + const prefix = String(config.prefixo || '').trim(); + + if (!ownerName) failures.push('O nome do dono principal da instância está vazio; execute npm run setup.'); + if (!/^\d{10,15}$/.test(ownerNumber)) { + failures.push('O número do dono principal da instância deve ter 10 a 15 dígitos; execute npm run setup.'); + } + if (!botName) failures.push('O nome local do bot está vazio; execute npm run setup.'); + if (!prefix) failures.push('O prefixo de comandos está vazio; execute npm run setup.'); + + if (ownerName && /^\d{10,15}$/.test(ownerNumber) && botName && prefix) { + console.log('✅ Dono principal da instância — configurado'); + console.log('✅ Nome do bot e prefixo — configurados'); + } +} + +function inspectOptionalIntegrations() { + console.log('\n🔌 Integrações opcionais\n'); + + const modeKeys = [ + 'BUNNYFY_AI_MODE', + 'BUNNYFY_YOUTUBE_MODE', + 'BUNNYFY_IMAGES_MODE', + 'BUNNYFY_STICKERS_MODE', + 'BUNNYFY_CANVAS_MODE', + 'BUNNYFY_LOGOS_MODE', + 'BUNNYFY_GAMES_MODE', + 'BUNNYFY_IMAGE_GEN_MODE', + 'BUNNYFY_TAVERN_RENDER_MODE', + 'BUNNYFY_NEXO_RENDER_MODE' + ]; + const allowedModes = new Set(['off', 'primary', 'exclusive']); + const modes = modeKeys.map(key => [key, String(process.env[key] || 'off').trim().toLowerCase()]); + + for (const [key, value] of modes) { + if (!allowedModes.has(value)) failures.push(`${key} possui modo inválido: use off, primary ou exclusive.`); + } + + const bunnyFyEnabled = isTrue(process.env.BUNNYFY_ENABLED); + const activeModes = modes.filter(([, value]) => value !== 'off'); + const bunnyFyBaseUrl = String(process.env.BUNNYFY_BASE_URL || '').trim(); + const bunnyFyToken = String(process.env.BUNNYFY_API_TOKEN || '').trim(); + + if (!bunnyFyEnabled) { + console.log('ℹ️ BunnyFy — desativada; núcleo e fallbacks disponíveis continuam independentes'); + } else if (!activeModes.length) { + warnings.push('BUNNYFY_ENABLED está ativo, mas nenhuma capacidade BunnyFy saiu de off.'); + } else { + if (!bunnyFyBaseUrl) failures.push('BunnyFy está ativa em alguma capacidade, mas BUNNYFY_BASE_URL está vazio.'); + if (!bunnyFyToken) failures.push('BunnyFy está ativa em alguma capacidade, mas BUNNYFY_API_TOKEN está vazio.'); + if (bunnyFyBaseUrl && bunnyFyToken) { + console.log(`✅ BunnyFy — configurada para ${activeModes.length} capacidade(s), sem exibir credencial`); + } + } + + const aiMode = bunnyFyEnabled + ? String(process.env.BUNNYFY_AI_MODE || 'off').trim().toLowerCase() + : 'off'; + const nvidiaConfigured = isPresent(process.env.NVIDIA_API_KEY); + + if (aiMode === 'exclusive') { + console.log('ℹ️ IA — exclusiva pela BunnyFy; chave NVIDIA direta não é necessária no bot'); + } else if (nvidiaConfigured) { + console.log(`✅ NVIDIA direta — ${maskedState(process.env.NVIDIA_API_KEY)}`); + } else if (aiMode === 'primary') { + warnings.push('IA está em primary, mas NVIDIA_API_KEY não foi configurada; o fallback direto ficará indisponível.'); + } else { + warnings.push('NVIDIA_API_KEY não configurada; a assistente por NVIDIA direta ficará indisponível, sem impedir o núcleo do bot.'); + } + + const vexKey = isPresent(process.env.VEX_API_KEY); + const vexSite = isPresent(process.env.VEX_SITE); + if (vexKey && vexSite) console.log('✅ VEX legado — configurado'); + else if (vexKey || vexSite) warnings.push('VEX está parcialmente configurada; preencha VEX_API_KEY e VEX_SITE ou deixe ambos vazios.'); + else console.log('ℹ️ VEX legado — não configurado'); + + const uploadToken = isPresent(process.env.UPLOAD_GITHUB_TOKEN); + const uploadRepo = isPresent(process.env.UPLOAD_GITHUB_REPO); + if (uploadToken && uploadRepo) console.log('✅ Upload GitHub legado — configurado'); + else if (uploadToken || uploadRepo) warnings.push('Upload GitHub legado está parcialmente configurado; token e repositório precisam existir juntos.'); + else console.log('ℹ️ Upload GitHub legado — não configurado'); +} + console.log('\n⛩️ Verificação do ambiente\n'); const nodeVersion = versionTuple(process.versions.node); @@ -53,19 +165,39 @@ if (isTermux) { else warnings.push('termux-wake-lock não foi encontrado. Atualize termux-tools com: pkg install termux-tools. Não é necessário instalar Termux:API para esse comando.'); } +const envPath = path.join(ROOT, '.env.local'); +if (fs.existsSync(envPath)) { + try { + loadLocalEnv(); + console.log('✅ .env.local — carregado sem exibir valores'); + } catch (error) { + failures.push(`.env.local não pôde ser carregado: ${error.message}`); + } +} else { + warnings.push('`.env.local` ainda não existe. Copie `.env.example` para `.env.local` ou execute o instalador oficial da plataforma.'); +} + const configPath = path.join(ROOT, 'dados', 'src', 'config.json'); const modulesPath = path.join(ROOT, 'node_modules'); -if (fs.existsSync(configPath)) console.log('✅ Configuração local encontrada'); -else warnings.push('Configuração local ainda não criada; execute npm run setup.'); +const localConfig = readLocalConfig(configPath); +if (localConfig) { + console.log('✅ Configuração local encontrada'); + inspectInstanceConfig(localConfig); +} else if (!fs.existsSync(configPath)) { + warnings.push('Configuração local ainda não criada; execute npm run setup.'); +} + if (fs.existsSync(modulesPath)) console.log('✅ Dependências locais encontradas'); else warnings.push('Dependências ainda não instaladas; execute npm ci.'); +inspectOptionalIntegrations(); + for (const warning of warnings) console.log(`⚠️ ${warning}`); for (const failure of failures) console.log(`❌ ${failure}`); if (failures.length) { - console.log('\n🚫 O ambiente ainda não está pronto. Corrija os itens acima e repita npm run preflight.\n'); + console.log('\n🚫 O ambiente ainda não está pronto. Corrija os itens obrigatórios acima e repita npm run preflight.\n'); process.exit(1); } -console.log('\n🛡️ Ambiente pronto. Siga para a configuração.\n'); +console.log('\n🛡️ Ambiente base pronto. Integrações marcadas como opcionais podem ser configuradas depois.\n'); From 1573f3a2fa2657bd4666c33f9544e356ef270105 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:14:49 -0300 Subject: [PATCH 34/49] =?UTF-8?q?Explicar=20instala=C3=A7=C3=A3o,=20dono?= =?UTF-8?q?=20e=20APIs=20no=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 67 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index ec185e5..a2933d6 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@  •  Arquitetura  •  + Configuração +  •  Primeiros passos  •  Problemas @@ -38,6 +40,7 @@ O SHOGUN foi pensado para grupos que querem mais do que meia dúzia de respostas automáticas. Ele combina administração, mídia, interação entre membros, economia persistente, RPG e recursos opcionais de IA sem transformar a instalação numa peregrinação por quinze serviços obrigatórios. +- **o núcleo inicia sem chave de API**; - **funciona sem IA** e ganha recursos extras quando integrações são configuradas; - **mantém sessão e dados localmente** no aparelho onde está rodando; - **trata Termux como plataforma de verdade**, não como nota de rodapé; @@ -143,7 +146,7 @@ powershell -ExecutionPolicy Bypass -File .\scripts\install-windows.ps1 npm start ``` -A primeira execução abre o fluxo de conexão e oferece **QR Code** ou **código de pareamento**. Depois disso, a sessão é reaproveitada nas próximas inicializações. +Os instaladores preservam um `.env.local` existente ou criam um automaticamente a partir de `.env.example`, com integrações externas desligadas por padrão. A primeira execução abre o fluxo de conexão e oferece **QR Code** ou **código de pareamento**. Depois disso, a sessão é reaproveitada nas próximas inicializações. --- @@ -169,9 +172,10 @@ O bot continua responsável pelo fluxo do WhatsApp e pelo estado do grupo. Integ - - - + + + +
1. Verifique
npm run preflight
confere Node, npm, Git e FFmpeg.
2. Configure
npm run setup
define dono, nome e prefixo.
3. Conecte
npm start
abre QR ou pareamento.
1. Instale
o instalador cria o ambiente local e instala dependências.
2. Configure
npm run setup
define o dono principal desta instância, nome e prefixo.
3. Verifique
npm run preflight
confere sistema, configuração e integrações.
4. Conecte
npm start
abre QR ou pareamento.
@@ -179,18 +183,51 @@ O bot continua responsável pelo fluxo do WhatsApp e pelo estado do grupo. Integ Preflight do SHOGUN

-A configuração local fica em `dados/src/config.json`. A sessão do WhatsApp fica em `dados/database/qr-code/`. +### Quem é o dono principal? + +```text +SHOGUN (projeto e créditos) + | + +-- sua instalação clonada + | + +-- dono principal da instância <- seu numerodono + | + +-- sessão WhatsApp + | + +-- grupos + +-- admins do grupo são outra coisa +``` + +O número informado no setup controla **esta cópia do bot** e os comandos reservados ao dono. Ele não muda a autoria do projeto e não significa “dono do grupo” no WhatsApp. A explicação completa, incluindo APIs e modos BunnyFy, está em **[Configuração da sua instância](docs/configuracao-da-instancia.md)**. + +A configuração local fica em `dados/src/config.json`, as opções privadas ficam em `.env.local` e a sessão do WhatsApp fica em `dados/database/qr-code/`. > [!CAUTION] -> A pasta `dados/database/qr-code/` contém credenciais da sessão vinculada. **Não envie, compacte nem publique esse diretório.** Quem obtiver esses arquivos pode comprometer a conta conectada. +> A pasta `dados/database/qr-code/`, `.env.local` e `dados/src/config.json` pertencem à sua instalação. **Não envie, compacte nem publique esses arquivos.** A sessão contém material de autenticação e os outros arquivos podem conter dados privados ou credenciais. + +--- + +## 🔑 APIs sem adivinhação + +Você **não precisa cadastrar uma pilha de chaves para chegar ao primeiro `!menu`**. + +| Situação | O que configurar | +| --- | --- | +| só quero instalar e usar o núcleo | setup + WhatsApp; nenhuma chave de API | +| quero BunnyFy | URL + credencial de consumidor BunnyFy e os modos desejados | +| quero IA NVIDIA direta | `NVIDIA_API_KEY` | +| quero IA exclusivamente pela BunnyFy | BunnyFy ativa + `BUNNYFY_AI_MODE=exclusive`; sem chave NVIDIA no bot | +| quero fallback VEX legado | `VEX_API_KEY` + `VEX_SITE` | + +O arquivo **[docs/configuracao-da-instancia.md](docs/configuracao-da-instancia.md)** contém a matriz completa e exemplos seguros. O `npm run preflight` mostra o que está configurado sem revelar valores. --- ## ⚙ Operação do dia a dia ```bash -npm run preflight # diagnóstico do ambiente -npm run setup # configuração inicial +npm run preflight # diagnóstico do ambiente e da configuração +npm run setup # configuração do dono/nome/prefixo npm start # iniciar ``` @@ -236,6 +273,18 @@ Requisito mínimo: **Node.js 20.19+**, npm, Git e FFmpeg. É fortemente recomendado. O SHOGUN funciona como aparelho vinculado à conta conectada. +
+O que significa “dono” no setup? +
+É o dono principal desta instalação: o número autorizado a usar comandos reservados ao dono. Não é o autor do projeto e não é automaticamente o administrador de todos os grupos. Veja Configuração da sua instância. +
+ +
+Preciso de chave de API para iniciar? +
+Não. O núcleo inicia sem chave de API. BunnyFy, NVIDIA, VEX e outras integrações são configuradas conforme os recursos que você quiser ativar. +
+
Preciso deixar o aparelho ligado?
@@ -258,7 +307,7 @@ Use o guia da sua plataforma. Ele acompanha os scripts existentes no repositóri ## Documentação -**[Primeiros passos](docs/primeiros-passos.md)** · **[Segurança](docs/seguranca.md)** · **[Solução de problemas](docs/solucao-de-problemas.md)** · **[Termux](docs/instalacao/termux.md)** · **[Windows](docs/instalacao/windows.md)** · **[Linux](docs/instalacao/linux.md)** · **[macOS](docs/instalacao/macos.md)** +**[Configuração da instância](docs/configuracao-da-instancia.md)** · **[Primeiros passos](docs/primeiros-passos.md)** · **[Segurança](docs/seguranca.md)** · **[Solução de problemas](docs/solucao-de-problemas.md)** · **[Termux](docs/instalacao/termux.md)** · **[Windows](docs/instalacao/windows.md)** · **[Linux](docs/instalacao/linux.md)** · **[macOS](docs/instalacao/macos.md)** ## Licença e créditos From 40c77ec3afee0d79035576bd4709d29ec1aad51f Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:15:07 -0300 Subject: [PATCH 35/49] =?UTF-8?q?Alinhar=20primeiros=20passos=20ao=20onboa?= =?UTF-8?q?rding=20da=20inst=C3=A2ncia?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/primeiros-passos.md | 53 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/docs/primeiros-passos.md b/docs/primeiros-passos.md index 98d29b4..5fce5a5 100644 --- a/docs/primeiros-passos.md +++ b/docs/primeiros-passos.md @@ -1,5 +1,25 @@ # Primeiros passos com o SHOGUN +## Antes de tudo: esta instalação é sua instância + +Ao executar o setup, o número salvo em `numerodono` vira o **dono principal +desta instância** do SHOGUN. É esse número que recebe privilégios reservados ao +dono do bot. + +Isso não altera a autoria do projeto e também não é a mesma coisa que ser +administrador de um grupo do WhatsApp. + +```text +projeto SHOGUN + └── sua instalação + ├── dono principal -> numerodono + ├── sessão WhatsApp + └── grupos -> administradores próprios +``` + +Leia **[Configuração da sua instância](configuracao-da-instancia.md)** para a +matriz completa de APIs e credenciais opcionais. + ## A inspeção Dentro da pasta do projeto: @@ -8,7 +28,12 @@ Dentro da pasta do projeto: npm run preflight ``` -Todos os itens obrigatórios devem aparecer com `✅`. +Todos os itens obrigatórios devem aparecer com `✅`. Avisos sobre NVIDIA, VEX, +BunnyFy ou outras integrações opcionais não impedem o núcleo de iniciar quando +esses recursos não estão sendo usados. + +O preflight também verifica `.env.local` e a configuração da instância sem +imprimir tokens ou chaves. ## A configuração @@ -16,7 +41,12 @@ Todos os itens obrigatórios devem aparecer com `✅`. npm run setup ``` -Informe seu nome, número com país e DDD, nome do bot e prefixo. Para manter um valor existente, apenas pressione Enter. +Informe seu nome, número com país e DDD, nome do bot e prefixo. Para manter um +valor existente, apenas pressione Enter. + +O setup grava `dados/src/config.json`. Os instaladores oficiais também criam +`.env.local` a partir de `.env.example` quando necessário, mantendo APIs +opcionais desligadas por padrão. ## A conexão @@ -24,7 +54,8 @@ Informe seu nome, número com país e DDD, nome do bot e prefixo. Para manter um npm start ``` -Escolha QR ou código de pareamento. A sessão fica local e será reutilizada no próximo início. +Escolha QR ou código de pareamento. A sessão fica local e será reutilizada no +próximo início. ## A primeira missão @@ -34,11 +65,23 @@ Envie: !menu ``` -Depois teste uma ferramenta simples, uma figurinha e um comando de grupo sem efeito destrutivo. Só dê cargo de administrador quando entender quais rotinas serão usadas. +Depois teste uma ferramenta simples, uma figurinha e um comando de grupo sem +efeito destrutivo. Só dê cargo de administrador quando entender quais rotinas +serão usadas. + +## APIs vêm depois do primeiro boot + +Você não precisa configurar BunnyFy, NVIDIA, VEX ou upload externo para provar +que o núcleo instalou corretamente. Primeiro confirme `!menu`; depois ative +somente as integrações que realmente quiser usar. + +Consulte **[Configuração da sua instância](configuracao-da-instancia.md)** para +saber exatamente qual variável pertence a cada capacidade. ## A rotina - `Ctrl+C` encerra com segurança; - `npm start` retoma a patrulha; -- `npm run setup` altera a configuração; +- `npm run setup` altera dono, nome e prefixo; +- `npm run preflight` diagnostica sistema, configuração e integrações; - `git pull --ff-only` e `npm ci` atualizam o código e as dependências. From a4a5aa37c66e2ce055790889c8cba1b3b6761145 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:15:34 -0300 Subject: [PATCH 36/49] =?UTF-8?q?Explicar=20dono=20e=20configura=C3=A7?= =?UTF-8?q?=C3=A3o=20no=20guia=20Windows?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/instalacao/windows.md | 64 +++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/docs/instalacao/windows.md b/docs/instalacao/windows.md index 1ed55a2..ed598fc 100644 --- a/docs/instalacao/windows.md +++ b/docs/instalacao/windows.md @@ -95,21 +95,40 @@ Set-Location "$HOME\shogun" powershell -ExecutionPolicy Bypass -File .\scripts\install-windows.ps1 ``` -O instalador verifica o ambiente, instala as dependências travadas pelo projeto e abre o setup. +O instalador verifica o ambiente, cria `.env.local` a partir de `.env.example` +se ele ainda não existir, instala as dependências travadas pelo projeto e abre +o setup. Integrações externas ficam desligadas por padrão. - - + +
Seu nomeidentificação local do dono
Númeropaís + DDD + número, somente dígitos
Seu nomeidentificação do dono principal desta instância
Númeropaís + DDD + número do dono principal, somente dígitos
Nome do botnome desta instalação
Prefixopor exemplo !
+### O que “dono” significa aqui + +```text +projeto SHOGUN + └── sua instalação no Windows + ├── dono principal -> número informado no setup + ├── sessão WhatsApp + └── grupos -> administradores próprios +``` + +O número configurado é o **dono principal desta cópia do bot** e recebe os +privilégios reservados ao dono. Isso não muda a autoria do projeto e não é a +mesma coisa que ser administrador de um grupo do WhatsApp. + Para refazer apenas essa configuração depois: ```powershell npm run setup ``` +Para entender BunnyFy, NVIDIA, VEX e quais chaves são opcionais, consulte +**[Configuração da sua instância](../configuracao-da-instancia.md)**. + --- ## 5 · Faça a inspeção antes do boot @@ -122,7 +141,13 @@ npm run preflight Preflight do SHOGUN no Windows

-O preflight verifica Node.js, npm, Git, FFmpeg e os arquivos locais necessários para iniciar. +O preflight verifica Node.js, npm, Git, FFmpeg, arquivos locais, dono principal +e o estado das integrações sem imprimir tokens. Avisos sobre APIs opcionais não +impedem o núcleo de iniciar quando esses recursos não estão sendo usados. + +> [!NOTE] +> Você não precisa de uma chave de API para chegar ao primeiro `!menu`. Configure +> integrações externas depois que o núcleo estiver funcionando. --- @@ -159,6 +184,23 @@ Se escolheu outro prefixo, use-o no lugar de `!`. --- +## APIs opcionais + +Depois que `!menu` estiver funcionando, abra `.env.local` somente se quiser +ativar recursos externos. A matriz atual está em +**[Configuração da sua instância](../configuracao-da-instancia.md)**. + +Resumo: + +- núcleo + WhatsApp: sem chave de API; +- BunnyFy: URL + credencial de consumidor quando ativada; +- NVIDIA direta: `NVIDIA_API_KEY` apenas para IA direta/fallback; +- VEX: `VEX_API_KEY` + `VEX_SITE` apenas no fallback legado correspondente. + +Nunca coloque chaves internas de providers da BunnyFy no bot. + +--- + ## Uso diário ### Parar @@ -212,12 +254,20 @@ Entre nela com Set-Location "$HOME\shogun". Não clone outra cópia --- -## 🔐 Proteja a sessão +## 🔐 Proteja a instalação + +Arquivos privados importantes: -A sessão vinculada fica em `dados/database/qr-code/`. +```text +.env.local +dados/src/config.json +dados/database/qr-code/ +``` > [!CAUTION] -> Não envie essa pasta para suporte, GitHub, Drive ou outras pessoas. Ela contém material de autenticação da conta conectada. +> Não envie esses arquivos para suporte, GitHub, Drive ou outras pessoas. A +> sessão contém material de autenticação e os demais podem conter configuração +> privada ou credenciais. Para diagnóstico adicional, execute `npm run preflight` e consulte **[Solução de problemas](../solucao-de-problemas.md)**. From 7f7ff599752678b62ae940b9e404d2748d302eba Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:15:56 -0300 Subject: [PATCH 37/49] =?UTF-8?q?Explicar=20dono=20e=20configura=C3=A7?= =?UTF-8?q?=C3=A3o=20no=20guia=20Linux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/instalacao/linux.md | 52 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/docs/instalacao/linux.md b/docs/instalacao/linux.md index 9ac1a5a..e991672 100644 --- a/docs/instalacao/linux.md +++ b/docs/instalacao/linux.md @@ -92,21 +92,40 @@ O caminho deve terminar em `/shogun`. bash scripts/install-linux.sh ``` -O instalador executa o preflight, instala as dependências travadas em `package-lock.json` e abre a configuração inicial. +O instalador cria `.env.local` a partir de `.env.example` quando necessário, +executa o preflight, instala as dependências travadas em `package-lock.json` e +abre a configuração inicial. Um `.env.local` que já exista é preservado. - - + +
Seu nomeidentificação local do dono
Númeropaís + DDD + número, somente dígitos
Seu nomeidentificação do dono principal desta instância
Númeropaís + DDD + número do dono principal, somente dígitos
Nome do botnome desta instalação
Prefixopor exemplo !
+### O dono desta instalação + +```text +projeto SHOGUN + └── sua instalação Linux + ├── dono principal -> numerodono + ├── sessão WhatsApp + └── grupos -> administradores próprios +``` + +`numerodono` identifica quem controla **esta instância** e pode usar comandos de +dono. Não altera a autoria do projeto e não transforma esse número no +administrador de todos os grupos. + Para refazer apenas o setup depois: ```bash npm run setup ``` +A matriz de BunnyFy, NVIDIA, VEX e demais opções está em +**[Configuração da sua instância](../configuracao-da-instancia.md)**. + --- ## 5 · Verifique antes de iniciar @@ -119,7 +138,13 @@ npm run preflight Preflight do SHOGUN no Linux

-O comando verifica Node.js, npm, Git, FFmpeg, configuração e dependências locais. +O comando verifica Node.js, npm, Git, FFmpeg, configuração, dono principal, +dependências e o estado das integrações sem revelar tokens. + +> [!NOTE] +> O núcleo não precisa de chave de API para chegar ao primeiro `!menu`. Avisos +> sobre integrações opcionais só significam que aquele recurso específico ainda +> não foi configurado. --- @@ -155,6 +180,21 @@ Se escolheu outro prefixo, substitua `!`. --- +## APIs opcionais + +Depois do primeiro `!menu`, edite `.env.local` apenas se quiser capacidades +externas. Resumo: + +- núcleo + WhatsApp: sem chave de API; +- BunnyFy: `BUNNYFY_ENABLED=true`, URL e credencial de consumidor; +- NVIDIA direta: `NVIDIA_API_KEY` para IA direta ou fallback; +- VEX legado: `VEX_API_KEY` + `VEX_SITE` somente quando esse fallback for usado. + +Veja **[Configuração da sua instância](../configuracao-da-instancia.md)** antes +de ativar modos `primary` ou `exclusive`. + +--- + ## Uso diário ### Parar @@ -224,7 +264,9 @@ dados/src/config.json ``` > [!CAUTION] -> Nunca publique a pasta de sessão. Ela contém material de autenticação do WhatsApp vinculado. +> Nunca publique esses arquivos. A sessão contém material de autenticação do +> WhatsApp e os arquivos de configuração podem conter informações privadas ou +> credenciais. Para diagnóstico adicional, rode `npm run preflight` e consulte **[Solução de problemas](../solucao-de-problemas.md)**. From 296c33b07eeb624c7c117007acfd2fc05ae652e9 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:16:19 -0300 Subject: [PATCH 38/49] =?UTF-8?q?Explicar=20dono=20e=20configura=C3=A7?= =?UTF-8?q?=C3=A3o=20no=20guia=20Termux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/instalacao/termux.md | 73 +++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/docs/instalacao/termux.md b/docs/instalacao/termux.md index add5b3c..1c49575 100644 --- a/docs/instalacao/termux.md +++ b/docs/instalacao/termux.md @@ -83,21 +83,41 @@ O instalador do repositório faz a parte tediosa em ordem previsível: 1. atualiza o índice do Termux; 2. instala **Git, Node.js LTS, FFmpeg e termux-tools**; -3. executa o preflight da plataforma; -4. instala as dependências travadas em `package-lock.json` com `npm ci`; -5. abre a configuração inicial. +3. cria `.env.local` a partir de `.env.example` se ainda não existir; +4. executa o preflight da plataforma; +5. instala as dependências travadas em `package-lock.json` com `npm ci`; +6. abre a configuração inicial. + +Um `.env.local` existente é preservado. APIs opcionais começam desligadas. ### O setup pergunta - - + +
Seu nomecomo o bot identifica o dono
Seu númeropaís + DDD + número, somente dígitos
Seu nomecomo o bot identifica o dono principal desta instância
Seu númeropaís + DDD + número do dono principal, somente dígitos
Nome do boto nome exibido pela instalação
Prefixopor exemplo !
A configuração é gravada localmente em `dados/src/config.json`. +### Quem é o dono principal? + +```text +projeto SHOGUN + └── sua instalação no Android + ├── dono principal -> numerodono + ├── sessão WhatsApp + └── grupos -> administradores próprios +``` + +O número do setup controla **esta cópia do bot** e seus comandos de dono. Isso +não muda os créditos/autoria do projeto e não é a mesma coisa que ser +administrador de um grupo. + +Veja **[Configuração da sua instância](../configuracao-da-instancia.md)** para +entender APIs e credenciais antes de preencher qualquer chave. + --- ## 5 · Impeça o Android de dormir em cima do bot @@ -119,7 +139,19 @@ Também retire o Termux da otimização agressiva de bateria do fabricante. Andr --- -## 6 · Inicie e conecte +## 6 · Verifique e conecte + +Antes do boot: + +```bash +npm run preflight +``` + +O diagnóstico verifica sistema, configuração, dono principal e integrações sem +imprimir tokens. Avisos sobre APIs opcionais não impedem o núcleo quando você +não usa aqueles recursos. + +Depois: ```bash npm start @@ -168,6 +200,22 @@ Se escolheu outro prefixo, troque `!` por ele. --- +## APIs opcionais + +Você não precisa de uma chave de API para chegar ao primeiro `!menu`. + +Depois que o núcleo estiver funcionando, edite `.env.local` somente para os +recursos que quiser ativar: + +- BunnyFy: URL + credencial de consumidor; +- NVIDIA direta: `NVIDIA_API_KEY`; +- VEX legado: `VEX_API_KEY` + `VEX_SITE`. + +A matriz completa e os modos `off`, `primary` e `exclusive` estão em +**[Configuração da sua instância](../configuracao-da-instancia.md)**. + +--- + ## Da próxima vez ```bash @@ -199,7 +247,8 @@ cd ~/shogun npm run preflight ``` -O preflight verifica **Node.js, npm, Git, FFmpeg, Termux, configuração e dependências locais**. +O preflight verifica **Node.js, npm, Git, FFmpeg, Termux, configuração, dono da +instância, dependências locais e estado das integrações opcionais**.
Node.js está abaixo de 20.19 @@ -248,18 +297,22 @@ npm run setup ## 🔐 A parte que você não deve mandar para ninguém -A sessão fica em: +Arquivos privados desta instalação: ```text +.env.local +dados/src/config.json dados/database/qr-code/ ``` > [!CAUTION] -> Esses arquivos representam acesso à sessão vinculada do WhatsApp. **Não envie a pasta, não coloque em Drive, não publique em GitHub e não cole seu conteúdo em suporte.** Só apague a sessão se realmente quiser desvincular e parear novamente. +> Esses arquivos podem representar acesso à sessão vinculada ou conter +> configuração privada. **Não envie, não coloque em Drive, não publique em +> GitHub e não cole seu conteúdo em suporte.** ## O mínimo obrigatório -**Necessário para o núcleo:** Android + Termux, Node.js 20.19+, npm, Git, FFmpeg e conexão com WhatsApp. +**Necessário para o núcleo:** Android + Termux, Node.js 20.19+, npm, Git, FFmpeg, configuração do dono e conexão com WhatsApp. **Opcional:** integrações externas, IA e capacidades que dependam de APIs específicas. A ausência delas não impede o núcleo do SHOGUN de iniciar e conectar. From 0922f8671917e1a089398aec65935220488971ad Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:16:36 -0300 Subject: [PATCH 39/49] =?UTF-8?q?Explicar=20dono=20e=20configura=C3=A7?= =?UTF-8?q?=C3=A3o=20no=20guia=20macOS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/instalacao/macos.md | 56 +++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/docs/instalacao/macos.md b/docs/instalacao/macos.md index 0c65235..3bbcf1a 100644 --- a/docs/instalacao/macos.md +++ b/docs/instalacao/macos.md @@ -63,15 +63,35 @@ Se a pasta já existir, use `cd ~/shogun` em vez de clonar novamente. bash scripts/install-macos.sh ``` -O script executa o preflight, instala as dependências travadas pelo `package-lock.json`, abre o setup e verifica as entradas principais do runtime. +O script cria `.env.local` a partir de `.env.example` se necessário, executa o +preflight, instala as dependências travadas pelo `package-lock.json`, abre o +setup e verifica as entradas principais do runtime. Um `.env.local` existente +é preservado. - - + +
Seu nomeidentificação local do dono
Númeropaís + DDD + número, somente dígitos
Seu nomeidentificação do dono principal desta instância
Númeropaís + DDD + número do dono principal, somente dígitos
Nome do botnome desta instalação
Prefixopor exemplo !
+### Quem é o dono principal? + +```text +projeto SHOGUN + └── sua instalação no macOS + ├── dono principal -> numerodono + ├── sessão WhatsApp + └── grupos -> administradores próprios +``` + +O número salvo pelo setup controla **esta instância** e seus comandos de dono. +Ele não altera a autoria do projeto e não é a mesma coisa que ser administrador +de um grupo. + +Veja **[Configuração da sua instância](../configuracao-da-instancia.md)** para a +matriz de integrações e credenciais opcionais. + --- ## 4 · Faça o preflight @@ -80,7 +100,12 @@ O script executa o preflight, instala as dependências travadas pelo `package-lo npm run preflight ``` -Esse comando confere os requisitos antes de você descobrir um deles faltando no meio do boot, que é o método clássico e menos divertido. +Esse comando confere os requisitos, a configuração do dono e o estado das +integrações sem mostrar tokens. Avisos sobre APIs opcionais não impedem o núcleo +quando esses recursos não estão sendo usados. + +> [!NOTE] +> Nenhuma chave de API é necessária apenas para chegar ao primeiro `!menu`. --- @@ -112,6 +137,19 @@ Se escolheu outro prefixo, use-o no lugar de `!`. --- +## APIs opcionais + +Depois de confirmar o núcleo, edite `.env.local` apenas para os recursos que +quiser ativar: + +- BunnyFy: URL + credencial de consumidor e modos desejados; +- NVIDIA direta: `NVIDIA_API_KEY` para IA direta/fallback; +- VEX legado: `VEX_API_KEY` + `VEX_SITE` somente quando usado. + +Detalhes: **[Configuração da sua instância](../configuracao-da-instancia.md)**. + +--- + ## Uso diário ### Iniciar novamente @@ -140,16 +178,20 @@ npm run preflight --- -## 🔐 Sessão do WhatsApp +## 🔐 Proteja a instalação -A sessão vinculada fica em: +Arquivos privados: ```text +.env.local +dados/src/config.json dados/database/qr-code/ ``` > [!CAUTION] -> Não publique, envie ou compartilhe essa pasta. Ela contém material de autenticação da conta conectada. +> Não publique, envie ou compartilhe esses arquivos. A sessão contém material +> de autenticação da conta conectada e as configurações podem conter dados +> privados ou credenciais. Para problemas adicionais, consulte **[Solução de problemas](../solucao-de-problemas.md)**. From 2bd8b07df8f8a4da46c023bb30558d32295b4d97 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:17:12 -0300 Subject: [PATCH 40/49] =?UTF-8?q?Manter=20integra=C3=A7=C3=B5es=20legadas?= =?UTF-8?q?=20realmente=20opt-in?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 379103a..5be742c 100644 --- a/.env.example +++ b/.env.example @@ -65,4 +65,4 @@ VEX_SITE= # Não é requisito geral do SHOGUN. Use apenas nos fluxos que ainda dependam # desse mecanismo e crie um token dedicado com o menor escopo possível. UPLOAD_GITHUB_TOKEN= -UPLOAD_GITHUB_REPO=uploadsnew/uploads +UPLOAD_GITHUB_REPO= From 019cd272674805a72e05af7fda2f2cce00943e2d Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:17:38 -0300 Subject: [PATCH 41/49] =?UTF-8?q?Tratar=20integra=C3=A7=C3=B5es=20ausentes?= =?UTF-8?q?=20como=20opcionais=20no=20preflight?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/preflight-platform.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/preflight-platform.mjs b/scripts/preflight-platform.mjs index 7734740..ea89f2a 100755 --- a/scripts/preflight-platform.mjs +++ b/scripts/preflight-platform.mjs @@ -128,7 +128,7 @@ function inspectOptionalIntegrations() { } else if (aiMode === 'primary') { warnings.push('IA está em primary, mas NVIDIA_API_KEY não foi configurada; o fallback direto ficará indisponível.'); } else { - warnings.push('NVIDIA_API_KEY não configurada; a assistente por NVIDIA direta ficará indisponível, sem impedir o núcleo do bot.'); + console.log('ℹ️ NVIDIA direta — não configurada; recurso opcional'); } const vexKey = isPresent(process.env.VEX_API_KEY); @@ -148,7 +148,7 @@ console.log('\n⛩️ Verificação do ambiente\n'); const nodeVersion = versionTuple(process.versions.node); if (atLeast(nodeVersion, MIN_NODE)) console.log(`✅ Node.js — v${process.versions.node}`); -else failures.push(`Node.js ${MIN_NODE.join('.')} ou superior é necessário; atual: ${process.versions.node}`); +else failures.push(`Node.js ${MIN_NODE.join('.')} ou superior é necessário; atual: v${process.versions.node}`); probe('npm', process.platform === 'win32' ? 'npm.cmd' : 'npm', ['--version']); probe('Git', 'git', ['--version']); From 0ff43ba93bf20cb06633b3a038f8d2ce8d0d480d Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:19:35 -0300 Subject: [PATCH 42/49] =?UTF-8?q?Adicionar=20trava=20de=20drift=20da=20con?= =?UTF-8?q?figura=C3=A7=C3=A3o=20p=C3=BAblica?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/validate-instance-config-contract.mjs | 216 ++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 scripts/validate-instance-config-contract.mjs diff --git a/scripts/validate-instance-config-contract.mjs b/scripts/validate-instance-config-contract.mjs new file mode 100644 index 0000000..ed7900a --- /dev/null +++ b/scripts/validate-instance-config-contract.mjs @@ -0,0 +1,216 @@ +#!/usr/bin/env node + +import fs from 'node:fs'; +import path from 'node:path'; + +const ROOT = path.resolve(import.meta.dirname, '..'); +const failures = []; +const notes = []; + +const SOURCE_ROOTS = [ + path.join(ROOT, 'dados', 'src'), + path.join(ROOT, 'src'), + path.join(ROOT, 'scripts') +]; + +const SKIP_DIRS = new Set([ + '.git', + 'node_modules', + 'dist', + 'dist-vnext', + 'coverage', + 'dados/database' +]); + +const USER_CONFIG_KEY = /^(?:BUNNYFY_|NVIDIA_|VEX_|UPLOAD_GITHUB_|SHOGUN_|BOT_NAME$|DEFAULT_PERSONA$)/; +const SECRET_LIKE = /(?:KEY|TOKEN|SECRET|PASSWORD|COOKIE)/; +const ALLOWED_MODES = new Set(['off', 'primary', 'exclusive']); + +function read(file) { + return fs.readFileSync(path.join(ROOT, file), 'utf8'); +} + +function walk(dir, output = []) { + if (!fs.existsSync(dir)) return output; + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const full = path.join(dir, entry.name); + const relative = path.relative(ROOT, full).replaceAll(path.sep, '/'); + if (entry.isDirectory()) { + if (SKIP_DIRS.has(entry.name) || SKIP_DIRS.has(relative)) continue; + walk(full, output); + continue; + } + if (/\.(?:[cm]?js|ts)$/.test(entry.name)) output.push(full); + } + return output; +} + +function parseEnvExample() { + const env = new Map(); + for (const rawLine of read('.env.example').split(/\r?\n/)) { + const line = rawLine.trim(); + if (!line || line.startsWith('#')) continue; + const match = line.match(/^([A-Z][A-Z0-9_]*)=(.*)$/); + if (!match) { + failures.push(`Linha inválida em .env.example: ${rawLine}`); + continue; + } + if (env.has(match[1])) failures.push(`Chave duplicada em .env.example: ${match[1]}`); + env.set(match[1], match[2]); + } + return env; +} + +function collectRuntimeKeys() { + const keys = new Map(); + const patterns = [ + /process\.env\.([A-Z][A-Z0-9_]*)/g, + /process\.env\[['"]([A-Z][A-Z0-9_]*)['"]\]/g, + /\benv\.([A-Z][A-Z0-9_]*)/g, + /['"]((?:BUNNYFY|NVIDIA|VEX|UPLOAD_GITHUB|SHOGUN)_[A-Z0-9_]+)['"]/g + ]; + + for (const file of walk(ROOT)) { + const relative = path.relative(ROOT, file).replaceAll(path.sep, '/'); + const content = fs.readFileSync(file, 'utf8'); + for (const pattern of patterns) { + pattern.lastIndex = 0; + let match; + while ((match = pattern.exec(content)) !== null) { + const key = match[1]; + if (!USER_CONFIG_KEY.test(key)) continue; + if (!keys.has(key)) keys.set(key, new Set()); + keys.get(key).add(relative); + } + } + } + return keys; +} + +function requireEnvKey(env, key) { + if (!env.has(key)) failures.push(`.env.example não documenta ${key}.`); +} + +function expectValue(env, key, expected) { + requireEnvKey(env, key); + if (env.has(key) && env.get(key) !== expected) { + failures.push(`${key} deve iniciar como ${JSON.stringify(expected)} no exemplo público.`); + } +} + +function validateSecretsAreBlank(env) { + for (const [key, value] of env.entries()) { + if (!SECRET_LIKE.test(key)) continue; + if (value.trim()) failures.push(`${key} parece segredo e deve ficar vazio em .env.example.`); + } +} + +function validateModes(env) { + for (const [key, value] of env.entries()) { + if (!key.startsWith('BUNNYFY_') || !key.endsWith('_MODE')) continue; + if (!ALLOWED_MODES.has(value)) { + failures.push(`${key} deve usar um modo seguro conhecido no exemplo: off, primary ou exclusive.`); + } + if (value !== 'off') failures.push(`${key} deve começar em off na distribuição pública.`); + } +} + +function validateInstaller(file) { + const content = read(file); + if (!content.includes('.env.example') || !content.includes('.env.local')) { + failures.push(`${file} não garante/explica o bootstrap de .env.local.`); + } + if (!content.includes('npm run setup')) failures.push(`${file} não executa npm run setup.`); +} + +function validateGuide(file) { + const content = read(file); + if (!content.includes('configuracao-da-instancia.md')) { + failures.push(`${file} não aponta para o guia canônico de configuração.`); + } + if (!/dono principal/i.test(content)) failures.push(`${file} não explica o dono principal da instância.`); + if (!/nenhuma chave|sem chave de API|não precisa de uma chave/i.test(content)) { + failures.push(`${file} não deixa claro que o núcleo inicia sem chave de API.`); + } +} + +const env = parseEnvExample(); +const runtimeKeys = collectRuntimeKeys(); + +for (const [key, files] of runtimeKeys.entries()) { + if (!env.has(key)) { + failures.push(`Configuração usada pelo código não documentada: ${key} (${[...files].slice(0, 4).join(', ')}).`); + } +} + +for (const key of [ + 'BOT_NAME', + 'DEFAULT_PERSONA', + 'SHOGUN_LOW_MEMORY', + 'BUNNYFY_ENABLED', + 'BUNNYFY_BASE_URL', + 'BUNNYFY_API_TOKEN', + 'BUNNYFY_AI_MODE', + 'BUNNYFY_YOUTUBE_MODE', + 'BUNNYFY_IMAGES_MODE', + 'BUNNYFY_STICKERS_MODE', + 'BUNNYFY_CANVAS_MODE', + 'BUNNYFY_LOGOS_MODE', + 'BUNNYFY_IMAGE_GEN_MODE', + 'BUNNYFY_TAVERN_RENDER_MODE', + 'BUNNYFY_NEXO_RENDER_MODE', + 'NVIDIA_API_KEY', + 'VEX_API_KEY', + 'VEX_SITE', + 'UPLOAD_GITHUB_TOKEN', + 'UPLOAD_GITHUB_REPO' +]) requireEnvKey(env, key); + +expectValue(env, 'BUNNYFY_ENABLED', 'false'); +validateSecretsAreBlank(env); +validateModes(env); + +for (const file of [ + 'scripts/install-linux.sh', + 'scripts/install-macos.sh', + 'scripts/install-termux.sh', + 'scripts/install-windows.ps1' +]) validateInstaller(file); + +for (const file of [ + 'README.md', + 'docs/primeiros-passos.md', + 'docs/instalacao/linux.md', + 'docs/instalacao/macos.md', + 'docs/instalacao/termux.md', + 'docs/instalacao/windows.md' +]) validateGuide(file); + +const configExample = JSON.parse(read('dados/src/config.example.json')); +for (const key of ['nomedono', 'numerodono', 'nomebot', 'prefixo']) { + if (!Object.hasOwn(configExample, key)) failures.push(`config.example.json não contém ${key}.`); +} +if (configExample.numerodono !== '55DDDNUMERO') { + failures.push('config.example.json deve manter número neutro, nunca um número real de dono.'); +} + +const preflight = read('scripts/preflight-platform.mjs'); +for (const key of ['BUNNYFY_ENABLED', 'BUNNYFY_BASE_URL', 'BUNNYFY_API_TOKEN', 'NVIDIA_API_KEY', 'VEX_API_KEY', 'VEX_SITE']) { + if (!preflight.includes(key)) failures.push(`preflight não audita ${key}.`); +} +if (!preflight.includes('Dono principal da instância')) { + failures.push('preflight não valida a identidade do dono principal da instância.'); +} + +notes.push(`${runtimeKeys.size} variáveis de configuração da instância encontradas no código.`); +notes.push(`${env.size} entradas documentadas em .env.example.`); + +for (const note of notes) console.log(`ℹ️ ${note}`); +for (const failure of failures) console.error(`❌ ${failure}`); + +if (failures.length) { + console.error(`\nContrato de configuração reprovado: ${failures.length} problema(s).\n`); + process.exit(1); +} + +console.log('\n✅ Contrato de configuração da instância aprovado.\n'); From 1fadcf705c2ef5acd16eaaf2eee87b5ab7721d58 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:19:51 -0300 Subject: [PATCH 43/49] =?UTF-8?q?Executar=20contrato=20de=20configura?= =?UTF-8?q?=C3=A7=C3=A3o=20na=20CI=20p=C3=BAblica?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/shogun-validate.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/shogun-validate.yml b/.github/workflows/shogun-validate.yml index 57c6229..2202b90 100644 --- a/.github/workflows/shogun-validate.yml +++ b/.github/workflows/shogun-validate.yml @@ -33,6 +33,8 @@ jobs: run: npm ci --no-audit --no-fund - name: Inspecionar plataforma run: npm run preflight + - name: Validar contrato de configuração pública + run: node scripts/validate-instance-config-contract.mjs - name: Validar arquitetura modular run: | npm run typecheck:vnext @@ -75,6 +77,7 @@ jobs: shell: bash run: | node --check scripts/preflight-platform.mjs + node --check scripts/validate-instance-config-contract.mjs node --check dados/src/.scripts/config.js node --check dados/src/.scripts/start.js node --check dados/src/.scripts/start-v9-fixed.js @@ -112,6 +115,7 @@ jobs: grep -q 'nodejs-lts' scripts/install-termux.sh grep -q 'ffmpeg' scripts/install-termux.sh grep -q 'termux-tools' scripts/install-termux.sh + grep -q '.env.local' scripts/install-termux.sh - name: Exercitar ramificação Termux do preflight env: TERMUX_VERSION: ci From 711f5bb63d4dae6d65586e5701e2d06b728ebccc Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:21:34 -0300 Subject: [PATCH 44/49] =?UTF-8?q?Evitar=20falsos=20positivos=20na=20audito?= =?UTF-8?q?ria=20de=20configura=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/validate-instance-config-contract.mjs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/validate-instance-config-contract.mjs b/scripts/validate-instance-config-contract.mjs index ed7900a..eaf9adc 100644 --- a/scripts/validate-instance-config-contract.mjs +++ b/scripts/validate-instance-config-contract.mjs @@ -66,11 +66,11 @@ function collectRuntimeKeys() { const patterns = [ /process\.env\.([A-Z][A-Z0-9_]*)/g, /process\.env\[['"]([A-Z][A-Z0-9_]*)['"]\]/g, - /\benv\.([A-Z][A-Z0-9_]*)/g, - /['"]((?:BUNNYFY|NVIDIA|VEX|UPLOAD_GITHUB|SHOGUN)_[A-Z0-9_]+)['"]/g + /\benv\.([A-Z][A-Z0-9_]*)/g ]; + const files = SOURCE_ROOTS.flatMap(sourceRoot => walk(sourceRoot, [])); - for (const file of walk(ROOT)) { + for (const file of files) { const relative = path.relative(ROOT, file).replaceAll(path.sep, '/'); const content = fs.readFileSync(file, 'utf8'); for (const pattern of patterns) { @@ -129,7 +129,7 @@ function validateGuide(file) { failures.push(`${file} não aponta para o guia canônico de configuração.`); } if (!/dono principal/i.test(content)) failures.push(`${file} não explica o dono principal da instância.`); - if (!/nenhuma chave|sem chave de API|não precisa de uma chave/i.test(content)) { + if (!/nenhuma chave|sem chave de API|não precisa de (?:uma )?chave/i.test(content)) { failures.push(`${file} não deixa claro que o núcleo inicia sem chave de API.`); } } From 96e2affd272ccabf843b60b3fb71e397d6e6b801 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:24:22 -0300 Subject: [PATCH 45/49] =?UTF-8?q?Explicitar=20aus=C3=AAncia=20de=20chave?= =?UTF-8?q?=20obrigat=C3=B3ria=20nos=20primeiros=20passos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/primeiros-passos.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/primeiros-passos.md b/docs/primeiros-passos.md index 5fce5a5..71ad6c9 100644 --- a/docs/primeiros-passos.md +++ b/docs/primeiros-passos.md @@ -71,9 +71,10 @@ serão usadas. ## APIs vêm depois do primeiro boot -Você não precisa configurar BunnyFy, NVIDIA, VEX ou upload externo para provar -que o núcleo instalou corretamente. Primeiro confirme `!menu`; depois ative -somente as integrações que realmente quiser usar. +O núcleo do SHOGUN funciona **sem chave de API obrigatória**. Você não precisa +configurar BunnyFy, NVIDIA, VEX ou upload externo para provar que a instalação +básica está correta. Primeiro confirme `!menu`; depois ative somente as +integrações que realmente quiser usar. Consulte **[Configuração da sua instância](configuracao-da-instancia.md)** para saber exatamente qual variável pertence a cada capacidade. From 72aafbf94456a4431d126bef81a15da0265a95a1 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:25:45 -0300 Subject: [PATCH 46/49] =?UTF-8?q?Cobrir=20todos=20os=20modos=20BunnyFy=20n?= =?UTF-8?q?a=20configura=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dados/src/services/bunnyfy/runtimeConfig.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/dados/src/services/bunnyfy/runtimeConfig.js b/dados/src/services/bunnyfy/runtimeConfig.js index 7140c00..f5ff607 100644 --- a/dados/src/services/bunnyfy/runtimeConfig.js +++ b/dados/src/services/bunnyfy/runtimeConfig.js @@ -17,7 +17,15 @@ const BUNNYFY_CONFIG_KEYS = Object.freeze([ 'BUNNYFY_STICKERS_MODE', 'BUNNYFY_CANVAS_MODE', 'BUNNYFY_LOGOS_MODE', - 'BUNNYFY_GAMES_MODE' + 'BUNNYFY_GAMES_MODE', + 'BUNNYFY_IMAGE_GEN_MODE', + 'BUNNYFY_TAVERN_RENDER_MODE', + 'BUNNYFY_NEXO_RENDER_MODE', + 'BUNNYFY_TRANSCRIPTION_MODE', + 'BUNNYFY_FACEBOOK_MODE', + 'BUNNYFY_PINTEREST_MODE', + 'BUNNYFY_TIKTOK_MODE', + 'BUNNYFY_KWAI_MODE' ]); const EXTRA_ALIASES = Object.freeze({ From fd9730648317ff8a883cf65e16277f0359f11db2 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:25:55 -0300 Subject: [PATCH 47/49] =?UTF-8?q?Expor=20modos=20BunnyFy=20omitidos=20no?= =?UTF-8?q?=20ambiente=20p=C3=BAblico?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.env.example b/.env.example index 5be742c..f554fc7 100644 --- a/.env.example +++ b/.env.example @@ -34,6 +34,11 @@ BUNNYFY_YOUTUBE_MODE=off BUNNYFY_YOUTUBE_TIMEOUT_MS=190000 BUNNYFY_YOUTUBE_MAX_BYTES=52428800 BUNNYFY_YOUTUBE_MAX_CONCURRENCY=4 +BUNNYFY_TRANSCRIPTION_MODE=off +BUNNYFY_FACEBOOK_MODE=off +BUNNYFY_PINTEREST_MODE=off +BUNNYFY_TIKTOK_MODE=off +BUNNYFY_KWAI_MODE=off BUNNYFY_IMAGES_MODE=off BUNNYFY_STICKERS_MODE=off BUNNYFY_CANVAS_MODE=off From 1d9a1afe78e2a1cf9db76767ba31720c047b4065 Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:26:18 -0300 Subject: [PATCH 48/49] =?UTF-8?q?Auditar=20modos=20BunnyFy=20sociais=20e?= =?UTF-8?q?=20transcri=C3=A7=C3=A3o=20no=20preflight?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/preflight-platform.mjs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/preflight-platform.mjs b/scripts/preflight-platform.mjs index ea89f2a..1303592 100755 --- a/scripts/preflight-platform.mjs +++ b/scripts/preflight-platform.mjs @@ -83,6 +83,11 @@ function inspectOptionalIntegrations() { const modeKeys = [ 'BUNNYFY_AI_MODE', 'BUNNYFY_YOUTUBE_MODE', + 'BUNNYFY_TRANSCRIPTION_MODE', + 'BUNNYFY_FACEBOOK_MODE', + 'BUNNYFY_PINTEREST_MODE', + 'BUNNYFY_TIKTOK_MODE', + 'BUNNYFY_KWAI_MODE', 'BUNNYFY_IMAGES_MODE', 'BUNNYFY_STICKERS_MODE', 'BUNNYFY_CANVAS_MODE', From cac7a2290e659522b2fc8e5b205559d812c9fd7a Mon Sep 17 00:00:00 2001 From: Alaska_dev Date: Tue, 25 Aug 2026 15:26:48 -0300 Subject: [PATCH 49/49] =?UTF-8?q?Validar=20modos=20din=C3=A2micos=20sem=20?= =?UTF-8?q?confundir=20c=C3=B3digos=20de=20erro?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/validate-instance-config-contract.mjs | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/scripts/validate-instance-config-contract.mjs b/scripts/validate-instance-config-contract.mjs index eaf9adc..461b0da 100644 --- a/scripts/validate-instance-config-contract.mjs +++ b/scripts/validate-instance-config-contract.mjs @@ -7,10 +7,11 @@ const ROOT = path.resolve(import.meta.dirname, '..'); const failures = []; const notes = []; -const SOURCE_ROOTS = [ +// Somente código de runtime. Scripts de CI/manutenção podem usar variáveis +// operacionais que não pertencem ao contrato de configuração do usuário. +const RUNTIME_ROOTS = [ path.join(ROOT, 'dados', 'src'), - path.join(ROOT, 'src'), - path.join(ROOT, 'scripts') + path.join(ROOT, 'src') ]; const SKIP_DIRS = new Set([ @@ -66,9 +67,13 @@ function collectRuntimeKeys() { const patterns = [ /process\.env\.([A-Z][A-Z0-9_]*)/g, /process\.env\[['"]([A-Z][A-Z0-9_]*)['"]\]/g, - /\benv\.([A-Z][A-Z0-9_]*)/g + /\benv\.([A-Z][A-Z0-9_]*)/g, + // Modos são frequentemente passados dinamicamente como string para + // resolveCapabilityMode(name, env), portanto não aparecem como env.KEY. + // Restringir a *_MODE evita confundir códigos de erro BUNNYFY_*. + /['"](BUNNYFY_[A-Z0-9_]+_MODE)['"]/g ]; - const files = SOURCE_ROOTS.flatMap(sourceRoot => walk(sourceRoot, [])); + const files = RUNTIME_ROOTS.flatMap(sourceRoot => walk(sourceRoot, [])); for (const file of files) { const relative = path.relative(ROOT, file).replaceAll(path.sep, '/'); @@ -139,7 +144,7 @@ const runtimeKeys = collectRuntimeKeys(); for (const [key, files] of runtimeKeys.entries()) { if (!env.has(key)) { - failures.push(`Configuração usada pelo código não documentada: ${key} (${[...files].slice(0, 4).join(', ')}).`); + failures.push(`Configuração usada pelo runtime não documentada: ${key} (${[...files].slice(0, 4).join(', ')}).`); } } @@ -152,10 +157,16 @@ for (const key of [ 'BUNNYFY_API_TOKEN', 'BUNNYFY_AI_MODE', 'BUNNYFY_YOUTUBE_MODE', + 'BUNNYFY_TRANSCRIPTION_MODE', + 'BUNNYFY_FACEBOOK_MODE', + 'BUNNYFY_PINTEREST_MODE', + 'BUNNYFY_TIKTOK_MODE', + 'BUNNYFY_KWAI_MODE', 'BUNNYFY_IMAGES_MODE', 'BUNNYFY_STICKERS_MODE', 'BUNNYFY_CANVAS_MODE', 'BUNNYFY_LOGOS_MODE', + 'BUNNYFY_GAMES_MODE', 'BUNNYFY_IMAGE_GEN_MODE', 'BUNNYFY_TAVERN_RENDER_MODE', 'BUNNYFY_NEXO_RENDER_MODE', @@ -195,14 +206,26 @@ if (configExample.numerodono !== '55DDDNUMERO') { } const preflight = read('scripts/preflight-platform.mjs'); -for (const key of ['BUNNYFY_ENABLED', 'BUNNYFY_BASE_URL', 'BUNNYFY_API_TOKEN', 'NVIDIA_API_KEY', 'VEX_API_KEY', 'VEX_SITE']) { +for (const key of [ + 'BUNNYFY_ENABLED', + 'BUNNYFY_BASE_URL', + 'BUNNYFY_API_TOKEN', + 'BUNNYFY_TRANSCRIPTION_MODE', + 'BUNNYFY_FACEBOOK_MODE', + 'BUNNYFY_PINTEREST_MODE', + 'BUNNYFY_TIKTOK_MODE', + 'BUNNYFY_KWAI_MODE', + 'NVIDIA_API_KEY', + 'VEX_API_KEY', + 'VEX_SITE' +]) { if (!preflight.includes(key)) failures.push(`preflight não audita ${key}.`); } if (!preflight.includes('Dono principal da instância')) { failures.push('preflight não valida a identidade do dono principal da instância.'); } -notes.push(`${runtimeKeys.size} variáveis de configuração da instância encontradas no código.`); +notes.push(`${runtimeKeys.size} variáveis/modos de configuração da instância encontrados no runtime.`); notes.push(`${env.size} entradas documentadas em .env.example.`); for (const note of notes) console.log(`ℹ️ ${note}`);