//////////////////////////////////////////////////////////////////////////////// // How to use // 1 - Vá na página conteudo do app - // 2 - Abra console do chrome e cole esse script inteiro // 2 - execute o comando abaixo em seguida arrumando os parametros //////////////////////////////////////////////////////////////////////////////// opt = { 'nomeApp': 'INFE Gestão de Condomínios', 'email': 'comercial@infe.com.br', 'telefone': '+551122936440', 'site': 'http://infe.com.br/', 'contatoUrl': 'https://www.seucondominio.com.br/contato?no_layout=true', 'descricaoBreve': 'Gestão financeira, administrativa e segurança eletrônica para condomínio', }; ///////////////////////////// // Rode esse primeiro // await rodarCriarApp(opt); ///////////////////////////// ///////////////////////////// // Depois todos abaixo ///////////////////////////// // await rodarPresencaLoja(opt); // await rodarCriarVersao(opt); // await rodarConteudoApp(opt); ///////////////////////////// // Depois esse isolado ///////////////////////////// // Nesse aqui você precisa entrar manualmente na pagina de "Permissões de acesso a fotos e vídeos" // await rodarPermissaoFotos(opt); // //////////////////////////////////////////////////////////////////////////////// (function () { function normalizar(txt) { return (txt || "") .toString() .normalize("NFD") .replace(/\p{Diacritic}/gu, "") .trim() .toLowerCase(); } function isVisivel(el) { return !!el && (el.offsetWidth || el.offsetHeight || el.getClientRects().length); } function isHabilitado(botao) { const aria = botao.getAttribute('aria-disabled'); return !botao.disabled && aria !== 'true'; } window.clickElemento = function(el) { if(el == undefined || el == null){ console.log("clickElemento não encontrou elemento para clicar") return; } // Dá um scroll pra garantir que não esteja coberto try { el.scrollIntoView({ block: 'center' }); } catch {} // Dispara eventos “reais” (alguns frameworks exigem) el.dispatchEvent(new MouseEvent('mousedown', { bubbles: true })); el.dispatchEvent(new MouseEvent('mouseup', { bubbles: true })); el.click(); } function clicarBotaoDaSecao(secao, titulo) { if (!secao) return false; // 1) Tenta o botão com aria-label que contém o título (mais preciso) let botao = secao.querySelector(`button[aria-label*="${titulo}"]`); // 2) Se não achar, cai para o botão com label visual "Iniciar declaração" dentro da secão if (!botao) { botao = Array.from(secao.querySelectorAll('button')) .find(b => (b.textContent || '').trim().toLowerCase() === 'iniciar declaração'); } if (botao && isVisivel(botao)) { botao.scrollIntoView({ block: 'center', behavior: 'instant' }); botao.click(); return true; } return false; } window.encontrarBarraDoBotao = function() { // Escopo preferencial return document.querySelector('publishing-bottom-bar, form-bottom-bar, [debug-id="publishing-bottom-bar"]') || document.querySelector('bottom-bar-base, [debug-id="bottom-bar"]') || document; } window.execEncontrarBotaoByDebugId = function (escopo, debugId) { const candidatos = Array.from( // escopo.querySelectorAll('button[debug-id="'+debugId+'"]') escopo.querySelectorAll('[debug-id="'+debugId+'"]') ); // 1) Primeiro tenta “main-button” com label “Salvar” let btn = candidatos.find(b => b.matches('button[debug-id="'+debugId+'"]') && normalizar(b.textContent) === 'salvar' ); if (btn && isVisivel(btn) && isHabilitado(btn)) return btn; // 2) Qualquer botão visível com label “Salvar” btn = candidatos.find(b => isVisivel(b) && isHabilitado(b) ); if (btn) return btn; // 3) Fallback: procura span de label dentro de botões const spans = Array.from(escopo.querySelectorAll('button .mdc-button__label, button span')); const spanSalvar = spans.find(s => normalizar(s.textContent) === 'salvar'); if (spanSalvar) { const b = spanSalvar.closest('button'); if (b && isVisivel(b) && isHabilitado(b)) return b; } return null; } function encontrarSecaoPorTitulo(titulo) { const alvo = normalizar(titulo); const secoes = document.querySelectorAll('console-section[debug-id="policy-summary"], console-section'); for (const secao of secoes) { // pega o heading dessa secão const heading = secao.querySelector('[debug-id="header-text"] .simple-html-contents'); if (!heading) continue; const hTxt = normalizar(heading.textContent); if (hTxt === alvo && isVisivel(secao)) { return secao; } } return null; } window.getInputFromBoxInput = function(box) { if (!box) return; // Se o próprio box já for um input, usa ele diretamente let input = box.tagName === 'INPUT' || box.tagName === 'TEXTAREA' ? box : box.querySelector('input, textarea'); return input; }; window.setTextoNoInputNoBoxInput = function(box, txt) { let input = getInputFromBoxInput(box); if (input) { setTextoNoInput(input, txt); } } window.setTextoNoInputByDebugId = function(cod, txt) { let box = getElByDebugId(cod); setTextoNoInputNoBoxInput(box, txt); }; window.setTextoNoInputByArialLabelTxt = function(cod, txt) { let box = getElByArialLabelTxt(cod); setTextoNoInputNoBoxInput(box, txt); }; window.clicarBotaoByDebugId = function(debugId){ let bot = encontrarBotaoByDebugId(debugId); clickElemento(bot) } window.setTextoNoInput = function(input, txt) { if (txt === undefined || txt === null) return; // não faz nada input.value = txt; input.dispatchEvent(new Event('input', { bubbles: true })); input.dispatchEvent(new Event('change', { bubbles: true })); }; window.clicarMenu = function(txtArial) { try { const el = getElByArialLabelTxt(txtArial); if (!el) { console.warn(`Elemento com aria-label contendo "${txtArial}" não encontrado.`); return; } const link = el.querySelector('a'); if (!link) { console.warn(`Nenhum encontrado dentro do elemento "${txtArial}".`); return; } if (typeof clickElemento === 'function') { clickElemento(link); } else { console.warn('Função clickElemento não definida.'); } } catch (e) { console.error('Erro ao executar clicarMenu:', e); } } window.getElByDebugId = function(debugId) { return document.querySelector('[debug-id="'+debugId+'"'); } window.getElByArialLabelTxt = function(txt) { // return document.querySelector('[aria-label="'+txt+'"'); return Array.from( document.querySelectorAll('[aria-label="'+txt+'"') ).filter(el => el.offsetParent !== null)[0]; } // window.setTextoNoInputByArialLabel = function(arialLabelCode, txt){ // let input = getElByArialLabelTxt(arialLabelCode) // setTextoNoInput(input, txt) // } window.voltarPaginaConteudoApp = function () { // procura no body o botão com o aria-label específico // const botao = document.querySelector('a[aria-label="Voltar para Conteúdo do app"'); const botao = getElByArialLabelTxt("Voltar para Conteúdo do app") if (!botao || !isVisivel(botao)) { console.warn('⚠️ Botão "Voltar para Conteúdo do app" não encontrado ou não visível.'); return false; } clickElemento(botao); console.log('🔙 Clique executado no botão "Voltar para Conteúdo do app".'); return true; }; window.encontrarBotaoByDebugId = function(debugId){ const barra = encontrarBarraDoBotao(); return execEncontrarBotaoByDebugId(barra, debugId) || execEncontrarBotaoByDebugId(document, debugId); } // Função pública window.clicarBotaoProximo = function () { const ids = ['button-next', 'next-button']; for (const id of ids) { if (encontrarBotaoByDebugId(id)) { return clicarBotaoByDebugId(id); } } }; window.clicarBotaoSalvar = function () { clicarBotaoByDebugId('main-button'); }; window.clicarBotaoSalvarRascunho = function () { clicarBotaoByDebugId('save-draft-button'); }; window.salvarEVoltarPaginaConteudoApp = async function (opt) { await sleep(5000); clicarBotaoSalvar(); await sleep(5000); voltarPaginaConteudoApp(); await sleep(5000); }; // Função pública window.abrirSecaoConteudoApp = function (titulo) { const secao = encontrarSecaoPorTitulo(titulo); if (!secao) { console.warn(`Seção não encontrada para título: "${titulo}"`); return false; } const ok = clicarBotaoDaSecao(secao, titulo); if (!ok) { console.warn(`Botão não encontrado/visível na seção: "${titulo}"`); } return ok; }; window.clicarNosTextos = function(textos){ setTimeout(function() { var elements = document.querySelectorAll('*'); elements.forEach(function(element) { // console.log(element.textContent) textos.forEach(function(texto) { try { if (element.textContent.match(texto, "i")) { element.click() } } catch { } }); }); }, 1000); } window.marcarCheckBox = function(textos){ clicarNosTextos(textos) } window.sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); })(); /////////////////////////////////////////// /////////////////////////////////////////// // rodarConteudoApp /////////////////////////////////////////// /////////////////////////////////////////// async function conteudoAnuncios(opt) { let nomeSecao = 'Anúncios' abrirSecaoConteudoApp(nomeSecao); await sleep(1000); marcarCheckBox([/Não, meu app não tem anúncios/]); await salvarEVoltarPaginaConteudoApp(); console.log('✅ Seção '+nomeSecao+' concluída'); } async function conteudoAppsGovernamentais(opt) { let nomeSecao = 'Apps governamentais' abrirSecaoConteudoApp(nomeSecao); await sleep(1000); marcarCheckBox([/Não/]); await salvarEVoltarPaginaConteudoApp(); console.log('✅ Seção '+nomeSecao+' concluída'); } async function conteudoIdPublicidade(opt) { let nomeSecao = 'ID de publicidade' abrirSecaoConteudoApp(nomeSecao); await sleep(1000); marcarCheckBox([/Sim/]); await sleep(800); marcarCheckBox([/Usados para coletar dados sobre a forma como os usuários utilizam o app ou o desemp/]); await salvarEVoltarPaginaConteudoApp(); console.log('✅ Seção '+nomeSecao+' concluída'); } async function conteudoRecursosFinanceiros(opt) { let nomeSecao = 'Recursos financeiros' abrirSecaoConteudoApp(nomeSecao); await sleep(3000); marcarCheckBox([/Meu app não oferece recursos financeiros/]); await sleep(3000); clicarBotaoProximo(); await salvarEVoltarPaginaConteudoApp(); console.log('✅ Seção '+nomeSecao+' concluída'); } async function conteudoSaude(opt) { let nomeSecao = 'Apps de saúde' abrirSecaoConteudoApp(nomeSecao); await sleep(1000); marcarCheckBox([/Meu app não tem recursos de saúde/]); await salvarEVoltarPaginaConteudoApp(); console.log('✅ Seção '+nomeSecao+' concluída'); } async function conteudoPoliticaPrivacidade(opt) { let nomeSecao = 'Política de Privacidade' abrirSecaoConteudoApp(nomeSecao); await sleep(4000); let nomeAppEncoded = encodeURIComponent(opt.nomeApp); let url = `https://www.seucondominio.com.br/politica-privacidade?no_layout=true&appName=${nomeAppEncoded}` setTextoNoInputByDebugId('privacy-policy-url-input', url) await salvarEVoltarPaginaConteudoApp(); console.log('✅ Seção '+nomeSecao+' concluída'); } async function conteudoAcessoApps(opt) { let nomeSecao = 'Acesso de apps' abrirSecaoConteudoApp(nomeSecao); await sleep(1000); marcarCheckBox([/Todas ou algumas funcionalidades do app são restritas./]); await sleep(1000); clicarNosTextos([/Adicionar instruções/]) await sleep(2000); setTextoNoInputByDebugId('name-input', "User") setTextoNoInputByDebugId('username-input', 'teste.seucondominio@gmail.com') setTextoNoInputByDebugId('password-input', 'testestaging') marcarCheckBox([/Nenhuma outra informação é necessária para acessar meu app/]); await sleep(1000); clicarBotaoByDebugId('apply-button'); await salvarEVoltarPaginaConteudoApp(); console.log('✅ Seção '+nomeSecao+' concluída'); } async function conteudoAppsClassificacaoConteudo(opt) { let nomeSecao = 'Classificações de conteúdo' abrirSecaoConteudoApp(nomeSecao); await sleep(2000); let botIniciar = document.querySelector('[debug-id="get-started-start-button"]') || document.querySelector('[debug-id="edit-button"]') clickElemento(botIniciar); await sleep(4000); setTextoNoInputByDebugId('email-address-input', opt.email) await sleep(1000); marcarCheckBox([ /Todos os Outros Tipos de Aplicações/, /Concordo com os Termos de Uso/ ]); await sleep(4000); clicarBotaoProximo(); await sleep(1000); marcarCheckBox([/Não/]); // marcarCheckBox([/Não/]); // await sleep(1000); // marcarCheckBox([/Não/]); await sleep(5000); clicarBotaoSalvar() await sleep(5000); clicarBotaoProximo(); await salvarEVoltarPaginaConteudoApp(); console.log('✅ Seção '+nomeSecao+' concluída'); } async function conteudoPublicoAlvo(opt) { let nomeSecao = 'Público-alvo e conteúdo' abrirSecaoConteudoApp(nomeSecao); await sleep(4000); marcarCheckBox([ /13 a 15/, /16 a 17/, /Maiores de 18 anos/, ]); await sleep(3000); clicarBotaoProximo(); await salvarEVoltarPaginaConteudoApp(); console.log('✅ Seção '+nomeSecao+' concluída'); } async function conteudoSegurancaDados(opt) { async function execPagina1(){ marcarCheckBox([/Sim/]); await sleep(1000); marcarCheckBox([/Sim/]); await sleep(1000); marcarCheckBox([/Nome de usuário e senha/]); await sleep(1000); setTextoNoInputByDebugId('account-deletion-url', opt.contatoUrl) marcarCheckBox([/Sim/]); await sleep(1000); setTextoNoInputByDebugId('data-deletion-url', opt.contatoUrl) console.log("pagina 1 executada") } async function execPagina2(){ let accordions = Array.from( document.querySelectorAll('[debug-id="console-section-expand-button-icon"') ).filter(el => el.offsetParent !== null); async function abrirAccordion(number){ clickElemento(accordions[number]) // abrir accorion informações pessoas await sleep(2000); } // abrirAccordion(0) marcarCheckBox([ /Local aproximado/, /Local exato/, ]); await sleep(3000); abrirAccordion(1) marcarCheckBox([ /Nome/, /Endereço de e-mail/, /IDs de usuários/, /Endereço/, /Número de telefone/, ]); await sleep(3000); abrirAccordion(13) marcarCheckBox([ /Identificadores do dispositivo e outros IDs/, ]); await sleep(3000); console.log("pagina 2 executada") } async function preencherItenDoAccordionPagina3(bot){ clickElemento(bot); await sleep(3000); marcarCheckBox([ /Estes dados são transmitidos do dispositivo do usuário a você /, /Estes dados são transferidos a terceiros, tanto no próprio dispositivo do usuário quanto para fora dele/, ]) await sleep(3000); marcarCheckBox([ /Sim, os dados coletados são processados de maneira efêmera/, /Os usuários podem escolher se os dados são coletados/, /Usados para funcionalidades do app, como ativação de certos recursos ou autenticação dos usuários/, ]) await sleep(3000); clicarBotaoByDebugId('save-button'); await sleep(5000); } async function preencherAccordionPagina3(acc){ clickElemento(acc) // abrir accordion await sleep(2000); // esperar aparecer os botoes let botoesDoAccordion = Array.from( document.querySelectorAll('[aria-label^="Abrir perguntas"]') ).filter(el => el.offsetParent !== null); for (const bot of botoesDoAccordion) { await preencherItenDoAccordionPagina3(bot) } } async function execPagina3(){ let accordions = Array.from( document.querySelectorAll('[debug-id="console-section-expand-button-icon"') ).filter(el => el.offsetParent !== null); for (const accordion of accordions) { await preencherAccordionPagina3(accordion) // await sleep(2000); } console.log("pagina 3 executada") } let nomeSecao = 'Segurança dos dados' abrirSecaoConteudoApp(nomeSecao); await sleep(2000); clicarBotaoProximo(); await sleep(2000); await execPagina1() // pagina 1 await sleep(5000); clicarBotaoProximo(); await sleep(4000); await execPagina2() // pagina 2 await sleep(4000); clicarBotaoProximo(); await sleep(2000); await execPagina3() // pagina 3 await sleep(2000); clicarBotaoProximo(); // salvar await salvarEVoltarPaginaConteudoApp(); console.log('✅ Seção '+nomeSecao+' concluída'); } async function rodarConteudoApp(opt) { clicarMenu("Conteúdo do app") await sleep(5000); await conteudoAcessoApps(opt); await conteudoIdPublicidade(opt); await conteudoAppsGovernamentais(opt); await conteudoAnuncios(opt); await conteudoRecursosFinanceiros(opt); await conteudoSaude(opt); await conteudoPoliticaPrivacidade(opt); await conteudoPublicoAlvo(opt); await conteudoSegurancaDados(opt); await conteudoAppsClassificacaoConteudo(opt); console.log('🎉 Conteudo: Todas as seções foram preenchidas com sucesso!'); } /////////////////////////////////////////// /////////////////////////////////////////// // rodarPresencaLoja /////////////////////////////////////////// /////////////////////////////////////////// async function lojaConfigLoja(opt) { async function salvarEFechar(){ await sleep(3000); clicarBotaoSalvar(); await sleep(3000); clickElemento(getElByArialLabelTxt('Fechar')); } nomeSecao = "Configurações da loja" clicarMenu(nomeSecao) await sleep(4000); // editar categoria financeiro clickElemento(getElByDebugId("edit-app-category-section-button")) await sleep(4000); clickElemento(document.querySelector('[debug-id="category-dropdown"] [buttondecorator]')) await sleep(3000); clicarNoTexto(/Finanças/) // clickElemento(document.querySelector('[id="a819A6D5E-2259-42FD-8A37-DEC0B82F7AB8--191"]')) await salvarEFechar(); // editar detalhes clickElemento(getElByDebugId("edit-store-listing-section-button")) await sleep(3000); setTextoNoInputByDebugId('email-input', opt.email) setTextoNoInputByDebugId('phone-input', opt.telefone) setTextoNoInputByDebugId('website-input', opt.site) await salvarEFechar(); console.log('✅ Seção '+nomeSecao+' concluída'); await sleep(5000); } async function lojaDetalhesDoApp(opt) { nomeSecao = "Páginas Detalhes do app" clicarMenu(nomeSecao) await sleep(3000); let botIniciar = document.querySelector('[essfield="editListingAction"] a') || document.querySelector('[debug-id="get-started-create-default-listing-button"]'); clickElemento(botIniciar) await sleep(3000); setTextoNoInputByArialLabelTxt('Nome do app', opt.nomeApp) setTextoNoInputByArialLabelTxt('Breve descrição do app', opt.descricaoBreve) await sleep(3000); clicarBotaoSalvarRascunho() await sleep(5000); } async function rodarPresencaLoja(opt) { await lojaConfigLoja(opt); await lojaDetalhesDoApp(opt); console.log('🎉 Loja: Todas as seções foram preenchidas com sucesso!'); } window.clicarNoTexto = function(txt){ clicarNosTextos([txt]); } /////////////////////////////////////////// /////////////////////////////////////////// // rodarCriarVersao /////////////////////////////////////////// /////////////////////////////////////////// async function versaoProducao(opt) { async function arrumarPaises(opt) { let abaPaises = getElByArialLabelTxt('Países / regiões') clickElemento(abaPaises); await sleep(5000); clicarNoTexto(/Adicionar países \/ regiões/); // clicarNoTexto(/Editar países \/ regiões/); await sleep(10000); clickElemento(getElByArialLabelTxt('Selecionar todas as linhas')); await sleep(2000); clicarBotaoSalvar(); } async function criarVersao(opt) { clicarBotaoByDebugId('create-android-release-button') await sleep(8000); setTextoNoInputByDebugId('whats-new', "\nApp para condomínios\n") setTextoNoInputByDebugId('version', "1.0") await sleep(1000); clicarBotaoByDebugId('save-button') } nomeSecao = "Produção" clicarMenu(nomeSecao) await sleep(5000); await arrumarPaises(opt) await sleep(5000); await criarVersao(opt) console.log('✅ Seção '+nomeSecao+' concluída'); await sleep(5000); } async function rodarCriarVersao(opt) { await versaoProducao(opt); console.log('🎉 rodarCriarVersao executada com sucesso!'); } /////////////////////////////////////////// /////////////////////////////////////////// // rodarPermissaoFotos /////////////////////////////////////////// /////////////////////////////////////////// async function fotosArumarPermissoes(opt) { // nomeSecao = "Produção" // clicarMenu(nomeSecao) // await sleep(1000); let txtImage = 'Permite o usuário selecionar e enviar fotos da galeria para o app (perfil, comprovantes e anexos em chamados/ocorrências). Somente itens escolhidos; sem leitura em segundo plano. Uso exclusivo dessa função; envio criptografado.' setTextoNoInputByArialLabelTxt('Descreva como seu app usa a permissão READ_MEDIA_IMAGES', txtImage) let txtVideo = 'Permite o usuário selecionar e enviar vídeos da galeria (registros de ocorrências/documentos audiovisuais). Apenas itens escolhidos; sem coleta em segundo plano. Uso restrito ao envio; transmissão criptografada.' setTextoNoInputByArialLabelTxt('Descreva como seu app usa a permissão READ_MEDIA_VIDEO', txtImage) await sleep(1000); clicarBotaoSalvar(); // console.log('✅ Seção '+nomeSecao+' concluída'); await sleep(5000); } async function rodarPermissaoFotos(opt) { await fotosArumarPermissoes(opt); console.log('🎉 Loja: Todas as seções foram preenchidas com sucesso!'); } /////////////////////////////////////////// /////////////////////////////////////////// // rodarCriarApp /////////////////////////////////////////// /////////////////////////////////////////// async function appCriar(opt) { clickElemento(document.querySelector('[debug-id="create-app-button"] a')); await sleep(5000); setTextoNoInputByDebugId('app-name-input', opt.nomeApp); marcarCheckBox([ /App/, /Grátis/, /Confirme se o app atende às Polític/, /Aceitar a legislação de exportação/, ]); await sleep(2000); let botSalvar = document.querySelector('[debug-id="create-app-button"] button') clickElemento(botSalvar); await sleep(20000); } async function rodarCriarApp(opt) { await appCriar(opt); console.log('🎉 rodarCriarApp executado com sucesso!'); }