From 0d3e8fd5325156d172e2837529e552fce2ada0ec Mon Sep 17 00:00:00 2001 From: KillovSky <55511420+KillovSky@users.noreply.github.com> Date: Sat, 14 Dec 2024 14:26:48 -0300 Subject: [PATCH] =?UTF-8?q?Egg=20PR=C3=89-Release=2014/12/24=20[BETA]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Melhorias que trabalhei ao longo desse tempo, não crie expectativas, estou ocupado com outros projetos e trabalhos, então não há muito feito. Corrige o comando everyone e ajusta diversos scripts e funções. Changelog detalhada vai vir quando essa branch for mergeada na main. --- docker/dockerfile => dockerfile | 0 lib/Commands/Default/index.js | 2 +- lib/Commands/Everyone/index.js | 138 +- lib/Commands/Handlers/utils.json | 3 +- lib/Commands/Main/Construct/index.js | 19 +- lib/Databases/Configurations/config.json | 4 + lib/Functions/Verifiers/Antilinks/index.js | 2 +- lib/Scripts/{ => APPs}/jsonexplorer.py | 0 lib/Scripts/{ => Launcher}/Toolbox.bat | 0 lib/Scripts/{ => Launcher}/Toolbox.cmd | 0 lib/Scripts/{ => Launcher}/Toolbox.go | 0 lib/Scripts/{ => Launcher}/Toolbox.lua | 0 lib/Scripts/Launcher/Toolbox.ps1 | 145 ++ lib/Scripts/Launcher/Toolbox.py | 97 ++ lib/Scripts/Launcher/Toolbox.rb | 57 + lib/Scripts/{ => Launcher}/Toolbox.sh | 36 +- lib/Scripts/{ => Launcher}/Toolbox.vbs | 46 +- lib/Scripts/{ => Options}/Custom.sh | 0 lib/Scripts/{ => Options}/Disconnect.sh | 0 lib/Scripts/{ => Options}/FixDatabase.js | 0 lib/Scripts/{ => Options}/MinifyIris.js | 0 lib/Scripts/{ => Options}/ModuleInstall.sh | 0 lib/Scripts/{ => Options}/ModuleUpdate.sh | 0 lib/Scripts/{ => Options}/PM2Install.sh | 0 lib/Scripts/{ => Options}/Reinstall.sh | 6 +- lib/Scripts/{ => Options}/Requirements.sh | 0 lib/Scripts/{ => Options}/Start.sh | 0 lib/Scripts/{ => Options}/Stop.sh | 0 lib/Scripts/{ => Options}/jsonEditor.sh | 6 +- lib/Scripts/{ => Options}/jsonFixer.js | 0 lib/Scripts/{ => Options}/jsoneditor.py | 0 lib/Scripts/{ => Others}/Hosts.sh | 0 lib/Scripts/{ => Others}/Menu.sh | 0 lib/Scripts/Others/Plugins.sh | 1252 +++++++++++++++++ lib/Scripts/Toolbox.exe | Bin 5120 -> 0 bytes lib/Scripts/Toolbox.jar | Bin 2034 -> 0 bytes lib/Scripts/Toolbox.ps1 | 40 - lib/Scripts/Toolbox.py | 49 - lib/Scripts/Toolbox.rb | 52 - lib/Wiki/Docker/README.md | 1 + .../Docker}/docker-compose-swarm.example.yml | 0 .../Wiki/Docker}/docker-compose.example.yml | 0 lib/Wiki/Homepage/{ => Original}/homepage.js | 0 lib/Wiki/Homepage/homepage.min.js | 1 + lib/Wiki/Homepage/index.html | 2 +- package.json | 5 +- 46 files changed, 1695 insertions(+), 268 deletions(-) rename docker/dockerfile => dockerfile (100%) rename lib/Scripts/{ => APPs}/jsonexplorer.py (100%) rename lib/Scripts/{ => Launcher}/Toolbox.bat (100%) rename lib/Scripts/{ => Launcher}/Toolbox.cmd (100%) rename lib/Scripts/{ => Launcher}/Toolbox.go (100%) rename lib/Scripts/{ => Launcher}/Toolbox.lua (100%) create mode 100644 lib/Scripts/Launcher/Toolbox.ps1 create mode 100644 lib/Scripts/Launcher/Toolbox.py create mode 100644 lib/Scripts/Launcher/Toolbox.rb rename lib/Scripts/{ => Launcher}/Toolbox.sh (82%) rename lib/Scripts/{ => Launcher}/Toolbox.vbs (61%) rename lib/Scripts/{ => Options}/Custom.sh (100%) rename lib/Scripts/{ => Options}/Disconnect.sh (100%) rename lib/Scripts/{ => Options}/FixDatabase.js (100%) rename lib/Scripts/{ => Options}/MinifyIris.js (100%) rename lib/Scripts/{ => Options}/ModuleInstall.sh (100%) rename lib/Scripts/{ => Options}/ModuleUpdate.sh (100%) rename lib/Scripts/{ => Options}/PM2Install.sh (100%) rename lib/Scripts/{ => Options}/Reinstall.sh (97%) rename lib/Scripts/{ => Options}/Requirements.sh (100%) rename lib/Scripts/{ => Options}/Start.sh (100%) rename lib/Scripts/{ => Options}/Stop.sh (100%) rename lib/Scripts/{ => Options}/jsonEditor.sh (92%) rename lib/Scripts/{ => Options}/jsonFixer.js (100%) rename lib/Scripts/{ => Options}/jsoneditor.py (100%) rename lib/Scripts/{ => Others}/Hosts.sh (100%) rename lib/Scripts/{ => Others}/Menu.sh (100%) create mode 100644 lib/Scripts/Others/Plugins.sh delete mode 100644 lib/Scripts/Toolbox.exe delete mode 100644 lib/Scripts/Toolbox.jar delete mode 100644 lib/Scripts/Toolbox.ps1 delete mode 100644 lib/Scripts/Toolbox.py delete mode 100644 lib/Scripts/Toolbox.rb create mode 100644 lib/Wiki/Docker/README.md rename {docker => lib/Wiki/Docker}/docker-compose-swarm.example.yml (100%) rename {docker => lib/Wiki/Docker}/docker-compose.example.yml (100%) rename lib/Wiki/Homepage/{ => Original}/homepage.js (100%) create mode 100644 lib/Wiki/Homepage/homepage.min.js diff --git a/docker/dockerfile b/dockerfile similarity index 100% rename from docker/dockerfile rename to dockerfile diff --git a/lib/Commands/Default/index.js b/lib/Commands/Default/index.js index 9a61cd9..b493746 100644 --- a/lib/Commands/Default/index.js +++ b/lib/Commands/Default/index.js @@ -205,7 +205,7 @@ async function caseDefault( ...Não aparecerão no menu */ case caseChecker('menu', true, isCmd): - const menuText = Indexer('bash').bash(`bash "${irisPath}/lib/Scripts/Menu.sh" "${argl[0]}" ${JSON.stringify(Indexer('sql').languages(region, 'Helper', 'Menu', true, true, env.value).value)} "${prefix}"`).value; + const menuText = Indexer('bash').bash(`bash "${irisPath}/lib/Scripts/Others/Menu.sh" "${argl[0]}" ${JSON.stringify(Indexer('sql').languages(region, 'Helper', 'Menu', true, true, env.value).value)} "${prefix}"`).value; const menuObject = config.useBanner.value && !argl.includes('-text') ? { image: { url: `${__dirname}/Cache/Banner.png` }, caption: menuText } : { text: menuText }; envInfo.results.value = await kill.sendMessage(chatId, menuObject, reply); break; diff --git a/lib/Commands/Everyone/index.js b/lib/Commands/Everyone/index.js index 59789b7..b34e558 100644 --- a/lib/Commands/Everyone/index.js +++ b/lib/Commands/Everyone/index.js @@ -87,15 +87,15 @@ async function tagEveryone( const { reply, chatId, - quoteThis, quotedMsgObj, isOwner, isGroupMsg, + isQuotedMsg, body, prefix, + typeFormatted, functions, isAllowed, - isQuotedMsg, decryptedMedia, mimetype, groupMembersIdFormated, @@ -138,80 +138,70 @@ async function tagEveryone( /* Se dono, admin, mod ou pode rodar */ } else if (isAllowed && isGroupMsg) { /* Define a Object inicial */ - let baileysMessage = { forward: quoteThis, mentions: noEveryone }; - - /* Se não for quoted, faz o jeito mais simples, encaminhando */ - if (!isQuotedMsg) { - /* Convertendo em string, usando replace e então parse! */ - baileysMessage.forward = Indexer('others').farpc(quoteThis, replaceCmd, '').value; - baileysMessage.forward = Indexer('others').farpc(baileysMessage.forward, /--show/gi, `\n\n@${noEveryFormatted.join(' @')}`).value; - - /* Se for menção, faz o jeito dificil */ - } else if (isQuotedMsg) { - /* Delete a forward por não ser usada aqui */ - delete baileysMessage.forward; - - /* Define os dados da mensagem por meio do seu tipo */ - switch (quotedTypeFormated) { - /* Imagem */ - case 'image': - baileysMessage.image = decryptedMedia; - baileysMessage.caption = (body || quotedMsgObj.caption || insertContext).replace(replaceCmd, '').replace(/--show/gi, `\n\n@${noEveryFormatted.join(' @')}`); - baileysMessage.mimetype = mimetype; - break; + let baileysMessage = { mentions: noEveryone }; + + /* Define como buscar */ + const switchTypeFt = isQuotedMsg ? quotedTypeFormated : typeFormatted; + + /* Define os dados da mensagem por meio do seu tipo */ + switch (switchTypeFt) { + /* Imagem */ + case 'image': + baileysMessage.image = decryptedMedia; + baileysMessage.caption = (body || quotedMsgObj.caption || insertContext).replace(/--show/gi, `\n\n@${noEveryFormatted.join(' @')}`).replace(replaceCmd, ''); + baileysMessage.mimetype = mimetype; + break; /* audio */ - case 'audio': - baileysMessage.audio = decryptedMedia; - baileysMessage.mimetype = mimetype; - baileysMessage.ptt = quotedMsgObj.ptt || true; - break; - - /* contact */ - case 'contact': - case 'contactsArray': - baileysMessage.contacts = { displayName: quotedMsgObj.displayName, contacts: quotedMsgObj.contacts }; - break; - - /* Documento */ - case 'document': - case 'documentWithCaption': - baileysMessage.document = decryptedMedia; - baileysMessage.mimetype = mimetype; - baileysMessage.fileName = quotedMsgObj.fileName; - baileysMessage.caption = (body || quotedMsgObj.caption || insertContext).replace(replaceCmd, '').replace(/--show/gi, `\n\n@${noEveryFormatted.join(' @')}`); - break; - - /* Stickers */ - case 'sticker': - /* Constrói o sticker, se deixar em 100% nos videos pode travar o sticker */ - baileysMessage = await new Sticker(decryptedMedia, { - ...stickerConfig, - type: 'default', - }).toMessage(); - baileysMessage.mentions = noEveryone; - break; - - /* Localização */ - case 'location': - case 'liveLocation': - baileysMessage.location = { degreesLatitude: quotedMsgObj.degreesLatitude, degreesLongitude: quotedMsgObj.degreesLongitude }; - break; - - /* Video */ - case 'video': - baileysMessage.video = decryptedMedia; - baileysMessage.caption = (body || quotedMsgObj.caption || insertContext).replace(replaceCmd, '').replace(/--show/gi, `\n\n@${noEveryFormatted.join(' @')}`); - baileysMessage.mimetype = mimetype; - break; - - /* Conversation, URL e outros */ - default: - baileysMessage.text = body || quotedMsgObj.matchedText || quotedMsgObj.text || quotedMsgObj.caption || quotedMsgObj.conversation || quotedMsgObj; - baileysMessage.text = typeof baileysMessage.text === 'object' ? insertContext : baileysMessage.text; - baileysMessage.text = baileysMessage.text.replace(replaceCmd, '').replace(/--show/gi, `\n\n@${noEveryFormatted.join(' @')}`); - break; - } + case 'audio': + baileysMessage.audio = decryptedMedia; + baileysMessage.mimetype = mimetype; + baileysMessage.ptt = quotedMsgObj.ptt || true; + break; + + /* contact */ + case 'contact': + case 'contactsArray': + baileysMessage.contacts = { displayName: quotedMsgObj.displayName, contacts: quotedMsgObj.contacts }; + break; + + /* Documento */ + case 'document': + case 'documentWithCaption': + baileysMessage.document = decryptedMedia; + baileysMessage.mimetype = mimetype; + baileysMessage.fileName = quotedMsgObj.fileName; + baileysMessage.caption = (body || quotedMsgObj.caption || insertContext).replace(/--show/gi, `\n\n@${noEveryFormatted.join(' @')}`).replace(replaceCmd, ''); + break; + + /* Stickers */ + case 'sticker': + /* Constrói o sticker, se deixar em 100% nos videos pode travar o sticker */ + baileysMessage = await new Sticker(decryptedMedia, { + ...stickerConfig, + type: 'default', + }).toMessage(); + break; + + /* Localização */ + case 'location': + case 'liveLocation': + baileysMessage.location = { degreesLatitude: quotedMsgObj.degreesLatitude, degreesLongitude: quotedMsgObj.degreesLongitude }; + break; + + /* Video */ + case 'video': + baileysMessage.video = decryptedMedia; + baileysMessage.caption = (body || quotedMsgObj.caption || insertContext).replace(/--show/gi, `\n\n@${noEveryFormatted.join(' @')}`).replace(replaceCmd, ''); + baileysMessage.mimetype = mimetype; + break; + + /* Conversation, URL e outros */ + default: + baileysMessage.text = body || quotedMsgObj.matchedText || quotedMsgObj.text || quotedMsgObj.caption || quotedMsgObj.conversation || quotedMsgObj; + baileysMessage.text = typeof baileysMessage.text === 'object' ? insertContext : baileysMessage.text; + baileysMessage.text = baileysMessage.text.replace(/--show/gi, `\n\n@${noEveryFormatted.join(' @')}`).replace(replaceCmd, ''); + break; } /* Reencaminha a mensagem da pessoa */ diff --git a/lib/Commands/Handlers/utils.json b/lib/Commands/Handlers/utils.json index 30121be..9185e6b 100644 --- a/lib/Commands/Handlers/utils.json +++ b/lib/Commands/Handlers/utils.json @@ -34,7 +34,8 @@ "Para configurar o limite de spam, defina o valor para declarar como spam, como por exemplo: 10 mídias", "Para configurar o modo de operação da URL, defina de 1 a 3 na frente com '-set', sendo que: 1 = Tudo/All | 2 = Invite/Convites | 3 = Porno/Virus/Fakenews/Apostas", "O antifake deve ser configurado com o DDI, ou seja, se quiser banir todos os números +1, apenas digite 1 no uso do comando.", - "O antispam deve ser definido com o argumento '-ban' se quiser que a pessoa seja removida, se não for o caso, você pode ignorar o uso do '-ban' e apenas inserir o número com '-set' antes, isso é a quantidade de mídias máximas enviadas de uma vez pela pessoa." + "O antispam deve ser definido com o argumento '-ban' se quiser que a pessoa seja removida, se não for o caso, você pode ignorar o uso do '-ban' e apenas inserir o número com '-set' antes, isso é a quantidade de mídias máximas enviadas de uma vez pela pessoa.", + "Se houver múltiplas Íris no mesmo grupo, é possivel definir qual Íris será executada usando o parametro '--only' e mencionando a Íris ou digitando seu número na frente." ], "exports": { "env": "env", diff --git a/lib/Commands/Main/Construct/index.js b/lib/Commands/Main/Construct/index.js index b718c0a..4223c0b 100644 --- a/lib/Commands/Main/Construct/index.js +++ b/lib/Commands/Main/Construct/index.js @@ -13,7 +13,7 @@ const Indexer = require('../../../index'); let envInfo = JSON.parse(fs.readFileSync(`${__dirname}/utils.json`)); const commands = JSON.parse(fs.readFileSync('./lib/Databases/Configurations/definitions.json')); const levelSettings = JSON.parse(fs.readFileSync('./lib/Databases/Configurations/leveling.json')); -let arrayOfCommands = JSON.parse(Indexer('bash').bash(`bash "${irisPath}/lib/Scripts/Menu.sh" "array"`).value); +let arrayOfCommands = JSON.parse(Indexer('bash').bash(`bash "${irisPath}/lib/Scripts/Others/Menu.sh" "array"`).value); const oldLanguage = region; let conditions = false; @@ -193,6 +193,7 @@ async function dataCollect( recMessage = Indexer('others').findkey(recMessage, messageKeys, ['object', 'string'], ['contextInfo', 'quotedMessage']).value || recMessage; recMessage = Indexer('others').findkey(recMessage, messageKeys, ['object', 'string'], ['contextInfo', 'quotedMessage']).value || recMessage; recMessage = Indexer('others').findkey(recMessage, messageKeys, ['object', 'string'], ['contextInfo', 'quotedMessage']).value || recMessage; + messageData.recMessage = recMessage; /* Define se é ViewOnce */ const viewOnceObj = messageData.quoteThis.message?.viewOnceMessageV2 || messageData.quoteThis.message?.viewOnceMessage; @@ -281,10 +282,6 @@ async function dataCollect( messageData.originalName = messageData.chat?.subject || ''; messageData.name = messageData.originalName; - /* Troque a linha acima por essa abaixo, caso der erros em ASCII e demais */ - // eslint-disable-next-line no-useless-escape - /* messageData.name = messageData.originalName.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ''); */ - /* Define o número de quem enviou */ messageData.user = chatMessage?.participant || chatMessage?.remoteJid || ''; @@ -295,9 +292,15 @@ async function dataCollect( messageData.originalPushname = message?.messages[0]?.pushName || '"Censored by Government"'; messageData.pushname = messageData.originalPushname; - /* Troque a linha acima por essa abaixo, caso der erros em ASCII e demais */ - /* eslint-disable-next-line no-useless-escape */ - /* messageData.pushname = messageData.originalPushname.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ''); */ + /* Se ativarem o fixEscape, faz ajuste para o SQLite */ + if (config.fixEscape.value) { + /* Ativa o escape adicional para evitar erros */ + /* eslint-disable-next-line no-useless-escape */ + messageData.pushname = messageData.originalPushname.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ''); + + // eslint-disable-next-line no-useless-escape + messageData.name = messageData.originalName.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ''); + } /* Determina a ID do Chat */ messageData.chatId = chatMessage?.remoteJid || messageData.user || ''; diff --git a/lib/Databases/Configurations/config.json b/lib/Databases/Configurations/config.json index 53bd2fc..9766c56 100644 --- a/lib/Databases/Configurations/config.json +++ b/lib/Databases/Configurations/config.json @@ -59,6 +59,10 @@ "description": "Defines what information is logged on the screen. A value of 1 prints all information, 2 for messages only, and 3 for commands only.", "value": 1 }, + "fixEscape": { + "description": "Enable this if you encounter errors with commas or symbols in SQLite. Note that this will remove, not escape, special characters. In anycase, still very useful with Íris database errors.", + "value": false + }, "fullError": { "description": "The error log method. When set to 'true,' it prints all information, making it ideal for bug reporting. Alternatively, setting it to 'false' is suitable for experts and those who prefer concise and stylish error messages.", "value": true diff --git a/lib/Functions/Verifiers/Antilinks/index.js b/lib/Functions/Verifiers/Antilinks/index.js index a231253..84a9a3e 100644 --- a/lib/Functions/Verifiers/Antilinks/index.js +++ b/lib/Functions/Verifiers/Antilinks/index.js @@ -120,7 +120,7 @@ async function filterLinks( /* Faz um for para verificar cada link */ for (let i = 0; i < urlData.hostnames.length; i += 1) { /* Define a execução no arquivo de hosts */ - const isBadURL = Indexer('bash').bash(`bash "${path.normalize(`${irisPath}/lib/Scripts/Hosts.sh`)}" "${urlData.hostnames[i]}" "${path.normalize(`${irisPath}/lib/Databases/Utilities/hosts.txt`)}"`).value; + const isBadURL = Indexer('bash').bash(`bash "${path.normalize(`${irisPath}/lib/Scripts/Others/Hosts.sh`)}" "${urlData.hostnames[i]}" "${path.normalize(`${irisPath}/lib/Databases/Utilities/hosts.txt`)}"`).value; /* Se o link existir no arquivo de hosts */ if (/1/gi.test(isBadURL)) { diff --git a/lib/Scripts/jsonexplorer.py b/lib/Scripts/APPs/jsonexplorer.py similarity index 100% rename from lib/Scripts/jsonexplorer.py rename to lib/Scripts/APPs/jsonexplorer.py diff --git a/lib/Scripts/Toolbox.bat b/lib/Scripts/Launcher/Toolbox.bat similarity index 100% rename from lib/Scripts/Toolbox.bat rename to lib/Scripts/Launcher/Toolbox.bat diff --git a/lib/Scripts/Toolbox.cmd b/lib/Scripts/Launcher/Toolbox.cmd similarity index 100% rename from lib/Scripts/Toolbox.cmd rename to lib/Scripts/Launcher/Toolbox.cmd diff --git a/lib/Scripts/Toolbox.go b/lib/Scripts/Launcher/Toolbox.go similarity index 100% rename from lib/Scripts/Toolbox.go rename to lib/Scripts/Launcher/Toolbox.go diff --git a/lib/Scripts/Toolbox.lua b/lib/Scripts/Launcher/Toolbox.lua similarity index 100% rename from lib/Scripts/Toolbox.lua rename to lib/Scripts/Launcher/Toolbox.lua diff --git a/lib/Scripts/Launcher/Toolbox.ps1 b/lib/Scripts/Launcher/Toolbox.ps1 new file mode 100644 index 0000000..94facd5 --- /dev/null +++ b/lib/Scripts/Launcher/Toolbox.ps1 @@ -0,0 +1,145 @@ +<# +.SYNOPSIS + Script para iniciar um script shell (Toolbox.sh) usando Git Bash com modos de fallback. + +.DESCRIPTION + Este script tenta executar um script em modo normal, alternativo ou absoluto, + garantindo que os logs sejam gerados adequadamente para monitoramento e solução de problemas. + +.PARAMETER ScriptToExecute + Caminho do script a ser executado. +#> + +# Constantes de exit code +$SuccessExitCode = 0 + +# Função para exibir mensagens de log +function Write-Log { + param ( + [string]$Message, + [string]$Level = "INFO" + ) + + # Criação de um timestamp para a mensagem de log + $Timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") + $LogMessage = "[$Timestamp] [$Level] $Message" + $LogFilePath = "Toolbox.log" + + # Adiciona a mensagem ao arquivo de log + Add-Content -Path $LogFilePath -Value $LogMessage +} + +# Função para verificar e ajustar o diretório atual +function Test-CurrentDirectory { + $CurrentDir = Get-Location + $TargetDir = "\lib\Scripts\Launcher" + + # Verifica se o diretório atual é o esperado + if ($CurrentDir.Path.EndsWith($TargetDir)) { + Set-Location -Path (Resolve-Path ..\..\..) # Volta três diretórios + Write-Log "Diretório alterado para: $(Get-Location)" + } else { + Write-Log "Diretório atual está correto: $CurrentDir" + } +} + +# Função para encontrar o caminho do git.exe +function Get-GitPath { + # Obtém o caminho do git.exe + $GitPath = (Get-Command git.exe -ErrorAction SilentlyContinue).Source + + if (-not $GitPath) { + Write-Log "Falha ao encontrar git.exe." "ERROR" + return $null + } + + # Retorna o caminho do bash.exe + return $GitPath.Replace("\cmd\git.exe", "\bin\bash.exe") +} + +# Função para iniciar o script e verificar seu sucesso +function Invoke-Script { + param ( + [string]$ScriptPath, + [string]$GitPath + ) + + Write-Log "Iniciando script: $ScriptPath" + + try { + # Inicia o processo do script + $process = Start-Process -FilePath $GitPath -ArgumentList $ScriptPath -Wait -PassThru + $ExitCode = $process.ExitCode + + # Verifica o código de saída do script + if ($ExitCode -ne $SuccessExitCode) { + Write-Log "Script executado com falha. Código de saída: $ExitCode" "ERROR" + } else { + Write-Log "Script executado com sucesso." + } + + return $ExitCode + } catch { + Write-Log "Erro ao executar o script: $_" "ERROR" + return 1 + } +} + +# Função para tentar o modo alternativo +function Start-Alternative { + Write-Log "Modo normal falhou, tentando modo alternativo em 5 segundos..." + Start-Sleep -Seconds 5 + + # Executa o script no modo alternativo + $ExitCode = Invoke-Script -ScriptPath $ScriptToExecute -GitPath "bash.exe" + + if ($ExitCode -eq $SuccessExitCode) { + Write-Log "Execução bem-sucedida no modo alternativo." + exit + } else { + Start-Absolute + } +} + +# Função para tentar executar o script a partir do caminho absoluto +function Start-Absolute { + $AbsoluteScriptPath = (Get-Item $ScriptToExecute).FullName + Write-Log "Tentando executar o script a partir do caminho absoluto: $AbsoluteScriptPath" + Start-Sleep -Seconds 5 + + # Executa o script no modo absoluto + $ExitCode = Invoke-Script -ScriptPath $AbsoluteScriptPath -GitPath "bash.exe" + + if ($ExitCode -eq $SuccessExitCode) { + Write-Log "Execução bem-sucedida no modo absoluto." + exit + } else { + Write-Log "Todos os modos falharam ou finalizaram. Contate o suporte se precisar." "ERROR" + pause + } + + Write-Host 'Leia o arquivo Toolbox.log se sua execução teve erros, envie o arquivo para o suporte para ajudar a corrigir eventuais falhas.' +} + +# Execução principal do script +Test-CurrentDirectory + +# Caminho do script a ser executado +$ScriptToExecute = "./lib/Scripts/Launcher/Toolbox.sh" + +# Obtém o caminho do Git Bash +$GitPath = Get-GitPath + +if ($GitPath) { + $RunCode = Invoke-Script -ScriptPath $ScriptToExecute -GitPath $GitPath + + if ($RunCode -eq $SuccessExitCode) { + Write-Log "Execução bem-sucedida no modo normal." + exit + } else { + Start-Alternative + } +} else { + Write-Log "Caminho do git.exe não encontrado, tentando abrir o bash diretamente..." "ERROR" + Start-Alternative +} diff --git a/lib/Scripts/Launcher/Toolbox.py b/lib/Scripts/Launcher/Toolbox.py new file mode 100644 index 0000000..07bf796 --- /dev/null +++ b/lib/Scripts/Launcher/Toolbox.py @@ -0,0 +1,97 @@ +# pylint: disable=C0103 # Snake-Case Filename Disable (Execução não é afetada por isso!) +""" +Módulo para iniciar a caixa de ferramentas com base no sistema operacional. + +Este script verifica o sistema operacional e executa o script apropriado +localizado no diretório 'lib/Scripts/Launcher'. +""" + +import subprocess +import platform +import os +import logging + +# Configuração básica do logging +logging.basicConfig(level=logging.INFO, format='\n%(asctime)s - %(levelname)s - %(message)s') + +def get_script_directory() -> str: + """ + Obtém o diretório do script com base no diretório atual. + + Retorna: + str: Caminho absoluto do diretório onde o script está localizado. + """ + current_dir = os.path.abspath(".") + + # Verifica se o diretório atual contém "lib/Scripts/Launcher" + if any(os.path.join(current_dir, f) == os.path.join(current_dir, "lib", "Scripts", "Launcher") + for f in ["", "lib", "Scripts", "Launcher"]): + # Define o diretório do script como três níveis acima + return os.path.abspath(os.path.join(current_dir, "..", "..", "..")) + + logging.warning("Diretório 'lib/Scripts/Launcher' não encontrado, usando o diretório atual.") + return current_dir + +def execute_script(script_path: str): + """ + Executa o script apropriado baseado no sistema operacional. + + Args: + script_path (str): Caminho absoluto do script a ser executado. + """ + try: + logging.info("Executando o script: %s no sistema %s.", script_path, platform.system()) + + if platform.system() in ["Linux", "Darwin"]: # Linux e macOS + subprocess.run(["bash", script_path], check=True) + + elif platform.system() == "Windows": + # Executa o script apropriado para Windows + execute_windows_script(script_path) + else: + logging.error("Sistema operacional não suportado.") + + except subprocess.CalledProcessError as e: + logging.error("Erro ao executar o script: %s", e) + +def execute_windows_script(script_path: str): + """ + Executa scripts no Windows usando diferentes terminais. + + Args: + script_path (str): Caminho absoluto do script a ser executado. + """ + cmd_executables = [ + ("cmd", ["/c", script_path]), + ("powershell", [script_path]), + ("cscript", [script_path]) + ] + + for cmd, args in cmd_executables: + if os.path.exists(os.path.join(os.getenv("SystemRoot"), "System32", f"{cmd}.exe")): + subprocess.run([cmd] + args, shell=True, check=True) + return # Sai após executar um script com sucesso + + logging.error("Nenhum terminal disponível para executar o script.") + +def start_toolbox(): + """ + Inicia a caixa de ferramentas com base no sistema operacional. + """ + script_dir = get_script_directory() + + # Determina o nome do script com base no sistema operacional + script_name = { + "Linux": "Toolbox.sh", + "Darwin": "Toolbox.sh", # macOS é identificado como Darwin + "Windows": "Toolbox.cmd" + }.get(platform.system()) + + if script_name: + script_path = os.path.join(script_dir, script_name) + execute_script(script_path) + else: + logging.error("Nome de script inválido ou sistema operacional não suportado nesse script.") + +if __name__ == "__main__": + start_toolbox() diff --git a/lib/Scripts/Launcher/Toolbox.rb b/lib/Scripts/Launcher/Toolbox.rb new file mode 100644 index 0000000..7cdec5b --- /dev/null +++ b/lib/Scripts/Launcher/Toolbox.rb @@ -0,0 +1,57 @@ +# Importa os módulos necessários +require 'rbconfig' +require 'pathname' + +# Inicia a ferramenta Toolbox +def start_toolbox + # Obtém o diretório atual absoluto + current_dir = Dir.pwd + script_dir = determine_script_directory(current_dir) + + # Verifica o sistema operacional e executa o script apropriado + case RbConfig::CONFIG['host_os'] + when /mswin|msys|mingw|cygwin|bccwin|wince|emc/ + run_windows_script(script_dir) + when /darwin|mac os|linux/ + run_unix_script(script_dir) + else + puts "Sistema operacional não suportado." + end +end + +# Determina o diretório do script com base no diretório atual +def determine_script_directory(current_dir) + if current_dir.include?("/lib/Scripts/Launcher") || current_dir.include?("\\lib\\Scripts\\Launcher") + # Define o caminho do script como dois diretórios acima + File.expand_path(File.join(current_dir, "..", "..", "..")) + else + # Caso contrário, usa o diretório atual + current_dir + end +end + +# Executa o script apropriado no Windows +def run_windows_script(script_dir) + if File.exist?(File.join(ENV['SystemRoot'], "System32", "cmd.exe")) + # Executa o script usando o CMD + system("cmd /c #{File.join(script_dir, 'lib', 'Scripts', 'Launcher', 'Toolbox.cmd')}") + elsif File.exist?(File.join(ENV['SystemRoot'], "System32", "WindowsPowerShell", "v1.0", "powershell.exe")) + # Executa o script usando o PowerShell + system("powershell #{File.join(script_dir, 'lib', 'Scripts', 'Launcher', 'Toolbox.ps1')}") + elsif File.exist?(File.join(ENV['SystemRoot'], "System32", "cscript.exe")) + # Executa o script usando o CScript (VBScript) + system("cscript #{File.join(script_dir, 'lib', 'Scripts', 'Launcher', 'Toolbox.vbs')}") + else + puts "Nenhum terminal disponível para executar o script." + end +end + +# Executa o script apropriado no MacOS e Linux +def run_unix_script(script_dir) + system("bash #{File.join(script_dir, 'lib', 'Scripts', 'Launcher', 'Toolbox.sh')}") +end + +# Ponto de entrada do script +if __FILE__ == $PROGRAM_NAME + start_toolbox +end diff --git a/lib/Scripts/Toolbox.sh b/lib/Scripts/Launcher/Toolbox.sh similarity index 82% rename from lib/Scripts/Toolbox.sh rename to lib/Scripts/Launcher/Toolbox.sh index 34e3ffc..7c346a1 100644 --- a/lib/Scripts/Toolbox.sh +++ b/lib/Scripts/Launcher/Toolbox.sh @@ -9,23 +9,23 @@ fi # Declara uma array de opções declare -A command_scripts=( - ["0"]="bash lib/Scripts/Toolbox.sh" - ["1"]="bash lib/Scripts/Stop.sh node" - ["2"]="bash lib/Scripts/Start.sh normal" - ["3"]="bash lib/Scripts/Start.sh hide" - ["4"]="bash lib/Scripts/Start.sh pm2hide" - ["5"]="bash lib/Scripts/Start.sh pm2show" - ["6"]="bash lib/Scripts/Stop.sh pm2" - ["7"]="bash lib/Scripts/Start.sh autoreboot" - ["8"]="bash lib/Scripts/Custom.sh" - ["9"]="bash lib/Scripts/ModuleUpdate.sh" - ["10"]="bash lib/Scripts/ModuleInstall.sh" - ["11"]="bash lib/Scripts/Disconnect.sh" - ["12"]="bash lib/Scripts/Reinstall.sh" - ["13"]="bash lib/Scripts/jsonEditor.sh" - ["14"]="bash lib/Scripts/PM2Install.sh" - ["15"]="bash lib/Scripts/Requirements.sh" - ["16"]="printf '\n[ÍRIS] → Aguarde, carregando...\n' && python lib/Scripts/jsonexplorer.py" + ["0"]="bash lib/Scripts/Launcher/Toolbox.sh" + ["1"]="bash lib/Scripts/Options/Stop.sh node" + ["2"]="bash lib/Scripts/Options/Start.sh normal" + ["3"]="bash lib/Scripts/Options/Start.sh hide" + ["4"]="bash lib/Scripts/Options/Start.sh pm2hide" + ["5"]="bash lib/Scripts/Options/Start.sh pm2show" + ["6"]="bash lib/Scripts/Options/Stop.sh pm2" + ["7"]="bash lib/Scripts/Options/Start.sh autoreboot" + ["8"]="bash lib/Scripts/Options/Custom.sh" + ["9"]="bash lib/Scripts/Options/ModuleUpdate.sh" + ["10"]="bash lib/Scripts/Options/ModuleInstall.sh" + ["11"]="bash lib/Scripts/Options/Disconnect.sh" + ["12"]="bash lib/Scripts/Options/Reinstall.sh" + ["13"]="bash lib/Scripts/Options/jsonEditor.sh" + ["14"]="bash lib/Scripts/Options/PM2Install.sh" + ["15"]="bash lib/Scripts/Options/Requirements.sh" + ["16"]="printf '\n[ÍRIS] → Aguarde, carregando...\n' && python lib/Scripts/APPs/jsonexplorer.py" ["17"]="npm run fixdb" ["18"]="printf '[ÍRIS] → Foi um prazer, volte sempre!\n'; exit 0" ) @@ -54,7 +54,7 @@ options=( # Verifica se o diretório atual é o correto checkInstall() { - if [[ -e package.json && -d lib/Scripts ]]; then + if [[ -e package.json && -d lib/Scripts/Launcher ]]; then echo 0 else echo 1 diff --git a/lib/Scripts/Toolbox.vbs b/lib/Scripts/Launcher/Toolbox.vbs similarity index 61% rename from lib/Scripts/Toolbox.vbs rename to lib/Scripts/Launcher/Toolbox.vbs index 46d56a3..8ae3a45 100644 --- a/lib/Scripts/Toolbox.vbs +++ b/lib/Scripts/Launcher/Toolbox.vbs @@ -6,7 +6,7 @@ Function quote(str) End Function ' Define as variáveis -Dim objShell, GIT_PATH, BASH_PATH, retVal, objFSO, currentDir, scriptPath +Dim objShell, GIT_PATH, BASH_PATH, retVal, objFSO, currentDir, scriptPath, absoluteScriptPath ' Inicializa as variáveis do objeto Set objFSO = CreateObject("Scripting.FileSystemObject") @@ -16,16 +16,19 @@ Set objShell = CreateObject("WScript.Shell") currentDir = objFSO.GetAbsolutePathName(".") ' Verifica se o caminho atual contém "/lib/Scripts" -If InStr(1, objFSO.GetAbsolutePathName("."), "\lib\Scripts", vbTextCompare) > 0 Then +If InStr(1, objFSO.GetAbsolutePathName("."), "\lib\Scripts\Launcher", vbTextCompare) > 0 Then ' Se sim, volta dois caminhos - currentDir = objFSO.GetParentFolderName(objFSO.GetParentFolderName(objFSO.GetAbsolutePathName("."))) + currentDir = objFSO.GetParentFolderName(objFSO.GetParentFolderName(objFSO.GetParentFolderName(objFSO.GetAbsolutePathName(".")))) Else ' Caso contrário, define o diretório atual currentDir = objFSO.GetAbsolutePathName(".") End If ' Define o local do script -scriptPath = "./lib/Scripts/Toolbox.sh" +scriptPath = "./lib/Scripts/Launcher/Toolbox.sh" + +' Define o local do script como um caminho absoluto +absoluteScriptPath = objFSO.BuildPath(currentDir, "lib\Scripts\Launcher\Toolbox.sh") ' Encontra o caminho do git.exe GIT_PATH = objShell.Exec("where git.exe").StdOut.ReadAll() @@ -54,15 +57,13 @@ retVal = objShell.Run("cmd /c " & quote(command), 1, True) ' Verifica se o modo normal foi bem-sucedido If retVal = 0 Then - WScript.Echo "Modo normal concluido com sucesso." WScript.Quit End If ' Define a forma alternativa Sub TryAlternative() ' Avisa que o modo original falhou - WScript.Echo "Modo normal falhou ou finalizou, usando modo alternativo em 5 segundos..." - WScript.Sleep 5000 + WScript.Echo "Modo normal falhou, tentanto por modo alternativo (Bash Direct Execution)..." ' Define o comando a ser executado Dim command @@ -73,18 +74,33 @@ Sub TryAlternative() ' Verifica se o modo alternativo foi bem-sucedido If retVal = 0 Then - WScript.Echo "Modo alternativo concluido com sucesso." + ' Sai do script WScript.Quit - Else + else ' Ambos os métodos falharam - WScript.Echo "Modo alternativo e normal falharam ou terminaram..." + WScript.Echo "Modo alternativo e normal falharam, tentando executar a partir do caminho absoluto (Absolute-Path Bash Execution)..." + TryAbsolute End If - ' Pede para sair - WScript.Echo "Pressione qualquer tecla para sair..." - WScript.StdIn.ReadLine() + ' Sai do script WScript.Quit End Sub -' Tenta o meio alternativo -TryAlternative \ No newline at end of file +' Define a função para tentar executar o script a partir do caminho absoluto +Sub TryAbsolute() + ' Define o comando a ser executado + Dim command + command = Replace(Replace(Replace(quote("bash.exe") & " -c " & quote(Replace(absoluteScriptPath, "\", "\\")), vbCrLf, ""), vbCr, ""), vbLf, "") + + ' Tenta iniciar o script no modo absoluto + retVal = objShell.Run("cmd /c " & quote(Replace(command, "\", "\\")), 1, True) + + ' Verifica se o modo absoluto foi bem-sucedido + If retVal <> 0 Then + ' Avisa das falhas + WScript.Echo "Modo absoluto e alternativo falhou ou finalizou, aperte para sair, se a Toolbox falhou contate o suporte." + End If +End Sub + +' Tenta o modo alternativo +TryAlternative diff --git a/lib/Scripts/Custom.sh b/lib/Scripts/Options/Custom.sh similarity index 100% rename from lib/Scripts/Custom.sh rename to lib/Scripts/Options/Custom.sh diff --git a/lib/Scripts/Disconnect.sh b/lib/Scripts/Options/Disconnect.sh similarity index 100% rename from lib/Scripts/Disconnect.sh rename to lib/Scripts/Options/Disconnect.sh diff --git a/lib/Scripts/FixDatabase.js b/lib/Scripts/Options/FixDatabase.js similarity index 100% rename from lib/Scripts/FixDatabase.js rename to lib/Scripts/Options/FixDatabase.js diff --git a/lib/Scripts/MinifyIris.js b/lib/Scripts/Options/MinifyIris.js similarity index 100% rename from lib/Scripts/MinifyIris.js rename to lib/Scripts/Options/MinifyIris.js diff --git a/lib/Scripts/ModuleInstall.sh b/lib/Scripts/Options/ModuleInstall.sh similarity index 100% rename from lib/Scripts/ModuleInstall.sh rename to lib/Scripts/Options/ModuleInstall.sh diff --git a/lib/Scripts/ModuleUpdate.sh b/lib/Scripts/Options/ModuleUpdate.sh similarity index 100% rename from lib/Scripts/ModuleUpdate.sh rename to lib/Scripts/Options/ModuleUpdate.sh diff --git a/lib/Scripts/PM2Install.sh b/lib/Scripts/Options/PM2Install.sh similarity index 100% rename from lib/Scripts/PM2Install.sh rename to lib/Scripts/Options/PM2Install.sh diff --git a/lib/Scripts/Reinstall.sh b/lib/Scripts/Options/Reinstall.sh similarity index 97% rename from lib/Scripts/Reinstall.sh rename to lib/Scripts/Options/Reinstall.sh index 6113ecc..1a83dc4 100644 --- a/lib/Scripts/Reinstall.sh +++ b/lib/Scripts/Options/Reinstall.sh @@ -94,7 +94,7 @@ select choice in "Sim" "Não"; do # Verifica se o arquivo não é symlinks.json, pois esse é sensivel if [ "$fileName" != "symlinks.json" ]; then # Executa o comando apenas para arquivos diferentes de symlinks.json - node lib/Scripts/jsonFixer.js "$configFile" "./lib/Databases/Configurations/$fileName" + node lib/Scripts/Options/jsonFixer.js "$configFile" "./lib/Databases/Configurations/$fileName" fi done @@ -117,7 +117,7 @@ select choice in "Sim" "Não"; do case $startOption in # Executa o programa de atualização "Sim (y)") - bash ./lib/Scripts/ModuleUpdate.sh + bash ./lib/Scripts/Options/ModuleUpdate.sh break ;; @@ -135,7 +135,7 @@ select choice in "Sim" "Não"; do case $startOption in # Executa a inicialização "Sim (y)") - bash ./lib/Scripts/Start.sh normal + bash ./lib/Scripts/Options/Start.sh normal break ;; diff --git a/lib/Scripts/Requirements.sh b/lib/Scripts/Options/Requirements.sh similarity index 100% rename from lib/Scripts/Requirements.sh rename to lib/Scripts/Options/Requirements.sh diff --git a/lib/Scripts/Start.sh b/lib/Scripts/Options/Start.sh similarity index 100% rename from lib/Scripts/Start.sh rename to lib/Scripts/Options/Start.sh diff --git a/lib/Scripts/Stop.sh b/lib/Scripts/Options/Stop.sh similarity index 100% rename from lib/Scripts/Stop.sh rename to lib/Scripts/Options/Stop.sh diff --git a/lib/Scripts/jsonEditor.sh b/lib/Scripts/Options/jsonEditor.sh similarity index 92% rename from lib/Scripts/jsonEditor.sh rename to lib/Scripts/Options/jsonEditor.sh index 8423ef6..42fba92 100644 --- a/lib/Scripts/jsonEditor.sh +++ b/lib/Scripts/Options/jsonEditor.sh @@ -7,7 +7,7 @@ if [ ! -d "lib" ]; then read -rp "[ÍRIS] → Parece que você não possui uma cópia da Íris. Deseja realizar a instalação? 1 (y), 2 (n): " opt case $opt in 1) - bash ./lib/Scripts/Toolbox.sh 15 + bash ./lib/Scripts/Launcher/Toolbox.sh 15 ;; 2) printf "[ÍRIS] → Ok, obrigado por utilizar este programa! <3\n" @@ -56,7 +56,7 @@ select jsonFile in "APIS" "Config" "Outros" "Nenhum"; do # Verifica se o arquivo escolhido existe if [ -f "$fileToEdit" ]; then # Executa o script Python para edição do JSON - python lib/Scripts/jsoneditor.py "$fileToEdit" + python lib/Scripts/Options/jsoneditor.py "$fileToEdit" break else printf "[ÍRIS] → O arquivo '%s' não existe. Faça uma reinstalação manual.\n" "$fileToEdit" @@ -70,7 +70,7 @@ select startOption in "Sim (y)" "Não (n)"; do case $startOption in # Executa a inicialização "Sim (y)") - bash ./lib/Scripts/Start.sh normal + bash ./lib/Scripts/Options/Start.sh normal break ;; diff --git a/lib/Scripts/jsonFixer.js b/lib/Scripts/Options/jsonFixer.js similarity index 100% rename from lib/Scripts/jsonFixer.js rename to lib/Scripts/Options/jsonFixer.js diff --git a/lib/Scripts/jsoneditor.py b/lib/Scripts/Options/jsoneditor.py similarity index 100% rename from lib/Scripts/jsoneditor.py rename to lib/Scripts/Options/jsoneditor.py diff --git a/lib/Scripts/Hosts.sh b/lib/Scripts/Others/Hosts.sh similarity index 100% rename from lib/Scripts/Hosts.sh rename to lib/Scripts/Others/Hosts.sh diff --git a/lib/Scripts/Menu.sh b/lib/Scripts/Others/Menu.sh similarity index 100% rename from lib/Scripts/Menu.sh rename to lib/Scripts/Others/Menu.sh diff --git a/lib/Scripts/Others/Plugins.sh b/lib/Scripts/Others/Plugins.sh new file mode 100644 index 0000000..8392b4a --- /dev/null +++ b/lib/Scripts/Others/Plugins.sh @@ -0,0 +1,1252 @@ +#!/bin/bash + +MINIDOCS="Uso: ./plugins.sh [update|install|upgrade|remove|--help|-h] + +Descrição: Gerencia plugins para projetos KillovSky, semelhante ao APT. + +Opções: + -h, --help Exibe esta mensagem de ajuda e sai. + update Atualiza o repositório de plugins. + install [bot@dev@command@version] Instala um plugin específico. + upgrade Atualiza todos os plugins instalados. + remove [bot@dev@command] Remove um plugin específico. + +Exemplos: + ./plugins.sh update + ./plugins.sh install bot@dev@command@latest + ./plugins.sh install + ./plugins.sh upgrade + ./plugins.sh remove bot@dev@command +" + +DOCUMENTATION=" +# ---------------------------------------------------------------------------- +# Uso: ./plugins.sh [update|install|upgrade|remove|--help|-h] +# +# Descrição: Gerencia plugins para projetos KillovSky, funcionando de forma semelhante ao APT, com opções para instalação, atualização, remoção e sincronização de repositórios de plugins. +# +# Opções: +# -h, --help, * +# Exibe esta mensagem de ajuda e sai. +# +# update +# Atualiza o repositório de plugins a partir do caminho especificado. +# +# install [bot@dev@command@version] +# Instala um plugin específico. Se 'version' for 'latest', instala a versão mais recente. +# +# upgrade +# Atualiza todos os plugins instalados. +# +# remove [bot@dev@command] +# Remove um plugin específico. +# +# Exemplos: +# ./plugins.sh update +# Atualiza os arquivos do repositório. +# +# ./plugins.sh install bot@dev@command@latest +# Instala um plugin específico. +# +# ./plugins.sh install +# Inicia instalação interativa. +# +# ./plugins.sh upgrade +# Atualiza todos os plugins instalados. +# +# ./plugins.sh remove bot@dev@command +# Remove um plugin específico. +# +# Funções Internas: +# is_root +# Verifica se o script está sendo executado como root. +# +# is_admin +# Verifica se o script está sendo executado como administrador no Git Bash/MinGW. +# +# select_option +# Exibe uma lista de opções ao usuário e retorna a escolhida. +# +# list_bots +# Lista bots disponíveis no diretório de repositórios. +# +# list_devs +# Lista desenvolvedores disponíveis para um bot específico. +# +# list_commands +# Lista comandos disponíveis para um bot e desenvolvedor. +# +# show_readme +# Exibe o conteúdo do README.md de um comando específico. +# +# list_versions +# Lista versões disponíveis para um comando. +# +# install_via_params +# Instala um comando a partir de parâmetros fornecidos no formato bot@dev@command@version. +# +# remove_function +# Remove um comando instalado. +# +# install_function +# Instala um comando interativamente. +# +# upgrade_function +# Atualiza todos os plugins instalados. +# +# main +# Função principal que gerencia as opções do script. +# +# Requisitos: +# - Bash (Linux, macOS, ou Git Bash no Windows) +# - JQ (para manipulação de JSON) +# - Git (para gerenciamento de repositórios) +# +# Instalação de dependências: +# +# 1. JQ: +# - Linux: sudo apt install jq +# - macOS: brew install jq /OU/ sudo port install jq +# - Windows: Baixe de https://jqlang.github.io/jq/download +# +# 2. Git: +# - Linux: sudo apt install git +# - macOS: brew install git +# - Windows: Baixe de https://git-scm.com/downloads +# +# ---------------------------------------------------------------------------- +" + +# Configurações gerais +REPO_DIR="Plugins" +REPO_URL="https://github.com/KillovSky/Plugins.git" +LOG_FILE="package_manager.log" +UPDATE_THRESHOLD=86400 # 24 horas +INIT_COMMAND="" # String que contém todos os args usados em outras funções (no inicio) +SILENT=false +INSTALLED_PACKAGES="installed_packages.log" # Caminho para o arquivo de pacotes instalados + +# Limpa o terminal no inicio +clear + +# ---------------------------------------------------------------------------- +# Função: log_action +# Descrição: Registra ações no arquivo de log e exibe no terminal com suporte a cores. +# O log é formatado com timestamp e mensagens coloridas dependendo do tipo de log. +# ---------------------------------------------------------------------------- +log_action() { + local message="$1" # Mensagem a ser exibida + local log_type="${2:-INFO}" # Tipo de log: INFO, ERROR, SUCCESS, etc. + local log_file="${LOG_FILE:-./default_log.log}" # Arquivo de log (padrão: default_log.log) + + # Verificar se o parâmetro --silent foi passado em INIT_COMMAND ou nos argumentos + if [[ "$@" == *"--silent"* || "$INIT_COMMAND" == *"--silent"* ]]; then + SILENT=true + fi + + # Cores para diferentes tipos de mensagens + local color_reset="\033[0m" + local color_info="\033[1;34m" # Azul para INFO + local color_success="\033[1;32m" # Verde para SUCCESS + local color_error="\033[1;31m" # Vermelho para ERROR + local color_warning="\033[1;33m" # Amarelo para WARN + + # Escolher cor com base no tipo de log + local color + case "$log_type" in + INFO) + color="$color_info" + ;; + SUCCESS) + color="$color_success" + ;; + ERROR) + color="$color_error" + ;; + WARN) + color="$color_warning" + ;; + *) + color="$color_reset" # Sem cor se o tipo for desconhecido + ;; + esac + + # Formatar mensagem com timestamp + local timestamp + timestamp=$(date '+%Y-%m-%d %H:%M:%S') + local formatted_message="$timestamp - $log_type: $message" + + # Se o modo silent não estiver ativado, exibe a mensagem no terminal com cor + if [[ "$SILENT" == false ]]; then + printf "${color}%s${color_reset}\n" "$formatted_message" + fi + + # Registrar a mensagem no arquivo de log (sem cores) + printf "%s\n" "$formatted_message" >> "$log_file" + + # Se for silent, remove tudo após qualquer prompt + if [[ "$SILENT" == true ]]; then + clear + fi +} + +# -------------------------------------------------------------------------- +# Função para exibir uma barra de progresso animada enquanto um processo +# em segundo plano está em execução. A barra de progresso pode ser usada +# para indicar que algo está acontecendo em tempo real. +# +# Parâmetros: +# $1 - PID do processo a ser monitorado. +# $2 (opcional) - Atraso entre cada atualização da animação. (padrão: 0.1s) +# $3 (opcional) - Caracteres usados na animação (padrão: "|/-\"). +# +# Exemplo de uso: +# some_long_process & +# progress_bar $! 0.1 '|/-\' +# -------------------------------------------------------------------------- +progress_bar() { + local pid=$1 # PID do processo que será monitorado + local delay=${2:-0.1} # Intervalo entre atualizações (padrão: 0.1s) + local spinstr=${3:-'|/-\'} # Caracteres de animação (padrão: "|/-\") + local temp_str # Variável temporária para manipulação da string + + # Validações de parâmetros + if ! ps -p "$pid" &>/dev/null; then + echo "Erro: PID $pid não encontrado." + return 1 + fi + + if [[ ! "$delay" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then + echo "Erro: O parâmetro 'delay' deve ser um número válido." + return 1 + fi + + # Função interna para exibir o próximo frame da animação + __update_spinner() { + local frame_char="${spinstr:0:1}" # Pega o primeiro caractere + temp_str="${spinstr:1}$frame_char" # Rotaciona a string + spinstr="$temp_str" # Atualiza a string para o próximo ciclo + printf " [%c] " "$frame_char" # Exibe o frame atual da animação + } + + # Inicia o loop de exibição enquanto o processo estiver ativo + while ps -p "$pid" &>/dev/null; do + __update_spinner # Exibe o próximo frame + sleep "$delay" # Pausa pelo intervalo especificado + printf "\b\b\b\b\b\b" # Remove a animação atual do terminal + done + + # Limpa os resíduos da animação após a conclusão + printf " \b\b\b\b" # Apaga qualquer resto da barra de progresso + echo # Move para a próxima linha no terminal + + return 0 +} + +# ---------------------------------------------------------------------------- +# Função para garantir que um diretório exista. Se o diretório não existir, +# ele será criado. Usa `mkdir -p` para criar diretórios aninhados, caso seja +# necessário. +# +# Parâmetros: +# $1 - Caminho do diretório a ser garantido +# +# Exemplo de uso: +# ensure_directories "/caminho/para/diretorio" +# ---------------------------------------------------------------------------- +ensure_directories() { + local dir_path="$1" # Caminho do diretório a ser garantido + + # Verifica se o diretório existe, se não existir, ele será criado. + if [[ ! -d "$dir_path" ]]; then + mkdir -p "$dir_path" + if [[ $? -eq 0 ]]; then + log_action "Diretório criado: $dir_path" "SUCCESS" + else + log_action "Erro ao criar o diretório: $dir_path" "ERROR" + exit 1 + fi + fi +} + +# ---------------------------------------------------------------------------- +# Função para verificar se o diretório especificado tem permissões de escrita. +# Se não houver permissão, a função registra o erro e encerra a execução. +# +# Parâmetros: +# $1 - Caminho do diretório a ser verificado +# +# Exemplo de uso: +# check_write_permissions "/caminho/para/diretorio" +# ---------------------------------------------------------------------------- +check_write_permissions() { + local dir="$1" # Caminho do diretório a ser verificado + + # Verifica se o diretório tem permissão de escrita + if [[ ! -w "$dir" ]]; then + log_action "Erro: Sem permissões de escrita em $dir." "ERROR" + exit 1 + else + log_action "Permissões de escrita positivas para $dir." "SUCCESS" + fi +} + +# ---------------------------------------------------------------------------- +# Função para sincronizar um repositório Git. A função verifica se o repositório +# existe localmente e, se sim, faz um pull para atualizá-lo. Se o repositório +# não existir, ele será clonado. Caso tenha sido atualizado recentemente, +# a função evitará pull excessivos, a menos que forçado. +# +# Parâmetros: +# $1 (opcional) - Flag "-y" para forçar a atualização, mesmo que recente. +# +# Exemplo de uso: +# sync_repo "-y" +# ---------------------------------------------------------------------------- +sync_repo() { + local force_update="$1" # Flag para forçar atualização (opcional) + local last_update # Armazena a última modificação do repositório + local current_time=$(date +%s) # Tempo atual em segundos + local age # Idade do último update do repositório + + # Garante que o diretório do repositório existe + ensure_directories "$REPO_DIR" + + # Verifica se há permissões de escrita no diretório + check_write_permissions "$REPO_DIR" + + # Se o repositório já existir localmente, tenta atualizá-lo + if [[ -d "$REPO_DIR/.git" ]]; then + last_update=$(stat -c %Y "$REPO_DIR") + age=$((current_time - last_update)) + + # Se o repositório for antigo o suficiente ou se a atualização for forçada + if [[ $age -ge $UPDATE_THRESHOLD || "$force_update" == "-y" ]]; then + log_action "Atualizando repositório..." "INFO" + git -C "$REPO_DIR" pull --quiet & # Atualiza em segundo plano + local pid=$! # Captura o PID do processo git + progress_bar "$pid" # Exibe barra de progresso + wait "$pid" # Espera a conclusão + log_action "Repositório atualizado com sucesso." "SUCCESS" + else + log_action "Repositório atualizado recentemente. Use '-y' para forçar." "INFO" + fi + else + # Se o repositório não existir, realiza o clone + log_action "Clonando o repositório..." "INFO" + git clone --quiet "$REPO_URL" "$REPO_DIR" & # Clona em segundo plano + local pid=$! # Captura o PID do processo git + progress_bar "$pid" # Exibe barra de progresso + wait "$pid" # Espera a conclusão + log_action "Repositório clonado com sucesso." "SUCCESS" + fi +} + +# ---------------------------------------------------------------------------- +# Função para encontrar o arquivo .zip com a versão mais alta dentro de um +# diretório. As versões são extraídas dos nomes dos arquivos, ordenadas, e a +# mais recente é retornada. +# +# Parâmetros: +# $1 - Caminho do diretório onde procurar pelos arquivos .zip +# +# Saída: +# - O nome do arquivo .zip com a versão mais alta, ou mensagem de erro +# +# Exemplo de uso: +# find_latest_version "/caminho/para/diretorio" +# ---------------------------------------------------------------------------- +find_latest_version() { + local dir="$1" # Caminho do diretório onde procurar pelos arquivos .zip + + # Valida se o diretório existe + if [[ ! -d "$dir" ]]; then + log_action "Erro: Diretório $dir não encontrado." "WARN" + return 1 + fi + + # Encontra todos os arquivos .zip e extrai seus nomes sem a extensão + local versions=($(find "$dir" -type f -iname "*.zip" -exec basename {} .zip \;)) + + # Verifica se há arquivos .zip disponíveis + if [[ ${#versions[@]} -eq 0 ]]; then + log_action "Nenhuma versão disponível no diretório $dir." "WARN" + return 1 + fi + + # Ordena as versões de forma case insensitive e captura a mais alta + local latest_version=$(printf "%s\n" "${versions[@]}" | sort -fV | tail -n 1) + + # Retorna o nome do arquivo .zip com a versão mais alta + echo "$latest_version.zip" + return 0 +} + +# ---------------------------------------------------------------------------- +# Função para verificar a existência de um diretório de instalação e perguntar +# ao usuário a ação desejada (sobrescrever, apagar e reinstalar, ou cancelar). +# +# Parâmetros: +# $1 - Caminho do arquivo JSON contendo informações sobre a instalação. +# $2 - Caminho do arquivo .zip que será instalado. +# $3 - Caminho do diretório de destino. +# ---------------------------------------------------------------------------- +check_and_handle_installation() { + local json_file="$1" # Caminho do arquivo JSON de configuração + local zip_file="$2" # Caminho do arquivo .zip a ser instalado + local final_dir="$3" # Caminho do arquivo .zip a ser instalado + local is_hotfix="" # Se for hotfix + local auto_install=false + local overwrite=false + + # Verifica se o parâmetro -y ou --yes foi passado para auto-instalar + if [[ "$@" =~ "-y" || "$@" =~ "--yes" ]]; then + auto_install=true + fi + + # Verifica se o parâmetro -O ou --overwrite foi passado + if [[ "$@" =~ "-O" || "$@" =~ "--overwrite" ]]; then + overwrite=true + fi + + # Verifica se o parâmetro -NO ou --no-overwrite foi passado + if [[ "$@" =~ "-NO" || "$@" =~ "--no-overwrite" ]]; then + overwrite=false + fi + + # Valida se o arquivo JSON existe + if [[ ! -f "$json_file" ]]; then + log_action "Erro: Arquivo de configuração $json_file não encontrado." "ERROR" + exit 1 + fi + + # Se o escolhido for HotFix (case insensitive) + if [[ "${zip_file,,}" == *"hotfix"* ]]; then + is_hotfix=" [HOTFIX VERSION, OPÇÃO RECOMENDADA!]" + fi + + # Extrai informações do arquivo JSON + local installed_dir=$(jq -r '.installed.value' "$json_file") + local install_dir=$(jq -r '.location.value' "$json_file") + + # Valida se o diretório de instalação já existe + if [[ -d "$installed_dir" ]]; then + printf "\n\n" + log_action "A pasta $installed_dir já existe." "WARN" + + # Se o modo auto-install estiver ativado, escolhe automaticamente + if [[ "$auto_install" == true ]]; then + log_action "Auto-instalação ativada, sobrescrevendo ou apagando conforme a flag -O ou -NO escolhida." "INFO" + if [[ "$overwrite" == true ]]; then + log_action "Sobrescrevendo conteúdo em $installed_dir..." "WARN" + else + log_action "Apagando o diretório $installed_dir e reinstalando..." "WARN" + rm -rf "$installed_dir" + fi + else + printf "O que você deseja fazer?\n\n" + printf "1) Apenas sobrescrever$is_hotfix\n" + printf "2) Apagar e instalar [Clean Install]\n" + printf "3) Cancelar\n\n" + read -rp "Escolha uma opção [1-3]: " choice + + case $choice in + 1) + log_action "Sobrescrevendo conteúdo em $installed_dir..." "WARN" + ;; + 2) + log_action "Apagando o diretório $installed_dir e reinstalando..." "WARN" + rm -rf "$installed_dir" + ;; + 3) + log_action "Operação cancelada pelo usuário." "INFO" + exit 0 + ;; + *) + log_action "Opção inválida. Operação cancelada." "INFO" + exit 1 + ;; + esac + fi + else + log_action "Diretório $installed_dir não encontrado. Iniciando instalação..." "INFO" + fi + + # Valida se o arquivo .zip existe + if [[ ! -f "$zip_file" ]]; then + log_action "Erro: Arquivo $zip_file não encontrado." "ERROR" + exit 1 + fi + + # Chama a função de instalação passando o arquivo .zip e o diretório de destino + install_zip "$zip_file" "$install_dir" "$final_dir" +} + +# ---------------------------------------------------------------------------- +# Função para descompactar um arquivo .zip em um diretório de destino. +# Exibe uma barra de progresso durante o processo de extração. +# +# Parâmetros: +# $1 - Caminho completo para o arquivo .zip +# $2 - Diretório de destino onde o arquivo será descompactado +# +# Exemplo de uso: +# install_zip "arquivo.zip" "/caminho/destino" +# ---------------------------------------------------------------------------- +install_zip() { + local zip_file="$1" # Caminho do arquivo .zip + local dest_dir="$2" # Diretório de destino + local final_dir="$3" # Diretorio pós-instalação + + # Valida se o arquivo .zip existe + if [[ ! -f "$zip_file" ]]; then + log_action "Erro: Arquivo $zip_file não encontrado." "ERROR" + return 1 + fi + + # Valida se o diretório de destino existe ou cria-o + ensure_directories "$dest_dir" + + printf "\n" # Breakline + + # Descompacta o arquivo e mostra a barra de progresso + log_action "Iniciando descompactação de $zip_file para $final_dir..." "INFO" + unzip -o "$zip_file" -d "$dest_dir" >/dev/null & # Redireciona a saída + local pid=$! # Pega o PID do processo de descompactação + + # Exibe a barra de progresso enquanto o processo está em execução + progress_bar "$pid" + wait "$pid" # Aguarda o término da descompactação + + if [[ $? -eq 0 ]]; then + log_action "Arquivo $zip_file descompactado com sucesso." "SUCCESS" + else + log_action "Erro ao descompactar $zip_file." "ERROR" + return 1 + fi + + printf "\n" # Breakline +} + +# ---------------------------------------------------------------------------- +# Função para baixar e descompactar a versão mais recente de um BOT, com suporte +# a instruções de pré-instalação e pós-configuração a partir de um arquivo JSON. +# +# Parâmetros: +# $1 - Nome do BOT +# $2 - Nome do desenvolvedor do BOT +# $3 - Nome do comando a ser instalado +# $4 - Versão a ser instalada (ou "latest" para a versão mais recente) +# +# Exemplo de uso: +# download_function "MeuBOT" "Desenvolvedor" "comando" "latest" +# ---------------------------------------------------------------------------- +download_function() { + local bot_name="$1" # Nome do BOT + local dev_name="$2" # Nome do desenvolvedor + local command_name="$3" # Nome do comando + local version="$4" # Versão a ser instalada + + # Define o diretório onde os arquivos .zip e JSON estão localizados + local zip_dir="$REPO_DIR/$bot_name/$dev_name/$command_name" + local json_file="$zip_dir/instruct.json" + + # Verifica se o arquivo JSON existe + if [[ ! -f "$json_file" ]]; then + log_action "Erro: Arquivo de instruções $json_file não encontrado." "ERROR" + return 1 + fi + + # Lê comandos de pré-instalação e pós-configuração do JSON + local install_path=$(jq -r '.location.value' "$json_file") + local final_dir=$(jq -r '.installed.value' "$json_file") + local pre_install_cmd=$(jq -r ".install.value.$(get_os).command" "$json_file") + local post_config_cmd=$(jq -r ".configuration.value.$(get_os).command" "$json_file") + + # Determina a versão mais recente se necessário + if [[ "$version" == "latest" ]]; then + version=$(find_latest_version "$zip_dir") || { + log_action "Erro: Não foi possível determinar a versão mais recente." "ERROR" + return 1 + } + fi + + # Formata o nome do arquivo + local zip_file="$zip_dir/$version" + + # Verifica se o arquivo ZIP existe + if [[ ! -f "$zip_file" ]]; then + log_action "Arquivo $version não encontrado." "ERROR" + return 1 + fi + + # Verifica se o diretório de instalação já existe e trata conforme o usuário + check_and_handle_installation "$json_file" "$zip_file" "$final_dir" + + # Executa o comando de pré-instalação, se houver + if [[ -n "$pre_install_cmd" ]]; then + log_action "Executando sistemas de de pré-instalação..." "WARN" + run_pre_install "$pre_install_cmd" + fi + + # Garante que o diretório de instalação existe + ensure_directories "$install_path" + + # Baixa e descompacta a versão + log_action "Baixando e descompactando $version para $install_path" "INFO" + install_zip "$zip_file" "$install_path" "$final_dir" + + # Executa o comando de pós-configuração, se houver + if [[ -n "$post_config_cmd" ]]; then + log_action "Executando sistemas de pós-configuração..." "WARN" + run_post_install "$post_config_cmd" "$install_path" + fi + + # Registro de sucesso + log_action "Função $command_name codename $version instalada com sucesso." "SUCCESS" +} + +# ---------------------------------------------------------------------------- +# Função para detectar o sistema operacional e retornar a chave correta +# que pode ser usada para executar comandos específicos do SO. +# +# Retorna: +# "linux" - para sistemas Linux +# "macos" - para sistemas macOS +# "windows" - para sistemas Windows (Cygwin, Mingw, MSYS) +# "other" - para qualquer outro sistema não identificado +# +# Exemplo de uso: +# os=$(get_os) +# if [[ "$os" == "linux" ]]; then +# echo "Este é um sistema Linux." +# fi +# ---------------------------------------------------------------------------- +get_os() { + local os_name="$(uname -s)" # Captura o nome do SO + + case "$os_name" in + Linux*) echo "linux" ;; + Darwin*) echo "macos" ;; + CYGWIN* | MINGW* | MSYS*) echo "windows" ;; + *) echo "other" ;; # Caso o SO não seja reconhecido + esac +} + +# ---------------------------------------------------------------------------- +# Função para confirmar com o usuário antes de executar um comando via eval. +# O comando é exibido na tela para que o usuário possa revisar antes de decidir. +# +# Parâmetros: +# $1 - Comando que será executado via eval +# +# Exemplo de uso: +# confirm_and_run_eval "echo 'Hello, World!'" +# ---------------------------------------------------------------------------- +confirm_and_run_eval() { + local script="$1" # Comando que será avaliado + local prompt_message # Mensagem de confirmação + + # Constroi a mensagem de confirmação com o comando + prompt_message="Deseja executar o seguinte comando de instalação?\n" + prompt_message+="$script\n\n[s] Sim | [n] Não\n~# Caution: " + + # Loop até que o usuário insira uma resposta válida + while true; do + # Exibe a mensagem e aguarda a resposta do usuário + read -rp "$(echo -e "$prompt_message")" confirm + + # Trata as respostas válidas + case "$confirm" in + [yY] | [sS]) # Sim + clear + # Tenta executar o comando + eval "$script" || { + log_action "Erro ao executar o comando: $script" "ERROR" + return 1 + } + log_action "Comando executado com sucesso: $script" "SUCCESS" + break + ;; + [nN]) # Não + clear + log_action "Execução do comando pulada. Continuando..." "WARN" + return 0 + ;; + *) # Opção inválida + echo "Opção inválida. Escolha [s] para sim ou [n] para não." "WARN" + ;; + esac + done +} + +# ---------------------------------------------------------------------------- +# Função para executar comandos pré-instalação (dependências). +# Verifica se existe um comando de pré-instalação válido e o executa, se aplicável. +# +# Parâmetros: +# $1 - Comando de pré-instalação a ser executado +# +# Exemplo de uso: +# run_pre_install "sudo apt-get install -y package" +# ---------------------------------------------------------------------------- +run_pre_install() { + local pre_cmd="$1" # Comando pré-instalação + + # Executa o comando se for diferente de "none" ou vazio + if [[ "$pre_cmd" != "none" && -n "$pre_cmd" ]]; then + confirm_and_run_eval "$pre_cmd" || { + log_action "Falha ao executar comando pré-instalação." "ERROR" + return 1 + } + else + log_action "Nenhum comando pré-instalação fornecido." "INFO" + fi +} + +# ---------------------------------------------------------------------------- +# Função para executar comandos pós-instalação (configuração). +# Verifica se existe um comando de pós-instalação válido e o executa, se aplicável. +# +# Parâmetros: +# $1 - Comando de pós-instalação a ser executado +# $2 - Caminho da instalação, utilizado se necessário pelo comando +# +# Exemplo de uso: +# run_post_install "sudo systemctl restart service" "/path/to/install" +# ---------------------------------------------------------------------------- +run_post_install() { + local post_cmd="$1" # Comando pós-instalação + local install_path="$2" # Caminho da instalação + + # Executa o comando se for diferente de "none" ou vazio + if [[ "$post_cmd" != "none" && -n "$post_cmd" ]]; then + confirm_and_run_eval "$post_cmd" || { + log_action "Falha ao executar comando pós-instalação." "ERROR" + return 1 + } + else + log_action "Nenhum comando pós-instalação fornecido." "INFO" + fi +} + +# ---------------------------------------------------------------------------- +# Função para listar os desenvolvedores (devs) disponíveis para um bot específico. +# Procura por diretórios dentro do caminho do bot e lista os nomes dos devs. +# +# Parâmetros: +# $1 - Nome do bot +# +# Exemplo de uso: +# list_devs "my_bot" +# ---------------------------------------------------------------------------- +list_devs() { + local bot_name="$1" # Nome do bot + local devs # Array para armazenar os devs encontrados + + # Busca por diretórios dentro da pasta do bot, que representam os devs + devs=($(find "$REPO_DIR/$bot_name" -mindepth 1 -maxdepth 1 -type d -exec basename {} \;)) + + # Verifica se encontrou algum dev + if [[ ${#devs[@]} -eq 0 ]]; then + log_action "Nenhum desenvolvedor encontrado para o bot $bot_name." "WARN" + return 1 + fi + + # Exibe as opções de devs e permite que o usuário selecione + select_option "Escolha um desenvolvedor disponível:" "${devs[@]}" || { + log_action "Seleção de desenvolvedor cancelada." "INFO" + return 1 + } + printf "\n" +} + +# ---------------------------------------------------------------------------- +# Função para listar os comandos disponíveis para um bot e desenvolvedor específicos. +# Procura por diretórios dentro do caminho do dev e lista os comandos. +# +# Parâmetros: +# $1 - Nome do bot +# $2 - Nome do desenvolvedor +# +# Exemplo de uso: +# list_commands "my_bot" "dev_name" +# ---------------------------------------------------------------------------- +list_commands() { + local bot_name="$1" # Nome do bot + local dev_name="$2" # Nome do desenvolvedor + local commands=() # Array para armazenar os comandos encontrados + local modified_times=() # Array para armazenar os tempos de modificação + + # Busca por diretórios dentro da pasta do dev, que representam os comandos + while IFS= read -r -d '' dir; do + commands+=("$(basename "$dir")") + modified_times+=("$(stat -c %Y "$dir")") # Armazena o timestamp de modificação + done < <(find "$REPO_DIR/$bot_name/$dev_name" -mindepth 1 -maxdepth 1 -type d -print0) + + # Verifica se encontrou algum comando + if [[ ${#commands[@]} -eq 0 ]]; then + log_action "Nenhum comando encontrado para o desenvolvedor $dev_name." "WARN" + return 1 + fi + + # Ordena os comandos com base no tempo de modificação (mais recente primeiro) + IFS=$'\n' sorted_commands=($(for i in "${!modified_times[@]}"; do + echo "${modified_times[i]} ${commands[i]}" + done | sort -nr | cut -d' ' -f2-)) + unset IFS + + # Exibe as opções de comandos e permite que o usuário selecione + select_option "Escolha um comando disponível:" "${sorted_commands[@]}" || { + log_action "Seleção de comando cancelada." "WARN" + return 1 + } + printf "\n" +} + +# ---------------------------------------------------------------------------- +# Função para exibir o conteúdo de um arquivo README.md com formatação básica. +# Faz uso de cores e formatações simples para melhorar a legibilidade dos cabeçalhos, +# listas e blocos de código. +# +# Parâmetros: +# $1 - Nome do bot +# $2 - Nome do desenvolvedor +# $3 - Nome do comando +# +# Exemplo de uso: +# show_readme "my_bot" "dev_name" "command_name" +# ---------------------------------------------------------------------------- +show_readme() { + local bot_name="$1" # Nome do bot + local dev_name="$2" # Nome do desenvolvedor + local command_name="$3" # Nome do comando + local readme_path="$REPO_DIR/$bot_name/$dev_name/$command_name/README.md" # Caminho do README.md + + # Verifica se o arquivo README.md existe + if [[ -f "$readme_path" ]]; then + clear # Limpa o terminal + + log_action "Exibindo README.md de $command_name..." "INFO" + + # Exibe o README.md com formatação básica usando awk + awk ' + BEGIN { printf "\n" } + # Cabeçalhos de nível 1 (H1) -> Azul + /^# / { printf "\033[1;34m%s\033[0m\n", substr($0, 3); next } + # Cabeçalhos de nível 2 (H2) -> Verde + /^## / { printf "\033[1;32m%s\033[0m\n", substr($0, 4); next } + # Cabeçalhos de nível 3 (H3) -> Amarelo + /^### / { printf "\033[1;33m%s\033[0m\n", substr($0, 5); next } + # Listas com marcadores -> Converte o "-" para "•" e mantém o conteúdo + /^- / { printf "• %s\n", substr($0, 3); next } + # Blocos de código cercados por "```" -> Alterna entre início e fim do código + /^```/ { in_code = !in_code; next } + # Exibe o conteúdo do bloco de código em branco + { if (in_code) { print "\033[1;37m" $0 "\033[0m" } else { print $0 } } + ' "$readme_path" + + printf "\n\n" # Adiciona uma quebra de linha no final + else + # Exibe uma mensagem de erro caso o README.md não seja encontrado + log_action "README.md não encontrado para o comando $command_name." "WARN" + return 1 + fi +} + +# Função para verificar se é root (Linux/WSL/macOS) +is_root() { + [ "$(id -u)" -eq 0 ] +} + +# Função para verificar se é admin (Git Bash/MinGW) +is_admin() { + if command -v net &> /dev/null; then + net session &> /dev/null + return $? + else + return 1 + fi +} + +# ---------------------------------------------------------------------------- +# Função auxiliar para exibir e selecionar opções de um array. +# Exibe as opções com paginação se houver mais de 10 itens. +# +# Parâmetros: +# $1 - Mensagem do prompt +# $@ - Lista de opções disponíveis +# +# Exemplo de uso: +# select_option "Escolha uma opção:" "${opcoes[@]}" +# ---------------------------------------------------------------------------- +select_option() { + local prompt="$1" + shift + local options=("$@") # Armazena as opções passadas como argumentos + local page=0 # Inicializa a página atual + local page_size=10 # Define o número máximo de opções por página + local choice # Variável para armazenar a opção escolhida + local total_options=${#options[@]} # Total de opções disponíveis + local total_pages=$(( (total_options + page_size - 1) / page_size )) # Total de páginas + + # Printa o local + printf "Process Working Directory (PWD): $(pwd)\n\n" + + # Verifica se há opções disponíveis + if (( total_options == 0 )); then + echo "Nenhuma opção disponível." + return 1 + fi + + while true; do + local start=$((page * page_size)) # Calcula o índice inicial para a página atual + local current_options=("${options[@]:$start:$page_size}") # Opções da página atual + + # Exibe o prompt e as opções atuais + echo "$prompt" + for i in "${!current_options[@]}"; do + printf "%s) %s\n" "$((i + 1))" "${current_options[i]}" + done + + # Exibe opções de navegação + echo "d) Próxima Página" + echo "a) Página Anterior" + printf "c) Cancelar\n\n" + + # Obtém o nome do usuário + USER=$(whoami) + + # Obtém o nome do computador + HOST=$(hostname) + + # Verifica se o usuário é root ou admin + if is_root || is_admin; then + PS3="${ADMIN} ~ ${USER}@${HOST}:~$" + else + PS3="${USER}@${HOST}:~$ " + fi + + # Exibe o prompt personalizado + read -rp "$PS3" REPLY + + case "$REPLY" in + "c" | "Cancelar") + echo "Operação cancelada." + exit 0 + ;; + "d" | "Próxima Página") + if (( page + 1 < total_pages )); then + page=$((page + 1)) # Avança para a próxima página + clear + else + printf "\nVocê já está na última página.\n" + fi + ;; + "a" | "Página Anterior") + if (( page > 0 )); then + page=$((page - 1)) # Volta para a página anterior + clear + else + printf "\nVocê já está na primeira página.\n" + fi + ;; + *) + # Verifica se a entrada é um número válido + if [[ "$REPLY" =~ ^[1-9][0-9]*$ ]] && (( REPLY >= 1 && REPLY <= ${#current_options[@]} )); then + choice="${current_options[$((REPLY - 1))]}" # Armazena a opção escolhida + clear + printf "\nVocê escolheu: %s" "$choice" + REPLY="$choice" + return 0 # Retorna sucesso + else + printf "\nSeleção inválida. Tente novamente." + fi + ;; + esac + done +} + + +# ---------------------------------------------------------------------------- +# Função para listar bots disponíveis no diretório de repositórios. +# Utiliza find para localizar diretórios (exceto ocultos) e permite selecionar um bot. +# ---------------------------------------------------------------------------- +list_bots() { + local bots + bots=($(find "$REPO_DIR" -mindepth 1 -maxdepth 1 -type d ! -name '.*' -exec basename {} \;)) + + # Verifica se há bots disponíveis + if [[ ${#bots[@]} -eq 0 ]]; then + log_action "Nenhum bot encontrado, execute a função update." "ERROR" + return 1 + fi + + # Chama a função para selecionar uma opção + select_option "Escolha um bot disponível:" "${bots[@]}" + printf "\n" +} + +# ---------------------------------------------------------------------------- +# Função para listar versões disponíveis (arquivos .zip) de um comando específico. +# Exibe as versões disponíveis para instalação. +# ---------------------------------------------------------------------------- +list_versions() { + local bot_name="$1" + local dev_name="$2" + local command_name="$3" + local versions + versions=($(find "$REPO_DIR/$bot_name/$dev_name/$command_name" -type f -name "*.zip")) + + # Verifica se há versões disponíveis + if [[ ${#versions[@]} -eq 0 ]]; then + log_action "Nenhuma versão disponível para a função $command_name." "WARN" + return 1 + fi + + # Cria um array para armazenar as opções formatadas + local formatted_versions=() + + for file in "${versions[@]}"; do + local filename=$(basename "$file") + local filesize_kb=$(stat -c%s "$file") # Tamanho do arquivo em bytes + filesize_kb=$((filesize_kb / 1024)) # Converte para KB + local mod_time=$(stat -c%y "$file") # Data de modificação + + # Formata a data de modificação + mod_time=$(date -d "$mod_time" +"%Y-%m-%d %H:%M:%S") + + # Adiciona a informação formatada ao array com o nome do arquivo em amarelo + formatted_versions+=("\"$filename\" | $mod_time | ${filesize_kb}KB") + done + + # Ordena as versões pela data de modificação (mais recente primeiro) + IFS=$'\n' sorted_versions=($(sort -r <<<"${formatted_versions[*]}")) + unset IFS + + # Chama a função para selecionar uma versão + select_option "Escolha uma versão disponível:" "${sorted_versions[@]}" + printf "\n" +} + + + +# ---------------------------------------------------------------------------- +# Função para instalar um comando via parâmetros formatados como bot@dev@command@version. +# Se "latest" for especificado para a versão, baixa a versão mais recente. +# ---------------------------------------------------------------------------- +install_via_params() { + IFS='@' read -ra args <<< "$1" + local bot_name="${args[0],,}" + local dev_name="${args[1],,}" + local command_name="${args[2],,}" + local version="${args[3],,}" + + # Verifica se os parâmetros necessários foram fornecidos + if [[ -z "$bot_name" || -z "$dev_name" || -z "$command_name" ]]; then + log_action "Parâmetros inválidos. Uso: bot@dev@command@version | bot@dev@command@latest" "INFO" + exit 1 + fi + + # Verifica se a versão é "latest" ou não + if [[ -z "$version" || "$version" == "latest" ]]; then + log_action "Instalando a versão mais recente de $command_name..." "INFO" + download_function "$bot_name" "$dev_name" "$command_name" "latest" + else + log_action "Instalando a versão $version de $command_name..." "INFO" + download_function "$bot_name" "$dev_name" "$command_name" "v$version.zip" + fi + + # Adiciona o comando à lista de pacotes instalados, removendo duplicatas + package_line="$bot_name@$dev_name@$command_name" + + # Verifica se o pacote já está presente no arquivo, se não, adiciona + grep -qxFi "$package_line" "$INSTALLED_PACKAGES" || echo "$package_line" >> "$INSTALLED_PACKAGES" +} + +# ---------------------------------------------------------------------------- +# Função para remover pacotes instalados com base nos parâmetros fornecidos. +# Formato esperado: bot@dev@command. +# ---------------------------------------------------------------------------- +remove_function() { + IFS='@' read -ra args <<< "$1" + local bot_name="${args[0],,}" + local dev_name="${args[1],,}" + local command_name="${args[2],,}" + + # Verifica se os parâmetros necessários foram fornecidos + if [[ -z "$bot_name" || -z "$dev_name" || -z "$command_name" ]]; then + log_action "Parâmetros inválidos. Uso: bot@dev@command" "WARN" + exit 1 + fi + + # Define o caminho do JSON e do diretório instalado + local zip_dir="$REPO_DIR/$bot_name/$dev_name/$command_name" + local json_file="$zip_dir/instruct.json" + local installed_dir=$(jq -r '.installed.value' "$json_file") + + # Verifica se o diretório instalado existe + if [[ -d "$installed_dir" ]]; then + # Localiza e remove o diretório de forma insensível a maiúsculas e minúsculas + find "$REPO_DIR/$bot_name/$dev_name" -iname "$command_name" -exec rm -rf {} + + log_action "Função $command_name removida com sucesso." "SUCCESS" + else + log_action "Função $command_name não encontrada." "WARN" + fi +} + + +# ---------------------------------------------------------------------------- +# Função principal de instalação interativa. Lista bots, devs e comandos para o usuário escolher. +# Exibe o README antes de solicitar confirmação para instalação. +# ---------------------------------------------------------------------------- +install_function() { + # Declaração de variáveis locais + local bot_name dev_name command_name version + + # Exibe a lista de bots disponíveis. Se falhar, retorna erro. + list_bots || return 1 + bot_name="${REPLY,,}" # Armazena o nome do bot em minúsculas + + # Exibe a lista de desenvolvedores do bot escolhido. Se falhar, retorna erro. + list_devs "$bot_name" || return 1 + dev_name="${REPLY,,}" # Armazena o nome do desenvolvedor em minúsculas + + # Exibe a lista de comandos disponíveis para o bot e desenvolvedor escolhidos. Se falhar, retorna erro. + list_commands "$bot_name" "$dev_name" || return 1 + command_name="${REPLY,,}" # Armazena o nome do comando em minúsculas + + # Exibe o conteúdo do README do comando selecionado + show_readme "$bot_name" "$dev_name" "$command_name" + + # Solicita confirmação do usuário para baixar o comando + read -rp "Deseja baixar esta função? (s/n): " confirm + printf "\n" + case "${confirm,,}" in + # Se o usuário confirmar com 'sim' (y/s), prossegue com a instalação + [y] | [s]) + clear # Limpa a tela + + # Exibe a lista de versões disponíveis para o comando selecionado + list_versions "$bot_name" "$dev_name" "$command_name" || return 1 + version="$REPLY" # Armazena a versão escolhida pelo usuário + download_function "$bot_name" "$dev_name" "$command_name" "$version" # Baixa o comando + + # Adiciona o comando à lista de pacotes instalados, removendo duplicatas + package_line="$bot_name@$dev_name@$command_name" + + # Verifica se o pacote já está presente no arquivo, se não, adiciona + grep -qxFi "$package_line" "$INSTALLED_PACKAGES" || echo "$package_line" >> "$INSTALLED_PACKAGES" + + # Log de sucesso na instalação + log_action "$bot_name@$dev_name@$command_name instalado com sucesso." "SUCCESS" + return 0 + ;; + # Se o usuário cancelar a instalação com 'não' (n), exibe uma mensagem e encerra + [n]) + log_action "Instalação cancelada." "WARN" + exit 0 + ;; + # Caso o usuário insira uma opção inválida + *) + echo "Opção inválida. Escolha [s] para sim ou [n] para não." + ;; + esac +} + +# Função para realizar a atualização dos pacotes instalados +upgrade_function() { + # Verifica se o arquivo de pacotes instalados existe. Caso contrário, registra um erro e retorna. + if [[ ! -f "$INSTALLED_PACKAGES" ]]; then + log_action "Nenhum pacote encontrado para atualização. Execute 'install' primeiro." "ERROR" + return 1 + fi + + # Cria uma variável para armazenar pacotes processados + declare -A processed_packages + + # Lê a lista de pacotes instalados e tenta reinstalar cada um + while IFS= read -r package; do + # Ignora pacotes vazios ou linhas com apenas espaços + if [[ -z "$package" || "$package" =~ ^[[:space:]]*$ ]]; then + continue + fi + + # Se o pacote já foi processado, pula para a próxima iteração + if [[ -n "${processed_packages[$package]}" ]]; then + continue + fi + + # Marca o pacote como processado + processed_packages["$package"]=1 + + # Divide o nome do pacote em partes (bot, dev, comando) + IFS='@' read -ra args <<< "$package" + + # Verifica se a linha tem o formato correto + if [[ ${#args[@]} -ne 3 ]]; then + log_action "Formato inválido para o pacote: $package. Ignorando..." "WARNING" + continue + fi + + local bot_name="${args[0],,}" # Armazena o nome do bot em minúsculas + local dev_name="${args[1],,}" # Armazena o nome do desenvolvedor em minúsculas + local command_name="${args[2],,}" # Armazena o nome do comando em minúsculas + + # Registra que o pacote está sendo reinstalado + log_action "Reinstalando o pacote $package..." "INFO" + + # Baixa a versão mais recente do comando + download_function "$bot_name" "$dev_name" "$command_name" "latest" + + # Registra o sucesso na atualização do pacote + log_action "$package atualizado com sucesso." "SUCCESS" + + done < "$INSTALLED_PACKAGES" +} + + +# ---------------------------------------------------------------------------- +# Função principal que gerencia as opções "update", "install", "upgrade" e "remove". +# "install" e "upgrade" aceitam formato de parâmetros ou instalação interativa. +# ---------------------------------------------------------------------------- +main() { + INIT_COMMAND="$@" # Define as args usadas + + # Verifica o primeiro parâmetro para determinar qual ação executar + case "${1,,}" in + "update") + # Se o comando for 'update', sincroniza o repositório com o segundo parâmetro + sync_repo "$2" + ;; + "install" | "upgrade") + # Se o comando for 'install' ou 'upgrade', verifica se o segundo parâmetro contém '@', indicando um pacote específico + if [[ "$2" == *"@"* ]]; then + install_via_params "$2" # Instala ou atualiza via parâmetros passados + else + # Se o comando for 'install', chama a função de instalação + if [[ "$1" == "install" ]]; then + install_function + # Se o comando for 'upgrade', chama a função de atualização + elif [[ "$1" == "upgrade" ]]; then + upgrade_function + fi + fi + ;; + "remove") + # Se o comando for 'remove', chama a função de remoção com o segundo parâmetro (pacote a ser removido) + remove_function "$2" + ;; + "-h"|"-H") + clear && printf "$MINIDOCS\nDocumentação COMPLETA: ./$0 --help" + ;; + # Caso o comando não seja válido, exibe uma mensagem de uso completa + *) + clear && printf "$DOCUMENTATION" + exit 1 + ;; + esac +} + +# Executa +main "$@" \ No newline at end of file diff --git a/lib/Scripts/Toolbox.exe b/lib/Scripts/Toolbox.exe deleted file mode 100644 index ec9fb6b229b35a7021e88d0b09224faa939c503d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5120 zcmeHKO>7)j9skdI{k4uav0a>m;4s-FbW_LUHF2UiwVU-f27fGB$5yI9GG0Hghs@5~ zzM0+HAR=F=R289udVmXXK)oULP^nb`AtA(xmJ5}7LY256AcPwdhnC;}&FqJr1k4rs z*7JYw|NSxV{pWe<`B$lhh~juY{+Q@(%sjFh{(G3HVMO5QBVO<{F+C(cEtbF)N?Mhmsyzp_>H_94ZLE~ASm z0ZK`13Hfu%6^OJnEq?b5gLlnuhT^9yv`DRz(qJX z?h+k2NIMK})9*j6u|rjaF@YC^*$*A;_fi%~0OQbe!8hXEW9d;70OU#5+I3q}0(P#QZc zk!Vvu$`Zv*3>|Azr)o(5N5-JhPkr&8_|T`ROWqQN+|b&=l=q`R|S zVmBnH^GF(1OGs>wL|j|s%>O6d;dCRD0VJ3|-B+}ggaH1WIQHSQpB#2ml2~zFq z7Q3_=yueyVSqu9mA$wSgu0BNWq1BgJ=%)H}sy z66;0SV$Nf1wHi^Fk*&d87~TNrYK)n>c6jmi%uVWOj^@jC3%U|Cm?Y&et&dY4>>un_ zziXiF9qFe)|J*aDW9d&}@yt~Ii&KW)9pPT9j#?S(Qs&ag7;lqSasj`OcX9SU&LsBW z?|GdMl;ahBmiPc$;soetZ|3Rmh!xeQv-39>W|)ar{u<*`uH0Z81ER+KQ!(OWLjOE} ziTcC6iQ4Ne4n83;y@o3t8Phl!#@VPvPXpeiEa0AoZ_w*lzo+Scz&b$*;~$`843-?% z@OceiGFb9WtP}Jb$nXg5hE+Jm0U>Y3awc=XOP96pbc(T;PF$lTcs+Ct$MGa!lFraO zbet~G`*ey%=#OLq{spm&Y3>-EGA`02y5a~ekT9-bt&HPZ@>#k?uNae%{2pXjcMf)b zWGsX7Iw)r}*QTEvtK`so#x2y1JzCU-H)ByBRZxfc9s=7peh93&`5AOt^Y_!9uIY>~ z$<2x@o}*PM-3_^8i5)??uQ!+3srRr!l#g62afb^2-n`xD}OS;F50LBf+9s018c)^onW`Yjbf^KSy-VN zM|mQi*l;|-3Ud|L)wD1lYsRsQp7aB!09hpw zu%8cX6)bpLl6(=|S(oY_wtK_FtXFlE^h$6`D`lY&v{#I(Q-s1weoZJJ*;3B6gDt5_ zI1bFHp&AJl8dm2}Gn(CT{J__48DF+bg63er4m5326)WtPYwGzD3hT-V#3H8_#ZEeS zqLaheAr5WOFy*O03hOe#3OKhT&h3MoRttNIjuxmyn^+0j!9(4{&^PHDl%a1DwTD*e z=mD$8S4raM!lQ(q1s%3RXV>A`!%EVN@SfANKsa1e#Td+?9W4hS-y(sP=QlRh>7L#g7IvjE*34*EUm)U9OyP;7l>D4eUGltDCh_C z^B@rriDk?lVy!^O1ch@e>6~rkW+HP3UN|q09#9p0rk3G@{g}YH$_3~Lnr1@MJdlqu zo7Yy@dP!?ZSYS^!G#za_^yZ<5g!&cjQ)#PQeM|Sb(|>#L)%*9qGWqTC`RVenzH^>B z-un9OwUeVCzKlk0w3uYXO~dE_lEfmGY@?PWMw|=)aIm7@^Kp}UF0@iCvY~S;G#@%zI?qnU-pHN9g{fdzTQ_rpw){y0lC6AP&f|1?GP=a8+5GclYcTEpqT12{`J zuv(xMoW47lm+}2u(Q?0tKm4fnW!8iUT#sh{k~Nvt)EP}%)2C<-r^3YvS-`2=!tUpB zj#z6|pBfJ*%!OnSogOVfZ^VBBqXuFMAjN&Fh=>ka+S4)_^sDeUimrm*MHg{vG3xR& z@ZQ{&!c)qAOgtGJg@){!KFfYnEE(MoxhLwrh7#} zTF0~q`$erW4Y@My>gTIgUpo~*XN645zxwqMJgG46;@_A{#U$w6PD<5kd=0=!@D zP>rk}&53I;2?-yPB~;NxWafX=Lm2e%XTKc3zEg6|YWS(0NR3#TlqtM|+{D*-B6V|h zZs=;t^aI=5v|Z_miPWy}Q`evCPK?{WFG?Hkt_cI4Kar{^@0wrO7A4ysDmeuueYq73 z6=dm}?U$_TNXjhPp0g$VAo{R}-eAf!>&6x~@nOczWnV^cQ~ z{juzFIW-(w2vo(_*NsEQ^ZAt4gKu9HD!2gbMmQ)+yih@$Vl$_lDsB)(;UCiKrJ7X} zqhSZFv{2#ZyeO)|HC=`iDcfK0s`8#tDYN2C7WmRMk=n9dUqnf1Bg2o0rWX3}zSzfy k>qUUT_;BqF0pYj($vAWc%<%s>Q~&>VXsu5K|3@nDFW2wUGXMYp diff --git a/lib/Scripts/Toolbox.jar b/lib/Scripts/Toolbox.jar deleted file mode 100644 index 9e72d7835f12a9354c11e0fe3ee0fa9c75483b63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2034 zcmZ{lcTm&W8is#TB!-Seiip$*A&>+D*&v`uTS74;C{-~?3lN&2DMgB*DZNOOsP&Tk-ON0RRL5;_=mv zz#bg{_y8L-dt*&YTXV$D5CGu0R!IN^0{xFwlH2yfYGZ6`X>LZe*RnC+uo-4rTWM;I z30rBxo(=zTpMadydAqo7Gdw&I`pgop)j|N8A{ixVgo9QDBDECOD0%(*SD~*$5cGDM zM9w7wq+}xvyq+dub@fl(NJa#Mn?V3{7j&tRz@2E%-9Iyl#Qk@C?xz475;;KYqCe@< zr5k6R93(9ycTyXRDU89w%dHK8bx{K>3@#d)2v!zuH_0L|}~#c=rg za%&STO!|Qe+q9`r%+vi>t;R_W|Bq?-UM-s z6hBr=6X{n2cntHCLml-T>_)mO6@47xYb!zz*ynWe-*x(76Kn|WG*wyOrre6lncp=n zPfugZzRAWEku0NoToobALFeI??54K&&Q5OxNvdbn9UDo)Q_oV>5Z&cP-CqWSGe~Ee zj#9`yH#UgaPd7X2=Gsz`b+(xwdYgTP52O8ip)~#lx8LVN`U@1ZOVvMvjWL!%rL^N7 z$h?UQ5MiNIR%LqDoFdviExu8bOw=UDg7KkI#ziBdLQobue( z-K@2x80TsO$Y;Ew6RM{VY<-wL4tsrZQa5G$m$lifoAPO*(r4-J>o{vmannA28pX_= zlb<6|b^iB~qPCKv-hs`Pmfnx*gfDZHJg-MsvP?*{DVL_WX1{cfDHNG3FBu+D(oF1kL!WVd&EPNRufri^$`$4RqD z{Z%A5I;Qg`L9i=oNmRUeX7=TzYHyI%OLW0Rz_ICYedcnU)P47z*wx=EV6{Fv{>KBh zI#PDnRDBWgR!W5YH_7cT`c^EX{%yY##pr0Rny%>6%SsH1fydhJ=l%wjvmt*!poN)V ziCln9L-dgyI6t!>CmODUmd}Hh>lj~C$(8X?!#9YjHc;;t5r$)w$(Kn^A7PB}w%ryr zi3rGGueZk?fA%8fNOAmkGu94+C9uJoC$ct`{z_r6Oyzf2l2Pvw5vG`9UHx{d879nY*9o%Dy6}^_QzTTh{iM5SJ`t{gGUaElY|25Rl<*maOIk8fXjk>(J;zs`jBmc~bKaNMNbmADTMDPHiZ;PW@47dB%a z2C7c(GaaBxQsNT8I5@xeZGk|(!ia-`W1R(wk5&G8Eix6Jz~)>qJo=kd0=w!0N5%1k z;1q&&ZnRzK&AfI@cWUguUCxM0_al(|0YF1=moxi#z`*|pB^Ne(^n-=}#^ydAN#G|q z_u^|8oIj<(Eq}D`!RYSr|Gcn^xxK-5G51rCx#dsj;jQ?&@d1FByB=`QV*o.cheat.some((o=>e.toLowerCase().includes(o.toLowerCase())))));if(!o)return;let t=o.cheat.indexOf(e.toLowerCase());t=t<=0?o.cheat.indexOf(e.toUpperCase()):t,t=t<=0?o.message.length-1:t,console.log(t),"string"==typeof o.action?window.location.href=o.action:"GTA San Andreas"===o.game?(document.querySelector("body > div.content-section.section1 > div.secImage1 > img").src="./Cheats/CJ.png",document.querySelector("#navbar > img").src="./Cheats/cjfavicon.jpeg",document.querySelector("body > div.content-section.section2 > div.secImage2 > img").src="./Cheats/bigsmoke.png",document.querySelector("body > div.content-section.section2 > div:nth-child(2) > div > h1").innerText="The streetz is cold dawg.",document.querySelector("#navbar > a").innerText="PROJECT CJ (AGARAGAN 1.0)",document.querySelector("body > div.content-section.section1 > div.google_translate_element > h1").innerText="Ah shit, here we go again.",document.querySelector("body > div.content-section.section1 > div:nth-child(1) > div").innerHTML="Grove Street, home. At least it was before I fucked everything up. Worst place in the world, and all we had to do was follow the damn train, CJ! Get us outta here, CJ! I ain't your bitch, officer! Stay away from me! You dropped a bomb on me! Hey, I gotta meet some very important record people. Make sure you get that on camera. I'm a maniac with a gun! Ain't nobody can tell me when to hit the john. I'm not scared of you, punk! You're a piece of shit! I'm taking you motherfuckers! Please, just leave me alone! Make it easy on yourself and run away! You trying to fuck with my head, man? Stop running, fool! You ain't gonna win, fool! You tricked me! You messing with a maniac, fool! I ain't no buster, fool! You're a busta! Respect has to be earned, sweet, just like money. I'm just your liability, CJ. You're a natural housebreaker, homie. Man, I'm done here, let's go! Send them ducats over here! Keep it coming, CJ.".replace(/(.{80})/g,"$1
"),document.querySelector("body > div.content-section.section2 > div:nth-child(2) > div > div").innerHTML="Hey, you gotta keep it real, man. Like it says in the book... We are both blessed and cursed. Same things make us laugh, make us cry. Ryda'... just chill the fuck out, man! You're naïve, my friend. We gotta keep our focus. I'll have 2 number nines, a number nine large. A number six with extra dip. A number seven. Two number forty-fives, one with cheese, and a large soda. You picked the wrong house, fool! CJ...? Aaaooooww my dog! Whassup? Ha ha ha ha! Oh shit! Roadblock up ahead! Fuck it, I'm goin' through! Hell no, I'm going through! Oh shit, the brakes is out! Shit! That's gonna be a hell of a story to tell when we passin' the blunt! Shit! That's gonna be a hell of a story to tell later on when we're passin' the blunt! C'mon. Let's bounce. A lot of people say gangsta rap is misogynistic posturing by fake-ass idiots who spend more time in drama school then they ever did pimping or hustling dope. Well, I assure you, OG Loc is the real thing. He's hated women all his life, he sold drugs to school children, he's murdered innocent people just for kicks, but he rhymes like an angel. And I assure you, it's all in a good cause. So either way, you could feel good about yourself listening to this music. Awww, motherfucker, my car! Come on, CJ! You can't keep up with the fat man? I do! I don't know, man. You can't knock a homie's hustle, Sweet. Yeah, but they're down with us, man.".replace(/(.{80})/g,"$1
"),document.querySelector("body > div.footer").innerText="HEY WOOZIE! I KNOW YOUR BLIND MAN, BUT YOU GOTTA SEE THIS!"):o.cheat.includes("sos")?(console.log("Emergência? Aqui estão alguns números úteis:\n- Polícia: 190\n- Bombeiros: 193\n- SAMU: 192\n- Defesa Civil: 199\n- Internacional: 112\nPara mais informações, acesse:"),console.log("https://www.gov.br/anatel/pt-br/regulado/numeracao/codigos-nacionais/servicos-de-utilidade-publica-e-de-emergencia"),console.log("https://www.gov.br/pf/pt-br/canais_atendimento"),console.log('Sua segurança é importante!\nPara redirecionamento, digite "ajudame".')):o.cheat.includes("arrowuparrowuparrowdownarrowdownarrowleftarrowrightarrowleftarrowrightba")?document.querySelector("body > div.content-section.section1 > div.secImage1 > img").src="./Cheats/arrows.gif":o.cheat.includes("reloadme")?location.reload():o.cheat.includes("glitchme")?forceGlitch=!0:o.cheat.includes("legiaoz")?window.top.location.href="https://chat.whatsapp.com/FvEhxZ9T31N6NjGTwfePcU":o.cheat.includes("ajudame")?window.top.location.href="https://www.gov.br/pf/pt-br/canais_atendimento":o.cheat.includes("suicid")&&(window.top.location.href="https://www.google.com/search?q=suicide+lines"),o.cheat.includes("sos")||console.log(`Oh, um código de trapaça! 😏\nCódigo: "${e.toUpperCase()}"\nPara: "${o.game}"\nEfeito: ${o.message[t]}\nO savegame está marcado como trapaceiro. Que vergonha, amigo! 🙈`),userInput=""}document.addEventListener("keydown",(e=>{userInput+=e.key.toLowerCase(),checkCheatCode(userInput)})),document.addEventListener("DOMContentLoaded",(()=>{const{body:e}=document,o=document.getElementById("navbar"),t=document.getElementById("dark-mode-switch"),a=document.getElementById("mode-icon"),n=document.querySelector(".navbar-brand"),i=document.querySelector("body > div.footer"),r=document.querySelectorAll("body > div.content-section.section1 > div:nth-child(1) > div > p"),s=document.querySelectorAll("body > div.content-section.section2 > div:nth-child(2) > div > div > p"),c=Array.from(r).map((e=>e.innerText)),d=Array.from(s).map((e=>e.innerText)),l=document.querySelector("body > div.footer").innerText;function u(t,n,i){e.className=t,o.className="navbar navbar-expand-lg navbar-dark "+("dark-mode"===t?"bg-dark":"bg-light"),a.classList.remove(n),a.classList.add(i),localStorage.setItem("dark-mode","dark-mode"===t?"enabled":null)}function m(){u("dark-mode","fa-moon","fa-sun")}t.addEventListener("click",(function(){e.classList.contains("dark-mode")?u("light-mode","fa-sun","fa-moon"):m()})),m();const g=o.offsetTop;function h(){const e=window.scrollY;o.style.position=e>g?"fixed":"relative",o.style.top=e>g?"0":"auto",o.classList.toggle("initial",e<=g)}function p(e,o){document.querySelectorAll(e).forEach((e=>{o?(e.classList.remove("hidethisfromscreen"),e.classList.add("show")):(e.classList.remove("show"),e.classList.add("hidethisfromscreen"))}))}window.onscroll=h,window.onload=h,i.addEventListener("click",(()=>{forceEnable+=1;const e=new Date,o=e.getMonth()+1,t=e.getDate();let a=12===o||1===t&&1===o;a=forceEnable>=3||a;const n=e.getFullYear()-2014,i=document.querySelectorAll(".firework");a&&!isFirework&&(document.body.classList.add("glitch-effect"),setTimeout((()=>{(forceEnable||12===o)&&(document.querySelector("body > div.content-section.section2 > div.secImage2 > img").src="./birthday.png",document.querySelector("body > div.content-section.section2 > div.secImage2 > img").style["border-radius"]="15%",document.querySelector("body > div.content-section.section2 > div:nth-child(2) > div > h1").innerText="🎁 Feliz aniversário para mim! 🎉",document.querySelector("body > div.content-section.section2 > div:nth-child(2) > div > div").innerHTML=`

Não acredito que já fazem ${n} anos que nasci! 🌟

🙇🏻‍♀️ Muito obrigada a todos por tornarem essa experiência tão única e especial!

Foi uma jornada repleta de emoções, aprendizados e conexões especiais! 💖

🚀 Juntos, construímos uma comunidade cheia de carinho e apoio mútuo.

Sou grata por fazer parte dessa jornada maravilhosa. 🤝

`),document.body.classList.remove("glitch-effect"),i.forEach((e=>{e.style.display="block",e.style.left=`${Math.floor(101*Math.random())}%`,e.style.top=`${Math.floor(101*Math.random())}%`})),isFirework=!isFirework}),1e3)),isFirework&&a&&(i.forEach((e=>{e.style.display="none",e.style.left=`${Math.floor(101*Math.random())}%`,e.style.top=`${Math.floor(101*Math.random())}%`})),document.body.classList.add("glitch-effect"),setTimeout((()=>{divpone=0,document.querySelectorAll("body > div.content-section.section2 > div:nth-child(2) > div > div > p").forEach((e=>{e.innerText=d[divpone],divpone+=1})),document.querySelector("body > div.content-section.section2 > div.secImage2 > img").src="./sticker.png",document.querySelector("body > div.content-section.section2 > div:nth-child(2) > div > h1").innerText="🌐 Quem me fez? ❓",document.body.classList.remove("glitch-effect"),isFirework=!isFirework}),1e3))})),n.addEventListener("click",(()=>{forceEnable+=1;const e=new Date,o=e.getMonth()+1,t=e.getDate();let a=12===o&&25===t;if(a=forceEnable>=3||a,a){const e=document.querySelector(".snowflakes"),o=isSnowing?"none":"block",t=document.querySelectorAll(".snowflake");e.classList.toggle("animate-snowfall",!isSnowing),document.querySelectorAll(".snowflake").forEach((e=>{e.style.display=o,e.style.left=`${Math.floor(101*Math.random())}%`})),isSnowing=!isSnowing,isSnowing&&!1===snowingInterval?snowingInterval=setInterval((()=>{(forceGlitch?1:Math.random()<.05)&&(document.body.classList.add("black-screen"),setTimeout((()=>{document.querySelector("body > div.content-section.section1 > div.secImage1.order-md-last > img").src="./monika.jpg",document.querySelector("body > div.content-section.section2 > div.secImage2 > img").src="./creepymonika.png",document.querySelector("#navbar > img").src="./glitch-header.jpg",document.querySelector("#navbar > a").innerText="JUST MONIKA.",document.querySelector("body > div.content-section.section2 > div:nth-child(2) > div > h1").innerText="%",document.querySelectorAll("body > div.content-section.section1 > div:nth-child(1) > div > p").forEach((e=>e.innerText="JUST MONIKA ".repeat(10))),document.querySelectorAll("body > div.content-section.section2 > div:nth-child(2) > div > div > p").forEach((e=>e.innerText="GET OF OF MY HEAD ".repeat(3))),document.querySelector("body > div.footer").innerText="THERE IS NOT GOD ".repeat(4),document.querySelectorAll(".snowflake").forEach((e=>{const o=document.createElement("img");o.src=`./glitch${Math.floor(5*Math.random())}.png`,o.style.width="180px",o.style.height="180px",o.classList.add("glitch-image"),o.style.left=`${Math.floor(100*Math.random())+1}%`,e.parentNode.replaceChild(o,e)})),document.body.classList.remove("black-screen"),document.body.classList.add("glitch-effect")}),1e3),setTimeout((()=>{document.body.classList.remove("glitch-effect"),document.body.classList.add("black-screen"),setTimeout((()=>{let e=0;document.querySelectorAll(".glitch-image").forEach((o=>{const a=t[e];a.style.left=`${Math.floor(101*Math.random())}%`,o.parentNode.replaceChild(a,o),e+=1})),divpone=0,document.querySelectorAll("body > div.content-section.section1 > div:nth-child(1) > div > p").forEach((e=>{e.innerText=c[divpone],divpone+=1})),divpone=0,document.querySelectorAll("body > div.content-section.section2 > div:nth-child(2) > div > div > p").forEach((e=>{e.innerText=d[divpone],divpone+=1})),document.querySelector("body > div.content-section.section1 > div.secImage1.order-md-last > img").src="./london.jpg",document.querySelector("body > div.content-section.section2 > div.secImage2 > img").src="./sticker.png",document.querySelector("body > div.content-section.section2 > div:nth-child(2) > div > h1").innerText="🌐 Quem me fez? ❓",document.querySelector("#navbar > img").src="./Favicon/favicon.ico",document.querySelector("#navbar > a").innerText="PROJETO ÍRIS",document.querySelector("body > div.footer").innerText=l,document.body.classList.remove("black-screen"),document.body.classList.add("glitch-effect"),setTimeout((()=>{forceGlitch=!1,document.body.classList.remove("black-screen","glitch-effect")}),1e3)}),1e3)}),5e3))}),1e4):!1!==snowingInterval&&clearInterval(snowingInterval)}})),document.getElementsByClassName("languageMenu")[0].addEventListener("click",(()=>{p("#defaultlanguage",!0),p("#hiddenlanguage",!1),p("#lastlanguage",!1),clickCounter=0})),document.getElementById("startDropdown").addEventListener("click",(function(){clickCounter>=4?(p("#defaultlanguage",!0),p("#hiddenlanguage",!1),p("#lastlanguage",!1),clickCounter=0):clickCounter>=2?(clickCounter+=1,p("#defaultlanguage",!1),p("#hiddenlanguage",!1),p("#lastlanguage",!0)):(p("#defaultlanguage",!1),p("#hiddenlanguage",!0),p("#lastlanguage",!1),clickCounter+=1),clickCounter+=1}))}));let gTranslateSelect=!1;const gTranslateLanguages="ja,en,fr,es,id,ms,hi,de,it,ru,la,ar";function initGoogleTranslate(){new google.translate.TranslateElement({pageLanguage:"pt",includedLanguages:gTranslateLanguages,layout:google.translate.TranslateElement.InlineLayout.HORIZONTAL},"google_translate_element"),gTranslateSelect=document.getElementById("google_translate_element").querySelector(".goog-te-combo")}function triggerChangeEvent(e){if(e.fireEvent)e.fireEvent("onchange");else{const o=document.createEvent("HTMLEvents");o.initEvent("change",!1,!0),e.dispatchEvent(o)}}function stopTranslating(){if(document.getElementsByClassName("goog-te-banner-frame")[0]){const e=(iframe.contentDocument||iframe.contentWindow.document).getElementsByTagName("button");for(let o=0;o=0){closeLink[0].click();break}}else window.location.reload()}function changeLanguage(e){gTranslateSelect&&"pt"!==e?(gTranslateSelect.value=e,triggerChangeEvent(gTranslateSelect)):"pt"===e&&gTranslateLanguages.split(",").includes(gTranslateSelect.value)&&stopTranslating()} \ No newline at end of file diff --git a/lib/Wiki/Homepage/index.html b/lib/Wiki/Homepage/index.html index f30b2f5..e771f67 100644 --- a/lib/Wiki/Homepage/index.html +++ b/lib/Wiki/Homepage/index.html @@ -37,7 +37,7 @@ - + diff --git a/package.json b/package.json index 2919fd9..5c31e01 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,14 @@ { "name": "iris", "version": "1.1.6", - "build_date": "11-08-2024", + "build_date": "02-10-2024", "build_name": "Fish", "private": true, "description": "Novo Projeto Íris, uma versão totalmente nova feita com novas APIs, sistemas, 13+ idiomas e muito mais, sendo um projeto novo, aberto e sem nenhum foco lucrativo.", "main": "lib/Initialize/checker.js", "scripts": { "start": "node lib/Initialize/checker.js", + "docker": "docker build -t Iris .", "toolbox": "lib/Scripts/Toolbox.sh", "bash": "bash lib/Scripts/Toolbox.sh", "bat": "lib\\Scripts\\Toolbox.bat", @@ -44,7 +45,7 @@ "dependencies": { "@ffmpeg-installer/ffmpeg": "^1.1.0", "@hapi/boom": "^10.0.1", - "@killovsky/gimages": "^1.0.0", + "@killovsky/gimages": "^1.1.0", "@killovsky/gtts": "^1.0.0", "@killovsky/nasa": "^1.0.1", "@killovsky/telegraph": "^1.0.0",