let checkResults = []; // Guide Modal btnGuide.addEventListener('click', () => { Swal.fire({ title: 'Panduan Penggunaan', html: ` `, }); }); // Auto-update IP Count Badge function updateLineCount() { const text = proxyInput.value.trim(); if (!text) { ipCountBadge.textContent = '0 IPs'; return; } const lines = text.split('\n').filter(line => line.trim().length > 0); ipCountBadge.textContent = lines.length + ' IPs'; } proxyInput.addEventListener('input', updateLineCount); btnClear.addEventListener('click', () => { proxyInput.value = ''; updateLineCount(); resultSection.classList.add('hidden'); resultsContainer.innerHTML = ''; checkResults = []; }); btnSample.addEventListener('click', () => { proxyInput.value = "43.218.77.16:1443\n128.199.134.152:443\n188.240.213.125:443"; updateLineCount(); }); // --- Filter Logic --- const filterBtns = document.querySelectorAll('.filter-btn'); filterBtns.forEach(btn => { btn.addEventListener('click', () => { // Update active state filterBtns.forEach(b => { b.classList.remove('text-[var(--mint)]', 'border-b-2', 'border-[var(--mint)]'); b.classList.add('text-[var(--muted)]'); }); btn.classList.remove('text-[var(--muted)]'); btn.classList.add('text-[var(--mint)]', 'border-b-2', 'border-[var(--mint)]'); const filterType = btn.getAttribute('data-filter'); renderResults(filterType); }); }); // --- Checker Logic --- async function checkSingleIP(targetIP) { try { const response = await fetch("/checker/check?ip=" + encodeURIComponent(targetIP)); const data = await response.json(); return { ip: targetIP, data: data, status: data.status === "ACTIVE" ? "live" : "dead" }; } catch (error) { return { ip: targetIP, data: { ip: targetIP, status: "ERROR", delay: "N/A", asOrganization: "Error" }, status: "dead" }; } } function renderResults(filterType = 'all') { resultsContainer.innerHTML = ''; let filtered = checkResults; if (filterType === 'live') filtered = checkResults.filter(r => r.status === 'live'); if (filterType === 'dead') filtered = checkResults.filter(r => r.status === 'dead'); filtered.forEach(item => { const d = item.data; const isLive = item.status === 'live'; const statusColor = isLive ? 'text-[var(--green)]' : 'text-[var(--red)]'; const statusBg = isLive ? 'bg-[var(--green)]/10' : 'bg-[var(--red)]/10'; const statusBorder = isLive ? 'border-[var(--green)]/30' : 'border-[var(--red)]/30'; const cardHTML = ` `; resultsContainer.insertAdjacentHTML('beforeend', cardHTML); }); } function updateStats() { const total = checkResults.length; const live = checkResults.filter(r => r.status === 'live').length; const dead = checkResults.filter(r => r.status === 'dead').length; document.getElementById('countAll').textContent = total; document.getElementById('countLive').textContent = live; document.getElementById('countDead').textContent = dead; } btnStartCheck.addEventListener('click', async () => { const text = proxyInput.value.trim(); if (!text) { Swal.fire({ icon: 'warning', title: 'Oops...', text: 'Masukkan setidaknya satu IP proxy!', background: 'var(--card)', color: 'var(--text)' }); return; } const ipList = text.split('\n').map(ip => ip.trim()).filter(ip => ip.length > 0); if (ipList.length === 0) return; // UI Loading state btnStartCheck.disabled = true; checkIcon.classList.add('hidden'); checkSpinner.classList.remove('hidden'); checkText.textContent = 'Memeriksa...'; progressInfo.classList.remove('hidden'); progressTotal.textContent = ipList.length; progressCount.textContent = '0'; resultSection.classList.remove('hidden'); resultsContainer.innerHTML = ''; checkResults = []; // Batch Processing const concurrencyLimit = 10; let checkedCount = 0; for (let i = 0; i < ipList.length; i += concurrencyLimit) { const chunk = ipList.slice(i, i + concurrencyLimit); const promises = chunk.map(async (ip) => { const res = await checkSingleIP(ip); checkResults.push(res); checkedCount++; progressCount.textContent = checkedCount; updateStats(); // Render with current filter const activeFilter = document.querySelector('.filter-btn.text-\\[var\\(--mint\\)\\]').getAttribute('data-filter'); renderResults(activeFilter); }); await Promise.all(promises); } // Restore UI state btnStartCheck.disabled = false; checkIcon.classList.remove('hidden'); checkSpinner.classList.add('hidden'); checkText.textContent = 'Start Check'; progressInfo.classList.add('hidden'); Swal.fire({ icon: 'success', title: 'Selesai!', text: `Selesai memeriksa ${ipList.length} IP.`, background: 'var(--card)', color: 'var(--text)', confirmButtonColor: 'var(--mint)' }); }); // --- Export / Copy Logic --- function getLiveIPsText() { return checkResults .filter(r => r.status === 'live') .map(r => r.ip) .join('\n'); } document.getElementById('btnCopyLive').addEventListener('click', () => { const text = getLiveIPsText(); if (!text) { Swal.fire({ icon: 'info', title: 'Kosong', text: 'Tidak ada IP Live untuk disalin.', background: 'var(--card)', color: 'var(--text)' }); return; } navigator.clipboard.writeText(text).then(() => { Swal.fire({ icon: 'success', title: 'Disalin!', text: 'IP Live berhasil disalin ke clipboard.', timer: 1500, showConfirmButton: false, background: 'var(--card)', color: 'var(--text)' }); }); }); document.getElementById('btnExportLive').addEventListener('click', () => { const text = getLiveIPsText(); if (!text) { Swal.fire({ icon: 'info', title: 'Kosong', text: 'Tidak ada IP Live untuk diekspor.', background: 'var(--card)', color: 'var(--text)' }); return; } const blob = new Blob([text], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'live_proxies.txt'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }); // Initial UI setup updateLineCount();