Promoção do Joce

Sorteios profissionais para as suas redes sociais

let comments = []; let loadingInterval = null; let fbAccessToken = null; // Inicializa o SDK do Facebook window.fbAsyncInit = function() { FB.init({ appId : '2099090147670312', cookie : true, xfbml : true, version : 'v19.0' }); console.log("Facebook SDK Inicializado com Sucesso"); }; // Extrai o shortcode do link inserido function getShortcode(url) { const match = url.match(/instagram\.com\/(?:p|reel)\/([a-zA-Z0-9_-]+)/); return match ? match[1] : null; } async function loadComments() { const link = document.getElementById('post-link').value; const shortcode = getShortcode(link); if (!shortcode) { alert("Por favor, insira um link válido de uma postagem do Instagram."); return; } const btn = document.getElementById('btn-load'); const btnText = document.getElementById('btn-text'); const spinner = document.getElementById('loading-spinner'); const progressContainer = document.getElementById('progress-container'); const progressBar = document.getElementById('progress-bar'); const progressPercent = document.getElementById('progress-percent'); const commentCountText = document.getElementById('comment-count'); btn.disabled = true; spinner.classList.remove('hidden'); progressContainer.classList.remove('hidden'); const updateProgress = (pct, msg) => { progressBar.style.width = pct + '%'; progressPercent.innerText = pct + '%'; commentCountText.innerText = msg; }; // Passo 1: Autenticação via Facebook updateProgress(10, "Aguardando Login no Facebook..."); FB.login(function(response) { if (response.authResponse) { fbAccessToken = response.authResponse.accessToken; updateProgress(30, "Login efetuado. Buscando suas Páginas..."); fetchInstagramData(shortcode, updateProgress); } else { alert("Você cancelou o login ou não autorizou o aplicativo."); resetApp(); } }, {scope: 'instagram_basic,instagram_manage_comments,pages_show_list,pages_read_engagement'}); } function fetchInstagramData(shortcode, updateProgress) { // Passo 2: Pegar as páginas do Facebook do usuário FB.api('/me/accounts', function(pagesResponse) { if (!pagesResponse || pagesResponse.error) { alert("Erro ao buscar Páginas do Facebook."); resetApp(); return; } if (pagesResponse.data.length === 0) { alert("Você não possui nenhuma Página do Facebook conectada ao seu perfil."); resetApp(); return; } updateProgress(50, "Buscando Conta do Instagram vinculada..."); findInstagramAccount(pagesResponse.data, 0, shortcode, updateProgress); }); } function findInstagramAccount(pages, index, shortcode, updateProgress) { if (index >= pages.length) { alert("Nenhuma conta do Instagram Comercial foi encontrada nas suas Páginas."); resetApp(); return; } const page = pages[index]; FB.api('/' + page.id + '?fields=instagram_business_account', function(igResponse) { if (igResponse && igResponse.instagram_business_account) { const igAccountId = igResponse.instagram_business_account.id; updateProgress(70, "Instagram encontrado. Localizando a postagem..."); findMedia(igAccountId, shortcode, updateProgress); } else { // Tenta a próxima página findInstagramAccount(pages, index + 1, shortcode, updateProgress); } }); } function findMedia(igAccountId, shortcode, updateProgress) { // Pega as postagens recentes para encontrar a que bate com o shortcode FB.api('/' + igAccountId + '/media?fields=id,shortcode', function(mediaResponse) { if (!mediaResponse || mediaResponse.error) { alert("Erro ao buscar as postagens do seu Instagram."); resetApp(); return; } const media = mediaResponse.data.find(m => m.shortcode === shortcode); if (!media) { alert("A postagem do link fornecido não foi encontrada na sua conta. Lembre-se: Você só pode sortear comentários de posts seus!"); resetApp(); return; } updateProgress(85, "Postagem encontrada! Baixando comentários..."); fetchAllComments(media.id, updateProgress); }); } function fetchAllComments(mediaId, updateProgress, afterToken = null, accumulated = []) { let endpoint = '/' + mediaId + '/comments?fields=id,text,from{username}'; if (afterToken) { endpoint += '&after=' + afterToken; } FB.api(endpoint, function(commentsResponse) { if (!commentsResponse || commentsResponse.error) { alert("Erro ao baixar os comentários."); resetApp(); return; } const newComments = commentsResponse.data.map(c => ({ id: c.id, user: c.from ? '@' + c.from.username : '@usuario_oculto', avatar: c.from ? `https://ui-avatars.com/api/?name=${c.from.username}&background=fcc419&color=0f172a` : 'https://ui-avatars.com/api/?name=U&background=fcc419&color=0f172a', text: c.text })); accumulated = accumulated.concat(newComments); updateProgress(90, `Baixados ${accumulated.length} comentários...`); if (commentsResponse.paging && commentsResponse.paging.cursors && commentsResponse.paging.cursors.after) { // Tem mais comentários, busca a próxima página fetchAllComments(mediaId, updateProgress, commentsResponse.paging.cursors.after, accumulated); } else { // Acabou finishLoading(accumulated, updateProgress); } }); } function finishLoading(realComments, updateProgress) { if (realComments.length === 0) { alert("Essa postagem não tem nenhum comentário para sortear."); resetApp(); return; } comments = realComments; updateProgress(100, `Sucesso! ${comments.length} comentários reais prontos!`); setTimeout(() => { document.getElementById('setup-panel').classList.add('hidden'); document.getElementById('raffle-panel').classList.remove('hidden'); renderReel(); }, 1000); } function renderReel() { const reel = document.getElementById('reel'); reel.innerHTML = ''; // Criar uma lista longa para o efeito de rotação (repetimos os comentários para parecer infinito) const displayList = [...comments, ...comments, ...comments, ...comments]; displayList.forEach((comment) => { const card = document.createElement('div'); card.className = 'comment-card'; card.innerHTML = `
${comment.user}
${comment.text}
`; reel.appendChild(card); }); } function startRaffle() { const btn = document.getElementById('btn-raffle'); const reel = document.getElementById('reel'); btn.disabled = true; btn.classList.add('opacity-50', 'cursor-not-allowed'); const cardHeight = 100; const winnerIndex = Math.floor(Math.random() * comments.length) + (comments.length * 2); // Centralizar o card no meio do container (350px / 2 = 175px) const targetOffset = (winnerIndex * cardHeight) - 125; reel.style.transform = `translateY(-${targetOffset}px)`; setTimeout(() => { showWinner(comments[winnerIndex % comments.length]); }, 5500); } function showWinner(winner) { const modal = document.getElementById('winner-modal'); const display = document.getElementById('winner-display'); display.innerHTML = `

${winner.user}

"${winner.text}"

`; modal.classList.remove('hidden'); // Confetes const duration = 3 * 1000; const end = Date.now() + duration; (function frame() { confetti({ particleCount: 3, angle: 60, spread: 55, origin: { x: 0 }, colors: ['#fcc419', '#ffffff', '#1a2332'] }); confetti({ particleCount: 3, angle: 120, spread: 55, origin: { x: 1 }, colors: ['#fcc419', '#ffffff', '#1a2332'] }); if (Date.now() < end) { requestAnimationFrame(frame); } }()); } /** * NOVA FUNÇÃO DE RESET: * Em vez de recarregar a página, resetamos o estado do DOM. */ function resetApp() { // Esconder o modal document.getElementById('winner-modal').classList.add('hidden'); // Voltar para o ecrã inicial document.getElementById('setup-panel').classList.remove('hidden'); document.getElementById('raffle-panel').classList.add('hidden'); // Limpar input document.getElementById('post-link').value = ''; // Resetar botão de carregamento const btnLoad = document.getElementById('btn-load'); btnLoad.disabled = false; document.getElementById('btn-text').innerText = "CARREGAR COMENTÁRIOS"; document.getElementById('loading-spinner').classList.add('hidden'); // Resetar barra de progresso document.getElementById('progress-container').classList.add('hidden'); document.getElementById('progress-bar').style.width = '0%'; document.getElementById('progress-percent').innerText = '0%'; // Resetar botão de sorteio const btnRaffle = document.getElementById('btn-raffle'); btnRaffle.disabled = false; btnRaffle.classList.remove('opacity-50', 'cursor-not-allowed'); // Resetar a roleta visualmente sem animação const reel = document.getElementById('reel'); reel.style.transition = 'none'; reel.style.transform = 'translateY(0)'; // Forçar o navegador a processar a mudança de posição antes de reativar a transição void reel.offsetHeight; reel.style.transition = 'transform 5s cubic-bezier(0.15, 0, 0.15, 1)'; // Parar qualquer intervalo que esteja a correr if (loadingInterval) clearInterval(loadingInterval); }